reformat code according to pycharm
Esse commit está contido em:
+115
-115
@@ -55,6 +55,7 @@ ALBUM_LOAD_CHUNK = 50
|
||||
# default chunk of albums to process when loading covers
|
||||
COVER_LOAD_CHUNK = 5
|
||||
|
||||
|
||||
class Cover(GObject.Object):
|
||||
'''
|
||||
Cover of an Album. It may be initialized either by a file path to the image
|
||||
@@ -73,7 +74,7 @@ class Cover(GObject.Object):
|
||||
def __init__(self, size, image):
|
||||
super(Cover, self).__init__()
|
||||
|
||||
assert isinstance( image, str ), "image should be a string"
|
||||
assert isinstance(image, str), "image should be a string"
|
||||
|
||||
self.original = image
|
||||
|
||||
@@ -114,7 +115,6 @@ class Shadow(Cover):
|
||||
|
||||
|
||||
class ShadowedCover(Cover):
|
||||
|
||||
def __init__(self, shadow, image):
|
||||
super(ShadowedCover, self).__init__(shadow.cover_size, image)
|
||||
|
||||
@@ -142,11 +142,11 @@ class ShadowedCover(Cover):
|
||||
|
||||
# draw cover
|
||||
Gdk.cairo_set_source_pixbuf(context, self.pixbuf, self._shadow.width,
|
||||
self._shadow.width)
|
||||
self._shadow.width)
|
||||
context.paint()
|
||||
|
||||
self.pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0,
|
||||
self._shadow.size, self._shadow.size)
|
||||
self._shadow.size, self._shadow.size)
|
||||
|
||||
|
||||
class Track(GObject.Object):
|
||||
@@ -162,7 +162,7 @@ class Track(GObject.Object):
|
||||
__gsignals__ = {
|
||||
'modified': (GObject.SIGNAL_RUN_LAST, None, ()),
|
||||
'deleted': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
@@ -231,8 +231,8 @@ class Track(GObject.Object):
|
||||
def album_artist_sort(self):
|
||||
sort = self.entry.get_string(
|
||||
RB.RhythmDBPropType.ALBUM_ARTIST_SORTNAME_FOLDED) or \
|
||||
self.entry.get_string(RB.RhythmDBPropType.ALBUM_ARTIST_FOLDED) or \
|
||||
self.entry.get_string(RB.RhythmDBPropType.ARTIST_FOLDED)
|
||||
self.entry.get_string(RB.RhythmDBPropType.ALBUM_ARTIST_FOLDED) or \
|
||||
self.entry.get_string(RB.RhythmDBPropType.ARTIST_FOLDED)
|
||||
|
||||
return NaturalString(sort)
|
||||
|
||||
@@ -240,7 +240,7 @@ class Track(GObject.Object):
|
||||
def album_sort(self):
|
||||
sort = self.entry.get_string(
|
||||
RB.RhythmDBPropType.ALBUM_SORTNAME_FOLDED) or \
|
||||
self.entry.get_string(RB.RhythmDBPropType.ALBUM_FOLDED)
|
||||
self.entry.get_string(RB.RhythmDBPropType.ALBUM_FOLDED)
|
||||
|
||||
return NaturalString(sort)
|
||||
|
||||
@@ -269,7 +269,7 @@ class Album(GObject.Object):
|
||||
'modified': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
'emptied': (GObject.SIGNAL_RUN_LAST, None, ()),
|
||||
'cover-updated': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
@@ -379,7 +379,7 @@ class Album(GObject.Object):
|
||||
def rating(self):
|
||||
if not self._rating:
|
||||
ratings = [track.rating for track in self._tracks
|
||||
if track.rating and track.rating != 0]
|
||||
if track.rating and track.rating != 0]
|
||||
|
||||
if len(ratings) > 0:
|
||||
self._rating = sum(ratings) / len(self._tracks)
|
||||
@@ -416,7 +416,7 @@ class Album(GObject.Object):
|
||||
|
||||
self._cover = new_cover
|
||||
self._cover_resized_id = self._cover.connect('resized',
|
||||
lambda *args: self.emit('cover-updated'))
|
||||
lambda *args: self.emit('cover-updated'))
|
||||
|
||||
self.emit('cover-updated')
|
||||
|
||||
@@ -435,7 +435,7 @@ class Album(GObject.Object):
|
||||
else:
|
||||
# otherwise, only return the entries over the threshold
|
||||
tracks = [track for track in self._tracks
|
||||
if track.rating >= rating_threshold]
|
||||
if track.rating >= rating_threshold]
|
||||
|
||||
return sorted(tracks, key=lambda track: (track.disc_number, track.track_number))
|
||||
|
||||
@@ -447,20 +447,20 @@ class Album(GObject.Object):
|
||||
'''
|
||||
self._tracks.append(track)
|
||||
ids = (track.connect('modified', self._track_modified),
|
||||
track.connect('deleted', self._track_deleted))
|
||||
track.connect('deleted', self._track_deleted))
|
||||
|
||||
self._signals_id[track] = ids
|
||||
self.emit('modified')
|
||||
|
||||
def _track_modified(self, track):
|
||||
print ("_track_modified")
|
||||
print("_track_modified")
|
||||
if track.album != self.name:
|
||||
self._track_deleted(track)
|
||||
else:
|
||||
self.emit('modified')
|
||||
|
||||
def _track_deleted(self, track):
|
||||
print ("_track_deleted")
|
||||
print("_track_deleted")
|
||||
self._tracks.remove(track)
|
||||
|
||||
#list(map(track.disconnect, self._signals_id[track]))
|
||||
@@ -497,15 +497,14 @@ class Album(GObject.Object):
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.name == other.name and \
|
||||
self.artist == other.artist
|
||||
self.artist == other.artist
|
||||
|
||||
def __ne__(self, other):
|
||||
return not other or\
|
||||
self.name + self.artist != other.name + other.artist
|
||||
return not other or \
|
||||
self.name + self.artist != other.name + other.artist
|
||||
|
||||
|
||||
class AlbumFilters(object):
|
||||
|
||||
@classmethod
|
||||
def nay_filter(cls, *args):
|
||||
def filt(*args):
|
||||
@@ -524,7 +523,7 @@ class AlbumFilters(object):
|
||||
|
||||
words = RB.search_fold(searchtext).split()
|
||||
params = list(map(RB.search_fold, [album.name, album.artist,
|
||||
album.artists, album.track_titles, album.composers]))
|
||||
album.artists, album.track_titles, album.composers]))
|
||||
matches = []
|
||||
|
||||
for word in words:
|
||||
@@ -572,7 +571,7 @@ class AlbumFilters(object):
|
||||
|
||||
words = RB.search_fold(searchtext).split()
|
||||
params = list(map(RB.search_fold, [album.artist,
|
||||
album.artists]))
|
||||
album.artists]))
|
||||
matches = []
|
||||
|
||||
for word in words:
|
||||
@@ -605,7 +604,7 @@ class AlbumFilters(object):
|
||||
if not searchtext:
|
||||
return True
|
||||
|
||||
return RB.search_fold(searchtext) in RB.search_fold(
|
||||
return RB.search_fold(searchtext) in RB.search_fold(
|
||||
album.track_titles)
|
||||
|
||||
return filt
|
||||
@@ -616,7 +615,7 @@ class AlbumFilters(object):
|
||||
if not searchtext:
|
||||
return True
|
||||
|
||||
return RB.search_fold(searchtext) in RB.search_fold(
|
||||
return RB.search_fold(searchtext) in RB.search_fold(
|
||||
album.composers)
|
||||
|
||||
return filt
|
||||
@@ -628,7 +627,7 @@ class AlbumFilters(object):
|
||||
return True
|
||||
|
||||
genres = RB.search_fold(' '.join(album.genres))
|
||||
return RB.search_fold(searchtext) in genres
|
||||
return RB.search_fold(searchtext) in genres
|
||||
|
||||
return filt
|
||||
|
||||
@@ -657,6 +656,7 @@ class AlbumFilters(object):
|
||||
or -1 for all albums older than our standard range which is 1930
|
||||
or an actual decade for 1930 to 2020
|
||||
'''
|
||||
|
||||
def filt(album):
|
||||
if not searchdecade:
|
||||
return True
|
||||
@@ -691,7 +691,6 @@ AlbumFilters.keys = {
|
||||
'decade': AlbumFilters.decade_filter
|
||||
}
|
||||
|
||||
|
||||
sort_keys = {
|
||||
'name': ('album_sort', 'album_sort'),
|
||||
'artist': ('album_artist_sort', 'album_artist_sort'),
|
||||
@@ -720,7 +719,7 @@ class AlbumsModel(GObject.Object):
|
||||
'visual-updated': ((GObject.SIGNAL_RUN_LAST, None, (object, object))),
|
||||
'filter-changed': ((GObject.SIGNAL_RUN_FIRST, None, ())),
|
||||
'album-added': ((GObject.SIGNAL_RUN_LAST, None, (object,)))
|
||||
}
|
||||
}
|
||||
|
||||
# list of columns names and positions on the TreeModel
|
||||
columns = {'tooltip': 0, 'pixbuf': 1, 'album': 2, 'markup': 3, 'show': 4}
|
||||
@@ -731,10 +730,10 @@ class AlbumsModel(GObject.Object):
|
||||
self._iters = {}
|
||||
self._albums = SortedCollection(
|
||||
key=lambda album: getattr(album, 'name'))
|
||||
self._sortkey = {'type':'name', 'order':True}
|
||||
self._sortkey = {'type': 'name', 'order': True}
|
||||
|
||||
self._tree_store = Gtk.ListStore(str, GdkPixbuf.Pixbuf, object, str,
|
||||
bool)
|
||||
bool)
|
||||
|
||||
# filters
|
||||
self._filters = {}
|
||||
@@ -757,7 +756,7 @@ class AlbumsModel(GObject.Object):
|
||||
markup = self.emit('generate-markup', album)
|
||||
|
||||
self._tree_store.set(tree_iter, self.columns['markup'],
|
||||
markup)
|
||||
markup)
|
||||
self._emit_signal(tree_iter, 'visual-updated')
|
||||
|
||||
def error(exception):
|
||||
@@ -766,7 +765,7 @@ class AlbumsModel(GObject.Object):
|
||||
return ALBUM_LOAD_CHUNK, process, None, error, None
|
||||
|
||||
def _album_modified(self, album):
|
||||
print ("_album_modified")
|
||||
print("_album_modified")
|
||||
tree_iter = self._iters[album.name][album.artist]['iter']
|
||||
|
||||
if self._tree_store.iter_is_valid(tree_iter):
|
||||
@@ -776,7 +775,7 @@ class AlbumsModel(GObject.Object):
|
||||
self._generate_values(album)
|
||||
|
||||
self._tree_store.set(tree_iter, self.columns['tooltip'], tooltip,
|
||||
self.columns['markup'], markup, self.columns['show'], hidden)
|
||||
self.columns['markup'], markup, self.columns['show'], hidden)
|
||||
|
||||
# reorder the album
|
||||
new_pos = self._albums.reorder(album)
|
||||
@@ -794,8 +793,8 @@ class AlbumsModel(GObject.Object):
|
||||
self._tree_store.move_before(tree_iter, old_iter)
|
||||
|
||||
# inform that the album is updated
|
||||
print ("album modified")
|
||||
print (album)
|
||||
print("album modified")
|
||||
print(album)
|
||||
self._emit_signal(tree_iter, 'album-updated')
|
||||
|
||||
def _cover_updated(self, album):
|
||||
@@ -806,7 +805,7 @@ class AlbumsModel(GObject.Object):
|
||||
pixbuf = album.cover.pixbuf
|
||||
|
||||
self._tree_store.set_value(tree_iter, self.columns['pixbuf'],
|
||||
pixbuf)
|
||||
pixbuf)
|
||||
|
||||
self._emit_signal(tree_iter, 'visual-updated')
|
||||
|
||||
@@ -836,12 +835,12 @@ class AlbumsModel(GObject.Object):
|
||||
tree_iter = self._tree_store.insert(self._albums.insert(album), values)
|
||||
# connect signals
|
||||
ids = (album.connect('modified', self._album_modified),
|
||||
album.connect('cover-updated', self._cover_updated),
|
||||
album.connect('emptied', self.remove))
|
||||
album.connect('cover-updated', self._cover_updated),
|
||||
album.connect('emptied', self.remove))
|
||||
if not album.name in self._iters:
|
||||
self._iters[album.name] = {}
|
||||
self._iters[album.name][album.artist] = {'album': album,
|
||||
'iter': tree_iter, 'ids': ids}
|
||||
'iter': tree_iter, 'ids': ids}
|
||||
self.emit('album-added', album)
|
||||
return tree_iter
|
||||
|
||||
@@ -859,8 +858,8 @@ class AlbumsModel(GObject.Object):
|
||||
|
||||
:param album: `Album` to be removed from the model.
|
||||
'''
|
||||
print ("album model remove")
|
||||
print (album)
|
||||
print("album model remove")
|
||||
print(album)
|
||||
self._albums.remove(album)
|
||||
self._tree_store.remove(self._iters[album.name][album.artist]['iter'])
|
||||
|
||||
@@ -944,7 +943,7 @@ class AlbumsModel(GObject.Object):
|
||||
self._iters[album.name][album.artist]['iter']))
|
||||
|
||||
def find_first_visible(self, filter_key, filter_arg, start=None,
|
||||
backwards=False):
|
||||
backwards=False):
|
||||
album_filter = AlbumFilters.keys[filter_key](filter_arg)
|
||||
|
||||
albums = reversed(self._albums) if backwards else self._albums
|
||||
@@ -999,12 +998,12 @@ class AlbumsModel(GObject.Object):
|
||||
key = source_settings[gs.PluginKey.SORT_BY]
|
||||
order = source_settings[gs.PluginKey.SORT_ORDER]
|
||||
|
||||
print ("current")
|
||||
print (self._sortkey)
|
||||
print("current")
|
||||
print(self._sortkey)
|
||||
|
||||
print ("registry")
|
||||
print (key)
|
||||
print (order)
|
||||
print("registry")
|
||||
print(key)
|
||||
print(order)
|
||||
|
||||
if key == self._sortkey['type']:
|
||||
key = None
|
||||
@@ -1022,11 +1021,11 @@ class AlbumsModel(GObject.Object):
|
||||
return keys
|
||||
|
||||
if not key and not reverse:
|
||||
print ("nothing to sort")
|
||||
print("nothing to sort")
|
||||
return
|
||||
|
||||
print (key)
|
||||
print (reverse)
|
||||
print(key)
|
||||
print(reverse)
|
||||
if key:
|
||||
props = sort_keys[key]
|
||||
self._albums.key = key_function
|
||||
@@ -1089,15 +1088,15 @@ class AlbumsModel(GObject.Object):
|
||||
def do_filter_changed(self):
|
||||
pos = 0
|
||||
for show_result in list(map(self._album_filter, self._albums)):
|
||||
self.show( self._albums[pos], show_result )
|
||||
self.show(self._albums[pos], show_result)
|
||||
pos = pos + 1
|
||||
|
||||
def _album_filter(self, album):
|
||||
for f in list(self._filters.values()):
|
||||
if not f(album):
|
||||
return False
|
||||
for f in list(self._filters.values()):
|
||||
if not f(album):
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
def recreate_text(self):
|
||||
'''
|
||||
@@ -1105,6 +1104,7 @@ class AlbumsModel(GObject.Object):
|
||||
'''
|
||||
self._recreate_text(iter(self._albums))
|
||||
|
||||
|
||||
class AlbumLoader(GObject.Object):
|
||||
'''
|
||||
Loads and updates Rhythmbox's tracks and albums, updating the model
|
||||
@@ -1116,7 +1116,7 @@ class AlbumLoader(GObject.Object):
|
||||
__gsignals__ = {
|
||||
'albums-load-finished': (GObject.SIGNAL_RUN_LAST, None, (object,)),
|
||||
'model-load-finished': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, album_manager):
|
||||
super(AlbumLoader, self).__init__()
|
||||
@@ -1129,11 +1129,11 @@ class AlbumLoader(GObject.Object):
|
||||
def _connect_signals(self):
|
||||
# connect signals for updating the albums
|
||||
self.entry_changed_id = self._album_manager.db.connect('entry-changed',
|
||||
self._entry_changed_callback)
|
||||
self._entry_changed_callback)
|
||||
self.entry_added_id = self._album_manager.db.connect('entry-added',
|
||||
self._entry_added_callback)
|
||||
self._entry_added_callback)
|
||||
self.entry_deleted_id = self._album_manager.db.connect('entry-deleted',
|
||||
self._entry_deleted_callback)
|
||||
self._entry_deleted_callback)
|
||||
|
||||
@idle_iterator
|
||||
def _load_albums(self):
|
||||
@@ -1155,7 +1155,7 @@ class AlbumLoader(GObject.Object):
|
||||
album = data['albums'][album_name][album_artist]
|
||||
else:
|
||||
album = Album(album_name, album_artist,
|
||||
self._album_manager.cover_man.unknown_cover)
|
||||
self._album_manager.cover_man.unknown_cover)
|
||||
data['albums'][album_name][album_artist] = album
|
||||
|
||||
album.add_track(track)
|
||||
@@ -1209,26 +1209,26 @@ class AlbumLoader(GObject.Object):
|
||||
# this now works correctly
|
||||
|
||||
def analyse_change(change):
|
||||
print (change.prop)
|
||||
print(change.prop)
|
||||
if change.prop is RB.RhythmDBPropType.ALBUM \
|
||||
or change.prop is RB.RhythmDBPropType.ALBUM_ARTIST \
|
||||
or change.prop is RB.RhythmDBPropType.ARTIST \
|
||||
or change.prop is RhythmDBPropType.ALBUM_SORTNAME \
|
||||
or change.prop is RhythmDBPropType.ALBUM_ARTIST_SORTNAME:
|
||||
or change.prop is RB.RhythmDBPropType.ALBUM_ARTIST \
|
||||
or change.prop is RB.RhythmDBPropType.ARTIST \
|
||||
or change.prop is RhythmDBPropType.ALBUM_SORTNAME \
|
||||
or change.prop is RhythmDBPropType.ALBUM_ARTIST_SORTNAME:
|
||||
# called when the album of a entry is modified
|
||||
track.emit('deleted')
|
||||
track.emit('modified')
|
||||
print ("change prop album or artist")
|
||||
print("change prop album or artist")
|
||||
self._allocate_track(track)
|
||||
|
||||
elif change.prop is RB.RhythmDBPropType.HIDDEN:
|
||||
# called when an entry gets hidden (e.g.:the sound file is
|
||||
# removed.
|
||||
if changes.new:
|
||||
print ("change prop new")
|
||||
print("change prop new")
|
||||
track.emit('deleted')
|
||||
else:
|
||||
print ("change prop dunno")
|
||||
print("change prop dunno")
|
||||
self._allocate_track(track)
|
||||
|
||||
# look at all the changes and update the albums accordingly
|
||||
@@ -1236,8 +1236,8 @@ class AlbumLoader(GObject.Object):
|
||||
track = self._tracks[Track(entry).location]
|
||||
|
||||
if rb3compat.is_rb3():
|
||||
#RB3 has a simple rhythmdbentrychange array to deal with so we
|
||||
#just need to loop each element of the array
|
||||
#RB3 has a simple rhythmdbentrychange array to deal with so we
|
||||
#just need to loop each element of the array
|
||||
|
||||
for change in changes:
|
||||
analyse_change(change)
|
||||
@@ -1255,7 +1255,7 @@ class AlbumLoader(GObject.Object):
|
||||
# lets just assume something has just changed
|
||||
|
||||
track = self._tracks[Track(entry).location]
|
||||
print ("except")
|
||||
print("except")
|
||||
track.emit('modified')
|
||||
|
||||
print("CoverArtBrowser DEBUG - end entry_changed_callback")
|
||||
@@ -1289,15 +1289,15 @@ class AlbumLoader(GObject.Object):
|
||||
album_artist = album_artist if album_artist else track.artist
|
||||
|
||||
if self._album_manager.model.contains(album_name, album_artist):
|
||||
print ("allocate track - contains")
|
||||
print("allocate track - contains")
|
||||
album = self._album_manager.model.get(album_name, album_artist)
|
||||
print (album)
|
||||
print(album)
|
||||
album.add_track(track)
|
||||
else:
|
||||
print ("allocate track - does not contain")
|
||||
print("allocate track - does not contain")
|
||||
album = Album(album_name, album_artist,
|
||||
self._album_manager.cover_man.unknown_cover)
|
||||
print (album)
|
||||
self._album_manager.cover_man.unknown_cover)
|
||||
print(album)
|
||||
album.add_track(track)
|
||||
self._album_manager.cover_man.load_cover(album)
|
||||
self._album_manager.model.add(album)
|
||||
@@ -1310,7 +1310,7 @@ class AlbumLoader(GObject.Object):
|
||||
print("CoverArtBrowser DEBUG - load_albums")
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
total=len(query_model), progress=0.)
|
||||
|
||||
print("CoverArtBrowser DEBUG - load_albums finished")
|
||||
|
||||
@@ -1324,7 +1324,6 @@ class AlbumLoader(GObject.Object):
|
||||
|
||||
|
||||
class CoverRequester(GObject.Object):
|
||||
|
||||
def __init__(self, cover_db):
|
||||
super(CoverRequester, self).__init__()
|
||||
|
||||
@@ -1383,7 +1382,7 @@ class CoverRequester(GObject.Object):
|
||||
|
||||
# add a timeout to the request
|
||||
Gdk.threads_add_timeout_seconds(GLib.PRIORITY_DEFAULT_IDLE, 40,
|
||||
self._next, self._queue_id)
|
||||
self._next, self._queue_id)
|
||||
else:
|
||||
# if there're no more elements, clean the state of the requester
|
||||
self._running = False
|
||||
@@ -1433,7 +1432,7 @@ class CoverManager(GObject.Object):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'load-finished': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
# properties
|
||||
has_finished_loading = False
|
||||
@@ -1446,12 +1445,12 @@ class CoverManager(GObject.Object):
|
||||
self._manager = manager
|
||||
self._requester = CoverRequester(self.cover_db)
|
||||
|
||||
self.unknown_cover = None #to be defined by inherited class
|
||||
self.album_manager = None #to be defined by inherited class
|
||||
self.unknown_cover = None #to be defined by inherited class
|
||||
self.album_manager = None #to be defined by inherited class
|
||||
|
||||
# connect the signal to update cover arts when added
|
||||
self.req_id = self.cover_db.connect('added',
|
||||
self.coverart_added_callback)
|
||||
self.coverart_added_callback)
|
||||
self.connect('load-finished', self._on_load_finished)
|
||||
|
||||
def _on_load_finished(self, *args):
|
||||
@@ -1536,10 +1535,10 @@ class CoverManager(GObject.Object):
|
||||
if not check_lastfm(self.force_lastfm_check):
|
||||
# display error message and quit
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("Enable LastFM plugin and log in first"))
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("Enable LastFM plugin and log in first"))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
@@ -1599,7 +1598,7 @@ class CoverManager(GObject.Object):
|
||||
self.update_cover(coverobject, cover)
|
||||
except:
|
||||
print("The URI doesn't point to an image or " + \
|
||||
"the image couldn't be opened.")
|
||||
"the image couldn't be opened.")
|
||||
|
||||
async = rb.Loader()
|
||||
async.get_url(uri, cover_update, coverobject)
|
||||
@@ -1625,28 +1624,28 @@ class AlbumCoverManager(CoverManager):
|
||||
self.connect('notify::cover-size', self._on_cover_size_changed)
|
||||
self.connect('notify::add-shadow', self._on_add_shadow_changed, plugin)
|
||||
self.connect('notify::shadow-image', self._on_add_shadow_changed,
|
||||
plugin)
|
||||
plugin)
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
setting.bind(gs.PluginKey.COVER_SIZE, self, 'cover_size',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
setting.bind(gs.PluginKey.ADD_SHADOW, self, 'add_shadow',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
setting.bind(gs.PluginKey.SHADOW_IMAGE, self, 'shadow_image',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def create_unknown_cover(self, plugin):
|
||||
# create the unknown cover
|
||||
self._shadow = Shadow(self.cover_size,
|
||||
rb.find_plugin_file(plugin, 'img/album-shadow-%s.png' %
|
||||
self.shadow_image))
|
||||
rb.find_plugin_file(plugin, 'img/album-shadow-%s.png' %
|
||||
self.shadow_image))
|
||||
self.unknown_cover = self.create_cover(
|
||||
rb.find_plugin_file(plugin, 'img/rhythmbox-missing-artwork.svg'))
|
||||
|
||||
super(AlbumCoverManager,self).create_unknown_cover(plugin)
|
||||
super(AlbumCoverManager, self).create_unknown_cover(plugin)
|
||||
|
||||
def create_cover(self, image):
|
||||
if self.add_shadow:
|
||||
@@ -1683,18 +1682,18 @@ class AlbumCoverManager(CoverManager):
|
||||
|
||||
def update_pixbuf_cover(self, coverobject, pixbuf):
|
||||
# if it's a pixbuf, assign it to all the artist for the album
|
||||
key = RB.ExtDBKey.create_storage('album', coverobject.name)
|
||||
key.add_field('artist', coverobject.artist)
|
||||
|
||||
self.cover_db.store(key, RB.ExtDBSourceType.USER_EXPLICIT,
|
||||
pixbuf)
|
||||
|
||||
for artist in coverobject.artists.split(', '):
|
||||
key = RB.ExtDBKey.create_storage('album', coverobject.name)
|
||||
key.add_field('artist', coverobject.artist)
|
||||
key.add_field('artist', artist)
|
||||
|
||||
self.cover_db.store(key, RB.ExtDBSourceType.USER_EXPLICIT,
|
||||
pixbuf)
|
||||
|
||||
for artist in coverobject.artists.split(', '):
|
||||
key = RB.ExtDBKey.create_storage('album', coverobject.name)
|
||||
key.add_field('artist', artist)
|
||||
|
||||
self.cover_db.store(key, RB.ExtDBSourceType.USER_EXPLICIT,
|
||||
pixbuf)
|
||||
pixbuf)
|
||||
|
||||
@idle_iterator
|
||||
def _resize_covers(self):
|
||||
@@ -1745,16 +1744,16 @@ class TextManager(GObject.Object):
|
||||
'''
|
||||
# connect signals for the loader properties
|
||||
self.connect('notify::display-text-ellipsize-enabled',
|
||||
self._on_notify_display_text_ellipsize)
|
||||
self._on_notify_display_text_ellipsize)
|
||||
self.connect('notify::display-text-ellipsize-length',
|
||||
self._on_notify_display_text_ellipsize)
|
||||
self._on_notify_display_text_ellipsize)
|
||||
self.connect('notify::display-font-size',
|
||||
self._on_notify_display_text_ellipsize)
|
||||
self._on_notify_display_text_ellipsize)
|
||||
|
||||
self._album_manager.model.connect('generate-tooltip',
|
||||
self._generate_tooltip)
|
||||
self._generate_tooltip)
|
||||
self._album_manager.model.connect('generate-markup',
|
||||
self._generate_markup_text)
|
||||
self._generate_markup_text)
|
||||
|
||||
def _connect_properties(self):
|
||||
'''
|
||||
@@ -1764,12 +1763,12 @@ class TextManager(GObject.Object):
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
setting.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE, self,
|
||||
'display_text_ellipsize_enabled', Gio.SettingsBindFlags.GET)
|
||||
'display_text_ellipsize_enabled', Gio.SettingsBindFlags.GET)
|
||||
setting.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE_LENGTH, self,
|
||||
'display_text_ellipsize_length',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
'display_text_ellipsize_length',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
setting.bind(gs.PluginKey.DISPLAY_FONT_SIZE, self, 'display_font_size',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _on_notify_display_text_ellipsize(self, *args):
|
||||
'''
|
||||
@@ -1784,7 +1783,7 @@ class TextManager(GObject.Object):
|
||||
the model.
|
||||
'''
|
||||
return cgi.escape(rb3compat.unicodeencode(_('%s by %s'), 'utf-8') % (album.name,
|
||||
album.artists))
|
||||
album.artists))
|
||||
|
||||
def _generate_markup_text(self, model, album):
|
||||
'''
|
||||
@@ -1815,6 +1814,7 @@ class TextManager(GObject.Object):
|
||||
markup = "<span font='%d'><b>%s</b>\n<i>%s</i></span>"
|
||||
return markup % (self.display_font_size, name, artist)
|
||||
|
||||
|
||||
class AlbumManager(GObject.Object):
|
||||
'''
|
||||
Main construction that glues together the different managers, the loader
|
||||
@@ -1832,7 +1832,7 @@ class AlbumManager(GObject.Object):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'sort': (GObject.SIGNAL_RUN_LAST, None, (object,))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, plugin, current_view):
|
||||
@@ -1847,6 +1847,7 @@ class AlbumManager(GObject.Object):
|
||||
self.loader = AlbumLoader(self)
|
||||
self.cover_man = AlbumCoverManager(plugin, self)
|
||||
from coverart_artistview import ArtistManager
|
||||
|
||||
self.artist_man = ArtistManager(plugin, self, plugin.shell)
|
||||
self.text_man = TextManager(self)
|
||||
self._show_policy = current_view.show_policy.initialise(self)
|
||||
@@ -1860,11 +1861,10 @@ class AlbumManager(GObject.Object):
|
||||
'''
|
||||
# connect signal to the loader so it shows the albums when it finishes
|
||||
self._load_finished_id = self.loader.connect('model-load-finished',
|
||||
self._load_finished_callback)
|
||||
self._load_finished_callback)
|
||||
self.connect('sort', self._sort_album)
|
||||
|
||||
def _sort_album(self, widget, param):
|
||||
|
||||
toolbar_type = param
|
||||
|
||||
if not toolbar_type or toolbar_type == "album":
|
||||
|
||||
+289
-285
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+103
-96
@@ -47,6 +47,8 @@ import os
|
||||
from collections import namedtuple
|
||||
|
||||
import tempfile, shutil
|
||||
|
||||
|
||||
def create_temporary_copy(path):
|
||||
temp_dir = tempfile.gettempdir()
|
||||
filename = tempfile.mktemp()
|
||||
@@ -54,8 +56,10 @@ def create_temporary_copy(path):
|
||||
shutil.copy2(path, temp_path)
|
||||
return temp_path
|
||||
|
||||
|
||||
ARTIST_LOAD_CHUNK = 50
|
||||
|
||||
|
||||
class Artist(GObject.Object):
|
||||
'''
|
||||
An album. It's conformed from one or more tracks, and many of it's
|
||||
@@ -69,7 +73,7 @@ class Artist(GObject.Object):
|
||||
'modified': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
'emptied': (GObject.SIGNAL_RUN_LAST, None, ()),
|
||||
'cover-updated': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
@@ -96,6 +100,7 @@ class Artist(GObject.Object):
|
||||
# lambda *args: self.emit('cover-updated'))
|
||||
|
||||
self.emit('cover-updated')
|
||||
|
||||
def create_ext_db_key(self):
|
||||
'''
|
||||
Returns an `RB.ExtDBKey`
|
||||
@@ -122,12 +127,12 @@ class ArtistsModel(GObject.Object):
|
||||
__gsignals__ = {
|
||||
'update-path': (GObject.SIGNAL_RUN_LAST, None, (object,)),
|
||||
'visual-updated': ((GObject.SIGNAL_RUN_LAST, None, (object, object)))
|
||||
}
|
||||
}
|
||||
|
||||
# list of columns names and positions on the TreeModel
|
||||
columns = {'tooltip': 0, 'pixbuf': 1,
|
||||
'artist_album': 2, 'show': 3,
|
||||
'empty': 4, 'markup': 5, 'expander': 6}
|
||||
'artist_album': 2, 'show': 3,
|
||||
'empty': 4, 'markup': 5, 'expander': 6}
|
||||
|
||||
def __init__(self, album_manager):
|
||||
super(ArtistsModel, self).__init__()
|
||||
@@ -139,7 +144,7 @@ class ArtistsModel(GObject.Object):
|
||||
key=lambda artist: getattr(artist, 'name'))
|
||||
|
||||
self._tree_store = Gtk.TreeStore(str, GdkPixbuf.Pixbuf, object,
|
||||
bool, str, str, str)
|
||||
bool, str, str, str)
|
||||
|
||||
# sorting idle call
|
||||
self._sort_process = None
|
||||
@@ -170,8 +175,8 @@ class ArtistsModel(GObject.Object):
|
||||
def _compare(self, model, row1, row2, user_data):
|
||||
|
||||
if not model.iter_has_child(row1) or \
|
||||
not model.iter_has_child(row2):
|
||||
return 0
|
||||
not model.iter_has_child(row2):
|
||||
return 0
|
||||
|
||||
sort_column = 0
|
||||
value1 = RB.search_fold(model.get_value(row1, sort_column))
|
||||
@@ -198,17 +203,17 @@ class ArtistsModel(GObject.Object):
|
||||
values = self._generate_artist_values(artist)
|
||||
# insert the values
|
||||
pos = self._artists.insert(artist)
|
||||
tree_iter = self._tree_store.insert(None,pos, values)
|
||||
child_iter = self._tree_store.insert(tree_iter, pos, values) # dummy child row so that the expand is available
|
||||
tree_iter = self._tree_store.insert(None, pos, values)
|
||||
child_iter = self._tree_store.insert(tree_iter, pos, values) # dummy child row so that the expand is available
|
||||
# connect signals
|
||||
ids = (artist.connect('modified', self._artist_modified),
|
||||
artist.connect('cover-updated', self._cover_updated),
|
||||
artist.connect('emptied', self.remove))
|
||||
artist.connect('cover-updated', self._cover_updated),
|
||||
artist.connect('emptied', self.remove))
|
||||
|
||||
if not artist.name in self._iters:
|
||||
self._iters[artist.name] = {}
|
||||
self._iters[artist.name] = {'artist_album': artist,
|
||||
'iter': tree_iter, 'dummy_iter': child_iter, 'ids': ids}
|
||||
'iter': tree_iter, 'dummy_iter': child_iter, 'ids': ids}
|
||||
return tree_iter
|
||||
|
||||
def _emit_signal(self, tree_iter, signal):
|
||||
@@ -225,7 +230,7 @@ class ArtistsModel(GObject.Object):
|
||||
self.emit(signal, tree_path, tree_iter)
|
||||
|
||||
def remove(self, *args):
|
||||
print ("artist remove")
|
||||
print("artist remove")
|
||||
|
||||
def _cover_updated(self, artist):
|
||||
tree_iter = self._iters[artist.name]['iter']
|
||||
@@ -235,12 +240,12 @@ class ArtistsModel(GObject.Object):
|
||||
pixbuf = artist.cover.pixbuf
|
||||
|
||||
self._tree_store.set_value(tree_iter, self.columns['pixbuf'],
|
||||
pixbuf)
|
||||
pixbuf)
|
||||
|
||||
self._emit_signal(tree_iter, 'visual-updated')
|
||||
|
||||
def _artist_modified(self, *args):
|
||||
print ("artist modified")
|
||||
print("artist modified")
|
||||
|
||||
def _on_update_path(self, widget, treepath):
|
||||
'''
|
||||
@@ -281,8 +286,8 @@ class ArtistsModel(GObject.Object):
|
||||
|
||||
# connect signals
|
||||
ids = (album.connect('modified', self._album_modified),
|
||||
album.connect('cover-updated', self._album_coverupdate),
|
||||
album.connect('emptied', self._album_emptied))
|
||||
album.connect('cover-updated', self._album_coverupdate),
|
||||
album.connect('emptied', self._album_emptied))
|
||||
|
||||
self._albumiters[album]['ids'] = ids
|
||||
|
||||
@@ -290,13 +295,13 @@ class ArtistsModel(GObject.Object):
|
||||
self._tree_store.remove(self._iters[artist.name]['dummy_iter'])
|
||||
del self._iters[artist.name]['dummy_iter']
|
||||
|
||||
self.sort() # ensure the added albums are sorted correctly
|
||||
self.sort() # ensure the added albums are sorted correctly
|
||||
|
||||
def _album_modified(self, album):
|
||||
print ("album modified")
|
||||
print (album)
|
||||
print("album modified")
|
||||
print(album)
|
||||
if not (album in self._albumiters):
|
||||
print ("not found in albumiters")
|
||||
print("not found in albumiters")
|
||||
return
|
||||
|
||||
tree_iter = self._albumiters[album]['iter']
|
||||
@@ -308,9 +313,9 @@ class ArtistsModel(GObject.Object):
|
||||
self._generate_album_values(album)
|
||||
|
||||
self._tree_store.set(tree_iter, self.columns['tooltip'], tooltip,
|
||||
self.columns['markup'], markup, self.columns['show'], show)
|
||||
self.columns['markup'], markup, self.columns['show'], show)
|
||||
|
||||
self.sort() # ensure the added albums are sorted correctly
|
||||
self.sort() # ensure the added albums are sorted correctly
|
||||
|
||||
def _album_emptied(self, album):
|
||||
'''
|
||||
@@ -318,11 +323,11 @@ class ArtistsModel(GObject.Object):
|
||||
|
||||
:param album: `Album` to be removed from the model.
|
||||
'''
|
||||
print ('album emptied')
|
||||
print (album)
|
||||
print (album.artist)
|
||||
print('album emptied')
|
||||
print(album)
|
||||
print(album.artist)
|
||||
if not (album in self._albumiters):
|
||||
print ("not found in albumiters")
|
||||
print("not found in albumiters")
|
||||
return
|
||||
|
||||
artist = self.get(album.artist)
|
||||
@@ -345,7 +350,7 @@ class ArtistsModel(GObject.Object):
|
||||
def _album_coverupdate(self, album):
|
||||
tooltip, pixbuf, album, show, blank, markup, empty = self._generate_album_values(album)
|
||||
self._tree_store.set_value(self._albumiters[album]['iter'],
|
||||
self.columns['pixbuf'], pixbuf)
|
||||
self.columns['pixbuf'], pixbuf)
|
||||
|
||||
def _generate_artist_values(self, artist):
|
||||
tooltip = artist.name
|
||||
@@ -353,11 +358,11 @@ class ArtistsModel(GObject.Object):
|
||||
show = True
|
||||
|
||||
return tooltip, pixbuf, artist, show, '', \
|
||||
GLib.markup_escape_text(tooltip), ''
|
||||
GLib.markup_escape_text(tooltip), ''
|
||||
|
||||
def _generate_album_values(self, album):
|
||||
tooltip = album.name
|
||||
pixbuf = album.cover.pixbuf.scale_simple(48,48,GdkPixbuf.InterpType.BILINEAR)
|
||||
pixbuf = album.cover.pixbuf.scale_simple(48, 48, GdkPixbuf.InterpType.BILINEAR)
|
||||
show = True
|
||||
|
||||
rating = album.rating
|
||||
@@ -366,14 +371,14 @@ class ArtistsModel(GObject.Object):
|
||||
else:
|
||||
rating = ''
|
||||
|
||||
year = ' (' + str(album.real_year) +')'
|
||||
year = ' (' + str(album.real_year) + ')'
|
||||
|
||||
track_count = album.track_count
|
||||
if track_count == 1:
|
||||
detail = rb3compat.unicodedecode(_(' with 1 track'), 'UTF-8')
|
||||
else:
|
||||
detail = rb3compat.unicodedecode(_(' with %d tracks') %
|
||||
track_count, 'UTF-8')
|
||||
track_count, 'UTF-8')
|
||||
|
||||
duration = album.duration / 60
|
||||
|
||||
@@ -381,20 +386,20 @@ class ArtistsModel(GObject.Object):
|
||||
detail += rb3compat.unicodedecode(_(' and a duration of 1 minute'), 'UTF-8')
|
||||
else:
|
||||
detail += rb3compat.unicodedecode(_(' and a duration of %d minutes') %
|
||||
duration, 'UTF-8')
|
||||
duration, 'UTF-8')
|
||||
|
||||
tooltip = rb3compat.unicodestr(tooltip, 'utf-8')
|
||||
tooltip = rb3compat.unicodeencode(tooltip, 'utf-8')
|
||||
import cgi
|
||||
|
||||
formatted = '<b><i>' + \
|
||||
cgi.escape(rb3compat.unicodedecode(tooltip, 'utf-8')) + \
|
||||
'</i></b>' + \
|
||||
year + \
|
||||
' ' + rating + \
|
||||
'\n<small>' + \
|
||||
GLib.markup_escape_text(detail) + \
|
||||
'</small>'
|
||||
cgi.escape(rb3compat.unicodedecode(tooltip, 'utf-8')) + \
|
||||
'</i></b>' + \
|
||||
year + \
|
||||
' ' + rating + \
|
||||
'\n<small>' + \
|
||||
GLib.markup_escape_text(detail) + \
|
||||
'</small>'
|
||||
|
||||
return tooltip, pixbuf, album, show, '', formatted, ''
|
||||
|
||||
@@ -465,10 +470,10 @@ class ArtistsModel(GObject.Object):
|
||||
return self.store[path][self.columns['artist_album']]
|
||||
|
||||
def get_path(self, artist):
|
||||
print (artist.name)
|
||||
print (self._iters[artist.name]['iter'])
|
||||
print(artist.name)
|
||||
print(self._iters[artist.name]['iter'])
|
||||
return self._tree_store.get_path(
|
||||
self._iters[artist.name]['iter'])
|
||||
self._iters[artist.name]['iter'])
|
||||
|
||||
def get_from_ext_db_key(self, key):
|
||||
'''
|
||||
@@ -511,7 +516,7 @@ class ArtistsModel(GObject.Object):
|
||||
'name_artist': ('album_sort', 'album_sort'),
|
||||
'year_artist': ('real_year', 'calc_year_sort'),
|
||||
'rating_artist': ('rating', 'album_sort')
|
||||
}
|
||||
}
|
||||
|
||||
props = sort_keys[key]
|
||||
|
||||
@@ -554,22 +559,22 @@ class ArtistsModel(GObject.Object):
|
||||
# now we have finished sorting, reapply the sort
|
||||
self.store.set_sort_column_id(*sortSettings)
|
||||
|
||||
class ArtistCellRenderer(Gtk.CellRendererPixbuf):
|
||||
|
||||
class ArtistCellRenderer(Gtk.CellRendererPixbuf):
|
||||
def __init__(self):
|
||||
super(ArtistCellRenderer, self).__init__()
|
||||
|
||||
def do_render(self, cr, widget,
|
||||
background_area,
|
||||
cell_area,
|
||||
flags):
|
||||
|
||||
newpix = self.props.pixbuf #.copy()
|
||||
background_area,
|
||||
cell_area,
|
||||
flags):
|
||||
newpix = self.props.pixbuf #.copy()
|
||||
#newpix = newpix.scale_simple(48,48,GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
Gdk.cairo_set_source_pixbuf(cr, newpix, 0, 0)
|
||||
cr.paint()
|
||||
|
||||
|
||||
class ArtistLoader(GObject.Object):
|
||||
'''
|
||||
Loads Artists - updating the model accordingly.
|
||||
@@ -580,7 +585,7 @@ class ArtistLoader(GObject.Object):
|
||||
__gsignals__ = {
|
||||
'artists-load-finished': (GObject.SIGNAL_RUN_LAST, None, (object,)),
|
||||
'model-load-finished': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, artist_manager, album_manager):
|
||||
super(ArtistLoader, self).__init__()
|
||||
@@ -597,7 +602,7 @@ class ArtistLoader(GObject.Object):
|
||||
model = list(set(album.artist for album in albums))
|
||||
|
||||
self._load_artists(iter(model), artists={}, model=model,
|
||||
total=len(model), progress=0.)
|
||||
total=len(model), progress=0.)
|
||||
|
||||
@idle_iterator
|
||||
def _load_artists(self):
|
||||
@@ -659,18 +664,18 @@ class ArtistLoader(GObject.Object):
|
||||
'''
|
||||
called when album-manager album-added signal is invoked
|
||||
'''
|
||||
print (album.artist)
|
||||
print(album.artist)
|
||||
if self._artist_manager.model.contains(album.artist):
|
||||
print ("contains artist")
|
||||
print("contains artist")
|
||||
artist = self._artist_manager.model.get(album.artist)
|
||||
self._artist_manager.model.add_album_to_artist(artist, [album])
|
||||
else:
|
||||
print ("new artist")
|
||||
print("new artist")
|
||||
artist = Artist(album.artist, self._artist_manager.cover_man.unknown_cover)
|
||||
self._artist_manager.model.add(artist)
|
||||
|
||||
class ArtistCoverManager(CoverManager):
|
||||
|
||||
class ArtistCoverManager(CoverManager):
|
||||
force_lastfm_check = True
|
||||
|
||||
def __init__(self, plugin, artist_manager):
|
||||
@@ -688,14 +693,15 @@ class ArtistCoverManager(CoverManager):
|
||||
self.unknown_cover = self.create_cover(
|
||||
rb.find_plugin_file(plugin, 'img/microphone.png'))
|
||||
|
||||
super(ArtistCoverManager,self).create_unknown_cover(plugin)
|
||||
super(ArtistCoverManager, self).create_unknown_cover(plugin)
|
||||
|
||||
def update_pixbuf_cover(self, coverobject, pixbuf):
|
||||
# if it's a pixbuf, assign it to all the artist for the artist
|
||||
key = RB.ExtDBKey.create_storage('artist', coverobject.name)
|
||||
|
||||
self.cover_db.store(key, RB.ExtDBSourceType.USER_EXPLICIT,
|
||||
pixbuf)
|
||||
pixbuf)
|
||||
|
||||
|
||||
class ArtistManager(GObject.Object):
|
||||
'''
|
||||
@@ -714,7 +720,7 @@ class ArtistManager(GObject.Object):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'sort': (GObject.SIGNAL_RUN_LAST, None, (object,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, plugin, album_manager, shell):
|
||||
super(ArtistManager, self).__init__()
|
||||
@@ -740,7 +746,6 @@ class ArtistManager(GObject.Object):
|
||||
self.connect('sort', self._sort_artist)
|
||||
|
||||
def _sort_artist(self, widget, param):
|
||||
|
||||
toolbar_type = param
|
||||
|
||||
if not toolbar_type or toolbar_type == "artist":
|
||||
@@ -749,6 +754,7 @@ class ArtistManager(GObject.Object):
|
||||
def _load_finished_callback(self, *args):
|
||||
self.cover_man.load_covers()
|
||||
|
||||
|
||||
class ArtistShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
@@ -770,6 +776,7 @@ class ArtistShowingPolicy(GObject.Object):
|
||||
self._album_manager = album_manager
|
||||
self._model = album_manager.model
|
||||
|
||||
|
||||
class ArtistView(Gtk.TreeView, AbstractView):
|
||||
__gtype_name__ = "ArtistView"
|
||||
|
||||
@@ -779,7 +786,7 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
|
||||
__gsignals__ = {
|
||||
'update-toolbar': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -822,7 +829,7 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
col.connect('clicked', self._artist_sort_clicked)
|
||||
self.append_column(col)
|
||||
col = Gtk.TreeViewColumn('', Gtk.CellRendererText(), text=4)
|
||||
self.append_column(col) # dummy column to expand horizontally
|
||||
self.append_column(col) # dummy column to expand horizontally
|
||||
|
||||
self.artist_manager = self.album_manager.artist_man
|
||||
self.artist_manager.model.store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
|
||||
@@ -835,13 +842,13 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
self.drag_dest_add_text_targets()
|
||||
self.connect('drag-drop', self.on_drag_drop)
|
||||
self.connect('drag-data-received',
|
||||
self.on_drag_data_received)
|
||||
self.on_drag_data_received)
|
||||
|
||||
# lastly support drag-drop from coverart to devices/nautilus etc
|
||||
# n.b. enabling of drag-source is controlled by the selection-changed to ensure
|
||||
# we dont allow drag from artists
|
||||
self.connect('drag-begin', self.on_drag_begin)
|
||||
self._targets = Gtk.TargetList.new([Gtk.TargetEntry.new("text/uri-list", 0, 0) ])
|
||||
self._targets = Gtk.TargetList.new([Gtk.TargetEntry.new("text/uri-list", 0, 0)])
|
||||
|
||||
# N.B. values taken from rhythmbox v2.97 widgets/rb_entry_view.c
|
||||
self._targets.add_uri_targets(1)
|
||||
@@ -850,13 +857,13 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
# define artist specific popup menu
|
||||
self.artist_popup_menu = Menu(self.plugin, self.shell)
|
||||
self.artist_popup_menu.load_from_file('ui/coverart_artist_pop_rb2.ui',
|
||||
'ui/coverart_artist_pop_rb3.ui')
|
||||
'ui/coverart_artist_pop_rb3.ui')
|
||||
signals = \
|
||||
{ 'play_album_menu_item' : self.source.play_album_menu_item_callback,
|
||||
'queue_album_menu_item' : self.source.queue_album_menu_item_callback,
|
||||
'add_to_playing_menu_item' : self.source.add_playlist_menu_item_callback,
|
||||
'new_playlist' : self.source.add_playlist_menu_item_callback,
|
||||
'artist_cover_search_menu_item' : self.cover_search_menu_item_callback
|
||||
{'play_album_menu_item': self.source.play_album_menu_item_callback,
|
||||
'queue_album_menu_item': self.source.queue_album_menu_item_callback,
|
||||
'add_to_playing_menu_item': self.source.add_playlist_menu_item_callback,
|
||||
'new_playlist': self.source.add_playlist_menu_item_callback,
|
||||
'artist_cover_search_menu_item': self.cover_search_menu_item_callback
|
||||
}
|
||||
|
||||
self.artist_popup_menu.connect_signals(signals)
|
||||
@@ -869,7 +876,7 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
def _connect_properties(self):
|
||||
setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
setting.bind(self.gs.PluginKey.ICON_AUTOMATIC, self,
|
||||
'icon_automatic', Gio.SettingsBindFlags.GET)
|
||||
'icon_automatic', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect('row-activated', self._row_activated)
|
||||
@@ -889,9 +896,9 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
|
||||
def cover_search_menu_item_callback(self, *args):
|
||||
self.artist_manager.cover_man.search_covers(self.get_selected_objects(just_artist=True),
|
||||
callback=self.source.update_request_status_bar)
|
||||
callback=self.source.update_request_status_bar)
|
||||
|
||||
def _query_tooltip( self, widget, x, y, key, tooltip ):
|
||||
def _query_tooltip(self, widget, x, y, key, tooltip):
|
||||
|
||||
try:
|
||||
winx, winy = self.convert_widget_to_bin_window_coords(x, y)
|
||||
@@ -901,8 +908,8 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
#active_object=self.artist_manager.model.store[treepath][self.artist_manager.model.columns['artist_album']]
|
||||
|
||||
if isinstance(active_object, Artist) and \
|
||||
treecolumn.get_title() == _('Covers') and \
|
||||
active_object.cover.original != self.artist_manager.cover_man.unknown_cover.original:
|
||||
treecolumn.get_title() == _('Covers') and \
|
||||
active_object.cover.original != self.artist_manager.cover_man.unknown_cover.original:
|
||||
# we display the tooltip if the row is an artist and the column
|
||||
# is actually the artist cover itself
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(active_object.cover.original)
|
||||
@@ -910,20 +917,20 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
src_width = pixbuf.get_width()
|
||||
src_height = pixbuf.get_height()
|
||||
|
||||
factor = min(float(256) / float(src_width), float(256) / float(src_height))
|
||||
new_width = int(src_width * factor + 0.5)
|
||||
factor = min(float(256) / float(src_width), float(256) / float(src_height))
|
||||
new_width = int(src_width * factor + 0.5)
|
||||
new_height = int(src_height * factor + 0.5)
|
||||
|
||||
pixbuf = create_pixbuf_from_file_at_size(
|
||||
active_object.cover.original, new_width, new_height)
|
||||
|
||||
tooltip.set_icon( pixbuf )
|
||||
tooltip.set_icon(pixbuf)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
except:
|
||||
pass
|
||||
pass
|
||||
|
||||
def _row_expanded(self, treeview, treeiter, treepath):
|
||||
'''
|
||||
@@ -947,7 +954,7 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
callback when artist popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
state,sensitive = self.shell.props.shell_player.get_playing()
|
||||
state, sensitive = self.shell.props.shell_player.get_playing()
|
||||
if not state:
|
||||
sensitive = False
|
||||
|
||||
@@ -982,12 +989,12 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
|
||||
self._last_row_was_artist = True
|
||||
|
||||
if event.button ==3:
|
||||
if event.button == 3:
|
||||
# on right click
|
||||
# display popup
|
||||
|
||||
self.artist_popup_menu.popup(self.source, 'popup_menu', 3,
|
||||
Gtk.get_current_event_time())
|
||||
Gtk.get_current_event_time())
|
||||
return
|
||||
|
||||
if event.button == 1:
|
||||
@@ -1001,14 +1008,14 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
|
||||
if self.source.click_count == 1:
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, active_object)
|
||||
self.source.show_hide_pane, active_object)
|
||||
|
||||
elif event.button ==3:
|
||||
elif event.button == 3:
|
||||
# on right click
|
||||
# display popup
|
||||
|
||||
self.popup.popup(self.source, 'popup_menu', 3,
|
||||
Gtk.get_current_event_time())
|
||||
Gtk.get_current_event_time())
|
||||
|
||||
self._last_row_was_artist = False
|
||||
|
||||
@@ -1018,19 +1025,19 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
def _selection_changed(self, *args):
|
||||
selected = self.get_selected_objects(just_artist=True)
|
||||
|
||||
print (selected)
|
||||
print(selected)
|
||||
if len(selected) == 0:
|
||||
self.source.entry_view.clear()
|
||||
return
|
||||
|
||||
if isinstance(selected[0], Artist):
|
||||
print ("selected artist")
|
||||
self.unset_rows_drag_source() # turn off drag-drop for artists
|
||||
print("selected artist")
|
||||
self.unset_rows_drag_source() # turn off drag-drop for artists
|
||||
|
||||
self.source.entryviewpane.update_cover(selected[0],
|
||||
self.artist_manager)
|
||||
else:
|
||||
print ("selected album")
|
||||
print("selected album")
|
||||
self.source.update_with_selection()
|
||||
# now turnon drag-drop for album.
|
||||
self.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
|
||||
@@ -1060,7 +1067,7 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
selection = self.get_selection()
|
||||
model, treeiter = selection.get_selected()
|
||||
if treeiter:
|
||||
active_object = model.get_value(treeiter,ArtistsModel.columns['artist_album'])
|
||||
active_object = model.get_value(treeiter, ArtistsModel.columns['artist_album'])
|
||||
if isinstance(active_object, Album):
|
||||
# have chosen an album then just return that album
|
||||
return [active_object]
|
||||
@@ -1081,14 +1088,14 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
|
||||
def scroll_to_album(self, album):
|
||||
if album:
|
||||
print ("switch to artist view")
|
||||
print (album)
|
||||
print("switch to artist view")
|
||||
print(album)
|
||||
artist = self.artist_manager.model.get(album.artist)
|
||||
path = self.artist_manager.model.get_path(artist)
|
||||
print (artist)
|
||||
print (path)
|
||||
print(artist)
|
||||
print(path)
|
||||
path = self.artist_manager.model.store.convert_child_path_to_path(path)
|
||||
print (path)
|
||||
print(path)
|
||||
if path:
|
||||
self.scroll_to_cell(path, self._artist_col)
|
||||
self.expand_row(path, False)
|
||||
@@ -1128,7 +1135,7 @@ class ArtistView(Gtk.TreeView, AbstractView):
|
||||
return result
|
||||
|
||||
def on_drag_data_received(self, widget, drag_context, x, y, data, info,
|
||||
time):
|
||||
time):
|
||||
'''
|
||||
Callback called when the drag source has prepared the data (pixbuf)
|
||||
for us to use.
|
||||
|
||||
+31
-28
@@ -41,10 +41,12 @@ from coverart_toolbar import TopToolbar
|
||||
|
||||
import coverart_rb3compat as rb3compat
|
||||
|
||||
|
||||
class CoverArtBrowserEntryType(RB.RhythmDBEntryType):
|
||||
'''
|
||||
Entry type for our source.
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
'''
|
||||
Initializes the entry type.
|
||||
@@ -97,33 +99,33 @@ class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
rb.append_plugin_source_path(theme, '/icons')
|
||||
|
||||
# lets assume that python3 versions of RB only has the new icon attribute in the source
|
||||
if rb3compat.PYVER >=3:
|
||||
iconfile = Gio.File.new_for_path(
|
||||
rb.find_plugin_file(self, 'img/covermgr_rb3.png'))
|
||||
if rb3compat.PYVER >= 3:
|
||||
iconfile = Gio.File.new_for_path(
|
||||
rb.find_plugin_file(self, 'img/covermgr_rb3.png'))
|
||||
|
||||
self.source = CoverArtBrowserSource(
|
||||
shell=self.shell,
|
||||
name=_("CoverArt"),
|
||||
entry_type=entry_type,
|
||||
plugin=self,
|
||||
icon=Gio.FileIcon.new(iconfile),
|
||||
query_model=self.shell.props.library_source.props.base_query_model)
|
||||
self.source = CoverArtBrowserSource(
|
||||
shell=self.shell,
|
||||
name=_("CoverArt"),
|
||||
entry_type=entry_type,
|
||||
plugin=self,
|
||||
icon=Gio.FileIcon.new(iconfile),
|
||||
query_model=self.shell.props.library_source.props.base_query_model)
|
||||
else:
|
||||
what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR)
|
||||
pxbf = GdkPixbuf.Pixbuf.new_from_file_at_size(
|
||||
rb.find_plugin_file(self, 'img/covermgr.png'), width, height)
|
||||
what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR)
|
||||
pxbf = GdkPixbuf.Pixbuf.new_from_file_at_size(
|
||||
rb.find_plugin_file(self, 'img/covermgr.png'), width, height)
|
||||
|
||||
self.source = CoverArtBrowserSource(
|
||||
shell=self.shell,
|
||||
name=_("CoverArt"), entry_type=entry_type,
|
||||
plugin=self, pixbuf=pxbf,
|
||||
query_model=self.shell.props.library_source.props.base_query_model)
|
||||
self.source = CoverArtBrowserSource(
|
||||
shell=self.shell,
|
||||
name=_("CoverArt"), entry_type=entry_type,
|
||||
plugin=self, pixbuf=pxbf,
|
||||
query_model=self.shell.props.library_source.props.base_query_model)
|
||||
|
||||
self.shell.register_entry_type_for_source(self.source, entry_type)
|
||||
self.shell.append_display_page(self.source, group)
|
||||
|
||||
self.source.props.query_model.connect('complete', self.load_complete)
|
||||
if rb3compat.PYVER >=3:
|
||||
if rb3compat.PYVER >= 3:
|
||||
self._externalmenu = ExternalPluginMenu(self)
|
||||
else:
|
||||
self._externalmenu = None
|
||||
@@ -157,7 +159,7 @@ class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
|
||||
if setting[gs.PluginKey.AUTOSTART]:
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.source)
|
||||
self.source)
|
||||
|
||||
def _translation_helper(self):
|
||||
'''
|
||||
@@ -178,8 +180,8 @@ class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
#. TRANSLATORS: percentage size that the image will be expanded
|
||||
scale = _('Scale by %:')
|
||||
|
||||
class ExternalPluginMenu(GObject.Object):
|
||||
|
||||
class ExternalPluginMenu(GObject.Object):
|
||||
toolbar_pos = GObject.property(type=str, default=TopToolbar.name)
|
||||
|
||||
def __init__(self, plugin):
|
||||
@@ -190,6 +192,7 @@ class ExternalPluginMenu(GObject.Object):
|
||||
self.source = plugin.source
|
||||
self.app_id = None
|
||||
from coverart_browser_source import Views
|
||||
|
||||
self._views = Views(self.shell)
|
||||
|
||||
self._connect_properties()
|
||||
@@ -201,13 +204,13 @@ class ExternalPluginMenu(GObject.Object):
|
||||
self.connect('notify::toolbar-pos', self._on_notify_toolbar_pos)
|
||||
self.shell.props.display_page_tree.connect(
|
||||
"selected", self.on_page_change
|
||||
)
|
||||
)
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _on_notify_toolbar_pos(self, *args):
|
||||
if self.toolbar_pos == TopToolbar.name:
|
||||
@@ -231,7 +234,7 @@ class ExternalPluginMenu(GObject.Object):
|
||||
self.action = Gio.SimpleAction.new_stateful(
|
||||
action_name, GLib.VariantType.new('s'),
|
||||
self._views.get_action_name(ListView.name)
|
||||
)
|
||||
)
|
||||
self.action.connect("activate", self.view_change_cb)
|
||||
app.add_action(self.action)
|
||||
|
||||
@@ -244,7 +247,7 @@ class ExternalPluginMenu(GObject.Object):
|
||||
menu_item.set_label(self._views.get_menu_name(view_name))
|
||||
menu_item.set_action_and_target_value(
|
||||
'app.' + action_name, self._views.get_action_name(view_name)
|
||||
)
|
||||
)
|
||||
section.append_item(menu_item)
|
||||
|
||||
menu.append_section(None, section)
|
||||
@@ -282,11 +285,11 @@ class ExternalPluginMenu(GObject.Object):
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting[gs.PluginKey.VIEW_NAME] = view_name
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.source)
|
||||
self.source)
|
||||
elif view_name == ListView.name:
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.library_source)
|
||||
self.shell.props.library_source)
|
||||
elif view_name == QueueView.name:
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.queue_source)
|
||||
self.shell.props.queue_source)
|
||||
|
||||
|
||||
+47
-46
@@ -33,6 +33,7 @@ from stars import ReactiveStar
|
||||
from stars import StarSize
|
||||
import coverart_rb3compat as rb3compat
|
||||
|
||||
|
||||
def webkit_support():
|
||||
'''
|
||||
function that returns True/False if webkit technology is supported
|
||||
@@ -41,6 +42,7 @@ def webkit_support():
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
return settings[gs.PluginKey.WEBKIT]
|
||||
|
||||
|
||||
class CoverLocale:
|
||||
'''
|
||||
This class manages the locale
|
||||
@@ -286,7 +288,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
builder = Gtk.Builder()
|
||||
builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
builder.add_from_file(rb.find_plugin_file(plugin,
|
||||
'ui/coverart_browser_prefs.ui'))
|
||||
'ui/coverart_browser_prefs.ui'))
|
||||
self.launchpad_button = builder.get_object('show_launchpad')
|
||||
self.launchpad_label = builder.get_object('launchpad_label')
|
||||
|
||||
@@ -304,19 +306,19 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
# bind the toggles to the settings
|
||||
toggle_statusbar = builder.get_object('custom_statusbar_checkbox')
|
||||
self.settings.bind(gs.PluginKey.CUSTOM_STATUSBAR,
|
||||
toggle_statusbar, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
toggle_statusbar, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toggle_bottom = builder.get_object('display_bottom_checkbox')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_BOTTOM, toggle_bottom,
|
||||
'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toggle_text = builder.get_object('display_text_checkbox')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT, toggle_text, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
box_text = builder.get_object('display_text_box')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT, box_text, 'sensitive',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
self.display_text_pos = self.settings[gs.PluginKey.DISPLAY_TEXT_POS]
|
||||
self.display_text_under_radiobutton = builder.get_object('display_text_under_radiobutton')
|
||||
@@ -327,40 +329,39 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
else:
|
||||
self.display_text_within_radiobutton.set_active(True)
|
||||
|
||||
|
||||
random_scale = builder.get_object('random_adjustment')
|
||||
self.settings.bind(gs.PluginKey.RANDOM, random_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toggle_text_ellipsize = builder.get_object(
|
||||
'display_text_ellipsize_checkbox')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE,
|
||||
toggle_text_ellipsize, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
toggle_text_ellipsize, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
box_text_ellipsize_length = builder.get_object(
|
||||
'display_text_ellipsize_length_box')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE,
|
||||
box_text_ellipsize_length, 'sensitive', Gio.SettingsBindFlags.GET)
|
||||
box_text_ellipsize_length, 'sensitive', Gio.SettingsBindFlags.GET)
|
||||
|
||||
spinner_text_ellipsize_length = builder.get_object(
|
||||
'display_text_ellipsize_length_spin')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE_LENGTH,
|
||||
spinner_text_ellipsize_length, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
spinner_text_ellipsize_length, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
spinner_font_size = builder.get_object(
|
||||
'display_font_spin')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_FONT_SIZE,
|
||||
spinner_font_size, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
spinner_font_size, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
cover_size_scale = builder.get_object('cover_size_adjustment')
|
||||
self.settings.bind(gs.PluginKey.COVER_SIZE, cover_size_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
add_shadow = builder.get_object('add_shadow_checkbox')
|
||||
self.settings.bind(gs.PluginKey.ADD_SHADOW, add_shadow, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
rated_box = builder.get_object('rated_box')
|
||||
self.stars = ReactiveStar(size=StarSize.BIG)
|
||||
@@ -375,21 +376,21 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
autostart = builder.get_object('autostart_checkbox')
|
||||
self.settings.bind(gs.PluginKey.AUTOSTART,
|
||||
autostart, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
autostart, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toolbar_pos_combo = builder.get_object('show_in_combobox')
|
||||
renderer = Gtk.CellRendererText()
|
||||
toolbar_pos_combo.pack_start(renderer, True)
|
||||
toolbar_pos_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.TOOLBAR_POS, toolbar_pos_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
light_source_combo = builder.get_object('light_source_combobox')
|
||||
renderer = Gtk.CellRendererText()
|
||||
light_source_combo.pack_start(renderer, True)
|
||||
light_source_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.SHADOW_IMAGE, light_source_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
combo_liststore = builder.get_object('combo_liststore')
|
||||
|
||||
@@ -403,11 +404,11 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
theme_combo.pack_start(renderer, True)
|
||||
theme_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.THEME, theme_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
button_relief = builder.get_object('button_relief_checkbox')
|
||||
self.settings.bind(gs.PluginKey.BUTTON_RELIEF, button_relief, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
# create user data files
|
||||
cachedir = RB.user_cache_dir() + "/coverart_browser/usericons"
|
||||
@@ -441,13 +442,13 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self._iters = {}
|
||||
for key in list(self._sheet.keys()):
|
||||
store_iter = self.alt_liststore.append([key, self._sheet[key]])
|
||||
self._iters[(key,self.GENRE_POPUP)] = store_iter
|
||||
self._iters[(key, self.GENRE_POPUP)] = store_iter
|
||||
|
||||
for key, value in self._sheet.genre_alternate.items():
|
||||
if key.genre_type == GenreConfiguredSpriteSheet.GENRE_USER:
|
||||
store_iter = self.alt_user_liststore.append([key.name,
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._iters[(key.name, self.GENRE_LIST)] = store_iter
|
||||
|
||||
self.amend_mode = False
|
||||
@@ -463,15 +464,15 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
padding_scale = builder.get_object('padding_adjustment')
|
||||
self.settings.bind(gs.PluginKey.ICON_PADDING, padding_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
spacing_scale = builder.get_object('spacing_adjustment')
|
||||
self.settings.bind(gs.PluginKey.ICON_SPACING, spacing_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
icon_automatic = builder.get_object('icon_automatic_checkbox')
|
||||
self.settings.bind(gs.PluginKey.ICON_AUTOMATIC,
|
||||
icon_automatic, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
icon_automatic, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
#flow tab
|
||||
flow_combo = builder.get_object('flow_combobox')
|
||||
@@ -479,27 +480,27 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
flow_combo.pack_start(renderer, True)
|
||||
flow_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.FLOW_APPEARANCE, flow_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_hide = builder.get_object('hide_caption_checkbox')
|
||||
self.settings.bind(gs.PluginKey.FLOW_HIDE_CAPTION,
|
||||
flow_hide, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
flow_hide, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_scale = builder.get_object('cover_scale_adjustment')
|
||||
self.settings.bind(gs.PluginKey.FLOW_SCALE, flow_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_width = builder.get_object('cover_width_adjustment')
|
||||
self.settings.bind(gs.PluginKey.FLOW_WIDTH, flow_width, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_max = builder.get_object('flow_max_adjustment')
|
||||
self.settings.bind(gs.PluginKey.FLOW_MAX, flow_max, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_automatic = builder.get_object('automatic_checkbox')
|
||||
self.settings.bind(gs.PluginKey.FLOW_AUTOMATIC,
|
||||
flow_automatic, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
flow_automatic, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
self.background_colour = self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR]
|
||||
self.white_radiobutton = builder.get_object('white_radiobutton')
|
||||
@@ -515,7 +516,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
def on_flow_combobox_changed(self, combobox):
|
||||
current_val = combobox.get_model()[combobox.get_active()][0]
|
||||
gs=GSetting()
|
||||
gs = GSetting()
|
||||
if self.settings[gs.PluginKey.FLOW_APPEARANCE] != current_val:
|
||||
if current_val == 'flow-vert':
|
||||
default_size = 150
|
||||
@@ -566,12 +567,12 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
if self.amend_mode:
|
||||
key = self._sheet.amend_genre_info(self.current_genre,
|
||||
entry_value, icon_value)
|
||||
entry_value, icon_value)
|
||||
|
||||
self.alt_user_liststore[self._iters[(self.current_genre,
|
||||
self.GENRE_LIST)]][1]=self._sheet[self._sheet.genre_alternate[key]]
|
||||
self.GENRE_LIST)]][1] = self._sheet[self._sheet.genre_alternate[key]]
|
||||
self.alt_user_liststore[self._iters[(self.current_genre,
|
||||
self.GENRE_LIST)]][0]=key.name
|
||||
self.GENRE_LIST)]][0] = key.name
|
||||
store_iter = self._iters[(self.current_genre, self.GENRE_LIST)]
|
||||
del self._iters[(self.current_genre, self.GENRE_LIST)]
|
||||
self._iters[(key.name, self.GENRE_LIST)] = store_iter
|
||||
@@ -579,12 +580,12 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
else:
|
||||
self.amend_mode = True
|
||||
key = self._sheet.amend_genre_info('',
|
||||
entry_value, icon_value)
|
||||
entry_value, icon_value)
|
||||
self.current_genre = key.name
|
||||
|
||||
store_iter = self.alt_user_liststore.append([key.name,
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._iters[(key.name, self.GENRE_LIST)] = store_iter
|
||||
selection = self.genre_view.get_selection()
|
||||
selection.select_iter(store_iter)
|
||||
@@ -597,15 +598,15 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
'''
|
||||
action when genre new icon button is pressed
|
||||
'''
|
||||
key = self._sheet.add_genre_icon( self.filechooserdialog.get_filename() )
|
||||
key = self._sheet.add_genre_icon(self.filechooserdialog.get_filename())
|
||||
store_iter = self.alt_liststore.append([key.name, self._sheet[key.name]])
|
||||
self._iters[(key.name,self.GENRE_POPUP)] = store_iter
|
||||
self._iters[(key.name, self.GENRE_POPUP)] = store_iter
|
||||
|
||||
gs = GSetting()
|
||||
last_genre_folder = self.filechooserdialog.get_current_folder()
|
||||
|
||||
print (last_genre_folder)
|
||||
print (self.filechooserdialog.get_filename())
|
||||
print(last_genre_folder)
|
||||
print(self.filechooserdialog.get_filename())
|
||||
if last_genre_folder:
|
||||
self.settings[gs.PluginKey.LAST_GENRE_FOLDER] = last_genre_folder
|
||||
|
||||
@@ -620,7 +621,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
if index != '':
|
||||
self.genre_combobox.set_active_iter(self._iters[(index, self.GENRE_POPUP)])
|
||||
self.amend_mode = True
|
||||
self.current_genre=rb3compat.unicodestr(model[genre_iter][0], 'utf-8')
|
||||
self.current_genre = rb3compat.unicodestr(model[genre_iter][0], 'utf-8')
|
||||
else:
|
||||
self.genre_entry.set_text('')
|
||||
self.genre_combobox.set_active_iter(None)
|
||||
@@ -655,7 +656,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
model, genre_iter = selection.get_selected()
|
||||
if genre_iter:
|
||||
index = rb3compat.unicodestr(model[genre_iter][0],'utf-8')
|
||||
index = rb3compat.unicodestr(model[genre_iter][0], 'utf-8')
|
||||
model.remove(genre_iter)
|
||||
|
||||
if index:
|
||||
@@ -703,7 +704,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
else:
|
||||
test = True
|
||||
|
||||
self.settings[gs.PluginKey.NEW_GENRE_ICON]=test
|
||||
self.settings[gs.PluginKey.NEW_GENRE_ICON] = test
|
||||
|
||||
def on_show_launchpad_toggled(self, button):
|
||||
self.launchpad_label.set_visible(button.get_active())
|
||||
|
||||
@@ -125,7 +125,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
self.props.shell.props.task_list.add_task(self.task_progress)
|
||||
|
||||
self.task_progress.props.task_progress = progress
|
||||
self.task_progress.props.task_label=progress_text
|
||||
self.task_progress.props.task_label = progress_text
|
||||
else:
|
||||
self.task_progress.props.task_outcome = RB.TaskOutcome.COMPLETE
|
||||
except:
|
||||
@@ -198,7 +198,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
ui = Gtk.Builder()
|
||||
ui.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
ui.add_from_file(rb.find_plugin_file(self.plugin,
|
||||
'ui/coverart_browser.ui'))
|
||||
'ui/coverart_browser.ui'))
|
||||
ui.connect_signals(self)
|
||||
|
||||
# load the page and put it in the source
|
||||
@@ -221,18 +221,18 @@ class CoverArtBrowserSource(RB.Source):
|
||||
# define menu's
|
||||
self.popup_menu = Menu(self.plugin, self.shell)
|
||||
self.popup_menu.load_from_file('ui/coverart_browser_pop_rb2.ui',
|
||||
'ui/coverart_browser_pop_rb3.ui')
|
||||
'ui/coverart_browser_pop_rb3.ui')
|
||||
self._external_plugins = None
|
||||
|
||||
signals = \
|
||||
{ 'play_album_menu_item' : self.play_album_menu_item_callback,
|
||||
'queue_album_menu_item' : self.queue_album_menu_item_callback,
|
||||
'add_to_playing_menu_item' : self.add_to_playing_menu_item_callback,
|
||||
'new_playlist' : self.add_playlist_menu_item_callback,
|
||||
'cover_search_menu_item' : self.cover_search_menu_item_callback,
|
||||
'export_embed_menu_item' : self.export_embed_menu_item_callback,
|
||||
'show_properties_menu_item' : self.show_properties_menu_item_callback,
|
||||
'play_similar_artist_menu_item' : self.play_similar_artist_menu_item_callback}
|
||||
{'play_album_menu_item': self.play_album_menu_item_callback,
|
||||
'queue_album_menu_item': self.queue_album_menu_item_callback,
|
||||
'add_to_playing_menu_item': self.add_to_playing_menu_item_callback,
|
||||
'new_playlist': self.add_playlist_menu_item_callback,
|
||||
'cover_search_menu_item': self.cover_search_menu_item_callback,
|
||||
'export_embed_menu_item': self.export_embed_menu_item_callback,
|
||||
'show_properties_menu_item': self.show_properties_menu_item_callback,
|
||||
'play_similar_artist_menu_item': self.play_similar_artist_menu_item_callback}
|
||||
|
||||
self.popup_menu.connect_signals(signals)
|
||||
self.popup_menu.connect('pre-popup', self.pre_popup_menu_callback)
|
||||
@@ -248,9 +248,9 @@ class CoverArtBrowserSource(RB.Source):
|
||||
#setup Track Pane
|
||||
setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
setting.bind(self.gs.PluginKey.PANED_POSITION,
|
||||
self.paned, 'collapsible-y', Gio.SettingsBindFlags.DEFAULT)
|
||||
self.paned, 'collapsible-y', Gio.SettingsBindFlags.DEFAULT)
|
||||
setting.bind(self.gs.PluginKey.DISPLAY_BOTTOM,
|
||||
self.paned.get_child2(), 'visible', Gio.SettingsBindFlags.DEFAULT)
|
||||
self.paned.get_child2(), 'visible', Gio.SettingsBindFlags.DEFAULT)
|
||||
self.entryviewpane = EntryViewPane(self.shell,
|
||||
self.plugin,
|
||||
self,
|
||||
@@ -263,9 +263,9 @@ class CoverArtBrowserSource(RB.Source):
|
||||
artist_info_paned = ui.get_object('vertical_info_paned')
|
||||
|
||||
self.artist_info = ArtistInfoPane(info_button_box,
|
||||
info_stack,
|
||||
artist_info_paned,
|
||||
self)
|
||||
info_stack,
|
||||
artist_info_paned,
|
||||
self)
|
||||
|
||||
# quick search
|
||||
self.quick_search = ui.get_object('quick_search_entry')
|
||||
@@ -307,23 +307,23 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
# set sensitivity of export menu item for iconview
|
||||
self.popup_menu.set_sensitive('export_embed_menu_item',
|
||||
CoverArtExport(self.plugin,
|
||||
self.shell, self.album_manager).is_search_plugin_enabled())
|
||||
CoverArtExport(self.plugin,
|
||||
self.shell, self.album_manager).is_search_plugin_enabled())
|
||||
|
||||
# setup the statusbar component
|
||||
self.statusbar = Statusbar(self)
|
||||
|
||||
# initialise the toolbar manager
|
||||
self.toolbar_manager = ToolbarManager(self.plugin, self.page,
|
||||
self.viewmgr)
|
||||
self.viewmgr)
|
||||
self.viewmgr.current_view.emit('update-toolbar')
|
||||
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
# setup the artist paned
|
||||
artist_pview = None
|
||||
for view in self.shell.props.library_source.get_property_views():
|
||||
print (view.props.title)
|
||||
print (_("Artist"))
|
||||
print(view.props.title)
|
||||
print(_("Artist"))
|
||||
if view.props.title == _("Artist"):
|
||||
artist_pview = view
|
||||
break
|
||||
@@ -333,10 +333,10 @@ class CoverArtBrowserSource(RB.Source):
|
||||
self.artist_treeview.set_model(artist_pview.get_model())
|
||||
setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
setting.bind(self.gs.PluginKey.ARTIST_PANED_POSITION,
|
||||
self, 'artist-paned-pos', Gio.SettingsBindFlags.DEFAULT)
|
||||
self, 'artist-paned-pos', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
self.artist_paned.connect('button-release-event',
|
||||
self.artist_paned_button_release_callback)
|
||||
self.artist_paned_button_release_callback)
|
||||
|
||||
# intercept JumpToPlaying Song action so that we can scroll to the playing album
|
||||
appshell = rb3compat.ApplicationShell(self.shell)
|
||||
@@ -363,7 +363,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
Callback when the popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
state,sensitive = self.shell.props.shell_player.get_playing()
|
||||
state, sensitive = self.shell.props.shell_player.get_playing()
|
||||
if not state:
|
||||
sensitive = False
|
||||
|
||||
@@ -373,8 +373,8 @@ class CoverArtBrowserSource(RB.Source):
|
||||
if not self._external_plugins:
|
||||
# initialise external plugin menu support
|
||||
self._external_plugins = \
|
||||
CreateExternalPluginMenu("ca_covers_view",
|
||||
8, self.popup_menu)
|
||||
CreateExternalPluginMenu("ca_covers_view",
|
||||
8, self.popup_menu)
|
||||
self._external_plugins.create_menu('popup_menu', True)
|
||||
|
||||
self.playlist_menu_item_callback()
|
||||
@@ -430,18 +430,18 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
def _change_artist_paned_pos(self, view_name):
|
||||
paned_positions = eval(self.artist_paned_pos)
|
||||
print (paned_positions)
|
||||
print(paned_positions)
|
||||
found = None
|
||||
for viewpos in paned_positions:
|
||||
if view_name in viewpos:
|
||||
found = viewpos
|
||||
break
|
||||
print (found)
|
||||
print(found)
|
||||
if not found:
|
||||
return
|
||||
|
||||
child_width = int(found.split(":")[1])
|
||||
print (child_width)
|
||||
print(child_width)
|
||||
|
||||
# odd case - if the pane is not visible but the position is zero
|
||||
# then the paned position on visible=true is some large arbitary value
|
||||
@@ -480,7 +480,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
# connect some signals to the loader to keep the source informed
|
||||
self.album_mod_id = self.album_manager.model.connect('album-updated',
|
||||
self.on_album_updated)
|
||||
self.on_album_updated)
|
||||
|
||||
self.notify_prog_id = self.album_manager.connect(
|
||||
'notify::progress', lambda *args: self.notify_status_changed())
|
||||
@@ -495,8 +495,8 @@ class CoverArtBrowserSource(RB.Source):
|
||||
print("CoverArtBrowser DEBUG - load_finished_callback")
|
||||
|
||||
#if not self.request_status_box.get_visible():
|
||||
# it should only be enabled if no cover request is going on
|
||||
#self.source_menu_search_all_item.set_sensitive(True)
|
||||
# it should only be enabled if no cover request is going on
|
||||
#self.source_menu_search_all_item.set_sensitive(True)
|
||||
|
||||
# enable sorting on the entryview
|
||||
self.entry_view.set_columns_clickable(True)
|
||||
@@ -529,11 +529,12 @@ class CoverArtBrowserSource(RB.Source):
|
||||
Callback called when the play similar artist option is selected from
|
||||
the cover view popup. It plays similar artists music.
|
||||
'''
|
||||
|
||||
def play_similar_artist_menu_item_callback(self, *args):
|
||||
if not self.echonest_similar_playlist:
|
||||
self.echonest_similar_playlist = \
|
||||
EchoNestPlaylist( self.shell,
|
||||
self.shell.props.queue_source)
|
||||
EchoNestPlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected_albums = self.viewmgr.current_view.get_selected_objects()
|
||||
album = selected_albums[0]
|
||||
@@ -605,10 +606,11 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
if total == 0 and threshold:
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("No tracks have been added because no tracks meet the favourite rating threshold"))
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_(
|
||||
"No tracks have been added because no tracks meet the favourite rating threshold"))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
@@ -652,7 +654,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
self.favourites)
|
||||
|
||||
def playlist_fillmenu(self, popup_menu, menubar, section_name,
|
||||
actiongroup, func, favourite=False):
|
||||
actiongroup, func, favourite=False):
|
||||
print("CoverArtBrowser DEBUG - playlist_fillmenu")
|
||||
|
||||
playlist_manager = self.shell.props.playlist_manager
|
||||
@@ -665,30 +667,30 @@ class CoverArtBrowserSource(RB.Source):
|
||||
if playlists_entries:
|
||||
for playlist in playlists_entries:
|
||||
if playlist.props.is_local and \
|
||||
isinstance(playlist, RB.StaticPlaylistSource):
|
||||
|
||||
args=(playlist, favourite)
|
||||
isinstance(playlist, RB.StaticPlaylistSource):
|
||||
args = (playlist, favourite)
|
||||
|
||||
# take the name of the playlist, strip out non-english characters and reduce the string
|
||||
# to just a-to-z characters i.e. this will make the action_name valid in RB3
|
||||
|
||||
ascii_name = unicodedata.normalize('NFKD', \
|
||||
rb3compat.unicodestr(playlist.props.name, 'utf-8')).encode('ascii','ignore')
|
||||
rb3compat.unicodestr(playlist.props.name, 'utf-8')).encode(
|
||||
'ascii', 'ignore')
|
||||
ascii_name = ascii_name.decode(encoding='UTF-8')
|
||||
ascii_name = re.sub(r'[^a-zA-Z]', '', ascii_name)
|
||||
action = actiongroup.add_action(func=func,
|
||||
action_name=ascii_name,
|
||||
playlist=playlist,favourite=favourite,
|
||||
label=playlist.props.name)
|
||||
action_name=ascii_name,
|
||||
playlist=playlist, favourite=favourite,
|
||||
label=playlist.props.name)
|
||||
|
||||
popup_menu.add_menu_item( menubar, section_name,
|
||||
action )
|
||||
popup_menu.add_menu_item(menubar, section_name,
|
||||
action)
|
||||
|
||||
def add_to_static_playlist_menu_item_callback(self, action, param, args):
|
||||
print('''CoverArtBrowser DEBUG -
|
||||
add_to_static_playlist_menu_item_callback''')
|
||||
|
||||
playlist=args['playlist']
|
||||
playlist = args['playlist']
|
||||
favourite = args['favourite']
|
||||
|
||||
self.queue_selected_album(playlist, favourite)
|
||||
@@ -715,10 +717,10 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
if num_albums <= to_queue:
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("The number of albums to randomly play is less than that displayed."))
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("The number of albums to randomly play is less than that displayed."))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
@@ -752,10 +754,11 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
if total == 0 and threshold:
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("No tracks have been added because no tracks meet the favourite rating threshold"))
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_(
|
||||
"No tracks have been added because no tracks meet the favourite rating threshold"))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
@@ -781,7 +784,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
self.request_status_box.show_all()
|
||||
|
||||
self.album_manager.cover_man.search_covers(selected_albums,
|
||||
self.update_request_status_bar)
|
||||
self.update_request_status_bar)
|
||||
|
||||
print("CoverArtBrowser DEBUG - end cover_search_menu_item_callback()")
|
||||
|
||||
@@ -795,7 +798,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
selected_albums = self.viewmgr.current_view.get_selected_objects()
|
||||
|
||||
CoverArtExport(self.plugin,
|
||||
self.shell, self.album_manager).embed_albums(selected_albums)
|
||||
self.shell, self.album_manager).embed_albums(selected_albums)
|
||||
|
||||
print("CoverArtBrowser DEBUG - export_embed_menu_item_callback()")
|
||||
|
||||
@@ -845,7 +848,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
force = PanedCollapsible.Paned.DEFAULT
|
||||
|
||||
if (album and self.click_count == 1 \
|
||||
and self.last_selected_album is album) or force != PanedCollapsible.Paned.DEFAULT:
|
||||
and self.last_selected_album is album) or force != PanedCollapsible.Paned.DEFAULT:
|
||||
# check if it's a second or third click on the album and expand
|
||||
# or collapse the entry view accordingly
|
||||
self.paned.expand(force)
|
||||
@@ -890,6 +893,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
try:
|
||||
if not self._search_preferences:
|
||||
from gi.repository import Peas
|
||||
|
||||
peas = Peas.Engine.get_default()
|
||||
plugin_info = peas.get_plugin_info('coverart_search_providers')
|
||||
module_name = plugin_info.get_module_name()
|
||||
@@ -901,15 +905,16 @@ class CoverArtBrowserSource(RB.Source):
|
||||
self._search_preferences.display_preferences_dialog(self._search_preferences)
|
||||
except:
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("Please install and activate the latest version of the Coverart Search Providers plugin"))
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_(
|
||||
"Please install and activate the latest version of the Coverart Search Providers plugin"))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
else:
|
||||
assert 1==2, ("unknown choice %s", choice)
|
||||
assert 1 == 2, ("unknown choice %s", choice)
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls, **kwargs):
|
||||
@@ -921,6 +926,7 @@ class CoverArtBrowserSource(RB.Source):
|
||||
|
||||
return cls.instance
|
||||
|
||||
|
||||
class Statusbar(GObject.Object):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
@@ -946,11 +952,11 @@ class Statusbar(GObject.Object):
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
settings.bind(gs.PluginKey.CUSTOM_STATUSBAR, self,
|
||||
'custom_statusbar_enabled', Gio.SettingsBindFlags.GET)
|
||||
'custom_statusbar_enabled', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self, source):
|
||||
self.connect('notify::custom-statusbar-enabled',
|
||||
self._custom_statusbar_enabled_changed)
|
||||
self._custom_statusbar_enabled_changed)
|
||||
self.connect('display-status', self._update)
|
||||
|
||||
def _custom_statusbar_enabled_changed(self, *args):
|
||||
@@ -981,29 +987,30 @@ class Statusbar(GObject.Object):
|
||||
if len(albums) == 1:
|
||||
#. TRANSLATORS - for example "abba's greatest hits by ABBA"
|
||||
self.status = rb3compat.unicodedecode(_('%s by %s') %
|
||||
(album.name, album.artist), 'UTF-8')
|
||||
(album.name, album.artist), 'UTF-8')
|
||||
else:
|
||||
#. TRANSLATORS - the number of albums that have been selected/highlighted
|
||||
self.status = rb3compat.unicodedecode(_('%d selected albums') %
|
||||
(len(albums)), 'UTF-8')
|
||||
(len(albums)), 'UTF-8')
|
||||
|
||||
if track_count == 1:
|
||||
self.status += rb3compat.unicodedecode(_(' with 1 track'), 'UTF-8')
|
||||
else:
|
||||
self.status += rb3compat.unicodedecode(_(' with %d tracks') %
|
||||
track_count, 'UTF-8')
|
||||
track_count, 'UTF-8')
|
||||
|
||||
if duration == 1:
|
||||
self.status += rb3compat.unicodedecode(_(' and a duration of 1 minute'), 'UTF-8')
|
||||
else:
|
||||
self.status += rb3compat.unicodedecode(_(' and a duration of %d minutes') %
|
||||
duration, 'UTF-8')
|
||||
duration, 'UTF-8')
|
||||
|
||||
def _update(self, widget, current_view):
|
||||
albums = current_view.get_selected_objects()
|
||||
self._generate_status(albums)
|
||||
self.current_statusbar.update(self.status)
|
||||
|
||||
|
||||
class SourceStatusBar(object):
|
||||
def __init__(self, source):
|
||||
self._source = source
|
||||
@@ -1032,6 +1039,7 @@ class CustomStatusBar(object):
|
||||
def update(self, status):
|
||||
self._label.set_text(status)
|
||||
|
||||
|
||||
class Views:
|
||||
'''
|
||||
This class describes the different views available
|
||||
@@ -1066,18 +1074,18 @@ class Views:
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
self._values[CoverIconView.name] = [_('Tiles'),
|
||||
GLib.Variant.new_string('coverart-browser-tile')]
|
||||
GLib.Variant.new_string('coverart-browser-tile')]
|
||||
if webkit_support():
|
||||
self._values[CoverFlowView.name] = [_('Flow'),
|
||||
GLib.Variant.new_string('coverart-browser-coverflow')]
|
||||
GLib.Variant.new_string('coverart-browser-coverflow')]
|
||||
self._values[ArtistView.name] = [_('Artist'),
|
||||
GLib.Variant.new_string('coverart-browser-artist')]
|
||||
GLib.Variant.new_string('coverart-browser-artist')]
|
||||
self._values[ListView.name] = [library_name,
|
||||
GLib.Variant.new_string('coverart-browser-list')]
|
||||
GLib.Variant.new_string('coverart-browser-list')]
|
||||
self._values[QueueView.name] = [queue_name,
|
||||
GLib.Variant.new_string('coverart-browser-queue')]
|
||||
GLib.Variant.new_string('coverart-browser-queue')]
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
print (self._values)
|
||||
print(self._values)
|
||||
|
||||
def get_view_names(self):
|
||||
return list(self._values.keys())
|
||||
@@ -1118,7 +1126,7 @@ class ViewManager(GObject.Object):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'new-view': (GObject.SIGNAL_RUN_LAST, None, (str,))
|
||||
}
|
||||
}
|
||||
|
||||
# properties
|
||||
view_name = GObject.property(type=str, default=CoverIconView.name)
|
||||
@@ -1133,13 +1141,13 @@ class ViewManager(GObject.Object):
|
||||
self._views = {}
|
||||
ui = Gtk.Builder()
|
||||
ui.add_from_file(rb.find_plugin_file(source.plugin,
|
||||
'ui/coverart_iconview.ui'))
|
||||
'ui/coverart_iconview.ui'))
|
||||
self._views[CoverIconView.name] = ui.get_object('covers_view')
|
||||
self._views[CoverFlowView.name] = CoverFlowView()
|
||||
self._views[ListView.name] = ListView()
|
||||
self._views[QueueView.name] = QueueView()
|
||||
ui.add_from_file(rb.find_plugin_file(source.plugin,
|
||||
'ui/coverart_artistview.ui'))
|
||||
'ui/coverart_artistview.ui'))
|
||||
self._views[ArtistView.name] = ui.get_object('artist_view')
|
||||
self._lastview = None
|
||||
|
||||
@@ -1167,7 +1175,7 @@ class ViewManager(GObject.Object):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.VIEW_NAME, self, 'view_name',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
def on_notify_view_name(self, *args):
|
||||
if self._lastview and self.view_name != self._lastview:
|
||||
@@ -1227,4 +1235,5 @@ class ViewManager(GObject.Object):
|
||||
|
||||
return colour
|
||||
|
||||
|
||||
GObject.type_register(CoverArtBrowserSource)
|
||||
|
||||
+57
-60
@@ -40,11 +40,12 @@ from collections import namedtuple
|
||||
|
||||
MenuNodeT = namedtuple('MenuNode', 'label menutype typevalue')
|
||||
|
||||
|
||||
def MenuNode(label, menutype=None, typevalue=None):
|
||||
return MenuNodeT(label, menutype, typevalue)
|
||||
|
||||
class OptionsController(GObject.Object):
|
||||
|
||||
class OptionsController(GObject.Object):
|
||||
# properties
|
||||
options = GObject.property(type=object, default=None)
|
||||
current_key = GObject.property(type=str, default=None)
|
||||
@@ -89,7 +90,7 @@ class OptionsController(GObject.Object):
|
||||
|
||||
return ConfiguredSpriteSheet(plugin, typestr, get_stock_size())
|
||||
|
||||
def create_button_image( self, plugin, image, icon_name):
|
||||
def create_button_image(self, plugin, image, icon_name):
|
||||
'''
|
||||
helper function to create a button image
|
||||
'''
|
||||
@@ -102,8 +103,8 @@ class OptionsController(GObject.Object):
|
||||
rb.find_plugin_file(self.plugin, path + icon_name),
|
||||
*get_stock_size())
|
||||
|
||||
class PlaylistPopupController(OptionsController):
|
||||
|
||||
class PlaylistPopupController(OptionsController):
|
||||
def __init__(self, plugin, album_model):
|
||||
super(PlaylistPopupController, self).__init__()
|
||||
|
||||
@@ -137,8 +138,8 @@ class PlaylistPopupController(OptionsController):
|
||||
playlist_model.connect('row-changed', self._update_options, shell)
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'playlist')
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'playlist')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -148,8 +149,8 @@ class PlaylistPopupController(OptionsController):
|
||||
self.update_images(False)
|
||||
|
||||
playlist_manager = shell.props.playlist_manager
|
||||
still_exists = self.current_key == self._library_name or\
|
||||
self.current_key == self._queue_name
|
||||
still_exists = self.current_key == self._library_name or \
|
||||
self.current_key == self._queue_name
|
||||
|
||||
# retrieve the options
|
||||
values = OrderedDict()
|
||||
@@ -171,7 +172,7 @@ class PlaylistPopupController(OptionsController):
|
||||
self.values = values
|
||||
self.options = list(values.keys())
|
||||
|
||||
self.current_key = self.current_key if still_exists else\
|
||||
self.current_key = self.current_key if still_exists else \
|
||||
self._library_name
|
||||
|
||||
def do_action(self):
|
||||
@@ -181,7 +182,7 @@ class PlaylistPopupController(OptionsController):
|
||||
self._album_model.remove_filter('model')
|
||||
else:
|
||||
self._album_model.replace_filter('model',
|
||||
playlist.get_query_model())
|
||||
playlist.get_query_model())
|
||||
|
||||
def get_current_image(self):
|
||||
playlist = self.values[self.current_key]
|
||||
@@ -215,7 +216,7 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
# create a new property model for the genres
|
||||
genres_model = RB.RhythmDBPropertyModel.new(shell.props.db,
|
||||
RB.RhythmDBPropType.GENRE)
|
||||
RB.RhythmDBPropType.GENRE)
|
||||
|
||||
query = shell.props.library_source.props.base_query_model
|
||||
genres_model.props.query_model = query
|
||||
@@ -238,11 +239,11 @@ class GenrePopupController(OptionsController):
|
||||
del self._spritesheet
|
||||
|
||||
self._spritesheet = GenreConfiguredSpriteSheet(self.plugin,
|
||||
'genre', get_stock_size())
|
||||
self._default_image = self.create_button_image( self.plugin,
|
||||
self._default_image, 'default_genre.png')
|
||||
self._unrecognised_image = self.create_button_image( self.plugin,
|
||||
self._unrecognised_image, 'unrecognised_genre.png')
|
||||
'genre', get_stock_size())
|
||||
self._default_image = self.create_button_image(self.plugin,
|
||||
self._default_image, 'default_genre.png')
|
||||
self._unrecognised_image = self.create_button_image(self.plugin,
|
||||
self._unrecognised_image, 'unrecognised_genre.png')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -259,7 +260,7 @@ class GenrePopupController(OptionsController):
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
setting.bind(gs.PluginKey.NEW_GENRE_ICON, self, 'new_genre_icon',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _update_options(self, *args):
|
||||
genres_model = args[-1]
|
||||
@@ -284,7 +285,7 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
self.options = options
|
||||
|
||||
self.current_key = self.current_key if still_exists else\
|
||||
self.current_key = self.current_key if still_exists else \
|
||||
self._initial_genre
|
||||
|
||||
def do_action(self):
|
||||
@@ -306,7 +307,7 @@ class GenrePopupController(OptionsController):
|
||||
image = self._find_alternates(test_genre)
|
||||
|
||||
if image == self._unrecognised_image and \
|
||||
test_genre in self._spritesheet:
|
||||
test_genre in self._spritesheet:
|
||||
image = self._spritesheet[test_genre]
|
||||
|
||||
return image
|
||||
@@ -334,7 +335,7 @@ class GenrePopupController(OptionsController):
|
||||
return sprite
|
||||
|
||||
for genre in sorted(self._spritesheet.locale_names,
|
||||
key=lambda b: (-len(b), b)):
|
||||
key=lambda b: (-len(b), b)):
|
||||
if RB.search_fold(genre) in test_genre:
|
||||
return self._spritesheet[self._spritesheet.locale_names[genre]]
|
||||
|
||||
@@ -352,7 +353,7 @@ class GenrePopupController(OptionsController):
|
||||
# test largest strings first (prevents spurious matches with
|
||||
# short strings)
|
||||
for genre in sorted(self._spritesheet.names,
|
||||
key=lambda b: (-len(b), b)):
|
||||
key=lambda b: (-len(b), b)):
|
||||
if RB.search_fold(genre) in test_genre:
|
||||
return self._spritesheet[genre]
|
||||
|
||||
@@ -362,7 +363,7 @@ class GenrePopupController(OptionsController):
|
||||
def _match_genres(self, test_genre, genre_type):
|
||||
case_search = CaseInsensitiveDict(
|
||||
dict((k.name, v) for k, v in self._spritesheet.genre_alternate.items()
|
||||
if k.genre_type==genre_type))
|
||||
if k.genre_type == genre_type))
|
||||
|
||||
if test_genre in case_search:
|
||||
return (True, self._spritesheet[case_search[test_genre]])
|
||||
@@ -378,20 +379,19 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
|
||||
class SortPopupController(OptionsController):
|
||||
|
||||
def __init__(self, plugin, viewmgr):
|
||||
super(SortPopupController, self).__init__()
|
||||
|
||||
self._viewmgr=viewmgr
|
||||
self._viewmgr = viewmgr
|
||||
self.plugin = plugin
|
||||
# sorts dictionary
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
self.values = OrderedDict([(_('Sort by album name'), 'name'),
|
||||
(_('Sort by album artist'), 'artist'),
|
||||
(_('Sort by year'), 'year'),
|
||||
(_('Sort by rating'), 'rating')])
|
||||
(_('Sort by album artist'), 'artist'),
|
||||
(_('Sort by year'), 'year'),
|
||||
(_('Sort by rating'), 'rating')])
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
@@ -407,8 +407,8 @@ class SortPopupController(OptionsController):
|
||||
list(self.values.values()).index(value)]
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'sort')
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'sort')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -426,8 +426,8 @@ class SortPopupController(OptionsController):
|
||||
sort = self.values[self.current_key]
|
||||
return self._spritesheet[sort]
|
||||
|
||||
class ArtistSortPopupController(OptionsController):
|
||||
|
||||
class ArtistSortPopupController(OptionsController):
|
||||
def __init__(self, plugin, viewmgr):
|
||||
super(ArtistSortPopupController, self).__init__()
|
||||
|
||||
@@ -438,8 +438,8 @@ class ArtistSortPopupController(OptionsController):
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
self.values = OrderedDict([(_('Sort by album name'), 'name_artist'),
|
||||
(_('Sort by year'), 'year_artist'),
|
||||
(_('Sort by rating'), 'rating_artist')])
|
||||
(_('Sort by year'), 'year_artist'),
|
||||
(_('Sort by rating'), 'rating_artist')])
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
@@ -449,20 +449,20 @@ class ArtistSortPopupController(OptionsController):
|
||||
value = source_settings[gs.PluginKey.SORT_BY_ARTIST]
|
||||
|
||||
if value not in list(self.values.values()):
|
||||
print ("here")
|
||||
print("here")
|
||||
value = 'name_artist'
|
||||
source_settings[gs.PluginKey.SORT_BY_ARTIST]=value
|
||||
source_settings[gs.PluginKey.SORT_BY_ARTIST] = value
|
||||
|
||||
self._spritesheet = None
|
||||
self.update_images(False)
|
||||
|
||||
self.current_key = list(self.values.keys())[
|
||||
list(self.values.values()).index(value)]
|
||||
print (self.current_key)
|
||||
print(self.current_key)
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'sort_artist')
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'sort_artist')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -499,10 +499,10 @@ class PropertiesMenuController(OptionsController):
|
||||
self.values[MenuNode(_('Download all covers'))] = 'download'
|
||||
self.values[MenuNode(_('Play random album'))] = 'random'
|
||||
self.values[MenuNode(_('Follow playing song'), 'check',
|
||||
(True if self.follow else False))] = 'follow'
|
||||
(True if self.follow else False))] = 'follow'
|
||||
self.values[MenuNode('separator1', 'separator')] = ''
|
||||
self.values[MenuNode(_('Use favourites only'), 'check',
|
||||
(True if self.favourites else False))] = 'favourite'
|
||||
(True if self.favourites else False))] = 'favourite'
|
||||
self.values[MenuNode('separator2', 'separator')] = ''
|
||||
self.values[MenuNode(_('Browser Preferences'))] = 'browser prefs'
|
||||
self.values[MenuNode(_('Search Preferences'))] = 'search prefs'
|
||||
@@ -535,12 +535,12 @@ class PropertiesMenuController(OptionsController):
|
||||
|
||||
def _change_key(self, dict, old, new):
|
||||
for i in range(len(dict)):
|
||||
k,v = dict.popitem(False)
|
||||
k, v = dict.popitem(False)
|
||||
dict[new if old == k else k] = v
|
||||
|
||||
def update_images(self, *args):
|
||||
self._image = self.create_button_image( self.plugin,
|
||||
None, 'properties.png')
|
||||
self._image = self.create_button_image(self.plugin,
|
||||
None, 'properties.png')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -564,8 +564,8 @@ class PropertiesMenuController(OptionsController):
|
||||
def get_current_description(self):
|
||||
return _('Properties')
|
||||
|
||||
class DecadePopupController(OptionsController):
|
||||
|
||||
class DecadePopupController(OptionsController):
|
||||
def __init__(self, plugin, album_model):
|
||||
super(DecadePopupController, self).__init__()
|
||||
|
||||
@@ -617,8 +617,8 @@ class DecadePopupController(OptionsController):
|
||||
self.current_key = self._initial_decade
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'decade')
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'decade')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -628,7 +628,7 @@ class DecadePopupController(OptionsController):
|
||||
self._album_model.remove_filter('decade')
|
||||
else:
|
||||
self._album_model.replace_filter('decade',
|
||||
self.values[self.current_key][0])
|
||||
self.values[self.current_key][0])
|
||||
|
||||
def get_current_image(self):
|
||||
decade = self.values[self.current_key][1]
|
||||
@@ -639,7 +639,6 @@ class DecadePopupController(OptionsController):
|
||||
|
||||
|
||||
class SortOrderToggleController(OptionsController):
|
||||
|
||||
toolbar_type = "album"
|
||||
|
||||
def __init__(self, plugin, viewmgr):
|
||||
@@ -650,7 +649,7 @@ class SortOrderToggleController(OptionsController):
|
||||
|
||||
# options
|
||||
self.values = OrderedDict([(_('Sort in descending order'), False),
|
||||
(_('Sort in ascending order'), True)])
|
||||
(_('Sort in ascending order'), True)])
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
self._images = []
|
||||
@@ -672,10 +671,10 @@ class SortOrderToggleController(OptionsController):
|
||||
if len(self._images) > 0:
|
||||
del self._images[:]
|
||||
|
||||
self._images.append(self.create_button_image( self.plugin,
|
||||
None, 'arrow_down.png'))
|
||||
self._images.append(self.create_button_image( self.plugin,
|
||||
None, 'arrow_up.png'))
|
||||
self._images.append(self.create_button_image(self.plugin,
|
||||
None, 'arrow_down.png'))
|
||||
self._images.append(self.create_button_image(self.plugin,
|
||||
None, 'arrow_up.png'))
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -688,8 +687,8 @@ class SortOrderToggleController(OptionsController):
|
||||
def get_current_image(self):
|
||||
return self._images[self.get_current_key_index()]
|
||||
|
||||
class ArtistSortOrderToggleController(SortOrderToggleController):
|
||||
|
||||
class ArtistSortOrderToggleController(SortOrderToggleController):
|
||||
toolbar_type = "artist"
|
||||
|
||||
def __init__(self, plugin, model):
|
||||
@@ -700,7 +699,6 @@ class ArtistSortOrderToggleController(SortOrderToggleController):
|
||||
|
||||
|
||||
class AlbumSearchEntryController(OptionsController):
|
||||
|
||||
# properties
|
||||
search_text = GObject.property(type=str, default='')
|
||||
|
||||
@@ -750,7 +748,7 @@ class AlbumSearchEntryController(OptionsController):
|
||||
|
||||
if search_text:
|
||||
self._album_model.replace_filter(self._filter_type,
|
||||
search_text)
|
||||
search_text)
|
||||
elif not force:
|
||||
self._album_model.remove_filter(self._filter_type)
|
||||
|
||||
@@ -783,12 +781,10 @@ class AlbumSearchEntryController(OptionsController):
|
||||
self._typing = True
|
||||
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 100,
|
||||
self._search_typing)
|
||||
|
||||
self._search_typing)
|
||||
|
||||
|
||||
class AlbumQuickSearchController(object):
|
||||
|
||||
def __init__(self, album_manager):
|
||||
self._album_manager = album_manager
|
||||
|
||||
@@ -799,7 +795,7 @@ class AlbumQuickSearchController(object):
|
||||
|
||||
def _on_quick_search(self, quick_search, search_text, *args):
|
||||
album = self._album_manager.model.find_first_visible('album_name',
|
||||
search_text)
|
||||
search_text)
|
||||
|
||||
if album:
|
||||
path = self._album_manager.model.get_path(album)
|
||||
@@ -824,20 +820,21 @@ class AlbumQuickSearchController(object):
|
||||
def _on_hide(self, quick_search, *args):
|
||||
self._album_manager.current_view.grab_focus()
|
||||
|
||||
class ViewController(OptionsController):
|
||||
|
||||
class ViewController(OptionsController):
|
||||
def __init__(self, shell, viewmgr):
|
||||
super(ViewController, self).__init__()
|
||||
|
||||
self._viewmgr = viewmgr
|
||||
|
||||
from coverart_browser_source import Views
|
||||
|
||||
views = Views(shell)
|
||||
|
||||
self.values = OrderedDict()
|
||||
for view_name in views.get_view_names():
|
||||
self.values[views.get_menu_name(view_name)] = view_name
|
||||
print (view_name)
|
||||
print(view_name)
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
viewmgr.connect('new-view', self.on_notify_view_name)
|
||||
|
||||
+36
-33
@@ -34,6 +34,7 @@ from os.path import expanduser
|
||||
from xml.sax.saxutils import escape
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
class FlowShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
@@ -55,6 +56,7 @@ class FlowShowingPolicy(GObject.Object):
|
||||
self._album_manager = album_manager
|
||||
self._model = album_manager.model
|
||||
|
||||
|
||||
class CoverFlowView(AbstractView):
|
||||
__gtype_name__ = "CoverFlowView"
|
||||
|
||||
@@ -76,6 +78,7 @@ class CoverFlowView(AbstractView):
|
||||
self.show_policy = FlowShowingPolicy(self)
|
||||
if webkit_support():
|
||||
from gi.repository import WebKit
|
||||
|
||||
self.view = WebKit.WebView()
|
||||
else:
|
||||
self.view = None
|
||||
@@ -89,33 +92,33 @@ class CoverFlowView(AbstractView):
|
||||
gs = GSetting()
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
settings.bind(gs.PluginKey.FLOW_APPEARANCE, self,
|
||||
'flow_appearance', Gio.SettingsBindFlags.GET)
|
||||
'flow_appearance', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_HIDE_CAPTION, self,
|
||||
'flow_hide', Gio.SettingsBindFlags.GET)
|
||||
'flow_hide', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_SCALE, self,
|
||||
'flow_scale', Gio.SettingsBindFlags.GET)
|
||||
'flow_scale', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_AUTOMATIC, self,
|
||||
'flow_automatic', Gio.SettingsBindFlags.GET)
|
||||
'flow_automatic', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_BACKGROUND_COLOUR, self,
|
||||
'flow_background', Gio.SettingsBindFlags.GET)
|
||||
'flow_background', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_WIDTH, self,
|
||||
'flow_width', Gio.SettingsBindFlags.GET)
|
||||
'flow_width', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_MAX, self,
|
||||
'flow_max', Gio.SettingsBindFlags.GET)
|
||||
'flow_max', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self, source):
|
||||
self.connect('notify::flow-background',
|
||||
self.filter_changed)
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-scale',
|
||||
self.filter_changed)
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-hide',
|
||||
self.filter_changed)
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-width',
|
||||
self.filter_changed)
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-appearance',
|
||||
self.filter_changed)
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-max',
|
||||
self.filter_changed)
|
||||
self.filter_changed)
|
||||
|
||||
def filter_changed(self, *args):
|
||||
# we can get several filter_changed calls per second
|
||||
@@ -161,9 +164,9 @@ class CoverFlowView(AbstractView):
|
||||
|
||||
string = string.replace('#BACKGROUND_COLOUR', background_colour)
|
||||
string = string.replace('#FOREGROUND_COLOUR', foreground_colour)
|
||||
string = string.replace('#FACTOR', str(float(self.flow_scale)/100))
|
||||
string = string.replace('#FACTOR', str(float(self.flow_scale) / 100))
|
||||
|
||||
if self.flow_hide:
|
||||
if self.flow_hide:
|
||||
caption = ""
|
||||
else:
|
||||
caption = '<div class="globalCaption"></div>'
|
||||
@@ -193,22 +196,22 @@ class CoverFlowView(AbstractView):
|
||||
#TRANSLATORS: for example 'Number of covers limited to 150'
|
||||
display_message = _("Number of covers limited to %d") % self.flow_max
|
||||
string = string.replace('#MAXCOVERS',
|
||||
'<p>' + display_message + '</p>')
|
||||
'<p>' + display_message + '</p>')
|
||||
|
||||
items = self.flow.initialise(self.album_manager.model, self.flow_max)
|
||||
|
||||
string = string.replace('#ITEMS', items)
|
||||
|
||||
base = os.path.dirname(path) + "/"
|
||||
base = os.path.dirname(path) + "/"
|
||||
Gdk.threads_enter()
|
||||
print (string)
|
||||
print(string)
|
||||
self.view.load_string(string, "text/html", "UTF-8", "file://" + base)
|
||||
Gdk.threads_leave()
|
||||
|
||||
if self._on_first_use:
|
||||
self._on_first_use = False
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, (self.last_album, PanedCollapsible.Paned.EXPAND))
|
||||
self.source.show_hide_pane, (self.last_album, PanedCollapsible.Paned.EXPAND))
|
||||
|
||||
def get_view_icon_name(self):
|
||||
return "flowview.png"
|
||||
@@ -219,7 +222,7 @@ class CoverFlowView(AbstractView):
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
super(CoverFlowView,self).initialise(source)
|
||||
super(CoverFlowView, self).initialise(source)
|
||||
|
||||
self.album_manager = source.album_manager
|
||||
self.ext_menu_pos = 6
|
||||
@@ -275,7 +278,7 @@ class CoverFlowView(AbstractView):
|
||||
|
||||
if self.source.click_count == 1:
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, album)
|
||||
self.source.show_hide_pane, album)
|
||||
|
||||
def item_activated_callback(self, album):
|
||||
'''
|
||||
@@ -291,8 +294,8 @@ class CoverFlowView(AbstractView):
|
||||
Callback called when something is dropped onto the flow view - hopefully a webpath
|
||||
to a picture
|
||||
'''
|
||||
print ("item_drop_callback %s" % webpath)
|
||||
print ("dropped on album %s" % album)
|
||||
print("item_drop_callback %s" % webpath)
|
||||
print("dropped on album %s" % album)
|
||||
self.album_manager.cover_man.update_cover(album, uri=webpath)
|
||||
|
||||
def get_selected_objects(self):
|
||||
@@ -319,8 +322,8 @@ class CoverFlowView(AbstractView):
|
||||
def scroll_to_album(self, album):
|
||||
self.flow.scroll_to_album(album, self.view)
|
||||
|
||||
class FlowControl(object):
|
||||
|
||||
class FlowControl(object):
|
||||
def __init__(self, callback_view):
|
||||
self.callback_view = callback_view
|
||||
self.album_identifier = {}
|
||||
@@ -368,7 +371,7 @@ class FlowControl(object):
|
||||
try:
|
||||
signal = args["signal"]
|
||||
except:
|
||||
print ("unhandled: %s " % title)
|
||||
print("unhandled: %s " % title)
|
||||
return
|
||||
|
||||
if signal == 'clickactive':
|
||||
@@ -380,9 +383,9 @@ class FlowControl(object):
|
||||
self.callback_view.item_activated_callback(self.album_identifier[int(args['param'][0])])
|
||||
elif signal == 'dropactive':
|
||||
self.callback_view.item_drop_callback(self.album_identifier[int(args['param'][0])],
|
||||
args['param'][1])
|
||||
args['param'][1])
|
||||
else:
|
||||
print ("unhandled signal: %s" % signal)
|
||||
print("unhandled signal: %s" % signal)
|
||||
|
||||
def scroll_to_album(self, album, webview):
|
||||
for row in self.album_identifier:
|
||||
@@ -399,11 +402,11 @@ class FlowControl(object):
|
||||
|
||||
def html_elements(fullfilename, title, caption, identifier):
|
||||
|
||||
return '<div class="item"><img class="content" src="' +\
|
||||
escape(fullfilename) + '" title="' +\
|
||||
escape(title) + '" identifier="' +\
|
||||
identifier + '"/> <div class="caption">' +\
|
||||
escape(caption) + '</div> </div>'
|
||||
return '<div class="item"><img class="content" src="' + \
|
||||
escape(fullfilename) + '" title="' + \
|
||||
escape(title) + '" identifier="' + \
|
||||
identifier + '"/> <div class="caption">' + \
|
||||
escape(caption) + '</div> </div>'
|
||||
|
||||
|
||||
for row in model.store:
|
||||
@@ -415,7 +418,7 @@ class FlowControl(object):
|
||||
|
||||
self.album_identifier[index] = row[album_col]
|
||||
items += html_elements(
|
||||
fullfilename = cover,
|
||||
fullfilename=cover,
|
||||
caption=row[album_col].name,
|
||||
title=row[album_col].artist,
|
||||
identifier=str(index))
|
||||
|
||||
+63
-61
@@ -38,8 +38,9 @@ import rb
|
||||
PLAY_SIZE_X = 30
|
||||
PLAY_SIZE_Y = 30
|
||||
|
||||
|
||||
class CellRendererThumb(Gtk.CellRendererPixbuf):
|
||||
markup=GObject.property(type=str, default="")
|
||||
markup = GObject.property(type=str, default="")
|
||||
|
||||
def __init__(self, font_description, cell_area_source):
|
||||
super(CellRendererThumb, self).__init__()
|
||||
@@ -48,9 +49,9 @@ class CellRendererThumb(Gtk.CellRendererPixbuf):
|
||||
ypad = 0
|
||||
|
||||
def do_render(self, cr, widget,
|
||||
background_area,
|
||||
cell_area,
|
||||
flags):
|
||||
background_area,
|
||||
cell_area,
|
||||
flags):
|
||||
|
||||
|
||||
x_offset = cell_area.x + 1
|
||||
@@ -58,20 +59,20 @@ class CellRendererThumb(Gtk.CellRendererPixbuf):
|
||||
wi = 0
|
||||
he = 0
|
||||
#IMAGE
|
||||
pixbuf = self.props.pixbuf.scale_simple(cell_area.width-2, cell_area.height-2,
|
||||
GdkPixbuf.InterpType.NEAREST)
|
||||
pixbuf = self.props.pixbuf.scale_simple(cell_area.width - 2, cell_area.height - 2,
|
||||
GdkPixbuf.InterpType.NEAREST)
|
||||
Gdk.cairo_set_source_pixbuf(cr, pixbuf, x_offset, y_offset)
|
||||
cr.paint()
|
||||
|
||||
alpha = 0.40
|
||||
|
||||
if((flags & Gtk.CellRendererState.PRELIT) == Gtk.CellRendererState.PRELIT):
|
||||
if ((flags & Gtk.CellRendererState.PRELIT) == Gtk.CellRendererState.PRELIT):
|
||||
alpha -= 0.15
|
||||
|
||||
if hasattr(Gtk.IconView, "get_cell_rect") and self.cell_area_source.hover_pixbuf:
|
||||
# this only works on Gtk+3.6 and later
|
||||
Gdk.cairo_set_source_pixbuf(cr,
|
||||
self.cell_area_source.hover_pixbuf, x_offset, y_offset)
|
||||
self.cell_area_source.hover_pixbuf, x_offset, y_offset)
|
||||
cr.paint()
|
||||
|
||||
#if((flags & Gtk.CellRendererState.SELECTED) == Gtk.CellRendererState.SELECTED or \
|
||||
@@ -79,26 +80,26 @@ class CellRendererThumb(Gtk.CellRendererPixbuf):
|
||||
# alpha -= 0.15
|
||||
|
||||
|
||||
if not(self.cell_area_source.display_text and self.cell_area_source.display_text_pos==False):
|
||||
if not (self.cell_area_source.display_text and self.cell_area_source.display_text_pos == False):
|
||||
return
|
||||
|
||||
#PANGO LAYOUT
|
||||
layout_width = cell_area.width - 2
|
||||
layout_width = cell_area.width - 2
|
||||
pango_layout = PangoCairo.create_layout(cr)
|
||||
pango_layout.set_markup(self.markup , -1)
|
||||
pango_layout.set_markup(self.markup, -1)
|
||||
pango_layout.set_alignment(Pango.Alignment.CENTER)
|
||||
pango_layout.set_font_description(self.font_description)
|
||||
pango_layout.set_width( int(layout_width * Pango.SCALE))
|
||||
pango_layout.set_width(int(layout_width * Pango.SCALE))
|
||||
pango_layout.set_wrap(Pango.WrapMode.WORD_CHAR)
|
||||
wi,he = pango_layout.get_pixel_size()
|
||||
wi, he = pango_layout.get_pixel_size()
|
||||
|
||||
rect_offset = y_offset + (int((2.0 * self.cell_area_source.cover_size) / 3.0))
|
||||
rect_height = int(self.cell_area_source.cover_size / 3.0)
|
||||
was_to_large = False;
|
||||
if(he > rect_height):
|
||||
if (he > rect_height):
|
||||
was_to_large = True
|
||||
pango_layout.set_ellipsize(Pango.EllipsizeMode.END)
|
||||
pango_layout.set_height( int((self.cell_area_source.cover_size / 3.0) * Pango.SCALE))
|
||||
pango_layout.set_height(int((self.cell_area_source.cover_size / 3.0) * Pango.SCALE))
|
||||
wi, he = pango_layout.get_pixel_size()
|
||||
|
||||
#RECTANGLE
|
||||
@@ -114,13 +115,13 @@ class CellRendererThumb(Gtk.CellRendererPixbuf):
|
||||
cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
|
||||
cr.move_to(x_offset,
|
||||
y_offset
|
||||
+ 2.0 * self.cell_area_source.cover_size / 3.0
|
||||
+ (((self.cell_area_source.cover_size/3.0) - he) / 2.0)
|
||||
)
|
||||
+ 2.0 * self.cell_area_source.cover_size / 3.0
|
||||
+ (((self.cell_area_source.cover_size / 3.0) - he) / 2.0)
|
||||
)
|
||||
PangoCairo.show_layout(cr, pango_layout)
|
||||
|
||||
class AlbumArtCellArea(Gtk.CellAreaBox):
|
||||
|
||||
class AlbumArtCellArea(Gtk.CellAreaBox):
|
||||
font_family = GObject.property(type=str, default="Sans")
|
||||
font_size = GObject.property(type=int, default=10)
|
||||
cover_size = GObject.property(type=int, default=0)
|
||||
@@ -150,13 +151,14 @@ class AlbumArtCellArea(Gtk.CellAreaBox):
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
setting.bind(gs.PluginKey.COVER_SIZE, self, 'cover-size',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(gs.PluginKey.DISPLAY_TEXT_POS, self, 'display-text-pos',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(gs.PluginKey.DISPLAY_TEXT, self, 'display-text',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
|
||||
class AlbumShowingPolicy(GObject.Object):
|
||||
'''
|
||||
@@ -182,7 +184,7 @@ class AlbumShowingPolicy(GObject.Object):
|
||||
|
||||
def _connect_signals(self):
|
||||
self._cover_view.props.vadjustment.connect('value-changed',
|
||||
self._viewport_changed)
|
||||
self._viewport_changed)
|
||||
self._model.connect('album-updated', self._album_updated)
|
||||
self._model.connect('visual-updated', self._album_updated)
|
||||
|
||||
@@ -215,6 +217,7 @@ class AlbumShowingPolicy(GObject.Object):
|
||||
# if our path is on the viewport, emit the signal to update it
|
||||
self._cover_view.queue_draw()
|
||||
|
||||
|
||||
class CoverIconView(EnhancedIconView, AbstractView):
|
||||
__gtype_name__ = "CoverIconView"
|
||||
|
||||
@@ -229,7 +232,7 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
|
||||
__gsignals__ = {
|
||||
'update-toolbar': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -257,7 +260,7 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
self._has_initialised = True
|
||||
|
||||
self.view_name = "covers_view"
|
||||
super(CoverIconView,self).initialise(source)
|
||||
super(CoverIconView, self).initialise(source)
|
||||
|
||||
self.shell = source.shell
|
||||
self.album_manager = source.album_manager
|
||||
@@ -269,7 +272,7 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
self.drag_dest_add_text_targets()
|
||||
self.connect('drag-drop', self.on_drag_drop)
|
||||
self.connect('drag-data-received',
|
||||
self.on_drag_data_received)
|
||||
self.on_drag_data_received)
|
||||
self.source.paned.connect("expanded", self.bottom_expander_expanded_callback)
|
||||
|
||||
# lastly support drag-drop from coverart to devices/nautilus etc
|
||||
@@ -278,7 +281,7 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
[], Gdk.DragAction.COPY)
|
||||
#targets = Gtk.TargetList.new([Gtk.TargetEntry.new("application/x-rhythmbox-entry", 0, 0),
|
||||
# Gtk.TargetEntry.new("text/uri-list", 0, 1) ])
|
||||
targets = Gtk.TargetList.new([Gtk.TargetEntry.new("text/uri-list", 0, 0) ])
|
||||
targets = Gtk.TargetList.new([Gtk.TargetEntry.new("text/uri-list", 0, 0)])
|
||||
# N.B. values taken from rhythmbox v2.97 widgets/rb_entry_view.c
|
||||
targets.add_uri_targets(1)
|
||||
|
||||
@@ -293,18 +296,18 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
|
||||
|
||||
self.hover_pixbufs = {
|
||||
'button_play':None,
|
||||
'button_play_hover':None,
|
||||
'button_playpause':None,
|
||||
'button_playpause_hover':None,
|
||||
'button_queue':None,
|
||||
'button_queue_hover':None }
|
||||
'button_play': None,
|
||||
'button_play_hover': None,
|
||||
'button_playpause': None,
|
||||
'button_playpause_hover': None,
|
||||
'button_queue': None,
|
||||
'button_queue_hover': None}
|
||||
|
||||
for pixbuf_type in self.hover_pixbufs:
|
||||
filename = 'img/' + pixbuf_type + '.png'
|
||||
filename = rb.find_plugin_file(self.plugin, filename)
|
||||
self.hover_pixbufs[pixbuf_type] = GdkPixbuf.Pixbuf.new_from_file_at_size(filename,
|
||||
PLAY_SIZE_X, PLAY_SIZE_Y)
|
||||
PLAY_SIZE_X, PLAY_SIZE_Y)
|
||||
|
||||
self._connect_properties()
|
||||
self._connect_signals()
|
||||
@@ -327,26 +330,26 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(self.gs.PluginKey.DISPLAY_TEXT, self,
|
||||
'display_text_enabled', Gio.SettingsBindFlags.GET)
|
||||
'display_text_enabled', Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(self.gs.PluginKey.ICON_AUTOMATIC, self,
|
||||
'icon_automatic', Gio.SettingsBindFlags.GET)
|
||||
'icon_automatic', Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(self.gs.PluginKey.DISPLAY_TEXT_POS, self,
|
||||
'display-text-pos', Gio.SettingsBindFlags.GET)
|
||||
'display-text-pos', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect("item-clicked", self.item_clicked_callback)
|
||||
self.connect("selection-changed", self.selectionchanged_callback)
|
||||
self.connect("item-activated", self.item_activated_callback)
|
||||
self.connect('notify::icon-spacing',
|
||||
self.on_notify_icon_spacing)
|
||||
self.on_notify_icon_spacing)
|
||||
self.connect('notify::icon-padding',
|
||||
self.on_notify_icon_padding)
|
||||
self.on_notify_icon_padding)
|
||||
self.connect('notify::display-text-enabled',
|
||||
self._activate_markup)
|
||||
self._activate_markup)
|
||||
self.connect('notify::display-text-pos',
|
||||
self._activate_markup)
|
||||
self._activate_markup)
|
||||
self.connect("motion-notify-event", self.on_pointer_motion)
|
||||
|
||||
def get_view_icon_name(self):
|
||||
@@ -383,7 +386,7 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
return result
|
||||
|
||||
def on_drag_data_received(self, widget, drag_context, x, y, data, info,
|
||||
time):
|
||||
time):
|
||||
'''
|
||||
Callback called when the drag source has prepared the data (pixbuf)
|
||||
for us to use.
|
||||
@@ -451,18 +454,17 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
|
||||
if path and hasattr(self, "get_cell_rect"):
|
||||
# get_cell_rect only exists in Gtk+3.6 and later
|
||||
valid, rect = self.get_cell_rect(path, None) # rect of widget coords
|
||||
valid, rect = self.get_cell_rect(path, None) # rect of widget coords
|
||||
|
||||
cursor_x, cursor_y = self.get_pointer() # returns widget coords
|
||||
cursor_x, cursor_y = self.get_pointer() # returns widget coords
|
||||
c_x = cursor_x - rect.x
|
||||
c_y = cursor_y - rect.y
|
||||
|
||||
sizing = (rect.width / 2) if in_vacinity else 0
|
||||
if c_x < (PLAY_SIZE_X + sizing) and \
|
||||
c_y < (PLAY_SIZE_Y + sizing) and \
|
||||
c_x > (self.icon_padding + self.icon_spacing) and \
|
||||
c_y > (self.icon_padding + self.icon_spacing):
|
||||
|
||||
if c_x < (PLAY_SIZE_X + sizing) and \
|
||||
c_y < (PLAY_SIZE_Y + sizing) and \
|
||||
c_x > (self.icon_padding + self.icon_spacing) and \
|
||||
c_y > (self.icon_padding + self.icon_spacing):
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -512,14 +514,14 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
if not self._recheck_in_progress:
|
||||
self._recheck_in_progress = True
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 150,
|
||||
recheck_hotspot, (path, False))
|
||||
recheck_hotspot, (path, False))
|
||||
hover = None
|
||||
else:
|
||||
hover = None
|
||||
if not self._recheck_in_progress:
|
||||
self._recheck_in_progress = True
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 450,
|
||||
recheck_hotspot, (path, True))
|
||||
recheck_hotspot, (path, True))
|
||||
else:
|
||||
hover = None
|
||||
|
||||
@@ -565,17 +567,17 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
# to play this new album ... just need a short interval
|
||||
# for the selection event to kick in first
|
||||
def delay(*args):
|
||||
if playing: # if we are playing then queue up the next album
|
||||
if playing: # if we are playing then queue up the next album
|
||||
self.source.queue_selected_album(None, self.source.favourites)
|
||||
else: # otherwise just play it
|
||||
else: # otherwise just play it
|
||||
self._last_play_path = path
|
||||
self.source.play_selected_album(self.source.favourites)
|
||||
|
||||
self.props.cell_area.hover_pixbuf= \
|
||||
self.hover_pixbufs['button_play_hover']
|
||||
self.props.cell_area.hover_pixbuf = \
|
||||
self.hover_pixbufs['button_play_hover']
|
||||
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
delay, None)
|
||||
delay, None)
|
||||
|
||||
return
|
||||
|
||||
@@ -587,10 +589,10 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
self.source.click_count += 1 if not ctrl and not shift else 0
|
||||
|
||||
if self.source.click_count == 1:
|
||||
album = self.album_manager.model.get_from_path(path)\
|
||||
album = self.album_manager.model.get_from_path(path) \
|
||||
if path else None
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, album)
|
||||
self.source.show_hide_pane, album)
|
||||
|
||||
def item_activated_callback(self, iconview, path):
|
||||
'''
|
||||
@@ -640,13 +642,13 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
# set the renderer
|
||||
self.pack_end(self._text_renderer, False)
|
||||
self.add_attribute(self._text_renderer,
|
||||
'markup', AlbumsModel.columns['markup'])
|
||||
'markup', AlbumsModel.columns['markup'])
|
||||
elif self._text_renderer:
|
||||
# remove the cell renderer
|
||||
self.props.cell_area.remove(self._text_renderer)
|
||||
|
||||
if self.display_text_enabled:
|
||||
self.set_tooltip_column(-1) # turnoff tooltips
|
||||
self.set_tooltip_column(-1) # turnoff tooltips
|
||||
else:
|
||||
self.set_tooltip_column(AlbumsModel.columns['tooltip'])
|
||||
|
||||
@@ -667,7 +669,7 @@ class CoverIconView(EnhancedIconView, AbstractView):
|
||||
return False
|
||||
|
||||
Gdk.threads_add_idle(GObject.PRIORITY_DEFAULT_IDLE,
|
||||
scroll_to_album, None)
|
||||
scroll_to_album, None)
|
||||
|
||||
|
||||
def switch_to_view(self, source, album):
|
||||
|
||||
+80
-76
@@ -39,10 +39,12 @@ from coverart_widgets import PixbufButton
|
||||
|
||||
MIN_IMAGE_SIZE = 100
|
||||
|
||||
|
||||
class EntryViewPane(object):
|
||||
'''
|
||||
encapulates all of the Track Pane objects
|
||||
'''
|
||||
|
||||
def __init__(self, shell, plugin, source, entry_view_grid, viewmgr):
|
||||
self.gs = GSetting()
|
||||
|
||||
@@ -84,7 +86,7 @@ class EntryViewPane(object):
|
||||
self.entry_view_grid.attach(self.stars, 1, 1, 1, 1)
|
||||
stack_switcher = Gtk.StackSwitcher()
|
||||
stack_switcher.set_stack(self.stack)
|
||||
self.entry_view_grid.attach( stack_switcher, 0, 1, 1, 1)
|
||||
self.entry_view_grid.attach(stack_switcher, 0, 1, 1, 1)
|
||||
viewtoggle = PixbufButton()
|
||||
viewtoggle.set_image(create_button_image(self.plugin, "entryview.png"))
|
||||
viewtoggle.props.halign = Gtk.Align.END
|
||||
@@ -101,8 +103,8 @@ class EntryViewPane(object):
|
||||
|
||||
self.entry_view_grid.show_all()
|
||||
|
||||
def entry_view_toggled(self, widget, initialised = False):
|
||||
print ("DEBUG - entry_view_toggled")
|
||||
def entry_view_toggled(self, widget, initialised=False):
|
||||
print("DEBUG - entry_view_toggled")
|
||||
if widget.get_active():
|
||||
next_view = self.entry_view_full
|
||||
show_coverart = False
|
||||
@@ -167,13 +169,13 @@ class EntryViewPane(object):
|
||||
|
||||
def cover_search(self, album_artist, manager):
|
||||
self.cover_search_pane.do_search(album_artist,
|
||||
manager.cover_man.update_cover)
|
||||
manager.cover_man.update_cover)
|
||||
|
||||
def update_selection(self, last_selected_album, click_count):
|
||||
'''
|
||||
Update the source view when an item gets selected.
|
||||
'''
|
||||
print ("DEBUG - update_with_selection")
|
||||
print("DEBUG - update_with_selection")
|
||||
selected = self.viewmgr.current_view.get_selected_objects()
|
||||
|
||||
# clear the entry view
|
||||
@@ -223,16 +225,16 @@ class EntryViewPane(object):
|
||||
# update the cover search pane with the first selected album
|
||||
if cover_search_pane_visible:
|
||||
self.cover_search_pane.do_search(selected[0],
|
||||
self.source.album_manager.cover_man.update_cover)
|
||||
self.source.album_manager.cover_man.update_cover)
|
||||
|
||||
return last_selected_album, click_count
|
||||
|
||||
class ResultsGrid(Gtk.Grid):
|
||||
|
||||
class ResultsGrid(Gtk.Grid):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'update-cover': (GObject.SIGNAL_RUN_LAST, None, (GObject.Object,RB.RhythmDBEntry))
|
||||
}
|
||||
'update-cover': (GObject.SIGNAL_RUN_LAST, None, (GObject.Object, RB.RhythmDBEntry))
|
||||
}
|
||||
image_width = 0
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -279,7 +281,7 @@ class ResultsGrid(Gtk.Grid):
|
||||
|
||||
def update_cover(self, widget, source, entry):
|
||||
|
||||
self.oldval = 0 # force a redraw
|
||||
self.oldval = 0 # force a redraw
|
||||
if entry:
|
||||
album = source.album_manager.model.get_from_dbentry(entry)
|
||||
self.pixbuf = GdkPixbuf.Pixbuf().new_from_file(album.cover.original)
|
||||
@@ -299,17 +301,17 @@ class ResultsGrid(Gtk.Grid):
|
||||
if alloc.height < 10:
|
||||
return
|
||||
|
||||
if (alloc.width / 3) <= (MIN_IMAGE_SIZE+30) or \
|
||||
(alloc.height) <= (MIN_IMAGE_SIZE+30):
|
||||
if (alloc.width / 3) <= (MIN_IMAGE_SIZE + 30) or \
|
||||
(alloc.height) <= (MIN_IMAGE_SIZE + 30):
|
||||
self.frame.props.visible = False
|
||||
else:
|
||||
self.frame.props.visible = True
|
||||
|
||||
framealloc = self.frame.get_allocation()
|
||||
minval = min(framealloc.width-30, framealloc.height-30)
|
||||
minval = min(framealloc.width - 30, framealloc.height - 30)
|
||||
if self.oldval == minval:
|
||||
return
|
||||
print ("resizing")
|
||||
print("resizing")
|
||||
self.oldval = minval
|
||||
if self.pixbuf:
|
||||
p = self.pixbuf.scale_simple(minval, minval, GdkPixbuf.InterpType.BILINEAR)
|
||||
@@ -324,7 +326,7 @@ class ResultsGrid(Gtk.Grid):
|
||||
self.stack.set_visible_child_name("image1")
|
||||
|
||||
def change_view(self, entry_view, show_coverart):
|
||||
print ("debug - change_view")
|
||||
print("debug - change_view")
|
||||
widget = self.get_child_at(0, 0)
|
||||
if widget:
|
||||
self.remove(widget)
|
||||
@@ -345,7 +347,6 @@ class ResultsGrid(Gtk.Grid):
|
||||
|
||||
|
||||
class BaseView(RB.EntryView):
|
||||
|
||||
def __init__(self, shell, source):
|
||||
'''
|
||||
Initializes the entryview.
|
||||
@@ -355,8 +356,8 @@ class BaseView(RB.EntryView):
|
||||
self.plugin = self.source.props.plugin
|
||||
|
||||
super(RB.EntryView, self).__init__(db=shell.props.db,
|
||||
shell_player=shell.props.shell_player, is_drag_source=True,
|
||||
visible_columns=[])
|
||||
shell_player=shell.props.shell_player, is_drag_source=True,
|
||||
visible_columns=[])
|
||||
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
@@ -369,28 +370,28 @@ class BaseView(RB.EntryView):
|
||||
|
||||
# connect signals to the shell to know when the playing state changes
|
||||
self.shell.props.shell_player.connect('playing-song-changed',
|
||||
self.playing_song_changed)
|
||||
self.playing_song_changed)
|
||||
self.shell.props.shell_player.connect('playing-changed',
|
||||
self.playing_changed)
|
||||
self.playing_changed)
|
||||
|
||||
self.actiongroup = ActionGroup(self.shell, 'coverentryplaylist_submenu')
|
||||
|
||||
self.external_plugins = None
|
||||
|
||||
self.source_query_model = self.source.source_query_model # RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
|
||||
self.source_query_model = self.source.source_query_model # RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
|
||||
self.qm = RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
|
||||
self.set_model(self.qm)
|
||||
|
||||
# connect the sort-order to the library source sort
|
||||
library_view = self.shell.props.library_source.get_entry_view()
|
||||
library_view.connect('notify::sort-order',
|
||||
self._on_library_sorting_changed)
|
||||
self._on_library_sorting_changed)
|
||||
self._on_library_sorting_changed(library_view,
|
||||
library_view.props.sort_order)
|
||||
library_view.props.sort_order)
|
||||
|
||||
# connect to the sort-order property
|
||||
# connect to the sort-order property
|
||||
self.connect('notify::sort-order', self._notify_sort_order,
|
||||
library_view)
|
||||
library_view)
|
||||
|
||||
self.echonest_similar_playlist = None
|
||||
self.echonest_similar_genre_playlist = None
|
||||
@@ -461,15 +462,15 @@ class BaseView(RB.EntryView):
|
||||
print("CoverArtBrowser DEBUG - do_show_popup()")
|
||||
|
||||
self.popup.popup(self.source,
|
||||
'entryview_popup_menu', 0, Gtk.get_current_event_time())
|
||||
'entryview_popup_menu', 0, Gtk.get_current_event_time())
|
||||
|
||||
return over_entry
|
||||
|
||||
def play_similar_artist_menu_item_callback(self, *args):
|
||||
if not self.echonest_similar_playlist:
|
||||
self.echonest_similar_playlist = \
|
||||
EchoNestPlaylist( self.shell,
|
||||
self.shell.props.queue_source)
|
||||
EchoNestPlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
@@ -478,8 +479,8 @@ class BaseView(RB.EntryView):
|
||||
def play_similar_genre_menu_item_callback(self, *args):
|
||||
if not self.echonest_similar_genre_playlist:
|
||||
self.echonest_similar_genre_playlist = \
|
||||
EchoNestGenrePlaylist( self.shell,
|
||||
self.shell.props.queue_source)
|
||||
EchoNestGenrePlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
@@ -488,8 +489,8 @@ class BaseView(RB.EntryView):
|
||||
def play_similar_track_menu_item_callback(self, *args):
|
||||
if not self.lastfm_similar_playlist:
|
||||
self.lastfm_similar_playlist = \
|
||||
LastFMTrackPlaylist( self.shell,
|
||||
self.shell.props.queue_source)
|
||||
LastFMTrackPlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
@@ -536,7 +537,7 @@ class BaseView(RB.EntryView):
|
||||
selected.reverse()
|
||||
|
||||
selected = sorted(selected,
|
||||
key=lambda song: song.get_ulong(RB.RhythmDBPropType.TRACK_NUMBER))
|
||||
key=lambda song: song.get_ulong(RB.RhythmDBPropType.TRACK_NUMBER))
|
||||
|
||||
for entry in selected:
|
||||
source.add_entry(entry, -1)
|
||||
@@ -551,7 +552,7 @@ class BaseView(RB.EntryView):
|
||||
|
||||
for entry in selected:
|
||||
self.shell.props.db.entry_set(entry, RB.RhythmDBPropType.RATING,
|
||||
rating)
|
||||
rating)
|
||||
|
||||
self.shell.props.db.commit()
|
||||
|
||||
@@ -599,7 +600,7 @@ class BaseView(RB.EntryView):
|
||||
|
||||
def add_to_static_playlist_menu_item_callback(self, action, param, args):
|
||||
print("CoverArtBrowser DEBUG - " + \
|
||||
"add_to_static_playlist_menu_item_callback")
|
||||
"add_to_static_playlist_menu_item_callback")
|
||||
|
||||
playlist = args['playlist']
|
||||
self.add_tracks_to_source(playlist)
|
||||
@@ -616,6 +617,7 @@ class BaseView(RB.EntryView):
|
||||
# update library source's view direction
|
||||
library_view.set_sorting_type(self.props.sort_order)
|
||||
|
||||
|
||||
class CoverArtCompactEntryView(BaseView):
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
@@ -628,12 +630,12 @@ class CoverArtCompactEntryView(BaseView):
|
||||
def display_columns(self):
|
||||
|
||||
self.col_map = OrderedDict([
|
||||
('track-number', RB.EntryViewColumn.TRACK_NUMBER),
|
||||
('title', RB.EntryViewColumn.TITLE),
|
||||
('artist', RB.EntryViewColumn.ARTIST),
|
||||
('rating', RB.EntryViewColumn.RATING),
|
||||
('duration', RB.EntryViewColumn.DURATION)
|
||||
])
|
||||
('track-number', RB.EntryViewColumn.TRACK_NUMBER),
|
||||
('title', RB.EntryViewColumn.TITLE),
|
||||
('artist', RB.EntryViewColumn.ARTIST),
|
||||
('rating', RB.EntryViewColumn.RATING),
|
||||
('duration', RB.EntryViewColumn.DURATION)
|
||||
])
|
||||
|
||||
for entry in self.col_map:
|
||||
visible = False if entry == 'artist' else True
|
||||
@@ -652,14 +654,14 @@ class CoverArtCompactEntryView(BaseView):
|
||||
popup.load_from_file('N/A',
|
||||
'ui/coverart_entryview_compact_pop_rb3.ui')
|
||||
signals = {
|
||||
'ev_compact_play_track_menu_item' : self.play_track_menu_item_callback,
|
||||
'ev_compact_queue_track_menu_item' : self.queue_track_menu_item_callback,
|
||||
'ev_compact_add_to_playing_menu_item' : self.add_to_playing_menu_item_callback,
|
||||
'ev_compact_new_playlist' : self.add_playlist_menu_item_callback,
|
||||
'ev_compact_show_properties_menu_item' : self.show_properties_menu_item_callback,
|
||||
'ev_compact_similar_track_menu_item' : self.play_similar_track_menu_item_callback,
|
||||
'ev_compact_similar_artist_menu_item' : self.play_similar_artist_menu_item_callback,
|
||||
'ev_compact_similar_genre_menu_item' : self.play_similar_genre_menu_item_callback }
|
||||
'ev_compact_play_track_menu_item': self.play_track_menu_item_callback,
|
||||
'ev_compact_queue_track_menu_item': self.queue_track_menu_item_callback,
|
||||
'ev_compact_add_to_playing_menu_item': self.add_to_playing_menu_item_callback,
|
||||
'ev_compact_new_playlist': self.add_playlist_menu_item_callback,
|
||||
'ev_compact_show_properties_menu_item': self.show_properties_menu_item_callback,
|
||||
'ev_compact_similar_track_menu_item': self.play_similar_track_menu_item_callback,
|
||||
'ev_compact_similar_artist_menu_item': self.play_similar_artist_menu_item_callback,
|
||||
'ev_compact_similar_genre_menu_item': self.play_similar_genre_menu_item_callback}
|
||||
|
||||
popup.connect_signals(signals)
|
||||
popup.connect('pre-popup', self.pre_popup_menu_callback)
|
||||
@@ -669,14 +671,14 @@ class CoverArtCompactEntryView(BaseView):
|
||||
print("CoverArtBrowser DEBUG - playlist_menu_item_callback")
|
||||
|
||||
self.source.playlist_fillmenu(self.popup, 'ev_compact_playlist_sub_menu_item', 'ev_compact_playlist_section',
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
|
||||
def pre_popup_menu_callback(self, *args):
|
||||
'''
|
||||
Callback when the popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
state,sensitive = self.shell.props.shell_player.get_playing()
|
||||
state, sensitive = self.shell.props.shell_player.get_playing()
|
||||
if not state:
|
||||
sensitive = False
|
||||
|
||||
@@ -684,11 +686,12 @@ class CoverArtCompactEntryView(BaseView):
|
||||
|
||||
if not self.external_plugins:
|
||||
self.external_plugins = \
|
||||
CreateExternalPluginMenu("ev_compact_entryview", 5, self.popup)
|
||||
CreateExternalPluginMenu("ev_compact_entryview", 5, self.popup)
|
||||
self.external_plugins.create_menu('entryview_compact_popup_menu')
|
||||
|
||||
self.playlist_menu_item_callback()
|
||||
|
||||
|
||||
class CoverArtEntryView(BaseView):
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
@@ -701,23 +704,23 @@ class CoverArtEntryView(BaseView):
|
||||
def display_columns(self):
|
||||
|
||||
self.col_map = OrderedDict([
|
||||
('track-number', RB.EntryViewColumn.TRACK_NUMBER),
|
||||
('title', RB.EntryViewColumn.TITLE),
|
||||
('genre', RB.EntryViewColumn.GENRE),
|
||||
('artist', RB.EntryViewColumn.ARTIST),
|
||||
('album', RB.EntryViewColumn.ALBUM),
|
||||
('composer', RB.EntryViewColumn.COMPOSER),
|
||||
('date', RB.EntryViewColumn.YEAR),
|
||||
('duration', RB.EntryViewColumn.DURATION),
|
||||
('bitrate', RB.EntryViewColumn.QUALITY),
|
||||
('play-count', RB.EntryViewColumn.PLAY_COUNT),
|
||||
('beats-per-minute', RB.EntryViewColumn.BPM),
|
||||
('comment', RB.EntryViewColumn.COMMENT),
|
||||
('location', RB.EntryViewColumn.LOCATION),
|
||||
('rating', RB.EntryViewColumn.RATING),
|
||||
('last-played', RB.EntryViewColumn.LAST_PLAYED),
|
||||
('first-seen', RB.EntryViewColumn.FIRST_SEEN)
|
||||
])
|
||||
('track-number', RB.EntryViewColumn.TRACK_NUMBER),
|
||||
('title', RB.EntryViewColumn.TITLE),
|
||||
('genre', RB.EntryViewColumn.GENRE),
|
||||
('artist', RB.EntryViewColumn.ARTIST),
|
||||
('album', RB.EntryViewColumn.ALBUM),
|
||||
('composer', RB.EntryViewColumn.COMPOSER),
|
||||
('date', RB.EntryViewColumn.YEAR),
|
||||
('duration', RB.EntryViewColumn.DURATION),
|
||||
('bitrate', RB.EntryViewColumn.QUALITY),
|
||||
('play-count', RB.EntryViewColumn.PLAY_COUNT),
|
||||
('beats-per-minute', RB.EntryViewColumn.BPM),
|
||||
('comment', RB.EntryViewColumn.COMMENT),
|
||||
('location', RB.EntryViewColumn.LOCATION),
|
||||
('rating', RB.EntryViewColumn.RATING),
|
||||
('last-played', RB.EntryViewColumn.LAST_PLAYED),
|
||||
('first-seen', RB.EntryViewColumn.FIRST_SEEN)
|
||||
])
|
||||
|
||||
for entry in self.col_map:
|
||||
visible = True if entry == 'title' else False
|
||||
@@ -727,7 +730,7 @@ class CoverArtEntryView(BaseView):
|
||||
gs = GSetting()
|
||||
rhythm_settings = gs.get_setting(gs.Path.RBSOURCE)
|
||||
rhythm_settings.connect('changed::visible-columns',
|
||||
self.on_visible_columns_changed)
|
||||
self.on_visible_columns_changed)
|
||||
self.on_visible_columns_changed(rhythm_settings, 'visible-columns')
|
||||
|
||||
def on_visible_columns_changed(self, settings, key):
|
||||
@@ -742,7 +745,7 @@ class CoverArtEntryView(BaseView):
|
||||
if entry != 'title':
|
||||
col.set_visible(False)
|
||||
|
||||
print ("CoverArtBrowser DEBUG - end on_visible_columns_changed()")
|
||||
print("CoverArtBrowser DEBUG - end on_visible_columns_changed()")
|
||||
|
||||
def define_menu(self):
|
||||
popup = Menu(self.plugin, self.shell)
|
||||
@@ -751,12 +754,12 @@ class CoverArtEntryView(BaseView):
|
||||
signals = {
|
||||
'ev_full_play_track_menu_item': self.play_track_menu_item_callback,
|
||||
'ev_full_queue_track_menu_item': self.queue_track_menu_item_callback,
|
||||
'ev_full_add_to_playing_menu_item' : self.add_to_playing_menu_item_callback,
|
||||
'ev_full_add_to_playing_menu_item': self.add_to_playing_menu_item_callback,
|
||||
'ev_full_new_playlist': self.add_playlist_menu_item_callback,
|
||||
'ev_full_show_properties_menu_item': self.show_properties_menu_item_callback,
|
||||
'ev_full_similar_track_menu_item': self.play_similar_track_menu_item_callback,
|
||||
'ev_full_similar_artist_menu_item': self.play_similar_artist_menu_item_callback,
|
||||
'ev_full_similar_genre_menu_item': self.play_similar_genre_menu_item_callback }
|
||||
'ev_full_similar_genre_menu_item': self.play_similar_genre_menu_item_callback}
|
||||
|
||||
popup.connect_signals(signals)
|
||||
popup.connect('pre-popup', self.pre_popup_menu_callback)
|
||||
@@ -766,14 +769,14 @@ class CoverArtEntryView(BaseView):
|
||||
print("CoverArtBrowser DEBUG - playlist_menu_item_callback")
|
||||
|
||||
self.source.playlist_fillmenu(self.popup, 'ev_full_playlist_sub_menu_item', 'ev_full_playlist_section',
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
|
||||
def pre_popup_menu_callback(self, *args):
|
||||
'''
|
||||
Callback when the popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
state,sensitive = self.shell.props.shell_player.get_playing()
|
||||
state, sensitive = self.shell.props.shell_player.get_playing()
|
||||
if not state:
|
||||
sensitive = False
|
||||
|
||||
@@ -781,11 +784,12 @@ class CoverArtEntryView(BaseView):
|
||||
|
||||
if not self.external_plugins:
|
||||
self.external_plugins = \
|
||||
CreateExternalPluginMenu("ev_full_entryview", 5, self.popup)
|
||||
CreateExternalPluginMenu("ev_full_entryview", 5, self.popup)
|
||||
self.external_plugins.create_menu('entryview_full_popup_menu')
|
||||
|
||||
self.playlist_menu_item_callback()
|
||||
|
||||
|
||||
GObject.type_register(CoverArtEntryView)
|
||||
GObject.type_register(CoverArtCompactEntryView)
|
||||
|
||||
|
||||
+17
-15
@@ -35,6 +35,7 @@ import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
class CoverArtExport(GObject.Object):
|
||||
'''
|
||||
This class provides for various export routines
|
||||
@@ -80,10 +81,10 @@ class CoverArtExport(GObject.Object):
|
||||
|
||||
ui = Gtk.Builder()
|
||||
ui.add_from_file(rb.find_plugin_file(self.plugin,
|
||||
'ui/coverart_exportembed.ui'))
|
||||
'ui/coverart_exportembed.ui'))
|
||||
ui.connect_signals(self)
|
||||
embeddialog = ui.get_object('exportembeddialog')
|
||||
folderchooserbutton = ui.get_object('folderchooserbutton')
|
||||
folderchooserbutton = ui.get_object('folderchooserbutton')
|
||||
use_album_name_checkbutton = ui.get_object('use_album_name_checkbutton')
|
||||
open_filemanager_checkbutton = ui.get_object('open_filemanager_checkbutton')
|
||||
convert_checkbutton = ui.get_object('convert_checkbutton')
|
||||
@@ -130,24 +131,25 @@ class CoverArtExport(GObject.Object):
|
||||
|
||||
if open_filemanager:
|
||||
#code taken from http://stackoverflow.com/questions/1795111/is-there-a-cross-platform-way-to-open-a-file-browser-in-python
|
||||
if sys.platform=='win32':
|
||||
if sys.platform == 'win32':
|
||||
import winreg
|
||||
path= r('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon')
|
||||
|
||||
path = r('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon')
|
||||
for root in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
|
||||
try:
|
||||
with winreg.OpenKey(root, path) as k:
|
||||
value, regtype= winreg.QueryValueEx(k, 'Shell')
|
||||
value, regtype = winreg.QueryValueEx(k, 'Shell')
|
||||
except WindowsError:
|
||||
pass
|
||||
else:
|
||||
if regtype in (winreg.REG_SZ, winreg.REG_EXPAND_SZ):
|
||||
shell= value
|
||||
shell = value
|
||||
break
|
||||
else:
|
||||
shell= 'Explorer.exe'
|
||||
shell = 'Explorer.exe'
|
||||
subprocess.Popen([shell, final_folder_store])
|
||||
|
||||
elif sys.platform=='darwin':
|
||||
elif sys.platform == 'darwin':
|
||||
subprocess.Popen(['open', final_folder_store])
|
||||
|
||||
else:
|
||||
@@ -245,7 +247,7 @@ class CoverArtExport(GObject.Object):
|
||||
encoder.set_property('target', 'bitrate')
|
||||
encoder.set_property('bitrate', self.TARGET_BITRATE)
|
||||
|
||||
xing = Gst.ElementFactory.make('xingmux', 'xing') # needed to make bitrate more accurate
|
||||
xing = Gst.ElementFactory.make('xingmux', 'xing') # needed to make bitrate more accurate
|
||||
mux = Gst.ElementFactory.make('id3v2mux', 'mux')
|
||||
if not mux:
|
||||
# use id3mux where not available
|
||||
@@ -274,10 +276,10 @@ class CoverArtExport(GObject.Object):
|
||||
Gst.Element.link(xing, mux)
|
||||
Gst.Element.link(mux, sink)
|
||||
|
||||
self.converter=converter
|
||||
self.source=source
|
||||
self.sink=sink
|
||||
self.encoder=encoder
|
||||
self.converter = converter
|
||||
self.source = source
|
||||
self.sink = sink
|
||||
self.encoder = encoder
|
||||
|
||||
def _calc_mp3_filename(self, filename, save_folder):
|
||||
finalname = os.path.basename(filename)
|
||||
@@ -288,12 +290,12 @@ class CoverArtExport(GObject.Object):
|
||||
|
||||
self.source.set_property('location', filename)
|
||||
self.sink.set_property('location', self._calc_mp3_filename(filename, save_folder))
|
||||
print (bitrate)
|
||||
print(bitrate)
|
||||
if bitrate < 32:
|
||||
bitrate = self.TARGET_BITRATE
|
||||
|
||||
self.encoder.set_property('bitrate', int(bitrate))
|
||||
print (bitrate)
|
||||
print(bitrate)
|
||||
|
||||
# Start playing
|
||||
ret = self.converter.set_state(Gst.State.PLAYING)
|
||||
|
||||
@@ -29,10 +29,12 @@ from coverart_rb3compat import ApplicationShell
|
||||
from coverart_rb3compat import Menu
|
||||
from coverart_utils import CaseInsensitiveDict
|
||||
|
||||
|
||||
class ExternalPlugin(GObject.Object):
|
||||
'''
|
||||
class for all supported ExternalPlugins
|
||||
'''
|
||||
|
||||
def __init__(self, **kargs):
|
||||
super(ExternalPlugin, self).__init__(**kargs)
|
||||
|
||||
@@ -67,16 +69,16 @@ class ExternalPlugin(GObject.Object):
|
||||
loaded_plugins = peas.get_loaded_plugins()
|
||||
|
||||
if self.attributes['plugin_name'] in CaseInsensitiveDict(loaded_plugins):
|
||||
print ("found %s" % self.attributes['plugin_name'])
|
||||
print("found %s" % self.attributes['plugin_name'])
|
||||
return True
|
||||
|
||||
print ("search for %s" % self.attributes['plugin_name'])
|
||||
print (loaded_plugins)
|
||||
print("search for %s" % self.attributes['plugin_name'])
|
||||
print(loaded_plugins)
|
||||
|
||||
return False
|
||||
|
||||
def create_menu_item(self, menubar, section_name, at_position,
|
||||
save_actiongroup, save_menu, for_album = False):
|
||||
save_actiongroup, save_menu, for_album=False):
|
||||
'''
|
||||
method to create the menu item appropriate to the plugin.
|
||||
A plugin can have many menu items - all menuitems are enclosed
|
||||
@@ -97,27 +99,28 @@ class ExternalPlugin(GObject.Object):
|
||||
return False
|
||||
|
||||
action = ApplicationShell(save_menu.shell).lookup_action(self.attributes['action_group_name'],
|
||||
self.attributes['action_name'], self.attributes['action_type'])
|
||||
self.attributes['action_name'],
|
||||
self.attributes['action_type'])
|
||||
|
||||
if action:
|
||||
self.attributes['action']=action
|
||||
self.attributes['action'] = action
|
||||
|
||||
if self.attributes['new_menu_name'] != '':
|
||||
self.attributes['label'] = self.attributes['new_menu_name']
|
||||
else:
|
||||
self.attributes['label']=action.label
|
||||
#self.attributes['sensitive']=action.get_sensitive()
|
||||
self.attributes['label'] = action.label
|
||||
#self.attributes['sensitive']=action.get_sensitive()
|
||||
else:
|
||||
print ("action not found")
|
||||
print (self.attributes)
|
||||
print("action not found")
|
||||
print(self.attributes)
|
||||
return False
|
||||
|
||||
action = save_actiongroup.add_action(func=self.menuitem_callback,
|
||||
action_name=self.attributes['action_name'], album=for_album,
|
||||
shell=save_menu.shell, label=self.attributes['label'])
|
||||
action_name=self.attributes['action_name'], album=for_album,
|
||||
shell=save_menu.shell, label=self.attributes['label'])
|
||||
|
||||
new_menu_item = save_menu.insert_menu_item(menubar, section_name,
|
||||
at_position, action)
|
||||
at_position, action)
|
||||
return new_menu_item
|
||||
|
||||
def do_deactivate(self):
|
||||
@@ -152,6 +155,7 @@ class ExternalPlugin(GObject.Object):
|
||||
|
||||
self.attributes['action'].activate()
|
||||
|
||||
|
||||
class CreateExternalPluginMenu(GObject.Object):
|
||||
'''
|
||||
This is the key class called to initialise all supported plugins
|
||||
@@ -160,6 +164,7 @@ class CreateExternalPluginMenu(GObject.Object):
|
||||
:param at_position: `int` position within the GtkMenu to create menu - ignored for RB2.99
|
||||
:param popup: `Menu` whole popupmenu including sub-menus
|
||||
'''
|
||||
|
||||
def __init__(self, section_name, at_position, popup, **kargs):
|
||||
super(CreateExternalPluginMenu, self).__init__(**kargs)
|
||||
|
||||
@@ -207,7 +212,7 @@ class CreateExternalPluginMenu(GObject.Object):
|
||||
|
||||
self.supported_plugins.append(ext)
|
||||
|
||||
def create_menu(self, menu_name, for_album = False):
|
||||
def create_menu(self, menu_name, for_album=False):
|
||||
'''
|
||||
method to create the menu items for all supported plugins
|
||||
|
||||
@@ -225,7 +230,7 @@ class CreateExternalPluginMenu(GObject.Object):
|
||||
|
||||
for plugin in self.supported_plugins:
|
||||
new_menu_item = plugin.create_menu_item(self.menu_name, self.section_name,
|
||||
self.at_position, self._actiongroup, self.menu, for_album)
|
||||
self.at_position, self._actiongroup, self.menu, for_album)
|
||||
|
||||
if (not items_added) and new_menu_item:
|
||||
items_added = True
|
||||
|
||||
@@ -21,6 +21,7 @@ from coverart_widgets import AbstractView
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
|
||||
|
||||
class ListShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
@@ -39,8 +40,8 @@ class ListShowingPolicy(GObject.Object):
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
class ListView(AbstractView):
|
||||
|
||||
class ListView(AbstractView):
|
||||
__gtype_name__ = "ListView"
|
||||
|
||||
name = 'listview'
|
||||
@@ -67,7 +68,7 @@ class ListView(AbstractView):
|
||||
self.initialise(source)
|
||||
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.library_source)
|
||||
self.shell.props.library_source)
|
||||
|
||||
def get_selected_objects(self):
|
||||
'''
|
||||
|
||||
+46
-45
@@ -28,11 +28,12 @@ import random
|
||||
|
||||
LOAD_CHUNK = 50
|
||||
|
||||
|
||||
class WebPlaylist(object):
|
||||
MAX_TRACKS_TO_ADD = 3 # number of tracks to add to a source for each fetch
|
||||
MIN_TRACKS_TO_FETCH = 5 # number of tracks in source before a fetch will be required
|
||||
TOTAL_TRACKS_REMEMBERED = 25 # total number of tracks for all artists before a fetch is allowed
|
||||
MAX_TRACKS_PER_ARTIST = 3 # number of tracks allowed to be remembered per artist
|
||||
MAX_TRACKS_TO_ADD = 3 # number of tracks to add to a source for each fetch
|
||||
MIN_TRACKS_TO_FETCH = 5 # number of tracks in source before a fetch will be required
|
||||
TOTAL_TRACKS_REMEMBERED = 25 # total number of tracks for all artists before a fetch is allowed
|
||||
MAX_TRACKS_PER_ARTIST = 3 # number of tracks allowed to be remembered per artist
|
||||
|
||||
def __init__(self, shell, source, playlist_name):
|
||||
|
||||
@@ -47,10 +48,10 @@ class WebPlaylist(object):
|
||||
self.tracks_not_played = 0
|
||||
# cache for artist information: valid for a month, can be used indefinitely
|
||||
# if offline, discarded if unused for six months
|
||||
self.info_cache = rb.URLCache(name = playlist_name,
|
||||
path = os.path.join('coverart_browser', playlist_name),
|
||||
refresh = 30,
|
||||
discard = 180)
|
||||
self.info_cache = rb.URLCache(name=playlist_name,
|
||||
path=os.path.join('coverart_browser', playlist_name),
|
||||
refresh=30,
|
||||
discard=180)
|
||||
self.info_cache.clean()
|
||||
|
||||
def playing_song_changed(self, player, entry):
|
||||
@@ -65,7 +66,7 @@ class WebPlaylist(object):
|
||||
if self.playlist_started and len(self.source.props.query_model) < self.MIN_TRACKS_TO_FETCH:
|
||||
self.start(entry)
|
||||
|
||||
def start(self, seed_entry, reinitialise = False):
|
||||
def start(self, seed_entry, reinitialise=False):
|
||||
artist = seed_entry.get_string(RB.RhythmDBPropType.ARTIST)
|
||||
|
||||
if reinitialise:
|
||||
@@ -74,7 +75,7 @@ class WebPlaylist(object):
|
||||
self.playlist_started = False
|
||||
|
||||
player = self.shell.props.shell_player
|
||||
_, is_playing = player.get_playing()
|
||||
_, is_playing = player.get_playing()
|
||||
|
||||
if is_playing:
|
||||
player.stop()
|
||||
@@ -89,7 +90,7 @@ class WebPlaylist(object):
|
||||
|
||||
search_artist = urllib.parse.quote(artist.encode("utf8"))
|
||||
if search_artist in self.played_artist:
|
||||
print ("we have already searched for that artist")
|
||||
print("we have already searched for that artist")
|
||||
return
|
||||
|
||||
self.search_entry = seed_entry
|
||||
@@ -109,7 +110,7 @@ class WebPlaylist(object):
|
||||
|
||||
def _clear_next(self):
|
||||
self.search_artists = ""
|
||||
self._running = False
|
||||
self._running = False
|
||||
|
||||
@idle_iterator
|
||||
def _load_albums(self):
|
||||
@@ -120,8 +121,8 @@ class WebPlaylist(object):
|
||||
lookup_title = entry.get_string(RB.RhythmDBPropType.TITLE_FOLDED)
|
||||
|
||||
if lookup in self.artist and \
|
||||
lookup_title in \
|
||||
self.artist[lookup]:
|
||||
lookup_title in \
|
||||
self.artist[lookup]:
|
||||
|
||||
if lookup not in self.candidate_artist:
|
||||
self.candidate_artist[lookup] = []
|
||||
@@ -129,13 +130,13 @@ class WebPlaylist(object):
|
||||
# N.B. every artist has an array of dicts with a known format of track & add-to-source elements
|
||||
# the following extracts the track-title and add-to-source to form a dict of track-title and a value
|
||||
# of the add-to-source
|
||||
d=dict((i['track-title'], i['add-to-source']) for i in self.candidate_artist[lookup])
|
||||
d = dict((i['track-title'], i['add-to-source']) for i in self.candidate_artist[lookup])
|
||||
if len(d) < self.MAX_TRACKS_PER_ARTIST and lookup_title not in d:
|
||||
# we only append a max of three tracks to each artist
|
||||
self.candidate_artist[lookup].append({
|
||||
'track':entry,
|
||||
'add-to-source':False,
|
||||
'track-title':lookup_title})
|
||||
'track': entry,
|
||||
'add-to-source': False,
|
||||
'track-title': lookup_title})
|
||||
self.tracks_not_played = self.tracks_not_played + 1
|
||||
|
||||
|
||||
@@ -155,10 +156,10 @@ class WebPlaylist(object):
|
||||
|
||||
def display_error_message(self):
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("No matching tracks have been found"))
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("No matching tracks have been found"))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
@@ -167,9 +168,9 @@ class WebPlaylist(object):
|
||||
entries = []
|
||||
for artist in self.candidate_artist:
|
||||
|
||||
d=dict((i['track'], (self.candidate_artist[artist].index(i),
|
||||
i['add-to-source'],
|
||||
artist)) for i in self.candidate_artist[artist])
|
||||
d = dict((i['track'], (self.candidate_artist[artist].index(i),
|
||||
i['add-to-source'],
|
||||
artist)) for i in self.candidate_artist[artist])
|
||||
|
||||
for entry, elements in d.items():
|
||||
element_pos, add_to_source, artist = elements
|
||||
@@ -180,7 +181,7 @@ class WebPlaylist(object):
|
||||
|
||||
count = 0
|
||||
for row in entries:
|
||||
print (row)
|
||||
print(row)
|
||||
entry, elements = list(row.items())[0]
|
||||
element_pos, add_to_source, artist = elements
|
||||
self.source.add_entry(entry, -1)
|
||||
@@ -193,13 +194,13 @@ class WebPlaylist(object):
|
||||
|
||||
player = self.shell.props.shell_player
|
||||
|
||||
_, is_playing = player.get_playing()
|
||||
_, is_playing = player.get_playing()
|
||||
|
||||
if len(self.source.props.query_model) > 0 and not is_playing:
|
||||
player.play_entry(self.source.props.query_model[0][0], self.source)
|
||||
|
||||
class LastFMTrackPlaylist(WebPlaylist):
|
||||
|
||||
class LastFMTrackPlaylist(WebPlaylist):
|
||||
def __init__(self, shell, source):
|
||||
WebPlaylist.__init__(self, shell, source, "lastfm_trackplaylist")
|
||||
|
||||
@@ -216,14 +217,14 @@ class LastFMTrackPlaylist(WebPlaylist):
|
||||
artist,
|
||||
title)
|
||||
|
||||
print (formatted_url)
|
||||
print(formatted_url)
|
||||
cachekey = "artist:%s:title:%s" % (artist, title)
|
||||
self.info_cache.fetch(cachekey, formatted_url, self.similar_info_cb, None)
|
||||
|
||||
def similar_info_cb(self, data, _):
|
||||
|
||||
if not data:
|
||||
print ("nothing to do")
|
||||
print("nothing to do")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
@@ -234,7 +235,7 @@ class LastFMTrackPlaylist(WebPlaylist):
|
||||
self.artist = {}
|
||||
|
||||
if 'similartracks' not in similar:
|
||||
print ("No matching data returned from LastFM")
|
||||
print("No matching data returned from LastFM")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
@@ -246,7 +247,7 @@ class LastFMTrackPlaylist(WebPlaylist):
|
||||
self.artist[name].append(RB.search_fold(song['name']))
|
||||
|
||||
if len(self.artist) == 0:
|
||||
print ("no artists returned")
|
||||
print("no artists returned")
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
@@ -256,10 +257,10 @@ class LastFMTrackPlaylist(WebPlaylist):
|
||||
query_model = self.shell.props.library_source.props.base_query_model
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
total=len(query_model), progress=0.)
|
||||
|
||||
|
||||
class EchoNestPlaylist(WebPlaylist):
|
||||
|
||||
def __init__(self, shell, source):
|
||||
WebPlaylist.__init__(self, shell, source, "echonest_playlist")
|
||||
|
||||
@@ -273,14 +274,14 @@ class EchoNestPlaylist(WebPlaylist):
|
||||
formatted_url = url.format(urllib.parse.quote(apikey),
|
||||
artist)
|
||||
|
||||
print (formatted_url)
|
||||
print(formatted_url)
|
||||
cachekey = "artist:%s" % artist
|
||||
self.info_cache.fetch(cachekey, formatted_url, self.similar_info_cb, None)
|
||||
|
||||
def similar_info_cb(self, data, _):
|
||||
|
||||
if not data:
|
||||
print ("nothing to do")
|
||||
print("nothing to do")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
@@ -291,7 +292,7 @@ class EchoNestPlaylist(WebPlaylist):
|
||||
self.artist = {}
|
||||
|
||||
if 'songs' not in similar['response']:
|
||||
print ("No matching data returned from EchoNest")
|
||||
print("No matching data returned from EchoNest")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
@@ -303,7 +304,7 @@ class EchoNestPlaylist(WebPlaylist):
|
||||
self.artist[name].append(RB.search_fold(song['title']))
|
||||
|
||||
if len(self.artist) == 0:
|
||||
print ("no artists returned")
|
||||
print("no artists returned")
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
@@ -313,10 +314,10 @@ class EchoNestPlaylist(WebPlaylist):
|
||||
query_model = self.shell.props.library_source.props.base_query_model
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
total=len(query_model), progress=0.)
|
||||
|
||||
|
||||
class EchoNestGenrePlaylist(WebPlaylist):
|
||||
|
||||
def __init__(self, shell, source):
|
||||
WebPlaylist.__init__(self, shell, source, "echonest_genre_playlist")
|
||||
|
||||
@@ -330,14 +331,14 @@ class EchoNestGenrePlaylist(WebPlaylist):
|
||||
formatted_url = url.format(urllib.parse.quote(apikey),
|
||||
genre)
|
||||
|
||||
print (formatted_url)
|
||||
print(formatted_url)
|
||||
cachekey = "genre:%s" % genre
|
||||
self.info_cache.fetch(cachekey, formatted_url, self.similar_info_cb, None)
|
||||
|
||||
def similar_info_cb(self, data, _):
|
||||
|
||||
if not data:
|
||||
print ("nothing to do")
|
||||
print("nothing to do")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
@@ -348,7 +349,7 @@ class EchoNestGenrePlaylist(WebPlaylist):
|
||||
self.artist = {}
|
||||
|
||||
if 'songs' not in similar['response']:
|
||||
print ("No matching data returned from EchoNest")
|
||||
print("No matching data returned from EchoNest")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
@@ -360,7 +361,7 @@ class EchoNestGenrePlaylist(WebPlaylist):
|
||||
self.artist[name].append(RB.search_fold(song['title']))
|
||||
|
||||
if len(self.artist) == 0:
|
||||
print ("no artists returned")
|
||||
print("no artists returned")
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
@@ -370,4 +371,4 @@ class EchoNestGenrePlaylist(WebPlaylist):
|
||||
query_model = self.shell.props.library_source.props.base_query_model
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
total=len(query_model), progress=0.)
|
||||
|
||||
@@ -21,6 +21,7 @@ from coverart_widgets import AbstractView
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
|
||||
|
||||
class QueueShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
@@ -39,8 +40,8 @@ class QueueShowingPolicy(GObject.Object):
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
class QueueView(AbstractView):
|
||||
|
||||
class QueueView(AbstractView):
|
||||
__gtype_name__ = "QueueView"
|
||||
|
||||
name = 'queueview'
|
||||
@@ -67,7 +68,7 @@ class QueueView(AbstractView):
|
||||
self.initialise(source)
|
||||
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.queue_source)
|
||||
self.shell.props.queue_source)
|
||||
|
||||
def get_selected_objects(self):
|
||||
'''
|
||||
|
||||
+65
-45
@@ -31,6 +31,7 @@ import sys
|
||||
import rb
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
def pygobject_version():
|
||||
'''
|
||||
returns float of the major and minor parts of a pygobject version
|
||||
@@ -40,7 +41,8 @@ def pygobject_version():
|
||||
|
||||
str_version = to_number(GObject.pygobject_version)
|
||||
|
||||
return float(str_version.rsplit('.',1)[0])
|
||||
return float(str_version.rsplit('.', 1)[0])
|
||||
|
||||
|
||||
def compare_pygobject_version(version):
|
||||
'''
|
||||
@@ -51,17 +53,18 @@ def compare_pygobject_version(version):
|
||||
|
||||
str_version = to_number(GObject.pygobject_version)
|
||||
|
||||
split = str_version.rsplit('.',2)
|
||||
split_compare = version.rsplit('.',2)
|
||||
split = str_version.rsplit('.', 2)
|
||||
split_compare = version.rsplit('.', 2)
|
||||
|
||||
if int(split_compare[0])<int(split[0]):
|
||||
if int(split_compare[0]) < int(split[0]):
|
||||
return True
|
||||
|
||||
if int(split_compare[1])<int(split[1]):
|
||||
if int(split_compare[1]) < int(split[1]):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
PYVER = sys.version_info[0]
|
||||
|
||||
if PYVER >= 3:
|
||||
@@ -75,64 +78,74 @@ if PYVER >= 3:
|
||||
else:
|
||||
import httplib
|
||||
|
||||
|
||||
def responses():
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return http.client.responses
|
||||
else:
|
||||
return httplib.responses
|
||||
|
||||
|
||||
def unicodestr(param, charset):
|
||||
if PYVER >=3:
|
||||
return param#str(param, charset)
|
||||
if PYVER >= 3:
|
||||
return param #str(param, charset)
|
||||
else:
|
||||
return unicode(param, charset)
|
||||
|
||||
|
||||
def unicodeencode(param, charset):
|
||||
if PYVER >=3:
|
||||
return param#str(param).encode(charset)
|
||||
if PYVER >= 3:
|
||||
return param #str(param).encode(charset)
|
||||
else:
|
||||
return unicode(param).encode(charset)
|
||||
|
||||
|
||||
def unicodedecode(param, charset):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return param
|
||||
else:
|
||||
return param.decode(charset)
|
||||
|
||||
|
||||
def urlparse(uri):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return urllib.parse.urlparse(uri)
|
||||
else:
|
||||
return rb2urlparse(uri)
|
||||
|
||||
|
||||
def url2pathname(url):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return urllib.request.url2pathname(url)
|
||||
else:
|
||||
return urllib.url2pathname(url)
|
||||
|
||||
|
||||
def urlopen(filename):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return urllib.request.urlopen(filename)
|
||||
else:
|
||||
return urllib.urlopen(filename)
|
||||
|
||||
|
||||
def pathname2url(filename):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return urllib.request.pathname2url(filename)
|
||||
else:
|
||||
return urllib.pathname2url(filename)
|
||||
|
||||
|
||||
def unquote(uri):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return urllib.parse.unquote(uri)
|
||||
else:
|
||||
return urllib.unquote(uri)
|
||||
|
||||
|
||||
def quote(uri, safe=None):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
if safe:
|
||||
return urllib.parse.quote(uri,safe=safe)
|
||||
return urllib.parse.quote(uri, safe=safe)
|
||||
else:
|
||||
return urllib.parse.quote(uri)
|
||||
else:
|
||||
@@ -141,25 +154,28 @@ def quote(uri, safe=None):
|
||||
else:
|
||||
return urllib.quote(uri)
|
||||
|
||||
|
||||
def quote_plus(uri):
|
||||
if PYVER >=3:
|
||||
if PYVER >= 3:
|
||||
return urllib.parse.quote_plus(uri)
|
||||
else:
|
||||
return urllib.quote_plus(uri)
|
||||
|
||||
|
||||
def is_rb3(*args):
|
||||
if hasattr(RB.Shell.props, 'ui_manager'):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class Menu(GObject.Object):
|
||||
'''
|
||||
Menu object used to create window popup menus
|
||||
'''
|
||||
__gsignals__ = {
|
||||
'pre-popup': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, plugin, shell):
|
||||
'''
|
||||
@@ -268,7 +284,7 @@ class Menu(GObject.Object):
|
||||
bar.show_all()
|
||||
uim.ensure_update()
|
||||
|
||||
def load_from_file(self, rb2_ui_filename, rb3_ui_filename ):
|
||||
def load_from_file(self, rb2_ui_filename, rb3_ui_filename):
|
||||
'''
|
||||
utility function to load the menu structure
|
||||
:param rb2_ui_filename: `str` RB2.98 and below UI file
|
||||
@@ -277,6 +293,7 @@ class Menu(GObject.Object):
|
||||
self.builder = Gtk.Builder()
|
||||
try:
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
|
||||
cl = CoverLocale()
|
||||
|
||||
self.builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
@@ -291,7 +308,7 @@ class Menu(GObject.Object):
|
||||
self.ui_filename = ui_filename
|
||||
|
||||
self.builder.add_from_file(rb.find_plugin_file(self.plugin,
|
||||
ui_filename))
|
||||
ui_filename))
|
||||
|
||||
def _connect_rb3_signals(self, signals):
|
||||
def _menu_connect(action_name, func):
|
||||
@@ -300,16 +317,16 @@ class Menu(GObject.Object):
|
||||
action.set_enabled(True)
|
||||
self.shell.props.window.add_action(action)
|
||||
|
||||
for key,value in signals.items():
|
||||
_menu_connect( key, value)
|
||||
for key, value in signals.items():
|
||||
_menu_connect(key, value)
|
||||
|
||||
def _connect_rb2_signals(self, signals):
|
||||
def _menu_connect(menu_item_name, func):
|
||||
menu_item = self.get_menu_object(menu_item_name)
|
||||
menu_item.connect('activate', func)
|
||||
|
||||
for key,value in signals.items():
|
||||
_menu_connect( key, value)
|
||||
for key, value in signals.items():
|
||||
_menu_connect(key, value)
|
||||
|
||||
def connect_signals(self, signals):
|
||||
'''
|
||||
@@ -359,7 +376,7 @@ class Menu(GObject.Object):
|
||||
popup_menu = app.get_plugin_menu(menu_name_or_link)
|
||||
else:
|
||||
popup_menu = item
|
||||
print (menu_name_or_link)
|
||||
print(menu_name_or_link)
|
||||
self._rbmenu_objects[menu_name_or_link] = popup_menu
|
||||
|
||||
return popup_menu
|
||||
@@ -387,14 +404,15 @@ class Menu(GObject.Object):
|
||||
menu = self.get_gtkmenu(source, menu_name)
|
||||
menu.popup(None, None, None, None, button, time)
|
||||
|
||||
|
||||
class ActionGroup(object):
|
||||
'''
|
||||
container for all Actions used to associate with menu items
|
||||
'''
|
||||
|
||||
# action_state
|
||||
STANDARD=0
|
||||
TOGGLE=1
|
||||
STANDARD = 0
|
||||
TOGGLE = 1
|
||||
|
||||
def __init__(self, shell, group_name):
|
||||
'''
|
||||
@@ -448,7 +466,7 @@ class ActionGroup(object):
|
||||
args['accel'] = accel
|
||||
return self.add_action(func, action_name, **args)
|
||||
|
||||
def add_action(self, func, action_name, **args ):
|
||||
def add_action(self, func, action_name, **args):
|
||||
'''
|
||||
Creates an Action and adds it to the ActionGroup
|
||||
|
||||
@@ -465,7 +483,7 @@ class ActionGroup(object):
|
||||
if 'label' in args:
|
||||
label = args['label']
|
||||
else:
|
||||
label=action_name
|
||||
label = action_name
|
||||
|
||||
if 'accel' in args:
|
||||
accel = args['accel']
|
||||
@@ -479,7 +497,7 @@ class ActionGroup(object):
|
||||
if is_rb3(self.shell):
|
||||
if state == ActionGroup.TOGGLE:
|
||||
action = Gio.SimpleAction.new_stateful(action_name, None,
|
||||
GLib.Variant('b', False))
|
||||
GLib.Variant('b', False))
|
||||
else:
|
||||
action = Gio.SimpleAction.new(action_name, None)
|
||||
|
||||
@@ -497,7 +515,7 @@ class ActionGroup(object):
|
||||
self.actiongroup.add_action(action)
|
||||
|
||||
if accel:
|
||||
app.add_accelerator(accel, action_type+"."+action_name, None)
|
||||
app.add_accelerator(accel, action_type + "." + action_name, None)
|
||||
else:
|
||||
if 'stock_id' in args:
|
||||
stock_id = args['stock_id']
|
||||
@@ -506,12 +524,12 @@ class ActionGroup(object):
|
||||
|
||||
if state == ActionGroup.TOGGLE:
|
||||
action = Gtk.ToggleAction(label=label,
|
||||
name=action_name,
|
||||
tooltip='', stock_id=stock_id)
|
||||
name=action_name,
|
||||
tooltip='', stock_id=stock_id)
|
||||
else:
|
||||
action = Gtk.Action(label=label,
|
||||
name=action_name,
|
||||
tooltip='', stock_id=stock_id)
|
||||
name=action_name,
|
||||
tooltip='', stock_id=stock_id)
|
||||
|
||||
if accel:
|
||||
self.actiongroup.add_action_with_accel(action, accel)
|
||||
@@ -528,6 +546,7 @@ class ActionGroup(object):
|
||||
|
||||
return act
|
||||
|
||||
|
||||
class ApplicationShell(object):
|
||||
'''
|
||||
Unique class that mirrors RB.Application & RB.Shell menu functionality
|
||||
@@ -537,6 +556,7 @@ class ApplicationShell(object):
|
||||
|
||||
class __impl:
|
||||
""" Implementation of the singleton interface """
|
||||
|
||||
def __init__(self, shell):
|
||||
self.shell = shell
|
||||
|
||||
@@ -620,9 +640,9 @@ class ApplicationShell(object):
|
||||
item.set_label(act.label)
|
||||
item.set_attribute_value("accel", GLib.Variant("s", act.accel))
|
||||
app = Gio.Application.get_default()
|
||||
index = menu+action_name
|
||||
index = menu + action_name
|
||||
app.add_plugin_menu_item(menu,
|
||||
index, item)
|
||||
index, item)
|
||||
self._uids[index] = menu
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
@@ -670,11 +690,11 @@ class ApplicationShell(object):
|
||||
elif popup_name == 'PodcastViewPopup':
|
||||
plugin_type = 'podcast-episode-popup'
|
||||
else:
|
||||
print ("unknown type %s" % plugin_type)
|
||||
print("unknown type %s" % plugin_type)
|
||||
|
||||
index = plugin_type+action_name
|
||||
index = plugin_type + action_name
|
||||
app.add_plugin_menu_item(plugin_type, index, item)
|
||||
self._uids[index]=plugin_type
|
||||
self._uids[index] = plugin_type
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
self._uids.append(uim.add_ui_from_string(ui_string))
|
||||
@@ -686,9 +706,8 @@ class ApplicationShell(object):
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
for uid in self._uids:
|
||||
|
||||
Gio.Application.get_default().remove_plugin_menu_item(self._uids[uid],
|
||||
uid)
|
||||
uid)
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
for uid in self._uids:
|
||||
@@ -713,6 +732,7 @@ class ApplicationShell(object):
|
||||
""" Delegate access to implementation """
|
||||
return setattr(self.__instance, attr, value)
|
||||
|
||||
|
||||
class Action(object):
|
||||
'''
|
||||
class that wraps around either a Gio.Action or a Gtk.Action
|
||||
@@ -851,7 +871,7 @@ class Action(object):
|
||||
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
menuitem.set_detailed_action('win.'+self.action.get_name())
|
||||
menuitem.set_detailed_action('win.' + self.action.get_name())
|
||||
else:
|
||||
menuitem.set_related_action(self.action)
|
||||
|
||||
|
||||
+28
-25
@@ -25,6 +25,7 @@ import coverart_rb3compat as rb3compat
|
||||
from coverart_album import Album
|
||||
from coverart_browser_prefs import webkit_support
|
||||
|
||||
|
||||
class CoverSearchPane(Gtk.Box):
|
||||
'''
|
||||
This UI represents a pane where different covers can be presented
|
||||
@@ -32,6 +33,7 @@ class CoverSearchPane(Gtk.Box):
|
||||
customize the default search and select covers from the pane and use them
|
||||
as the covers (either with a double click or dragging them).
|
||||
'''
|
||||
|
||||
def __init__(self, plugin, selection_color):
|
||||
'''
|
||||
Initializes the pane, loading it's html templates and it's ui.
|
||||
@@ -54,26 +56,26 @@ class CoverSearchPane(Gtk.Box):
|
||||
'''
|
||||
Loads the templates and stylesheets to be used by the pane.
|
||||
'''
|
||||
# input_encoding='utf-8',
|
||||
# input_encoding='utf-8',
|
||||
|
||||
path = rb.find_plugin_file(plugin,
|
||||
'tmpl/albumartsearch-tmpl.html')
|
||||
'tmpl/albumartsearch-tmpl.html')
|
||||
self.template = Template(filename=path,
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
path = rb.find_plugin_file(plugin,
|
||||
'tmpl/albumartsearchempty-tmpl.html')
|
||||
'tmpl/albumartsearchempty-tmpl.html')
|
||||
self.empty_template = Template(filename=path,
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
path = rb.find_plugin_file(plugin,
|
||||
'tmpl/artistartsearch-tmpl.html')
|
||||
'tmpl/artistartsearch-tmpl.html')
|
||||
self.artist_template = Template(filename=path,
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
self.styles = rb.find_plugin_file(plugin, 'tmpl/main.css')
|
||||
|
||||
def init_gui(self):
|
||||
@@ -82,6 +84,7 @@ class CoverSearchPane(Gtk.Box):
|
||||
'''
|
||||
#---- set up webkit pane -----#
|
||||
from gi.repository import WebKit
|
||||
|
||||
self.webview = WebKit.WebView()
|
||||
settings = self.webview.get_settings()
|
||||
settings.set_property('enable-default-context-menu', False)
|
||||
@@ -102,7 +105,7 @@ class CoverSearchPane(Gtk.Box):
|
||||
of the album or artist passed.
|
||||
|
||||
'''
|
||||
print ("coverart-search do_search")
|
||||
print("coverart-search do_search")
|
||||
if coverobject is self.current_searchobject:
|
||||
return
|
||||
|
||||
@@ -119,9 +122,9 @@ class CoverSearchPane(Gtk.Box):
|
||||
if artist.upper() == "UNKNOWN":
|
||||
artist = ""
|
||||
|
||||
if not(album_name == "" and artist == ""):
|
||||
if not (album_name == "" and artist == ""):
|
||||
artist = rb3compat.unicodestr(artist.replace('&', '&'),
|
||||
'utf-8')
|
||||
'utf-8')
|
||||
album_name = rb3compat.unicodestr(album_name.replace('&', '&'), 'utf-8')
|
||||
self.render_album_art_search(artist, album_name)
|
||||
else:
|
||||
@@ -130,9 +133,9 @@ class CoverSearchPane(Gtk.Box):
|
||||
if artist_name.upper() == "UNKNOWN":
|
||||
artist_name = ""
|
||||
|
||||
if not(artist_name == ""):
|
||||
if not (artist_name == ""):
|
||||
artist = rb3compat.unicodestr(artist_name.replace('&', '&'),
|
||||
'utf-8')
|
||||
'utf-8')
|
||||
self.render_artist_art_search(artist)
|
||||
|
||||
|
||||
@@ -141,22 +144,22 @@ class CoverSearchPane(Gtk.Box):
|
||||
Renders the template on the webview.
|
||||
'''
|
||||
temp_file = self.template.render(artist=artist, album=album_name,
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
|
||||
print ("here")
|
||||
print("here")
|
||||
self.webview.load_string(temp_file, 'text/html', 'utf-8',
|
||||
self.basepath)
|
||||
self.basepath)
|
||||
|
||||
def render_artist_art_search(self, artist):
|
||||
'''
|
||||
Renders the template on the webview.
|
||||
'''
|
||||
temp_file = self.artist_template.render(artist=artist,
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
|
||||
print ("here")
|
||||
print("here")
|
||||
self.webview.load_string(temp_file, 'text/html', 'utf-8',
|
||||
self.basepath)
|
||||
self.basepath)
|
||||
|
||||
def clear(self):
|
||||
'''
|
||||
@@ -166,7 +169,7 @@ class CoverSearchPane(Gtk.Box):
|
||||
temp_file = self.empty_template.render(stylesheet=self.styles)
|
||||
|
||||
self.webview.load_string(temp_file, 'text/html', 'utf-8',
|
||||
self.basepath)
|
||||
self.basepath)
|
||||
|
||||
def set_cover(self, webview, arg):
|
||||
'''
|
||||
|
||||
+23
-20
@@ -39,6 +39,7 @@ from coverart_browser_prefs import webkit_support
|
||||
|
||||
import rb
|
||||
|
||||
|
||||
class Toolbar(GObject.Object):
|
||||
def __init__(self, plugin, mainbox, controllers):
|
||||
super(Toolbar, self).__init__()
|
||||
@@ -81,7 +82,7 @@ class Toolbar(GObject.Object):
|
||||
search_entry.controller = controllers['search']
|
||||
|
||||
Theme(self.plugin).connect('theme_changed', self._theme_changed,
|
||||
controllers)
|
||||
controllers)
|
||||
|
||||
self.builder = builder.get_object('toolbar')
|
||||
|
||||
@@ -93,6 +94,7 @@ class Toolbar(GObject.Object):
|
||||
for controller in list(controllers.values()):
|
||||
controller.update_images(True)
|
||||
|
||||
|
||||
class TopToolbar(Toolbar):
|
||||
ui = 'ui/coverart_topbar.ui'
|
||||
name = 'main'
|
||||
@@ -115,11 +117,11 @@ class LeftToolbar(Toolbar):
|
||||
if self.builder.get_visible():
|
||||
self.builder.hide()
|
||||
self.plugin.shell.remove_widget(self.builder,
|
||||
RB.ShellUILocation.SIDEBAR)
|
||||
RB.ShellUILocation.SIDEBAR)
|
||||
|
||||
def show(self):
|
||||
self.plugin.shell.add_widget(self.builder,
|
||||
RB.ShellUILocation.SIDEBAR, expand=False, fill=False)
|
||||
RB.ShellUILocation.SIDEBAR, expand=False, fill=False)
|
||||
self.builder.show()
|
||||
|
||||
|
||||
@@ -131,26 +133,27 @@ class RightToolbar(Toolbar):
|
||||
if self.builder.get_visible():
|
||||
self.builder.hide()
|
||||
self.plugin.shell.remove_widget(self.builder,
|
||||
RB.ShellUILocation.RIGHT_SIDEBAR)
|
||||
RB.ShellUILocation.RIGHT_SIDEBAR)
|
||||
|
||||
def show(self):
|
||||
self.plugin.shell.add_widget(self.builder,
|
||||
RB.ShellUILocation.RIGHT_SIDEBAR, expand=False, fill=False)
|
||||
RB.ShellUILocation.RIGHT_SIDEBAR, expand=False, fill=False)
|
||||
self.builder.show()
|
||||
|
||||
|
||||
class ToolbarObject(object):
|
||||
#properties
|
||||
|
||||
PROPERTIES='properties_button'
|
||||
SORT_BY='sort_by'
|
||||
SORT_ORDER='sort_order'
|
||||
SORT_BY_ARTIST='sort_by_artist'
|
||||
SORT_ORDER_ARTIST='sort_order_artist'
|
||||
GENRE='genre_button'
|
||||
PLAYLIST='playlist_button'
|
||||
DECADE='decade_button'
|
||||
SEARCH='search'
|
||||
VIEW='view_button'
|
||||
PROPERTIES = 'properties_button'
|
||||
SORT_BY = 'sort_by'
|
||||
SORT_ORDER = 'sort_order'
|
||||
SORT_BY_ARTIST = 'sort_by_artist'
|
||||
SORT_ORDER_ARTIST = 'sort_order_artist'
|
||||
GENRE = 'genre_button'
|
||||
PLAYLIST = 'playlist_button'
|
||||
DECADE = 'decade_button'
|
||||
SEARCH = 'search'
|
||||
VIEW = 'view_button'
|
||||
|
||||
|
||||
class ToolbarManager(GObject.Object):
|
||||
@@ -166,11 +169,11 @@ class ToolbarManager(GObject.Object):
|
||||
# initialize toolbars
|
||||
self._bars = {}
|
||||
self._bars[TopToolbar.name] = TopToolbar(plugin, main_box,
|
||||
controllers)
|
||||
controllers)
|
||||
self._bars[LeftToolbar.name] = LeftToolbar(plugin, main_box,
|
||||
controllers)
|
||||
controllers)
|
||||
self._bars[RightToolbar.name] = RightToolbar(plugin, main_box,
|
||||
controllers)
|
||||
controllers)
|
||||
|
||||
self.last_toolbar_pos = None
|
||||
# connect signal and properties
|
||||
@@ -201,12 +204,12 @@ class ToolbarManager(GObject.Object):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _create_controllers(self, plugin, viewmgr):
|
||||
controllers = {}
|
||||
|
||||
album_model=viewmgr.source.album_manager.model
|
||||
album_model = viewmgr.source.album_manager.model
|
||||
controllers[ToolbarObject.PROPERTIES] = \
|
||||
PropertiesMenuController(plugin, viewmgr.source)
|
||||
controllers[ToolbarObject.SORT_BY] = \
|
||||
|
||||
+54
-35
@@ -35,14 +35,17 @@ from coverart_search_providers import lastfm_connected
|
||||
from coverart_search_providers import get_search_providers
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
class FauxTb(object):
|
||||
def __init__(self, tb_frame, tb_lineno, tb_next):
|
||||
self.tb_frame = tb_frame
|
||||
self.tb_lineno = tb_lineno
|
||||
self.tb_next = tb_next
|
||||
|
||||
|
||||
def current_stack(skip=0):
|
||||
try: 1/0
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError:
|
||||
f = sys.exc_info()[2].tb_frame
|
||||
for i in range(skip + 2):
|
||||
@@ -53,6 +56,7 @@ def current_stack(skip=0):
|
||||
f = f.f_back
|
||||
return lst
|
||||
|
||||
|
||||
def extend_traceback(tb, stack):
|
||||
"""Extend traceback with stack info."""
|
||||
head = tb
|
||||
@@ -60,17 +64,20 @@ def extend_traceback(tb, stack):
|
||||
head = FauxTb(tb_frame, tb_lineno, head)
|
||||
return head
|
||||
|
||||
|
||||
def full_exc_info():
|
||||
"""Like sys.exc_info, but includes the full traceback."""
|
||||
t, v, tb = sys.exc_info()
|
||||
full_tb = extend_traceback(tb, current_stack(1))
|
||||
return t, v, full_tb
|
||||
|
||||
|
||||
def dumpstack(message):
|
||||
''' dumps the current stack - useful of debugging
|
||||
'''
|
||||
logging.error(message, exc_info=full_exc_info())
|
||||
|
||||
|
||||
def uniquify_and_sort(iterable):
|
||||
''' Removes duplicates of an iterables and returns a list of unique
|
||||
elements.
|
||||
@@ -86,6 +93,7 @@ def uniquify_and_sort(iterable):
|
||||
|
||||
GenreType = namedtuple("GenreType", ["name", "genre_type"])
|
||||
|
||||
|
||||
class NaturalString(str):
|
||||
'''
|
||||
this class implements an object that can naturally compare
|
||||
@@ -97,7 +105,7 @@ class NaturalString(str):
|
||||
super(NaturalString, self).__init__()
|
||||
convert = lambda text: int(text) if text.isdigit() else text.lower()
|
||||
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)',
|
||||
key)]
|
||||
key)]
|
||||
|
||||
self._string_elements = alphanum_key(string)
|
||||
|
||||
@@ -298,7 +306,6 @@ class SortedCollection(object):
|
||||
|
||||
|
||||
class ReversedSortedCollection(object):
|
||||
|
||||
def __init__(self, sorted_collection):
|
||||
self._sorted_collection = sorted_collection
|
||||
|
||||
@@ -354,7 +361,6 @@ class ReversedSortedCollection(object):
|
||||
|
||||
|
||||
class IdleCallIterator(object):
|
||||
|
||||
def __init__(self, chunk, process, after=None, error=None, finish=None):
|
||||
default = lambda *_: None
|
||||
|
||||
@@ -403,6 +409,7 @@ def idle_iterator(func):
|
||||
|
||||
return iter_function
|
||||
|
||||
|
||||
class Theme:
|
||||
'''
|
||||
This class manages the theme details
|
||||
@@ -421,7 +428,7 @@ class Theme:
|
||||
'''
|
||||
__gsignals__ = {
|
||||
'theme_changed': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
# below public variables and methods that can be called for Theme
|
||||
def __init__(self, plugin):
|
||||
'''
|
||||
@@ -453,11 +460,11 @@ class Theme:
|
||||
|
||||
def _connect_properties(self):
|
||||
self.setting.bind(self.gs.PluginKey.THEME, self,
|
||||
'theme', Gio.SettingsBindFlags.GET)
|
||||
'theme', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect('notify::theme', self._on_theme_changed,
|
||||
None)
|
||||
None)
|
||||
|
||||
def _on_theme_changed(self, *args):
|
||||
self.emit('theme_changed')
|
||||
@@ -480,11 +487,11 @@ class Theme:
|
||||
""" Delegate access to implementation """
|
||||
return setattr(self.__instance, attr, value)
|
||||
|
||||
class SpriteSheet(object):
|
||||
|
||||
class SpriteSheet(object):
|
||||
def __init__(self, image, icon_width, icon_height, x_spacing, y_spacing,
|
||||
x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color=None, size=None):
|
||||
x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color=None, size=None):
|
||||
# load the image
|
||||
base_image = GdkPixbuf.Pixbuf.new_from_file(image)
|
||||
|
||||
@@ -499,15 +506,15 @@ class SpriteSheet(object):
|
||||
for y in range(0, down_dimension):
|
||||
for x in range(0, across_dimension):
|
||||
sprite = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True,
|
||||
8, icon_width, icon_height)
|
||||
8, icon_width, icon_height)
|
||||
|
||||
base_image.copy_area(x_start + (x * delta_x),
|
||||
y_start + (y * delta_y), icon_width, icon_height,
|
||||
sprite, 0, 0)
|
||||
y_start + (y * delta_y), icon_width, icon_height,
|
||||
sprite, 0, 0)
|
||||
|
||||
if size:
|
||||
sprite = sprite.scale_simple(size[0], size[1],
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
self._sprites.append(sprite)
|
||||
|
||||
@@ -517,14 +524,15 @@ class SpriteSheet(object):
|
||||
def __getitem__(self, index):
|
||||
return self._sprites[index]
|
||||
|
||||
|
||||
class ConfiguredSpriteSheet(object):
|
||||
def __init__(self, plugin, sprite_name, size=None):
|
||||
popups = rb.find_plugin_file(plugin, 'img/popups.xml')
|
||||
root = ET.parse(open(popups)).getroot()
|
||||
base = 'theme/theme[@folder_name="' + Theme(plugin).current\
|
||||
+ '"]/spritesheet[@name="' + sprite_name + '"]/'
|
||||
image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current\
|
||||
+ '/' + root.xpath(base + 'image')[0].text)
|
||||
base = 'theme/theme[@folder_name="' + Theme(plugin).current \
|
||||
+ '"]/spritesheet[@name="' + sprite_name + '"]/'
|
||||
image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current \
|
||||
+ '/' + root.xpath(base + 'image')[0].text)
|
||||
icon_width = int(root.xpath(base + 'icon')[0].attrib['width'])
|
||||
icon_height = int(root.xpath(base + 'icon')[0].attrib['height'])
|
||||
x_spacing = int(root.xpath(base + 'spacing')[0].attrib['x'])
|
||||
@@ -536,7 +544,7 @@ class ConfiguredSpriteSheet(object):
|
||||
|
||||
try:
|
||||
alpha_color = list(map(int,
|
||||
root.xpath(base + 'alpha')[0].text.split(' ')))
|
||||
root.xpath(base + 'alpha')[0].text.split(' ')))
|
||||
except:
|
||||
alpha_color = None
|
||||
|
||||
@@ -547,7 +555,7 @@ class ConfiguredSpriteSheet(object):
|
||||
lang = cl.get_locale()
|
||||
|
||||
base = sprite_name + '/' + sprite_name + \
|
||||
'[@spritesheet="' + sprite_name + '"]'
|
||||
'[@spritesheet="' + sprite_name + '"]'
|
||||
|
||||
for elem in root.xpath(base + '[not(@xml:lang)]'):
|
||||
self.names.append(elem.text)
|
||||
@@ -557,12 +565,12 @@ class ConfiguredSpriteSheet(object):
|
||||
|
||||
if (not self.locale_names) and len(lang) > 2:
|
||||
for elem in root.xpath(base + '[@xml:lang="' + \
|
||||
lang[0:2] + '"]'):
|
||||
lang[0:2] + '"]'):
|
||||
self.locale_names[elem.text] = elem.attrib['name']
|
||||
|
||||
self._sheet = SpriteSheet(image, icon_width, icon_height, x_spacing,
|
||||
y_spacing, x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color, size)
|
||||
y_spacing, x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color, size)
|
||||
|
||||
self._genre_db = RB.ExtDB(name='cb_genre')
|
||||
|
||||
@@ -581,6 +589,7 @@ class ConfiguredSpriteSheet(object):
|
||||
def keys(self):
|
||||
return self.names
|
||||
|
||||
|
||||
class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
'''
|
||||
A sprite-sheet of genres. Creates a pixbuf representation of a picture
|
||||
@@ -602,7 +611,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
|
||||
def __init__(self, plugin, sprite_name, size=None):
|
||||
super(GenreConfiguredSpriteSheet, self).__init__(plugin, sprite_name,
|
||||
size)
|
||||
size)
|
||||
self.genre_alternate = {} # contains GenreType tuples
|
||||
self._alt_icons = {}
|
||||
self._sprite_name = sprite_name
|
||||
@@ -626,7 +635,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
sprite = GdkPixbuf.Pixbuf.new_from_file(icon_location)
|
||||
if self._size:
|
||||
sprite = sprite.scale_simple(self._size[0], self._size[1],
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
self._alt_icons[str(index)] = sprite
|
||||
self.names.append(str(index))
|
||||
@@ -654,7 +663,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
# if (not self.locale_alternate) and len(lang) > 2:
|
||||
if len(lang) > 2:
|
||||
for elem in root.xpath(base + '[@xml:lang="' + \
|
||||
lang[0:2] + '"]/alt'):
|
||||
lang[0:2] + '"]/alt'):
|
||||
self.genre_alternate[GenreType(name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre']
|
||||
|
||||
def add_genre_icon(self, filename):
|
||||
@@ -675,7 +684,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
|
||||
if self._size:
|
||||
pixbuf = pixbuf.scale_simple(self._size[0], self._size[1],
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
self._alt_icons[new_genre.name] = pixbuf
|
||||
self.names.append(new_genre.name)
|
||||
@@ -731,6 +740,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
print("nothing found to amend")
|
||||
return None
|
||||
|
||||
|
||||
def get_stock_size():
|
||||
what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.BUTTON)
|
||||
|
||||
@@ -742,30 +752,38 @@ def create_pixbuf_from_file_at_size(filename, width, height):
|
||||
|
||||
if pixbuf.get_width() != width or pixbuf.get_height() != height:
|
||||
pixbuf = pixbuf.scale_simple(width, height,
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
return pixbuf
|
||||
|
||||
|
||||
'''
|
||||
class to search through a dict without case-sensitivity nor
|
||||
unicode vs string issues
|
||||
'''
|
||||
|
||||
|
||||
class CaseInsensitiveDict(collections.Mapping):
|
||||
def __init__(self, d):
|
||||
self._d = d
|
||||
self._s = dict((RB.search_fold(k), k) for k in d)
|
||||
|
||||
def __contains__(self, k):
|
||||
return RB.search_fold(k) in self._s
|
||||
|
||||
def __len__(self):
|
||||
return len(self._s)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._s)
|
||||
|
||||
def __getitem__(self, k):
|
||||
return self._d[self._s[RB.search_fold(k)]]
|
||||
|
||||
def actual_key_case(self, k):
|
||||
return self._s.get(RB.search_fold(k))
|
||||
|
||||
|
||||
def check_lastfm(force_check=False):
|
||||
'''
|
||||
check validity of lastfm connection
|
||||
@@ -776,24 +794,25 @@ def check_lastfm(force_check=False):
|
||||
'''
|
||||
|
||||
providers = get_search_providers()
|
||||
print (providers)
|
||||
print (force_check)
|
||||
print(providers)
|
||||
print(force_check)
|
||||
|
||||
if force_check or 'lastfm-search' in providers:
|
||||
connected = lastfm_connected()
|
||||
print (connected)
|
||||
print(connected)
|
||||
return connected
|
||||
elif not 'lastfm-search' in providers:
|
||||
print ("not lastm-search")
|
||||
print("not lastm-search")
|
||||
return True
|
||||
else:
|
||||
print ("returning default")
|
||||
print("returning default")
|
||||
return False
|
||||
|
||||
|
||||
def create_button_image(plugin, icon_name):
|
||||
'create a pixbuf for the given icon_name sized according to the stock icon size'
|
||||
path = 'img/'
|
||||
|
||||
return create_pixbuf_from_file_at_size(
|
||||
rb.find_plugin_file(plugin, path + icon_name),
|
||||
*get_stock_size())
|
||||
rb.find_plugin_file(plugin, path + icon_name),
|
||||
*get_stock_size())
|
||||
|
||||
+57
-53
@@ -30,9 +30,11 @@ from coverart_browser_prefs import GSetting
|
||||
|
||||
import rb
|
||||
|
||||
|
||||
def enum(**enums):
|
||||
return type('Enum', (object,), enums)
|
||||
|
||||
|
||||
class OptionsWidget(Gtk.Widget):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OptionsWidget, self).__init__(*args, **kwargs)
|
||||
@@ -54,7 +56,7 @@ class OptionsWidget(Gtk.Widget):
|
||||
|
||||
# connect signals
|
||||
self._options_changed_id = self._controller.connect('notify::options',
|
||||
self._update_options)
|
||||
self._update_options)
|
||||
self._current_key_changed_id = self._controller.connect(
|
||||
'notify::current-key', self._update_current_key)
|
||||
self._update_image_changed_id = self._controller.connect(
|
||||
@@ -107,7 +109,7 @@ class OptionsWidget(Gtk.Widget):
|
||||
|
||||
allocation = self.get_allocation()
|
||||
|
||||
ret, x,y = window.get_origin()
|
||||
ret, x, y = window.get_origin()
|
||||
x += allocation.x
|
||||
y += allocation.y
|
||||
|
||||
@@ -123,12 +125,12 @@ class OptionsWidget(Gtk.Widget):
|
||||
|
||||
return x, y
|
||||
|
||||
class OptionsPopupWidget(OptionsWidget):
|
||||
|
||||
class OptionsPopupWidget(OptionsWidget):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
OptionsWidget.__init__(self, *args, **kwargs)
|
||||
@@ -202,10 +204,10 @@ class OptionsPopupWidget(OptionsWidget):
|
||||
|
||||
if align:
|
||||
self._popup_menu.popup(None, None, self._popup_callback, self, 0,
|
||||
Gtk.get_current_event_time())
|
||||
Gtk.get_current_event_time())
|
||||
else:
|
||||
self._popup_menu.popup(None, None, None, None, 0,
|
||||
Gtk.get_current_event_time())
|
||||
Gtk.get_current_event_time())
|
||||
|
||||
def do_delete_thyself(self):
|
||||
self.clear_popupmenu()
|
||||
@@ -213,7 +215,6 @@ class OptionsPopupWidget(OptionsWidget):
|
||||
|
||||
|
||||
class EnhancedButton(Gtk.ToggleButton):
|
||||
|
||||
button_relief = GObject.property(type=bool, default=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -222,10 +223,10 @@ class EnhancedButton(Gtk.ToggleButton):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.BUTTON_RELIEF, self,
|
||||
'button_relief', Gio.SettingsBindFlags.GET)
|
||||
'button_relief', Gio.SettingsBindFlags.GET)
|
||||
|
||||
self.connect('notify::button-relief',
|
||||
self.on_notify_button_relief)
|
||||
self.on_notify_button_relief)
|
||||
|
||||
def on_notify_button_relief(self, *arg):
|
||||
if self.button_relief:
|
||||
@@ -235,7 +236,6 @@ class EnhancedButton(Gtk.ToggleButton):
|
||||
|
||||
|
||||
class PixbufButton(EnhancedButton):
|
||||
|
||||
button_relief = GObject.property(type=bool, default=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -260,7 +260,7 @@ class PixbufButton(EnhancedButton):
|
||||
transparent alpha blend on it."""
|
||||
pixbuf = pixbuf.copy()
|
||||
|
||||
w,h = pixbuf.get_width(), pixbuf.get_height()
|
||||
w, h = pixbuf.get_width(), pixbuf.get_height()
|
||||
surface = cairo.ImageSurface(
|
||||
cairo.FORMAT_ARGB32, pixbuf.get_width(), pixbuf.get_height())
|
||||
context = cairo.Context(surface)
|
||||
@@ -284,7 +284,7 @@ class PopupButton(PixbufButton, OptionsPopupWidget):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
'''
|
||||
@@ -293,7 +293,7 @@ class PopupButton(PixbufButton, OptionsPopupWidget):
|
||||
PixbufButton.__init__(self, *args, **kwargs)
|
||||
OptionsPopupWidget.__init__(self, *args, **kwargs)
|
||||
|
||||
self._popup_menu.attach_to_widget(self, None) #critical to ensure theming works
|
||||
self._popup_menu.attach_to_widget(self, None) #critical to ensure theming works
|
||||
self._popup_menu.connect('deactivate', self.popup_deactivate)
|
||||
|
||||
# initialise some variables
|
||||
@@ -322,13 +322,14 @@ class PopupButton(PixbufButton, OptionsPopupWidget):
|
||||
self.show_popup()
|
||||
self.set_active(True)
|
||||
|
||||
|
||||
class TextPopupButton(EnhancedButton, OptionsPopupWidget):
|
||||
__gtype_name__ = "TextPopupButton"
|
||||
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
'''
|
||||
@@ -337,7 +338,7 @@ class TextPopupButton(EnhancedButton, OptionsPopupWidget):
|
||||
EnhancedButton.__init__(self, *args, **kwargs)
|
||||
OptionsPopupWidget.__init__(self, *args, **kwargs)
|
||||
|
||||
self._popup_menu.attach_to_widget(self, None) #critical to ensure theming works
|
||||
self._popup_menu.attach_to_widget(self, None) #critical to ensure theming works
|
||||
self._popup_menu.connect('deactivate', self.popup_deactivate)
|
||||
|
||||
# initialise some variables
|
||||
@@ -362,7 +363,7 @@ class MenuButton(PixbufButton, OptionsPopupWidget):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
'''
|
||||
@@ -371,7 +372,7 @@ class MenuButton(PixbufButton, OptionsPopupWidget):
|
||||
PixbufButton.__init__(self, *args, **kwargs)
|
||||
OptionsPopupWidget.__init__(self, *args, **kwargs)
|
||||
|
||||
self._popup_menu.attach_to_widget(self, None) #critical to ensure theming works
|
||||
self._popup_menu.attach_to_widget(self, None) #critical to ensure theming works
|
||||
self._popup_menu.connect('deactivate', self.popup_deactivate)
|
||||
self._states = {}
|
||||
|
||||
@@ -484,8 +485,8 @@ class ImageToggleButton(PixbufButton, OptionsWidget):
|
||||
|
||||
|
||||
class ImageRadioButton(Gtk.RadioButton, OptionsWidget):
|
||||
# this is legacy code that will not as yet work with
|
||||
# the new toolbar - consider removing this later
|
||||
# this is legacy code that will not as yet work with
|
||||
# the new toolbar - consider removing this later
|
||||
|
||||
__gtype_name__ = "ImageRadioButton"
|
||||
|
||||
@@ -501,10 +502,10 @@ class ImageRadioButton(Gtk.RadioButton, OptionsWidget):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.BUTTON_RELIEF, self,
|
||||
'button_relief', Gio.SettingsBindFlags.GET)
|
||||
'button_relief', Gio.SettingsBindFlags.GET)
|
||||
|
||||
self.connect('notify::button-relief',
|
||||
self.on_notify_button_relief)
|
||||
self.on_notify_button_relief)
|
||||
|
||||
# initialise some variables
|
||||
self.image_display = False
|
||||
@@ -545,9 +546,10 @@ class ImageRadioButton(Gtk.RadioButton, OptionsWidget):
|
||||
def update_current_key(self):
|
||||
# update the current image and tooltip
|
||||
#self.set_image(self._controller.get_current_image(Gtk.Buildable.get_name(self)))
|
||||
self.set_tooltip_text("") #self._controller.get_current_description())
|
||||
self.set_tooltip_text("") #self._controller.get_current_description())
|
||||
|
||||
from gi.repository import Gdk
|
||||
|
||||
if self.controller.current_key == Gtk.Buildable.get_name(self):
|
||||
self.set_active(True)
|
||||
self._set_colour(Gtk.StateFlags.NORMAL)
|
||||
@@ -571,18 +573,19 @@ class ImageRadioButton(Gtk.RadioButton, OptionsWidget):
|
||||
if not self._active_colour:
|
||||
self._active_colour = get_standard_colour(label0, Gtk.StateFlags.NORMAL)
|
||||
|
||||
if state_flag == Gtk.StateFlags.INSENSITIVE:
|
||||
if state_flag == Gtk.StateFlags.INSENSITIVE:
|
||||
label0.override_color(Gtk.StateType.NORMAL, self._not_active_colour)
|
||||
else:
|
||||
label0.override_color(Gtk.StateType.NORMAL, self._active_colour)
|
||||
|
||||
|
||||
class SearchEntry(RB.SearchEntry, OptionsPopupWidget):
|
||||
__gtype_name__ = "SearchEntry"
|
||||
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
RB.SearchEntry.__init__(self, *args, **kwargs)
|
||||
@@ -637,7 +640,7 @@ class QuickSearchEntry(Gtk.Frame):
|
||||
__gsignals__ = {
|
||||
'quick-search': (GObject.SIGNAL_RUN_LAST, None, (str,)),
|
||||
'arrow-pressed': (GObject.SIGNAL_RUN_LAST, None, (object,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(QuickSearchEntry, self).__init__(*args, **kwargs)
|
||||
@@ -645,7 +648,7 @@ class QuickSearchEntry(Gtk.Frame):
|
||||
|
||||
# text entry for the quick search input
|
||||
text_entry = Gtk.Entry(halign='center', valign='center',
|
||||
margin=5)
|
||||
margin=5)
|
||||
|
||||
self.add(text_entry)
|
||||
|
||||
@@ -677,7 +680,7 @@ class QuickSearchEntry(Gtk.Frame):
|
||||
return False
|
||||
|
||||
Gdk.threads_add_timeout_seconds(GLib.PRIORITY_DEFAULT_IDLE, 4,
|
||||
hide_on_timeout, None)
|
||||
hide_on_timeout, None)
|
||||
|
||||
def do_parent_set(self, old_parent, *args):
|
||||
if old_parent:
|
||||
@@ -685,12 +688,12 @@ class QuickSearchEntry(Gtk.Frame):
|
||||
|
||||
parent = self.get_parent()
|
||||
self._on_parent_key_press_id = parent.connect('key-press-event',
|
||||
self._on_parent_key_press, self.get_child())
|
||||
self._on_parent_key_press, self.get_child())
|
||||
|
||||
def _on_parent_key_press(self, parent, event, entry):
|
||||
if not self.get_visible() and \
|
||||
event.keyval not in [Gdk.KEY_Shift_L, Gdk.KEY_Shift_R,
|
||||
Gdk.KEY_Control_L, Gdk.KEY_Control_R, Gdk.KEY_Escape]:
|
||||
event.keyval not in [Gdk.KEY_Shift_L, Gdk.KEY_Shift_R,
|
||||
Gdk.KEY_Control_L, Gdk.KEY_Control_R, Gdk.KEY_Escape]:
|
||||
# grab focus, redirect the pressed key and make the quick search
|
||||
# entry visible
|
||||
entry.set_text('')
|
||||
@@ -758,12 +761,11 @@ class ProxyPopupButton(Gtk.Frame):
|
||||
|
||||
|
||||
class OptionsListViewWidget(OptionsWidget):
|
||||
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,)),
|
||||
'deactivate': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
OptionsWidget.__init__(self, *args, **kwargs)
|
||||
@@ -773,7 +775,7 @@ class OptionsListViewWidget(OptionsWidget):
|
||||
def controller(self, controller):
|
||||
ui = Gtk.Builder()
|
||||
ui.add_from_file(rb.find_plugin_file(controller.plugin,
|
||||
'ui/coverart_listwindow.ui'))
|
||||
'ui/coverart_listwindow.ui'))
|
||||
ui.connect_signals(self)
|
||||
self._listwindow = ui.get_object('listwindow')
|
||||
self._liststore = ui.get_object('liststore')
|
||||
@@ -838,10 +840,10 @@ class OptionsListViewWidget(OptionsWidget):
|
||||
if self._increment:
|
||||
if button is self._scrolldown_button:
|
||||
adjustment.set_value(adjustment.get_value()
|
||||
+ self._step)
|
||||
+ self._step)
|
||||
else:
|
||||
adjustment.set_value(adjustment.get_value()
|
||||
- self._step)
|
||||
- self._step)
|
||||
|
||||
return self._increment
|
||||
|
||||
@@ -851,7 +853,7 @@ class OptionsListViewWidget(OptionsWidget):
|
||||
self.on_scroll_button_released()
|
||||
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 50,
|
||||
scroll, None)
|
||||
scroll, None)
|
||||
|
||||
def on_scroll_button_leave(self, *args):
|
||||
self._increment = False
|
||||
@@ -884,7 +886,7 @@ class ListViewButton(PixbufButton, OptionsListViewWidget):
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (str,)),
|
||||
'deactivate': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
'''
|
||||
@@ -934,9 +936,9 @@ class EnhancedIconView(Gtk.IconView):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'item-clicked': (GObject.SIGNAL_RUN_LAST, None, (object, object))
|
||||
}
|
||||
}
|
||||
|
||||
object_column = GObject.property(type=int, default= -1)
|
||||
object_column = GObject.property(type=int, default=-1)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EnhancedIconView, self).__init__(*args, **kwargs)
|
||||
@@ -957,7 +959,7 @@ class EnhancedIconView(Gtk.IconView):
|
||||
# don't need to reaccommodate if it's a vertical change
|
||||
self._reallocate_count += 1
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 500,
|
||||
self._reallocate_columns, None)
|
||||
self._reallocate_columns, None)
|
||||
|
||||
Gtk.IconView.do_size_allocate(self, allocation)
|
||||
|
||||
@@ -983,7 +985,7 @@ class EnhancedIconView(Gtk.IconView):
|
||||
# if the item being clicked isn't selected, we should clear
|
||||
# the current selection
|
||||
if len(self.get_selected_objects()) > 0 and \
|
||||
not self.path_is_selected(current_path):
|
||||
not self.path_is_selected(current_path):
|
||||
self.unselect_all()
|
||||
|
||||
self.select_path(current_path)
|
||||
@@ -1011,7 +1013,7 @@ class EnhancedIconView(Gtk.IconView):
|
||||
|
||||
model = self.get_model()
|
||||
selected_objects = list(reversed([model[selected][self.object_column]
|
||||
for selected in selected_items]))
|
||||
for selected in selected_items]))
|
||||
|
||||
return selected_objects
|
||||
|
||||
@@ -1048,7 +1050,7 @@ class PanedCollapsible(Gtk.Paned):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'expanded': (GObject.SIGNAL_RUN_LAST, None, (bool,))
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PanedCollapsible, self).__init__(*args, **kwargs)
|
||||
@@ -1059,7 +1061,7 @@ class PanedCollapsible(Gtk.Paned):
|
||||
self.connect('notify::collapsible1', self._on_collapsible1_changed)
|
||||
self.connect('notify::collapsible2', self._on_collapsible2_changed)
|
||||
self.connect('notify::collapsible_label',
|
||||
self._on_collapsible_label_changed)
|
||||
self._on_collapsible_label_changed)
|
||||
|
||||
def _on_collapsible1_changed(self, *args):
|
||||
if self.collapsible1 and self.collapsible2:
|
||||
@@ -1072,7 +1074,7 @@ class PanedCollapsible(Gtk.Paned):
|
||||
|
||||
def _on_collapsible2_changed(self, *args):
|
||||
if self.collapsible1 and self.collapsible2:
|
||||
# check consistency, only one collapsible at a time
|
||||
# check consistency, only one collapsible at a time
|
||||
self.collapsible1 = False
|
||||
|
||||
child = self.get_child2()
|
||||
@@ -1193,16 +1195,16 @@ class PanedCollapsible(Gtk.Paned):
|
||||
|
||||
def _create_expander(self, widget):
|
||||
self._expander = Gtk.Expander(label=self.collapsible_label,
|
||||
visible=True)
|
||||
visible=True)
|
||||
self._expander.add(widget)
|
||||
|
||||
# connect the expanded signal
|
||||
self._expander.connect('notify::expanded',
|
||||
self._on_collapsible_expanded)
|
||||
self._on_collapsible_expanded)
|
||||
|
||||
# connect the initial collapse
|
||||
self._allocate_id = self._expander.connect('size-allocate',
|
||||
self._initial_collapse)
|
||||
self._initial_collapse)
|
||||
|
||||
return self._expander
|
||||
|
||||
@@ -1213,8 +1215,8 @@ class PanedCollapsible(Gtk.Paned):
|
||||
|
||||
def _collapse(self):
|
||||
new_y = self.get_allocated_height() - \
|
||||
self.get_handle_window().get_height() - \
|
||||
self._expander.get_label_widget().get_allocated_height()
|
||||
self.get_handle_window().get_height() - \
|
||||
self._expander.get_label_widget().get_allocated_height()
|
||||
|
||||
self.set_position(new_y)
|
||||
|
||||
@@ -1228,7 +1230,7 @@ class PanedCollapsible(Gtk.Paned):
|
||||
self._expander.set_expanded(True)
|
||||
elif force == PanedCollapsible.Paned.COLLAPSE:
|
||||
self._expander.set_expanded(False)
|
||||
elif force==PanedCollapsible.Paned.DEFAULT:
|
||||
elif force == PanedCollapsible.Paned.DEFAULT:
|
||||
self._expander.set_expanded(not self._expander.get_expanded())
|
||||
|
||||
def get_expansion_status(self):
|
||||
@@ -1241,6 +1243,7 @@ class PanedCollapsible(Gtk.Paned):
|
||||
|
||||
return value
|
||||
|
||||
|
||||
class AbstractView(GObject.Object):
|
||||
'''
|
||||
intention is to document 'the must have' methods all views should define
|
||||
@@ -1255,7 +1258,7 @@ class AbstractView(GObject.Object):
|
||||
# where abstractview is part of multiple inheritance
|
||||
__gsignals__ = {
|
||||
'update-toolbar': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super(AbstractView, self).__init__()
|
||||
@@ -1272,6 +1275,7 @@ class AbstractView(GObject.Object):
|
||||
by default the toolbar objects are made visible
|
||||
'''
|
||||
from coverart_toolbar import ToolbarObject
|
||||
|
||||
self.source.toolbar_manager.set_enabled(True, ToolbarObject.SORT_BY)
|
||||
self.source.toolbar_manager.set_enabled(True, ToolbarObject.SORT_ORDER)
|
||||
self.source.toolbar_manager.set_enabled(False, ToolbarObject.SORT_BY_ARTIST)
|
||||
@@ -1360,5 +1364,5 @@ class AbstractView(GObject.Object):
|
||||
if selected:
|
||||
manager = self.get_default_manager()
|
||||
cover_search_pane.do_search(selected[0],
|
||||
manager.cover_man.update_cover)
|
||||
manager.cover_man.update_cover)
|
||||
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
import gi
|
||||
from gi.repository import Pango
|
||||
from gi.repository import Gtk
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
|
||||
import logging
|
||||
|
||||
+13
-15
@@ -57,6 +57,7 @@ class ShapeStar():
|
||||
coords = []
|
||||
|
||||
from math import cos, pi, sin
|
||||
|
||||
step = pi / points
|
||||
|
||||
for i in range(2 * points):
|
||||
@@ -72,7 +73,7 @@ class ShapeStar():
|
||||
|
||||
def layout(self, cr, x, y, w, h):
|
||||
points = [(sx_sy[0] * w + x, sx_sy[1] * h + y)
|
||||
for sx_sy in self.coords]
|
||||
for sx_sy in self.coords]
|
||||
cr.move_to(*points[0])
|
||||
|
||||
for p in points[1:]:
|
||||
@@ -82,7 +83,6 @@ class ShapeStar():
|
||||
|
||||
|
||||
class StarRenderer(ShapeStar):
|
||||
|
||||
def __init__(self):
|
||||
ShapeStar.__init__(self, 5, 0.6)
|
||||
|
||||
@@ -107,7 +107,7 @@ class StarRenderer(ShapeStar):
|
||||
|
||||
# public
|
||||
def create_normal_surfaces(self,
|
||||
context, vis_width, vis_height, star_width):
|
||||
context, vis_width, vis_height, star_width):
|
||||
|
||||
rgba1 = context.get_border_color(Gtk.StateFlags.NORMAL)
|
||||
rgba0 = context.get_color(Gtk.StateFlags.ACTIVE)
|
||||
@@ -118,7 +118,7 @@ class StarRenderer(ShapeStar):
|
||||
|
||||
# paint full
|
||||
full_surf = cairo.ImageSurface(
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
|
||||
cr = cairo.Context(full_surf)
|
||||
cr.set_source(lin)
|
||||
@@ -136,7 +136,7 @@ class StarRenderer(ShapeStar):
|
||||
|
||||
# paint empty
|
||||
empty_surf = cairo.ImageSurface(
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
|
||||
cr = cairo.Context(empty_surf)
|
||||
cr.set_source(lin)
|
||||
@@ -154,11 +154,11 @@ class StarRenderer(ShapeStar):
|
||||
return full_surf, empty_surf
|
||||
|
||||
def create_reactive_surfaces(self,
|
||||
context, vis_width, vis_height, star_width):
|
||||
context, vis_width, vis_height, star_width):
|
||||
|
||||
# paint full
|
||||
full_surf = cairo.ImageSurface(
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
|
||||
cr = cairo.Context(full_surf)
|
||||
if self.rounded:
|
||||
@@ -196,7 +196,7 @@ class StarRenderer(ShapeStar):
|
||||
|
||||
# paint empty
|
||||
empty_surf = cairo.ImageSurface(
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
cairo.FORMAT_ARGB32, vis_width, vis_height)
|
||||
|
||||
cr = cairo.Context(empty_surf)
|
||||
if self.rounded:
|
||||
@@ -230,8 +230,8 @@ class StarRenderer(ShapeStar):
|
||||
|
||||
elif self.hints == StarRenderHints.REACTIVE:
|
||||
surfs = self.create_reactive_surfaces(
|
||||
context, vis_width,
|
||||
vis_height, star_width)
|
||||
context, vis_width,
|
||||
vis_height, star_width)
|
||||
|
||||
# dict keys
|
||||
full_key, empty_key = self._get_mangled_keys(size)
|
||||
@@ -319,13 +319,13 @@ class Star(Gtk.EventBox, StarRenderer):
|
||||
self.yalign = yalign
|
||||
self.queue_draw()
|
||||
|
||||
#~ def set_padding(*args):
|
||||
#~ def set_padding(*args):
|
||||
#~ return
|
||||
|
||||
def get_alignment(self):
|
||||
return self.xalign, self.yalign
|
||||
|
||||
#~ def get_padding(*args):
|
||||
#~ def get_padding(*args):
|
||||
#~ return
|
||||
|
||||
def on_style_updated(self, widget):
|
||||
@@ -396,7 +396,6 @@ class Star(Gtk.EventBox, StarRenderer):
|
||||
|
||||
|
||||
class StarRatingsWidget(Gtk.HBox):
|
||||
|
||||
def __init__(self):
|
||||
Gtk.Box.__init__(self)
|
||||
self.set_spacing(StockEms.SMALL)
|
||||
@@ -423,12 +422,11 @@ class StarRatingsWidget(Gtk.HBox):
|
||||
|
||||
|
||||
class ReactiveStar(Star):
|
||||
|
||||
__gsignals__ = {
|
||||
"changed": (GObject.SignalFlags.RUN_LAST,
|
||||
None,
|
||||
(),)
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, size=StarSize.SMALL):
|
||||
Star.__init__(self, size)
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário