850 linhas
28 KiB
Python
850 linhas
28 KiB
Python
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
|
#
|
|
# Copyright (C) 2012 - fossfreedom
|
|
# Copyright (C) 2012 - Agustin Carrasco
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2, or (at your option)
|
|
# any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
from datetime import date
|
|
from collections import OrderedDict
|
|
from collections import namedtuple
|
|
|
|
from gi.repository import GObject
|
|
from gi.repository import Gdk
|
|
from gi.repository import RB
|
|
from gi.repository import Gio
|
|
from gi.repository import GLib
|
|
|
|
from coverart_browser_prefs import CoverLocale
|
|
from coverart_browser_prefs import GSetting
|
|
from coverart_utils import create_pixbuf_from_file_at_size
|
|
from coverart_utils import GenreConfiguredSpriteSheet
|
|
from coverart_utils import ConfiguredSpriteSheet
|
|
from coverart_utils import get_stock_size
|
|
from coverart_utils import CaseInsensitiveDict
|
|
from coverart_utils import Theme
|
|
import rb
|
|
|
|
|
|
MenuNodeT = namedtuple('MenuNode', 'label menutype typevalue')
|
|
|
|
|
|
def MenuNode(label, menutype=None, typevalue=None):
|
|
return MenuNodeT(label, menutype, typevalue)
|
|
|
|
|
|
class OptionsController(GObject.Object):
|
|
# properties
|
|
options = GObject.property(type=object, default=None)
|
|
current_key = GObject.property(type=str, default=None)
|
|
update_image = GObject.property(type=bool, default=False)
|
|
enabled = GObject.property(type=bool, default=True)
|
|
|
|
def __init__(self):
|
|
super(OptionsController, self).__init__()
|
|
|
|
# connect the variations on the current key to the controllers action
|
|
self.connect('notify::current-key', self._do_action)
|
|
|
|
def get_current_key_index(self):
|
|
return self.options.index(self.current_key)
|
|
|
|
def option_selected(self, key):
|
|
if key != self.current_key:
|
|
# update the current value
|
|
self.current_key = key
|
|
|
|
def _do_action(self, *args):
|
|
self.do_action()
|
|
|
|
def do_action(self):
|
|
pass
|
|
|
|
def get_current_image(self):
|
|
return None
|
|
|
|
def get_current_description(self):
|
|
return self.current_key
|
|
|
|
def update_images(self, *args):
|
|
pass
|
|
|
|
def create_spritesheet(self, plugin, sheet, typestr):
|
|
'''
|
|
helper function to create a specific spritesheet
|
|
'''
|
|
if sheet:
|
|
del sheet
|
|
|
|
return ConfiguredSpriteSheet(plugin, typestr, get_stock_size())
|
|
|
|
def create_button_image(self, plugin, image, icon_name):
|
|
'''
|
|
helper function to create a button image
|
|
'''
|
|
if image:
|
|
del image
|
|
|
|
path = 'img/' + Theme(self.plugin).current + '/'
|
|
|
|
return create_pixbuf_from_file_at_size(
|
|
rb.find_plugin_file(self.plugin, path + icon_name),
|
|
*get_stock_size())
|
|
|
|
|
|
class PlaylistPopupController(OptionsController):
|
|
def __init__(self, plugin, album_model):
|
|
super(PlaylistPopupController, self).__init__()
|
|
|
|
self._album_model = album_model
|
|
|
|
shell = plugin.shell
|
|
self.plugin = plugin
|
|
|
|
# get the library name and initialize the superclass with it
|
|
self._library_name = shell.props.library_source.props.name
|
|
|
|
# get the queue name
|
|
self._queue_name = shell.props.queue_source.props.name
|
|
|
|
if " (" in self._queue_name:
|
|
self._queue_name = self._queue_name[0:self._queue_name.find(" (")]
|
|
|
|
self._spritesheet = None
|
|
self._update_options(shell)
|
|
|
|
# get the playlist model so we can monitor changes
|
|
playlist_model = shell.props.display_page_model
|
|
|
|
# connect signals to update playlists
|
|
playlist_model.connect('row-inserted', self._update_options, shell)
|
|
playlist_model.connect('row-deleted', self._update_options, shell)
|
|
playlist_model.connect('row-changed', self._update_options, shell)
|
|
|
|
def update_images(self, *args):
|
|
self._spritesheet = self.create_spritesheet(self.plugin,
|
|
self._spritesheet, 'playlist')
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def _update_options(self, *args):
|
|
shell = args[-1]
|
|
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
|
|
|
|
# retrieve the options
|
|
values = OrderedDict()
|
|
|
|
# library and play queue sources
|
|
values[self._library_name] = None
|
|
values[self._queue_name] = shell.props.queue_source
|
|
|
|
# playlists
|
|
playlists_entries = playlist_manager.get_playlists()
|
|
|
|
for playlist in playlists_entries:
|
|
if playlist.props.is_local:
|
|
name = playlist.props.name
|
|
values[name] = playlist
|
|
|
|
still_exists = still_exists or name == self.current_key
|
|
|
|
self.values = values
|
|
self.options = list(values.keys())
|
|
|
|
self.current_key = self.current_key if still_exists else \
|
|
self._library_name
|
|
|
|
def do_action(self):
|
|
playlist = self.values[self.current_key]
|
|
|
|
if not playlist:
|
|
self._album_model.remove_filter('model')
|
|
else:
|
|
self._album_model.replace_filter('model',
|
|
playlist.get_query_model())
|
|
|
|
def get_current_image(self):
|
|
playlist = self.values[self.current_key]
|
|
|
|
if self.current_key == self._library_name:
|
|
image = self._spritesheet['music']
|
|
elif self._queue_name in self.current_key:
|
|
image = self._spritesheet['queue']
|
|
elif isinstance(playlist, RB.StaticPlaylistSource):
|
|
image = self._spritesheet['playlist']
|
|
else:
|
|
image = self._spritesheet['smart']
|
|
|
|
return image
|
|
|
|
|
|
class GenrePopupController(OptionsController):
|
|
# properties
|
|
new_genre_icon = GObject.property(type=bool, default=False)
|
|
|
|
def __init__(self, plugin, album_model):
|
|
super(GenrePopupController, self).__init__()
|
|
|
|
cl = CoverLocale()
|
|
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
|
|
|
self._album_model = album_model
|
|
|
|
shell = plugin.shell
|
|
self.plugin = plugin
|
|
|
|
# create a new property model for the genres
|
|
genres_model = RB.RhythmDBPropertyModel.new(shell.props.db,
|
|
RB.RhythmDBPropType.GENRE)
|
|
|
|
query = shell.props.library_source.props.base_query_model
|
|
genres_model.props.query_model = query
|
|
|
|
# initial genre
|
|
self._initial_genre = _('All Genres')
|
|
|
|
self._spritesheet = None
|
|
self._default_image = None
|
|
self._unrecognised_image = None
|
|
|
|
self._connect_properties()
|
|
self._connect_signals(query, genres_model)
|
|
|
|
# generate initial popup
|
|
self._update_options(genres_model)
|
|
|
|
def update_images(self, *args):
|
|
if self._spritesheet:
|
|
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')
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def _connect_signals(self, query, genres_model):
|
|
# connect signals to update genres
|
|
self.connect('notify::new-genre-icon', self._update_options, genres_model)
|
|
query.connect('row-inserted', self._update_options, genres_model)
|
|
query.connect('row-deleted', self._update_options, genres_model)
|
|
query.connect('row-changed', self._update_options, genres_model)
|
|
|
|
def _connect_properties(self):
|
|
gs = GSetting()
|
|
setting = gs.get_setting(gs.Path.PLUGIN)
|
|
|
|
setting.bind(gs.PluginKey.NEW_GENRE_ICON, self, 'new_genre_icon',
|
|
Gio.SettingsBindFlags.GET)
|
|
|
|
def _update_options(self, *args):
|
|
genres_model = args[-1]
|
|
|
|
self.update_images(False)
|
|
|
|
still_exists = False
|
|
|
|
# retrieve the options
|
|
options = []
|
|
row_num = 0
|
|
for row in genres_model:
|
|
if row_num == 0:
|
|
cl = CoverLocale()
|
|
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
|
genre = _('All Genres')
|
|
row_num = row_num + 1
|
|
else:
|
|
genre = row[0]
|
|
|
|
options.append(genre)
|
|
|
|
still_exists = still_exists or genre == self.current_key
|
|
|
|
self.options = options
|
|
|
|
self.current_key = self.current_key if still_exists else \
|
|
self._initial_genre
|
|
|
|
def do_action(self):
|
|
'''
|
|
called when genre popup menu item chosen
|
|
return None if the first entry in popup returned
|
|
'''
|
|
if self.current_key == self._initial_genre:
|
|
self._album_model.remove_filter('genre')
|
|
else:
|
|
self._album_model.replace_filter('genre', self.current_key)
|
|
|
|
def get_current_image(self):
|
|
test_genre = self.current_key.lower()
|
|
|
|
if test_genre == self._initial_genre.lower():
|
|
image = self._default_image
|
|
else:
|
|
image = self._find_alternates(test_genre)
|
|
|
|
if image == self._unrecognised_image and \
|
|
test_genre in self._spritesheet:
|
|
image = self._spritesheet[test_genre]
|
|
|
|
return image
|
|
|
|
def _find_alternates(self, test_genre):
|
|
# the following genre checks are required
|
|
# 1. if we have user defined genres
|
|
# 2. then check locale specific system genres
|
|
# 3. then check local specific alternates
|
|
# 4. then check if we system genres
|
|
|
|
# where necessary check if any of the genres are a substring
|
|
# of test_genre - check in reverse order so that we
|
|
# test largest strings first (prevents spurious matches with
|
|
# short strings)
|
|
# N.B. we use RB.search_fold since the strings can be
|
|
# in a mixture of cases, both unicode (normalized or not) and str
|
|
# and as usual python cannot mix and match these types.
|
|
|
|
|
|
test_genre = RB.search_fold(test_genre)
|
|
|
|
ret, sprite = self._match_genres(test_genre, self._spritesheet.GENRE_USER)
|
|
if ret:
|
|
return sprite
|
|
|
|
for genre in sorted(self._spritesheet.locale_names,
|
|
key=lambda b: (-len(b), b)):
|
|
if RB.search_fold(genre) in test_genre:
|
|
return self._spritesheet[self._spritesheet.locale_names[genre]]
|
|
|
|
# next check locale alternates
|
|
ret, sprite = self._match_genres(test_genre, self._spritesheet.GENRE_LOCALE)
|
|
if ret:
|
|
return sprite
|
|
|
|
ret, sprite = self._match_genres(test_genre, self._spritesheet.GENRE_SYSTEM)
|
|
if ret:
|
|
return sprite
|
|
|
|
# check if any of the default genres are a substring
|
|
# of test_genre - check in reverse order so that we
|
|
# test largest strings first (prevents spurious matches with
|
|
# short strings)
|
|
for genre in sorted(self._spritesheet.names,
|
|
key=lambda b: (-len(b), b)):
|
|
if RB.search_fold(genre) in test_genre:
|
|
return self._spritesheet[genre]
|
|
|
|
# if no matches then default to unrecognised image
|
|
return self._unrecognised_image
|
|
|
|
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 test_genre in case_search:
|
|
return (True, self._spritesheet[case_search[test_genre]])
|
|
else:
|
|
return (False, None)
|
|
|
|
|
|
def get_current_description(self):
|
|
cl = CoverLocale()
|
|
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
|
if self.current_key == self._initial_genre:
|
|
return _('All Genres')
|
|
else:
|
|
return self.current_key
|
|
|
|
|
|
class SortPopupController(OptionsController):
|
|
def __init__(self, plugin, viewmgr):
|
|
super(SortPopupController, self).__init__()
|
|
|
|
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')])
|
|
|
|
self.options = list(self.values.keys())
|
|
|
|
# get the current sort key and initialise the superclass
|
|
gs = GSetting()
|
|
source_settings = gs.get_setting(gs.Path.PLUGIN)
|
|
value = source_settings[gs.PluginKey.SORT_BY]
|
|
|
|
self._spritesheet = None
|
|
self.update_images(False)
|
|
|
|
self.current_key = list(self.values.keys())[
|
|
list(self.values.values()).index(value)]
|
|
|
|
def update_images(self, *args):
|
|
self._spritesheet = self.create_spritesheet(self.plugin,
|
|
self._spritesheet, 'sort')
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def do_action(self):
|
|
sort = self.values[self.current_key]
|
|
|
|
gs = GSetting()
|
|
settings = gs.get_setting(gs.Path.PLUGIN)
|
|
settings[gs.PluginKey.SORT_BY] = sort
|
|
|
|
self._viewmgr.current_view.get_default_manager().emit('sort', "album")
|
|
|
|
def get_current_image(self):
|
|
sort = self.values[self.current_key]
|
|
return self._spritesheet[sort]
|
|
|
|
|
|
class ArtistSortPopupController(OptionsController):
|
|
def __init__(self, plugin, viewmgr):
|
|
super(ArtistSortPopupController, self).__init__()
|
|
|
|
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_artist'),
|
|
(_('Sort by year'), 'year_artist'),
|
|
(_('Sort by rating'), 'rating_artist')])
|
|
|
|
self.options = list(self.values.keys())
|
|
|
|
# get the current sort key and initialise the superclass
|
|
gs = GSetting()
|
|
source_settings = gs.get_setting(gs.Path.PLUGIN)
|
|
value = source_settings[gs.PluginKey.SORT_BY_ARTIST]
|
|
|
|
if value not in list(self.values.values()):
|
|
print("here")
|
|
value = 'name_artist'
|
|
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)
|
|
|
|
def update_images(self, *args):
|
|
self._spritesheet = self.create_spritesheet(self.plugin,
|
|
self._spritesheet, 'sort_artist')
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def do_action(self):
|
|
sort = self.values[self.current_key]
|
|
|
|
gs = GSetting()
|
|
settings = gs.get_setting(gs.Path.PLUGIN)
|
|
settings[gs.PluginKey.SORT_BY_ARTIST] = sort
|
|
|
|
self._viewmgr.current_view.get_default_manager().emit('sort', "artist")
|
|
|
|
def get_current_image(self):
|
|
sort = self.values[self.current_key]
|
|
return self._spritesheet[sort]
|
|
|
|
|
|
class PropertiesMenuController(OptionsController):
|
|
favourites = GObject.property(type=bool, default=False)
|
|
follow = GObject.property(type=bool, default=False)
|
|
|
|
def __init__(self, plugin, source):
|
|
super(PropertiesMenuController, self).__init__()
|
|
|
|
self._source = source
|
|
self.plugin = plugin
|
|
self._connect_properties()
|
|
# sorts dictionary
|
|
cl = CoverLocale()
|
|
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
|
# options
|
|
self.values = OrderedDict()
|
|
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'
|
|
self.values[MenuNode('separator1', 'separator')] = ''
|
|
self.values[MenuNode(_('Use favourites only'), 'check',
|
|
(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'
|
|
|
|
self.options = list(self.values.keys())
|
|
|
|
self.update_images(False)
|
|
|
|
if self.favourites:
|
|
self._source.propertiesbutton_callback('favourite')
|
|
|
|
if self.follow:
|
|
self._source.propertiesbutton_callback('follow')
|
|
|
|
self.current_key = None
|
|
|
|
def _connect_properties(self):
|
|
gs = GSetting()
|
|
setting = gs.get_setting(gs.Path.PLUGIN)
|
|
setting.bind(
|
|
gs.PluginKey.USE_FAVOURITES,
|
|
self,
|
|
'favourites',
|
|
Gio.SettingsBindFlags.DEFAULT)
|
|
setting.bind(
|
|
gs.PluginKey.FOLLOWING,
|
|
self,
|
|
'follow',
|
|
Gio.SettingsBindFlags.DEFAULT)
|
|
|
|
def _change_key(self, dict, old, new):
|
|
for i in range(len(dict)):
|
|
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')
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def do_action(self):
|
|
if self.current_key:
|
|
key = [node for node in self.values if node.label == self.current_key]
|
|
|
|
if self.current_key == _('Use favourites only'):
|
|
self.favourites = not self.favourites
|
|
|
|
if self.current_key == _('Follow playing song'):
|
|
self.follow = not self.follow
|
|
|
|
self._source.propertiesbutton_callback(self.values[key[0]])
|
|
self.current_key = None
|
|
|
|
def get_current_image(self):
|
|
return self._image
|
|
|
|
def get_current_description(self):
|
|
return _('Properties')
|
|
|
|
|
|
class DecadePopupController(OptionsController):
|
|
def __init__(self, plugin, album_model):
|
|
super(DecadePopupController, self).__init__()
|
|
|
|
self._album_model = album_model
|
|
self.plugin = plugin
|
|
|
|
self._spritesheet = None
|
|
|
|
# decade options
|
|
cl = CoverLocale()
|
|
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
|
|
|
self.values = OrderedDict()
|
|
|
|
self.values[_('All Decades')] = [-1, 'All Decades']
|
|
# '20s' as in the decade 2010
|
|
self.values[_('20s')] = [2020, '20s']
|
|
#'10s' as in the decade 2010
|
|
self.values[_('10s')] = [2010, '10s']
|
|
#'00s' as in the decade 2000
|
|
self.values[_('00s')] = [2000, '00s']
|
|
#'90s' as in the decade 1990
|
|
self.values[_('90s')] = [1990, '90s']
|
|
#'80s' as in the decade 1980
|
|
self.values[_('80s')] = [1980, '80s']
|
|
#'70s' as in the decade 1970
|
|
self.values[_('70s')] = [1970, '70s']
|
|
#'60s' as in the decade 1960
|
|
self.values[_('60s')] = [1960, '60s']
|
|
#'50s' as in the decade 1950
|
|
self.values[_('50s')] = [1950, '50s']
|
|
#'40s' as in the decade 1940
|
|
self.values[_('40s')] = [1940, '40s']
|
|
#'30s' as in the decade 1930
|
|
self.values[_('30s')] = [1930, '30s']
|
|
#'Older' as in 'older than the year 1930'
|
|
self.values[_('Older')] = [-1, 'Older']
|
|
|
|
self.options = list(self.values.keys())
|
|
|
|
# if we aren't on the 20s yet, remove it
|
|
if date.today().year < 2020:
|
|
self.options.remove(_('20s'))
|
|
|
|
# define a initial decade an set the initial key
|
|
self._initial_decade = self.options[0]
|
|
self.update_images(False)
|
|
|
|
self.current_key = self._initial_decade
|
|
|
|
def update_images(self, *args):
|
|
self._spritesheet = self.create_spritesheet(self.plugin,
|
|
self._spritesheet, 'decade')
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def do_action(self):
|
|
if self.current_key == self._initial_decade:
|
|
self._album_model.remove_filter('decade')
|
|
else:
|
|
self._album_model.replace_filter('decade',
|
|
self.values[self.current_key][0])
|
|
|
|
def get_current_image(self):
|
|
decade = self.values[self.current_key][1]
|
|
return self._spritesheet[decade]
|
|
|
|
def get_current_description(self):
|
|
return self.current_key
|
|
|
|
|
|
class SortOrderToggleController(OptionsController):
|
|
toolbar_type = "album"
|
|
|
|
def __init__(self, plugin, viewmgr):
|
|
super(SortOrderToggleController, self).__init__()
|
|
|
|
self._viewmgr = viewmgr
|
|
self.plugin = plugin
|
|
|
|
# options
|
|
self.values = OrderedDict([(_('Sort in descending order'), False),
|
|
(_('Sort in ascending order'), True)])
|
|
self.options = list(self.values.keys())
|
|
|
|
self._images = []
|
|
|
|
# set the current key
|
|
self.gs = GSetting()
|
|
self.settings = self.gs.get_setting(self.gs.Path.PLUGIN)
|
|
self.key = self.get_key()
|
|
sort_order = self.settings[self.key]
|
|
self.current_key = list(self.values.keys())[
|
|
list(self.values.values()).index(sort_order)]
|
|
self.update_images(False)
|
|
|
|
def get_key(self):
|
|
return self.gs.PluginKey.SORT_ORDER
|
|
|
|
def update_images(self, *args):
|
|
# initialize images
|
|
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'))
|
|
|
|
if args[-1]:
|
|
self.update_image = True
|
|
|
|
def do_action(self):
|
|
sort_order = self.values[self.current_key]
|
|
self.settings[self.key] = sort_order
|
|
self._viewmgr.current_view.get_default_manager().emit('sort', self.toolbar_type)
|
|
|
|
def get_current_image(self):
|
|
return self._images[self.get_current_key_index()]
|
|
|
|
|
|
class ArtistSortOrderToggleController(SortOrderToggleController):
|
|
toolbar_type = "artist"
|
|
|
|
def __init__(self, plugin, model):
|
|
super(ArtistSortOrderToggleController, self).__init__(plugin, model)
|
|
|
|
def get_key(self):
|
|
return self.gs.PluginKey.SORT_ORDER_ARTIST
|
|
|
|
|
|
class AlbumSearchEntryController(OptionsController):
|
|
# properties
|
|
search_text = GObject.property(type=str, default='')
|
|
|
|
def __init__(self, album_model):
|
|
super(AlbumSearchEntryController, self).__init__()
|
|
|
|
self._album_model = album_model
|
|
self._filter_type = 'all'
|
|
|
|
# options
|
|
self.values = OrderedDict()
|
|
self.values[_('Search all fields')] = 'all'
|
|
self.values[_('Search album artists')] = 'album_artist'
|
|
self.values[_('Search track artists')] = 'artist'
|
|
self.values[_('Search composers')] = 'composers'
|
|
self.values[_('Search albums')] = 'album_name'
|
|
self.values[_('Search titles')] = 'track'
|
|
|
|
self.options = list(self.values.keys())
|
|
self.current_key = list(self.values.keys())[0]
|
|
|
|
self._typing = False
|
|
self._typing_counter = 0
|
|
self._current_search_text = ""
|
|
|
|
def do_action(self):
|
|
# remove old filter
|
|
self._album_model.remove_filter(self._filter_type, False)
|
|
|
|
# assign the new filter
|
|
self._filter_type = self.values[self.current_key]
|
|
|
|
self.do_search(self.search_text, True)
|
|
|
|
def _search_typing(self, *args):
|
|
self._typing_counter = self._typing_counter + 1
|
|
|
|
if self._typing_counter >= 4 and self._typing:
|
|
self._typing = False
|
|
self._change_filter(self._current_search_text, False)
|
|
|
|
return self._typing
|
|
|
|
def _change_filter(self, search_text, force):
|
|
# self.search_text = search_text
|
|
self._current_search_text = search_text
|
|
|
|
if search_text:
|
|
self._album_model.replace_filter(self._filter_type,
|
|
search_text)
|
|
elif not force:
|
|
self._album_model.remove_filter(self._filter_type)
|
|
|
|
def do_search(self, search_text, force=False):
|
|
'''
|
|
if self.search_text != search_text or force:
|
|
self.search_text = search_text
|
|
|
|
if search_text:
|
|
self._album_model.replace_filter(self._filter_type,
|
|
search_text)
|
|
elif not force:
|
|
self._album_model.remove_filter(self._filter_type)
|
|
|
|
'''
|
|
# self.search_text = search_text
|
|
if force:
|
|
self._typing_counter = 99
|
|
self._typing = False
|
|
self._change_filter(search_text, force)
|
|
return
|
|
|
|
if self._current_search_text != search_text:
|
|
|
|
#self.search_text = search_text
|
|
self._current_search_text = search_text
|
|
self._typing_counter = 0
|
|
|
|
if not self._typing:
|
|
self._typing = True
|
|
|
|
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 100,
|
|
self._search_typing)
|
|
|
|
|
|
class AlbumQuickSearchController(object):
|
|
def __init__(self, album_manager):
|
|
self._album_manager = album_manager
|
|
|
|
def connect_quick_search(self, quick_search):
|
|
quick_search.connect('quick-search', self._on_quick_search)
|
|
quick_search.connect('arrow-pressed', self._on_arrow_pressed)
|
|
quick_search.connect('hide', self._on_hide)
|
|
|
|
def _on_quick_search(self, quick_search, search_text, *args):
|
|
album = self._album_manager.model.find_first_visible('album_name',
|
|
search_text)
|
|
|
|
if album:
|
|
path = self._album_manager.model.get_path(album)
|
|
self._album_manager.current_view.select_and_scroll_to_path(path)
|
|
|
|
def _on_arrow_pressed(self, quick_search, key, *args):
|
|
current = self._album_manager.current_view.get_selected_objects()[0]
|
|
search_text = quick_search.get_text()
|
|
album = None
|
|
|
|
if key == Gdk.KEY_Up:
|
|
album = self._album_manager.model.find_first_visible(
|
|
'album_name', search_text, current, True)
|
|
elif key == Gdk.KEY_Down:
|
|
album = self._album_manager.model.find_first_visible(
|
|
'album_name', search_text, current)
|
|
|
|
if album:
|
|
path = self._album_manager.model.get_path(album)
|
|
self._album_manager.current_view.select_and_scroll_to_path(path)
|
|
|
|
def _on_hide(self, quick_search, *args):
|
|
self._album_manager.current_view.grab_focus()
|
|
|
|
|
|
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)
|
|
|
|
self.options = list(self.values.keys())
|
|
viewmgr.connect('new-view', self.on_notify_view_name)
|
|
|
|
def on_notify_view_name(self, *args):
|
|
for key in self.options:
|
|
if self.values[key] == self._viewmgr.view_name:
|
|
self.current_key = key
|
|
|
|
def do_action(self):
|
|
if self._viewmgr.view_name != self.values[self.current_key]:
|
|
self._viewmgr.view_name = self.values[self.current_key]
|