fixup! Adjust line length to match Code Style Guide (see #103)

This commit is contained in:
coderkun 2024-05-27 18:29:01 +02:00
parent c04216e634
commit ded9cf026b
11 changed files with 326 additions and 685 deletions

View file

@ -11,9 +11,7 @@ from gi.repository import Gtk, GObject, Adw
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/album-headerbar.ui')
class AlbumHeaderbar(Adw.Bin):
__gtype_name__ = 'McgAlbumHeaderbar'
__gsignals__ = {
'close': (GObject.SIGNAL_RUN_FIRST, None, ())
}
__gsignals__ = {'close': (GObject.SIGNAL_RUN_FIRST, None, ())}
# Widgets
standalone_title = Gtk.Template.Child()

View file

@ -15,10 +15,8 @@ class Application(Gtk.Application):
DOMAIN = 'mcg'
def __init__(self):
super().__init__(
application_id=Application.ID,
flags=Gio.ApplicationFlags.FLAGS_NONE
)
super().__init__(application_id=Application.ID,
flags=Gio.ApplicationFlags.FLAGS_NONE)
self._window = None
self._info_dialog = None
self._verbosity = logging.WARNING
@ -56,25 +54,20 @@ class Application(Gtk.Application):
self._info_dialog.set_application_name("CoverGrid")
self._info_dialog.set_version("3.2.1")
self._info_dialog.set_comments(
"""CoverGrid is a client for the Music Player Daemon, focusing on
albums instead of single tracks.
"""
)
"""CoverGrid is a client for the Music Player Daemon, focusing on \
albums instead of single tracks.""")
self._info_dialog.set_website("https://www.suruatoel.xyz/codes/mcg")
self._info_dialog.set_license_type(Gtk.License.GPL_3_0)
self._info_dialog.set_issue_url(
"https://git.suruatoel.xyz/coderkun/mcg"
)
"https://git.suruatoel.xyz/coderkun/mcg")
self._info_dialog.present()
def on_menu_quit(self, action, value):
self.quit()
def _setup_logging(self):
logging.basicConfig(
level=self._verbosity,
format="%(asctime)s %(levelname)s: %(message)s"
)
logging.basicConfig(level=self._verbosity,
format="%(asctime)s %(levelname)s: %(message)s")
def _load_settings(self):
self._settings = Gio.Settings.new(Application.ID)
@ -87,10 +80,8 @@ class Application(Gtk.Application):
styleProvider = Gtk.CssProvider()
styleProvider.load_from_resource(self._get_resource_path('gtk.css'))
Gtk.StyleContext.add_provider_for_display(
Gdk.Display.get_default(),
styleProvider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
Gdk.Display.get_default(), styleProvider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
def _setup_actions(self):
action = Gio.SimpleAction.new("info", None)

View file

@ -188,10 +188,8 @@ class Client(Base):
def get_output_devices(self):
"""Determine the list of audio output devices."""
self._logger.info("get output devices")
self._add_action_signal(
Client.SIGNAL_LOAD_OUTPUT_DEVICES,
self._get_output_devices
)
self._add_action_signal(Client.SIGNAL_LOAD_OUTPUT_DEVICES,
self._get_output_devices)
def enable_output_device(self, device, enabled):
"""Enable/disable an audio output device."""
@ -208,10 +206,8 @@ class Client(Base):
def load_playlist(self):
self._logger.info("load playlist")
self._add_action_signal(
Client.SIGNAL_LOAD_PLAYLIST,
self._load_playlist
)
self._add_action_signal(Client.SIGNAL_LOAD_PLAYLIST,
self._load_playlist)
def clear_playlist(self):
"""Clear the current playlist"""
@ -268,10 +264,8 @@ class Client(Base):
def get_albumart(self, album):
self._logger.info("get albumart")
self._add_action_signal(
Client.SIGNAL_LOAD_ALBUMART,
self._get_albumart, album
)
self._add_action_signal(Client.SIGNAL_LOAD_ALBUMART,
self._get_albumart, album)
def get_albumart_now(self, album):
self._logger.info("get albumart now")
@ -301,13 +295,8 @@ class Client(Base):
def _connect_socket(self, host, port):
sock = None
error = None
resources = socket.getaddrinfo(
host,
port,
socket.AF_UNSPEC,
socket.SOCK_STREAM,
socket.IPPROTO_TCP
)
resources = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
socket.SOCK_STREAM, socket.IPPROTO_TCP)
for res in resources:
af, socktype, proto, canonname, sa = res
try:
@ -331,9 +320,8 @@ class Client(Base):
if not greeting.startswith(Client.PROTOCOL_GREETING):
self._disconnect_socket()
raise ProtocolException("invalid greeting: {}".format(greeting))
self._protocol_version = greeting[
len(Client.PROTOCOL_GREETING):
].strip()
self._protocol_version = greeting[len(Client.PROTOCOL_GREETING
):].strip()
self._logger.debug("protocol version: %s", self._protocol_version)
def _disconnect(self):
@ -446,7 +434,7 @@ class Client(Base):
artists = 0
if 'artists' in stats:
artists = int(stats['artists'])
# Albums
# Albums
albums = 0
if 'albums' in stats:
albums = int(stats['albums'])
@ -497,12 +485,7 @@ class Client(Base):
self._logger.debug("album: %r", album)
# Tracks
songs = self._parse_list(
self._call(
'find album ',
album.get_title()
),
['file']
)
self._call('find album ', album.get_title()), ['file'])
for song in songs:
track = self._extract_track(song)
if track:
@ -515,12 +498,8 @@ class Client(Base):
def _load_playlist(self):
self._playlist = []
songs = self._parse_list(
self._call(
'playlistinfo'
),
['file', 'playlist']
)
songs = self._parse_list(self._call('playlistinfo'),
['file', 'playlist'])
for song in songs:
self._logger.debug("song: %r", song)
# Track
@ -528,13 +507,11 @@ class Client(Base):
self._logger.debug("track: %r", track)
# Album
album = self._extract_album(song, lookup=False)
if (
len(self._playlist) == 0
or self._playlist[len(self._playlist)-1] != album
):
if (len(self._playlist) == 0
or self._playlist[len(self._playlist) - 1] != album):
self._playlist.append(album)
else:
album = self._playlist[len(self._playlist)-1]
album = self._playlist[len(self._playlist) - 1]
self._logger.debug("album: %r", album)
if track:
album.add_track(track)
@ -584,11 +561,7 @@ class Client(Base):
self._logger.info("addid: %r", track.get_file())
track_id = None
track_id_response = self._parse_dict(
self._call(
'addid',
track.get_file()
)
)
self._call('addid', track.get_file()))
if 'id' in track_id_response:
track_id = track_id_response['id']
self._logger.debug("track id: %r", track_id)
@ -613,33 +586,24 @@ class Client(Base):
def _get_albumart(self, album):
if album in self._albums:
album = self._albums[album]
self._logger.debug(
"get albumart for album \"%s\"",
album.get_title()
)
self._logger.debug("get albumart for album \"%s\"",
album.get_title())
# Use "albumart" command
if album.get_tracks():
try:
return (
album,
self._read_binary(
'albumart',
album.get_tracks()[0].get_file(),
False
)
)
return (album,
self._read_binary('albumart',
album.get_tracks()[0].get_file(),
False))
except CommandException as e:
# The "albumart" command throws an exception if not found
if e.get_error_number() != Client.PROTOCOL_ERROR_NOEXISTS:
raise e
# If no albumart can be found, use "readpicture" command
for track in album.get_tracks():
data = self._read_binary(
'readpicture',
track.get_file(),
True
)
data = self._read_binary('readpicture',
track.get_file(), True)
if data:
return (album, data)
@ -648,11 +612,9 @@ class Client(Base):
def _start_worker(self):
"""Start the worker thread which waits for action to be performed."""
self._logger.debug("start worker")
self._worker = threading.Thread(
target=self._run,
name='mcg-worker',
args=()
)
self._worker = threading.Thread(target=self._run,
name='mcg-worker',
args=())
self._worker.setDaemon(True)
self._worker.start()
self._logger.debug("worker started")
@ -680,12 +642,8 @@ class Client(Base):
def _add_action_signal(self, signal, method, *args):
"""Add an action to the action list that triggers a callback."""
self._logger.debug(
"add action signal %r: %r (%r)",
signal,
method.__name__,
args
)
self._logger.debug("add action signal %r: %r (%r)", signal,
method.__name__, args)
future = Future(signal)
future.add_done_callback(self._callback_future)
self._add_action_future(future, method, *args)
@ -741,11 +699,7 @@ class Client(Base):
def _write(self, command, args=None):
if args is not None and len(args) > 0:
line = '{} "{}"\n'.format(
command,
'" "'.join(
str(x).replace('"', '\\\"') for x in args
)
)
command, '" "'.join(str(x).replace('"', '\\\"') for x in args))
else:
line = '{}\n'.format(command)
self._logger.debug("write: %r", line)
@ -828,7 +782,7 @@ class Client(Base):
if not data:
data = bytearray(size)
# Create a view for the current chunk of data
data_view = memoryview(data)[offset:offset+binary]
data_view = memoryview(data)[offset:offset + binary]
# Read actual bytes
self._read_bytes(data_view, binary)
offset += binary
@ -858,9 +812,9 @@ class Client(Base):
def _buffer_get_char(self, char):
pos = self._buffer.find(char)
if pos < 0:
pos = len(self._buffer)-1
buf = self._buffer[0:pos+1]
self._buffer = self._buffer[pos+1:]
pos = len(self._buffer) - 1
buf = self._buffer[0:pos + 1]
self._buffer = self._buffer[pos + 1:]
return buf
def _buffer_get_size(self, size):
@ -994,8 +948,7 @@ class MCGAlbum:
def get_artists(self):
if self._albumartists:
return [
artist
for artist in self._artists
artist for artist in self._artists
if artist not in self._albumartists
]
return self._artists
@ -1138,8 +1091,7 @@ class MCGTrack:
def get_artists(self):
if self._albumartists:
return [
artist
for artist in self._artists
artist for artist in self._artists
if artist not in self._albumartists
]
return self._artists
@ -1164,7 +1116,7 @@ class MCGTrack:
if type(track) is list:
track = track[0]
if type(track) is str and '/' in track:
track = track[0: track.index('/')]
track = track[0:track.index('/')]
if track is not None:
try:
track = int(track)
@ -1201,13 +1153,10 @@ class MCGTrack:
class MCGPlaylistTrack(MCGTrack):
def __init__(self, track, id, pos):
MCGTrack.__init__(
self,
track.get_artists(),
track.get_title(),
track.get_file()
)
MCGTrack.__init__(self, track.get_artists(), track.get_title(),
track.get_file())
self.set_albumartists(track.get_albumartists())
self.set_track(track.get_track())
self.set_length(track.get_length())
@ -1228,11 +1177,7 @@ class MCGConfig(configparser.ConfigParser):
def __init__(self, filename):
configparser.ConfigParser.__init__(self)
self._filename = os.path.expanduser(
os.path.join(
MCGConfig.CONFIG_DIR,
filename
)
)
os.path.join(MCGConfig.CONFIG_DIR, filename))
self._create_dir()
def load(self):
@ -1258,12 +1203,8 @@ class MCGCache():
self._logger = logging.getLogger(__name__)
self._host = host
self._size = size
self._dirname = os.path.expanduser(
os.path.join(
MCGCache.DIRNAME,
host
)
)
self._dirname = os.path.expanduser(os.path.join(
MCGCache.DIRNAME, host))
if not os.path.exists(self._dirname):
os.makedirs(self._dirname)
self._read_size()
@ -1284,8 +1225,7 @@ class MCGCache():
self._logger.warning(
"invalid cache file: %s, deleting file",
filename,
exc_info=True
)
exc_info=True)
size = None
# Clear cache if size has changed
if size != self._size:

View file

@ -31,9 +31,7 @@ class ConnectionPanel(Adw.Bin):
# Zeroconf provider
self._zeroconf_provider = ZeroconfProvider()
self._zeroconf_provider.connect_signal(
ZeroconfProvider.SIGNAL_SERVICE_NEW,
self.on_new_service
)
ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service)
def on_new_service(self, service):
name, host, port = service

View file

@ -15,8 +15,8 @@ class CoverPanel(Gtk.Overlay):
__gtype_name__ = 'McgCoverPanel'
__gsignals__ = {
'toggle-fullscreen': (GObject.SIGNAL_RUN_FIRST, None, ()),
'set-song': (GObject.SIGNAL_RUN_FIRST, None, (int, int,)),
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,))
'set-song': (GObject.SIGNAL_RUN_FIRST, None, (int, int, )),
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str, ))
}
# Widgets
@ -48,8 +48,7 @@ class CoverPanel(Gtk.Overlay):
self._timer = None
self._properties = {}
self._icon_theme = Gtk.IconTheme.get_for_display(
Gdk.Display.get_default()
)
Gdk.Display.get_default())
self._fullscreened = False
self._current_size = None
@ -64,10 +63,8 @@ class CoverPanel(Gtk.Overlay):
# Button controller for songs scale
buttonController = Gtk.GestureClick()
buttonController.connect('pressed', self.on_songs_scale_pressed)
buttonController.connect(
'unpaired-release',
self.on_songs_scale_released
)
buttonController.connect('unpaired-release',
self.on_songs_scale_released)
self.songs_scale.add_controller(buttonController)
def get_toolbar(self):
@ -94,7 +91,7 @@ class CoverPanel(Gtk.Overlay):
time = self._current_album.get_length()
tracks = self._current_album.get_tracks()
pos = 0
for index in range(len(tracks)-1, -1, -1):
for index in range(len(tracks) - 1, -1, -1):
time = time - tracks[index].get_length()
pos = tracks[index].get_pos()
if time < value:
@ -107,11 +104,8 @@ class CoverPanel(Gtk.Overlay):
# Set labels
self.album_title_label.set_label(album.get_title())
self.album_date_label.set_label(', '.join(album.get_dates()))
self.album_artist_label.set_label(
', '.join(
album.get_albumartists()
)
)
self.album_artist_label.set_label(', '.join(
album.get_albumartists()))
# Set tracks
self._set_tracks(album)
@ -135,7 +129,7 @@ class CoverPanel(Gtk.Overlay):
for index in range(0, pos):
time = time + tracks[index].get_length()
self.songs_scale.set_value(time+1)
self.songs_scale.set_value(time + 1)
self._timer = GObject.timeout_add(1000, self._playing)
def set_pause(self):
@ -180,18 +174,12 @@ class CoverPanel(Gtk.Overlay):
if length > 0 and length < album.get_length():
cur_length = cur_length + 1
self.songs_scale.add_mark(
cur_length,
Gtk.PositionType.RIGHT,
GObject.markup_escape_text(
Utils.create_track_title(track)
)
)
cur_length, Gtk.PositionType.RIGHT,
GObject.markup_escape_text(Utils.create_track_title(track)))
length = length + track.get_length()
self.songs_scale.add_mark(
length,
Gtk.PositionType.RIGHT,
"{0[0]:02d}:{0[1]:02d} minutes".format(divmod(length, 60))
)
length, Gtk.PositionType.RIGHT,
"{0[0]:02d}:{0[1]:02d} minutes".format(divmod(length, 60)))
def _enable_tracklist(self):
if self._current_album:
@ -228,7 +216,10 @@ class CoverPanel(Gtk.Overlay):
current_width, current_height = self._current_size
if size_width == current_width and size_height == current_height:
return
self._current_size = (size_width, size_height,)
self._current_size = (
size_width,
size_height,
)
# Get pixelbuffer
pixbuf = self._cover_pixbuf
@ -243,15 +234,10 @@ class CoverPanel(Gtk.Overlay):
ratio = min(ratioW, ratioH)
ratio = min(ratio, 1)
# Neue Breite und Höhe berechnen
width = int(math.floor(pixbuf.get_width()*ratio))
height = int(math.floor(pixbuf.get_height()*ratio))
width = int(math.floor(pixbuf.get_width() * ratio))
height = int(math.floor(pixbuf.get_height() * ratio))
if width <= 0 or height <= 0:
return
self.cover_image.set_from_pixbuf(
pixbuf.scale_simple(
width,
height,
GdkPixbuf.InterpType.HYPER
)
)
pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
self.cover_image.show()

View file

@ -25,15 +25,14 @@ class LibraryPanel(Adw.Bin):
'open-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
'close-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
'update': (GObject.SIGNAL_RUN_FIRST, None, ()),
'play': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
'queue': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
'queue-multiple': (
GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)
),
'item-size-changed': (GObject.SIGNAL_RUN_FIRST, None, (int,)),
'sort-order-changed': (GObject.SIGNAL_RUN_FIRST, None, (int,)),
'sort-type-changed': (GObject.SIGNAL_RUN_FIRST, None, (bool,)),
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
'play': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
'queue': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
'queue-multiple':
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
'item-size-changed': (GObject.SIGNAL_RUN_FIRST, None, (int, )),
'sort-order-changed': (GObject.SIGNAL_RUN_FIRST, None, (int, )),
'sort-type-changed': (GObject.SIGNAL_RUN_FIRST, None, (bool, )),
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
}
# Widgets
@ -88,8 +87,7 @@ class LibraryPanel(Adw.Bin):
self._library_lock = threading.Lock()
self._library_stop = threading.Event()
self._icon_theme = Gtk.IconTheme.get_for_display(
Gdk.Display.get_default()
)
Gdk.Display.get_default())
self._standalone_pixbuf = None
self._selected_albums = []
self._is_selected = False
@ -97,20 +95,16 @@ class LibraryPanel(Adw.Bin):
# Widgets
# Header bar
self._headerbar_standalone = AlbumHeaderbar()
self._headerbar_standalone.connect(
'close',
self.on_standalone_close_clicked
)
self._headerbar_standalone.connect('close',
self.on_standalone_close_clicked)
# Library Grid: Model
self._library_grid_model = Gio.ListStore()
self._library_grid_filter = Gtk.FilterListModel()
self._library_grid_filter.set_model(self._library_grid_model)
self._library_grid_selection_multi = Gtk.MultiSelection.new(
self._library_grid_filter
)
self._library_grid_filter)
self._library_grid_selection_single = Gtk.SingleSelection.new(
self._library_grid_filter
)
self._library_grid_filter)
# Library Grid
self.library_grid.set_model(self._library_grid_selection_single)
# Toolbar menu
@ -124,10 +118,8 @@ class LibraryPanel(Adw.Bin):
# Button controller for grid scale
buttonController = Gtk.GestureClick()
buttonController.connect(
'unpaired-release',
self.on_grid_scale_released
)
buttonController.connect('unpaired-release',
self.on_grid_scale_released)
self.grid_scale.add_controller(buttonController)
def get_headerbar_standalone(self):
@ -146,15 +138,13 @@ class LibraryPanel(Adw.Bin):
self.library_grid.set_model(self._library_grid_selection_multi)
self.library_grid.set_single_click_activate(False)
self.library_grid.get_style_context().add_class(
Utils.CSS_SELECTION
)
Utils.CSS_SELECTION)
else:
self.actionbar_revealer.set_reveal_child(False)
self.library_grid.set_model(self._library_grid_selection_single)
self.library_grid.set_single_click_activate(True)
self.library_grid.get_style_context().remove_class(
Utils.CSS_SELECTION
)
Utils.CSS_SELECTION)
@Gtk.Template.Callback()
def on_update_clicked(self, widget):
@ -182,8 +172,7 @@ class LibraryPanel(Adw.Bin):
def on_sort_toggled(self, widget):
if widget.get_active():
self._sort_order = [
key
for key, value in self._toolbar_sort_buttons.items()
key for key, value in self._toolbar_sort_buttons.items()
if value is widget
][0]
self._sort_grid_model()
@ -205,10 +194,7 @@ class LibraryPanel(Adw.Bin):
@Gtk.Template.Callback()
def on_filter_entry_changed(self, widget):
self._library_grid_filter.set_filter(
SearchFilter(
self.filter_entry.get_text()
)
)
SearchFilter(self.filter_entry.get_text()))
@Gtk.Template.Callback()
def on_library_grid_clicked(self, widget, position):
@ -269,8 +255,7 @@ class LibraryPanel(Adw.Bin):
button = self._toolbar_sort_buttons[sort]
if button:
self._sort_order = [
key
for key, value in self._toolbar_sort_buttons.items()
key for key, value in self._toolbar_sort_buttons.items()
if value is button
][0]
if not button.get_active():
@ -300,10 +285,12 @@ class LibraryPanel(Adw.Bin):
def set_albums(self, host, albums):
self._host = host
self._library_stop.set()
threading.Thread(
target=self._set_albums,
args=(host, albums, self._item_size,)
).start()
threading.Thread(target=self._set_albums,
args=(
host,
albums,
self._item_size,
)).start()
def set_albumart(self, album, data):
if album in self._selected_albums:
@ -320,20 +307,14 @@ class LibraryPanel(Adw.Bin):
GObject.idle_add(self._show_image)
def _sort_grid_model(self):
GObject.idle_add(
self._library_grid_model.sort,
self._grid_model_compare_func,
self._sort_order,
self._sort_type
)
GObject.idle_add(self._library_grid_model.sort,
self._grid_model_compare_func, self._sort_order,
self._sort_type)
def _grid_model_compare_func(self, item1, item2, criterion, order):
return client.MCGAlbum.compare(
item1.get_album(),
item2.get_album(),
criterion,
(order == Gtk.SortType.DESCENDING)
)
return client.MCGAlbum.compare(item1.get_album(), item2.get_album(),
criterion,
(order == Gtk.SortType.DESCENDING))
def stop_threads(self):
self._library_stop.set()
@ -342,10 +323,8 @@ class LibraryPanel(Adw.Bin):
self._library_lock.acquire()
self._albums = albums
stack_transition_type = self.stack.get_transition_type()
GObject.idle_add(
self.stack.set_transition_type,
Gtk.StackTransitionType.NONE
)
GObject.idle_add(self.stack.set_transition_type,
Gtk.StackTransitionType.NONE)
GObject.idle_add(self.stack.set_visible_child, self.progress_box)
GObject.idle_add(self.progress_bar.set_fraction, 0.0)
GObject.idle_add(self.stack.set_transition_type, stack_transition_type)
@ -367,26 +346,18 @@ class LibraryPanel(Adw.Bin):
self._logger.exception("Failed to load albumart", e)
if pixbuf is None:
pixbuf = self._icon_theme.lookup_icon(
Utils.STOCK_ICON_DEFAULT,
None,
self._item_size,
self._item_size,
Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC
)
Utils.STOCK_ICON_DEFAULT, None, self._item_size,
self._item_size, Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
if pixbuf is not None:
self._grid_pixbufs[album.get_id()] = pixbuf
GObject.idle_add(
self._library_grid_model.append,
GridItem(album, pixbuf)
)
GObject.idle_add(self._library_grid_model.append,
GridItem(album, pixbuf))
i += 1
GObject.idle_add(self.progress_bar.set_fraction, i/n)
GObject.idle_add(
self.progress_bar.set_text,
locale.gettext("Loading images")
)
GObject.idle_add(self.progress_bar.set_fraction, i / n)
GObject.idle_add(self.progress_bar.set_text,
locale.gettext("Loading images"))
self._library_lock.release()
GObject.idle_add(self.stack.set_visible_child, self.scroll)
@ -394,10 +365,12 @@ class LibraryPanel(Adw.Bin):
def _set_widget_grid_size(self, grid_widget, size, vertical):
self._library_stop.set()
threading.Thread(
target=self._set_widget_grid_size_thread,
args=(grid_widget, size, vertical,)
).start()
threading.Thread(target=self._set_widget_grid_size_thread,
args=(
grid_widget,
size,
vertical,
)).start()
def _set_widget_grid_size_thread(self, grid_widget, size, vertical):
self._library_lock.acquire()
@ -411,20 +384,12 @@ class LibraryPanel(Adw.Bin):
pixbuf = self._grid_pixbufs[album_id]
if pixbuf is not None:
pixbuf = pixbuf.scale_simple(
size,
size,
GdkPixbuf.InterpType.NEAREST
)
pixbuf = pixbuf.scale_simple(size, size,
GdkPixbuf.InterpType.NEAREST)
else:
pixbuf = self._icon_theme.lookup_icon(
Utils.STOCK_ICON_DEFAULT,
None,
size,
size,
Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC
)
Utils.STOCK_ICON_DEFAULT, None, size, size,
Gtk.TextDirection.LTR, Gtk.IconLookupFlags.FORCE_SYMBOLIC)
GObject.idle_add(grid_item.set_cover, pixbuf)
if self._library_stop.is_set():
@ -456,11 +421,7 @@ class LibraryPanel(Adw.Bin):
for index in range(countMin, countMax):
pixel = int(width / index)
pixel = pixel - (2 * int(pixel / 100))
self.grid_scale.add_mark(
pixel,
Gtk.PositionType.BOTTOM,
None
)
self.grid_scale.add_mark(pixel, Gtk.PositionType.BOTTOM, None)
def _open_standalone(self):
self.library_stack.set_visible_child(self.panel_standalone)
@ -491,38 +452,24 @@ class LibraryPanel(Adw.Bin):
ratio = min(ratioW, ratioH)
ratio = min(ratio, 1)
# Neue Breite und Höhe berechnen
width = int(math.floor(pixbuf.get_width()*ratio))
height = int(math.floor(pixbuf.get_height()*ratio))
width = int(math.floor(pixbuf.get_width() * ratio))
height = int(math.floor(pixbuf.get_height() * ratio))
if width <= 0 or height <= 0:
return
# Pixelpuffer auf Oberfläche zeichnen
self.standalone_image.set_from_pixbuf(
pixbuf.scale_simple(
width,
height,
GdkPixbuf.InterpType.HYPER
)
)
pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
self.standalone_image.show()
def _get_default_image(self):
return self._icon_theme.lookup_icon(
Utils.STOCK_ICON_DEFAULT,
None,
512,
512,
Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC
)
return self._icon_theme.lookup_icon(Utils.STOCK_ICON_DEFAULT, None,
512, 512, Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
def _get_selected_albums(self):
albums = []
for i in range(self.library_grid.get_model().get_n_items()):
if self.library_grid.get_model().is_selected(i):
albums.append(
self.library_grid.get_model()
.get_item(i)
.get_album()
.get_id()
)
albums.append(self.library_grid.get_model().get_item(
i).get_album().get_id())
return albums

View file

@ -22,18 +22,12 @@ class PlaylistPanel(Adw.Bin):
'open-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
'close-standalone': (GObject.SIGNAL_RUN_FIRST, None, ()),
'clear-playlist': (GObject.SIGNAL_RUN_FIRST, None, ()),
'remove-album': (
GObject.SIGNAL_RUN_FIRST,
None,
(GObject.TYPE_PYOBJECT,)
),
'remove-multiple-albums': (
GObject.SIGNAL_RUN_FIRST,
None,
(GObject.TYPE_PYOBJECT,)
),
'play': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)),
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str,)),
'remove-album':
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
'remove-multiple-albums':
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
'play': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, )),
'albumart': (GObject.SIGNAL_RUN_FIRST, None, (str, )),
}
# Widgets
@ -66,8 +60,7 @@ class PlaylistPanel(Adw.Bin):
self._playlist_lock = threading.Lock()
self._playlist_stop = threading.Event()
self._icon_theme = Gtk.IconTheme.get_for_display(
Gdk.Display.get_default()
)
Gdk.Display.get_default())
self._standalone_pixbuf = None
self._selected_albums = []
self._is_selected = False
@ -75,18 +68,14 @@ class PlaylistPanel(Adw.Bin):
# Widgets
# Header bar
self._headerbar_standalone = AlbumHeaderbar()
self._headerbar_standalone.connect(
'close',
self.on_headerbar_close_clicked
)
self._headerbar_standalone.connect('close',
self.on_headerbar_close_clicked)
# Playlist Grid: Model
self._playlist_grid_model = Gio.ListStore()
self._playlist_grid_selection_multi = Gtk.MultiSelection.new(
self._playlist_grid_model
)
self._playlist_grid_model)
self._playlist_grid_selection_single = Gtk.SingleSelection.new(
self._playlist_grid_model
)
self._playlist_grid_model)
# Playlist Grid
self.playlist_grid.set_model(self._playlist_grid_selection_single)
@ -106,15 +95,13 @@ class PlaylistPanel(Adw.Bin):
self.playlist_grid.set_model(self._playlist_grid_selection_multi)
self.playlist_grid.set_single_click_activate(False)
self.playlist_grid.get_style_context().add_class(
Utils.CSS_SELECTION
)
Utils.CSS_SELECTION)
else:
self.actionbar_revealer.set_reveal_child(False)
self.playlist_grid.set_model(self._playlist_grid_selection_single)
self.playlist_grid.set_single_click_activate(True)
self.playlist_grid.get_style_context().remove_class(
Utils.CSS_SELECTION
)
Utils.CSS_SELECTION)
@Gtk.Template.Callback()
def on_clear_clicked(self, widget):
@ -177,10 +164,12 @@ class PlaylistPanel(Adw.Bin):
def set_playlist(self, host, playlist):
self._host = host
self._playlist_stop.set()
threading.Thread(
target=self._set_playlist,
args=(host, playlist, self._item_size,)
).start()
threading.Thread(target=self._set_playlist,
args=(
host,
playlist,
self._item_size,
)).start()
def set_albumart(self, album, data):
if album in self._selected_albums:
@ -221,13 +210,9 @@ class PlaylistPanel(Adw.Bin):
self._logger.exception("Failed to load albumart")
if pixbuf is None:
pixbuf = self._icon_theme.lookup_icon(
Utils.STOCK_ICON_DEFAULT,
None,
self._item_size,
self._item_size,
Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC
)
Utils.STOCK_ICON_DEFAULT, None, self._item_size,
self._item_size, Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
if pixbuf is not None:
self._playlist_grid_model.append(GridItem(album, pixbuf))
@ -276,35 +261,24 @@ class PlaylistPanel(Adw.Bin):
ratio = min(ratioW, ratioH)
ratio = min(ratio, 1)
# Neue Breite und Höhe berechnen
width = int(math.floor(pixbuf.get_width()*ratio))
height = int(math.floor(pixbuf.get_height()*ratio))
width = int(math.floor(pixbuf.get_width() * ratio))
height = int(math.floor(pixbuf.get_height() * ratio))
if width <= 0 or height <= 0:
return
# Pixelpuffer auf Oberfläche zeichnen
self.standalone_image.set_from_pixbuf(
pixbuf.scale_simple(
width,
height,
GdkPixbuf.InterpType.HYPER
)
)
pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER))
self.standalone_image.show()
def _get_default_image(self):
return self._icon_theme.lookup_icon(
Utils.STOCK_ICON_DEFAULT,
None,
512,
512,
Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC
)
return self._icon_theme.lookup_icon(Utils.STOCK_ICON_DEFAULT, None,
512, 512, Gtk.TextDirection.LTR,
Gtk.IconLookupFlags.FORCE_SYMBOLIC)
def _get_selected_albums(self):
albums = []
for i in range(self.playlist_grid.get_model().get_n_items()):
if self.playlist_grid.get_model().is_selected(i):
albums.append(
self.playlist_grid.get_model().get_item(i).get_album()
)
self.playlist_grid.get_model().get_item(i).get_album())
return albums

View file

@ -12,11 +12,10 @@ from gi.repository import Gtk, Adw, GObject
class ServerPanel(Adw.Bin):
__gtype_name__ = 'McgServerPanel'
__gsignals__ = {
'change-output-device': (
GObject.SIGNAL_RUN_FIRST,
None,
(GObject.TYPE_PYOBJECT,bool,)
),
'change-output-device': (GObject.SIGNAL_RUN_FIRST, None, (
GObject.TYPE_PYOBJECT,
bool,
)),
}
# Widgets
@ -61,14 +60,11 @@ class ServerPanel(Adw.Bin):
file = self._none_label
self.status_file.set_markup(file)
# Audio information
if audio:
if audio:
parts = audio.split(":")
if len(parts) == 3:
audio = "{}Hz, {}bit, {}channels".format(
parts[0],
parts[1],
parts[2]
)
parts[0], parts[1], parts[2])
else:
audio = self._none_label
self.status_audio.set_markup(audio)
@ -102,18 +98,14 @@ class ServerPanel(Adw.Bin):
if device.get_id() in self._output_buttons.keys():
self._output_buttons[device.get_id()].freeze_notify()
self._output_buttons[device.get_id()].set_active(
device.is_enabled()
)
device.is_enabled())
self._output_buttons[device.get_id()].thaw_notify()
else:
button = Gtk.CheckButton.new_with_label(device.get_name())
if device.is_enabled():
button.set_active(True)
handler = button.connect(
'toggled',
self.on_output_device_toggled,
device
)
handler = button.connect('toggled',
self.on_output_device_toggled, device)
self.output_devices.insert(button, -1)
self._output_buttons[device.get_id()] = button
@ -121,5 +113,5 @@ class ServerPanel(Adw.Bin):
for id in self._output_buttons.keys():
if id not in device_ids:
self.output_devices.remove(
self._output_buttons[id].get_parent()
)
self._output_buttons[id].get_parent())

View file

@ -35,11 +35,8 @@ class Utils:
if albumart:
pixbuf = Utils.load_pixbuf(albumart)
if pixbuf is not None:
pixbuf = pixbuf.scale_simple(
size,
size,
GdkPixbuf.InterpType.HYPER
)
pixbuf = pixbuf.scale_simple(size, size,
GdkPixbuf.InterpType.HYPER)
pixbuf.savev(cache_url, 'jpeg', [], [])
return pixbuf
@ -47,9 +44,7 @@ class Utils:
label = ', '.join(album.get_albumartists())
if album.get_artists():
label = locale.gettext("{} feat. {}").format(
label,
", ".join(album.get_artists())
)
label, ", ".join(album.get_artists()))
return label
def create_length_label(album):
@ -62,9 +57,7 @@ class Utils:
title = track.get_title()
if track.get_artists():
title = locale.gettext("{} feat. {}").format(
title,
", ".join(track.get_artists())
)
title, ", ".join(track.get_artists()))
return title
def generate_id(values):
@ -95,8 +88,7 @@ class GridItem(GObject.GObject):
if cover:
self.cover = Gdk.Texture.new_for_pixbuf(cover)
self.tooltip = GObject.markup_escape_text("\n".join([
album.get_title(),
', '.join(album.get_dates()),
album.get_title(), ', '.join(album.get_dates()),
Utils.create_artists_label(album),
Utils.create_length_label(album)
]))

View file

@ -92,52 +92,35 @@ class Window(Adw.ApplicationWindow):
self._panels.append(self._cover_panel)
# Playlist panel
self._playlist_panel = PlaylistPanel(self._mcg)
self._playlist_panel.connect(
'open-standalone',
self.on_panel_open_standalone
)
self._playlist_panel.connect(
'close-standalone',
self.on_panel_close_standalone
)
self._playlist_panel.connect('open-standalone',
self.on_panel_open_standalone)
self._playlist_panel.connect('close-standalone',
self.on_panel_close_standalone)
self._panels.append(self._playlist_panel)
# Library panel
self._library_panel = LibraryPanel(self._mcg)
self._library_panel.connect(
'open-standalone',
self.on_panel_open_standalone
)
self._library_panel.connect(
'close-standalone',
self.on_panel_close_standalone
)
self._library_panel.connect('open-standalone',
self.on_panel_open_standalone)
self._library_panel.connect('close-standalone',
self.on_panel_close_standalone)
self._panels.append(self._library_panel)
# Stack
self.content_stack.add_child(self._connection_panel)
self.panel_stack.add_titled_with_icon(
self._server_panel,
'server-panel',
locale.gettext("Server"),
"network-wired-symbolic"
)
self.panel_stack.add_titled_with_icon(
self._cover_panel,
'cover-panel',
locale.gettext("Cover"),
"image-x-generic-symbolic"
)
self.panel_stack.add_titled_with_icon(
self._playlist_panel,
'playlist-panel',
locale.gettext("Playlist"),
"view-list-symbolic"
)
self.panel_stack.add_titled_with_icon(
self._library_panel,
'library-panel',
locale.gettext("Library"),
"emblem-music-symbolic"
)
self.panel_stack.add_titled_with_icon(self._server_panel,
'server-panel',
locale.gettext("Server"),
"network-wired-symbolic")
self.panel_stack.add_titled_with_icon(self._cover_panel, 'cover-panel',
locale.gettext("Cover"),
"image-x-generic-symbolic")
self.panel_stack.add_titled_with_icon(self._playlist_panel,
'playlist-panel',
locale.gettext("Playlist"),
"view-list-symbolic")
self.panel_stack.add_titled_with_icon(self._library_panel,
'library-panel',
locale.gettext("Library"),
"emblem-music-symbolic")
# Toolbar stack
self.toolbar_stack.add_child(self._server_panel.get_toolbar())
self.toolbar_stack.add_child(self._cover_panel.get_toolbar())
@ -147,30 +130,21 @@ class Window(Adw.ApplicationWindow):
# Properties
self._set_headerbar_sensitive(False, False)
self._connection_panel.set_host(
self._settings.get_string(Window.SETTING_HOST)
)
self._settings.get_string(Window.SETTING_HOST))
self._connection_panel.set_port(
self._settings.get_int(Window.SETTING_PORT)
)
self._settings.get_int(Window.SETTING_PORT))
if use_keyring:
self._connection_panel.set_password(
keyring.get_password(
ZeroconfProvider.KEYRING_SYSTEM,
ZeroconfProvider.KEYRING_USERNAME
)
)
keyring.get_password(ZeroconfProvider.KEYRING_SYSTEM,
ZeroconfProvider.KEYRING_USERNAME))
self._playlist_panel.set_item_size(
self._settings.get_int(Window.SETTING_ITEM_SIZE)
)
self._settings.get_int(Window.SETTING_ITEM_SIZE))
self._library_panel.set_item_size(
self._settings.get_int(Window.SETTING_ITEM_SIZE)
)
self._settings.get_int(Window.SETTING_ITEM_SIZE))
self._library_panel.set_sort_order(
self._settings.get_enum(Window.SETTING_SORT_ORDER)
)
self._settings.get_enum(Window.SETTING_SORT_ORDER))
self._library_panel.set_sort_type(
self._settings.get_boolean(Window.SETTING_SORT_TYPE)
)
self._settings.get_boolean(Window.SETTING_SORT_TYPE))
# Signals
self.connect("notify::default-width", self.on_resize)
@ -178,131 +152,69 @@ class Window(Adw.ApplicationWindow):
self.connect("notify::maximized", self.on_maximized)
self.connect("notify::fullscreened", self.on_fullscreened)
self._connection_panel.connect(
'connection-changed',
self.on_connection_panel_connection_changed
)
self.panel_stack.connect(
'notify::visible-child',
self.on_stack_switched
)
self._server_panel.connect(
'change-output-device',
self.on_server_panel_output_device_changed
)
self._cover_panel.connect(
'toggle-fullscreen',
self.on_cover_panel_toggle_fullscreen
)
'connection-changed', self.on_connection_panel_connection_changed)
self.panel_stack.connect('notify::visible-child',
self.on_stack_switched)
self._server_panel.connect('change-output-device',
self.on_server_panel_output_device_changed)
self._cover_panel.connect('toggle-fullscreen',
self.on_cover_panel_toggle_fullscreen)
self._cover_panel.connect('set-song', self.on_cover_panel_set_song)
self._cover_panel.connect('albumart', self.on_cover_panel_al