[gnome-music] widgets: Split up the widgets
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music] widgets: Split up the widgets
- Date: Thu, 6 Oct 2016 21:51:00 +0000 (UTC)
commit 03785a4ea8bed25f3d7abf9e48e6e2fb29346075
Author: Marinus Schraal <mschraal src gnome org>
Date: Wed Oct 5 01:49:46 2016 +0200
widgets: Split up the widgets
configure.ac | 1 +
gnomemusic/Makefile.am | 3 +-
gnomemusic/views/albumsview.py | 4 +-
gnomemusic/views/artistsview.py | 4 +-
gnomemusic/views/baseview.py | 4 +-
gnomemusic/views/searchview.py | 7 +-
gnomemusic/widgets.py | 991 ------------------------------
gnomemusic/widgets/Makefile.am | 9 +
gnomemusic/widgets/albumwidget.py | 359 +++++++++++
gnomemusic/widgets/artistalbumswidget.py | 197 ++++++
gnomemusic/widgets/artistalbumwidget.py | 217 +++++++
gnomemusic/widgets/playlistdialog.py | 187 ++++++
gnomemusic/widgets/starhandlerwidget.py | 129 ++++
gnomemusic/window.py | 4 +-
po/POTFILES.in | 6 +-
15 files changed, 1117 insertions(+), 1005 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f23d189..25bd76b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,6 +53,7 @@ AC_CONFIG_FILES([
data/AboutDialog.ui
gnomemusic/Makefile
gnomemusic/views/Makefile
+ gnomemusic/widgets/Makefile
po/Makefile.in
libgd/Makefile
])
diff --git a/gnomemusic/Makefile.am b/gnomemusic/Makefile.am
index 1d3587d..408cfde 100644
--- a/gnomemusic/Makefile.am
+++ b/gnomemusic/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = views
+SUBDIRS = views widgets
appdir = $(pythondir)/gnomemusic/
@@ -14,7 +14,6 @@ app_PYTHON = \
playlists.py\
utils.py \
query.py \
- widgets.py \
searchbar.py \
window.py
diff --git a/gnomemusic/views/albumsview.py b/gnomemusic/views/albumsview.py
index 9f29b19..76e8f85 100644
--- a/gnomemusic/views/albumsview.py
+++ b/gnomemusic/views/albumsview.py
@@ -30,8 +30,8 @@ from gnomemusic.albumartcache import ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.toolbar import ToolbarState
from gnomemusic.views.baseview import BaseView
+from gnomemusic.widgets.albumwidget import AlbumWidget
import gnomemusic.utils as utils
-import gnomemusic.widgets as Widgets
class AlbumsView(BaseView):
@@ -42,7 +42,7 @@ class AlbumsView(BaseView):
@log
def __init__(self, window, player):
BaseView.__init__(self, 'albums', _("Albums"), window, None)
- self._albumWidget = Widgets.AlbumWidget(player, self)
+ self._albumWidget = AlbumWidget(player, self)
self.player = player
self.add(self._albumWidget)
self.albums_selected = []
diff --git a/gnomemusic/views/artistsview.py b/gnomemusic/views/artistsview.py
index fbee543..9d9a51e 100644
--- a/gnomemusic/views/artistsview.py
+++ b/gnomemusic/views/artistsview.py
@@ -28,8 +28,8 @@ from gi.repository import Gd, GLib, Gtk, Pango
from gnomemusic import log
from gnomemusic.grilo import grilo
from gnomemusic.views.baseview import BaseView
+from gnomemusic.widgets.artistalbumswidget import ArtistAlbumsWidget
import gnomemusic.utils as utils
-import gnomemusic.widgets as Widgets
class ArtistsView(BaseView):
@@ -135,7 +135,7 @@ class ArtistsView(BaseView):
artistAlbums = None
- artistAlbums = Widgets.ArtistAlbums(
+ artistAlbums = ArtistAlbumsWidget(
artist, albums, self.player,
self.header_bar, self.selection_toolbar, self.window
)
diff --git a/gnomemusic/views/baseview.py b/gnomemusic/views/baseview.py
index 8aeeab0..68dccfb 100644
--- a/gnomemusic/views/baseview.py
+++ b/gnomemusic/views/baseview.py
@@ -28,7 +28,7 @@ from gi.repository import Gd, Gdk, GdkPixbuf, GObject, Gtk
from gnomemusic import log
from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
from gnomemusic.grilo import grilo
-import gnomemusic.widgets as Widgets
+from gnomemusic.widgets.starhandlerwidget import StarHandlerWidget
import gnomemusic.utils as utils
@@ -86,7 +86,7 @@ class BaseView(Gtk.Stack):
if not use_sidebar or sidebar:
self._grid.add(self._box)
- self.star_handler = Widgets.StarHandler(self, 9)
+ self.star_handler = StarHandlerWidget(self, 9)
self._cursor = None
self.window = window
self.header_bar = window.toolbar
diff --git a/gnomemusic/views/searchview.py b/gnomemusic/views/searchview.py
index 8805990..4b31e1f 100644
--- a/gnomemusic/views/searchview.py
+++ b/gnomemusic/views/searchview.py
@@ -33,8 +33,9 @@ from gnomemusic.playlists import Playlists
from gnomemusic.query import Query
from gnomemusic.toolbar import ToolbarState
from gnomemusic.views.baseview import BaseView
+from gnomemusic.widgets.albumwidget import AlbumWidget
+from gnomemusic.widgets.artistalbumswidget import ArtistAlbumsWidget
import gnomemusic.utils as utils
-import gnomemusic.widgets as Widgets
playlists = Playlists.get_default()
@@ -81,7 +82,7 @@ class SearchView(BaseView):
self.albums_selected = []
self._albums = {}
- self._albumWidget = Widgets.AlbumWidget(player, self)
+ self._albumWidget = AlbumWidget(player, self)
self.add(self._albumWidget)
self.artists_albums_selected = []
@@ -138,7 +139,7 @@ class SearchView(BaseView):
artist = self.model.get_value(_iter, 2)
albums = self._artists[artist.casefold()]['albums']
- self._artistAlbumsWidget = Widgets.ArtistAlbums(
+ self._artistAlbumsWidget = ArtistAlbumsWidget(
artist, albums, self.player,
self.header_bar, self.selection_toolbar, self.window, True
)
diff --git a/gnomemusic/widgets/Makefile.am b/gnomemusic/widgets/Makefile.am
new file mode 100644
index 0000000..8f4d03c
--- /dev/null
+++ b/gnomemusic/widgets/Makefile.am
@@ -0,0 +1,9 @@
+appdir = $(pythondir)/gnomemusic/widgets/
+
+app_PYTHON = \
+ __init__.py \
+ albumwidget.py \
+ artistalbumswidget.py \
+ artistalbumwidget.py \
+ playlistdialog.py \
+ starhandlerwidget.py
diff --git a/gnomemusic/widgets/__init__.py b/gnomemusic/widgets/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/gnomemusic/widgets/albumwidget.py b/gnomemusic/widgets/albumwidget.py
new file mode 100644
index 0000000..d6ed953
--- /dev/null
+++ b/gnomemusic/widgets/albumwidget.py
@@ -0,0 +1,359 @@
+# Copyright (c) 2016 The GNOME Music Developers
+#
+# GNOME Music 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 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music 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 GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+from gettext import gettext as _, ngettext
+from gi.repository import Gd, Gdk, GdkPixbuf, GLib, GObject, Gtk, Pango
+
+from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.grilo import grilo
+from gnomemusic import log
+from gnomemusic.player import DiscoveryStatus
+from gnomemusic.playlists import Playlists, StaticPlaylists
+from gnomemusic.widgets.starhandlerwidget import StarHandlerWidget
+import gnomemusic.utils as utils
+
+NOW_PLAYING_ICON_NAME = 'media-playback-start-symbolic'
+ERROR_ICON_NAME = 'dialog-error-symbolic'
+
+playlists = Playlists.get_default()
+
+
+class AlbumWidget(Gtk.EventBox):
+ """Album widget.
+
+ The album widget consists of an image with the album art
+ on the left and a list of songs on the right.
+ """
+
+ _duration = 0
+
+ def __repr__(self):
+ return '<AlbumWidget>'
+
+ @log
+ def __init__(self, player, parent_view):
+ """Initialize the AlbumWidget.
+
+ :param player: The player object
+ :param parent_view: The view this widget is part of
+ """
+ Gtk.EventBox.__init__(self)
+
+ scale = self.get_scale_factor()
+ self._cache = AlbumArtCache(scale)
+ self._loading_icon_surface = DefaultIcon(scale).get(
+ DefaultIcon.Type.loading,
+ ArtSize.small)
+ self._no_artwork_icon_surface = DefaultIcon(scale).get(
+ DefaultIcon.Type.music,
+ ArtSize.small)
+
+ self._player = player
+ self._iter_to_clean = None
+
+ self._ui = Gtk.Builder()
+ self._ui.add_from_resource('/org/gnome/Music/AlbumWidget.ui')
+ self._create_model()
+ self.view = Gd.MainView(
+ shadow_type=Gtk.ShadowType.NONE
+ )
+ self.view.set_view_type(Gd.MainViewType.LIST)
+ self._album = None
+ self._header_bar = None
+ self.view.connect('item-activated', self._on_item_activated)
+
+ view_box = self._ui.get_object('view')
+ self._ui.get_object('scrolledWindow').set_placement(Gtk.CornerType.
+ TOP_LEFT)
+ self.view.connect('selection-mode-request',
+ self._on_selection_mode_request)
+ child_view = self.view.get_children()[0]
+ child_view.set_margin_top(64)
+ child_view.set_margin_bottom(64)
+ child_view.set_margin_end(32)
+ self.view.remove(child_view)
+ view_box.add(child_view)
+
+ self.add(self._ui.get_object('AlbumWidget'))
+ self._star_handler = StarHandlerWidget(self, 9)
+ self._add_list_renderers()
+ self.get_style_context().add_class('view')
+ self.get_style_context().add_class('content-view')
+ self.view.get_generic_view().get_style_context().remove_class('view')
+ self.show_all()
+
+ @log
+ def _on_selection_mode_request(self, *args):
+ """Selection mode toggled."""
+ self._header_bar._select_button.clicked()
+
+ @log
+ def _on_item_activated(self, widget, id, path):
+ """List row activated."""
+ if self._star_handler.star_renderer_click:
+ self._star_handler.star_renderer_click = False
+ return
+
+ _iter = self.model.get_iter(path)
+
+ if self.model[_iter][10] != DiscoveryStatus.FAILED:
+ if (self._iter_to_clean
+ and self._player.playlistId == self._album):
+ item = self.model[self._iter_to_clean][5]
+ title = utils.get_media_title(item)
+ self.model[self._iter_to_clean][0] = title
+ # Hide now playing icon
+ self.model[self._iter_to_clean][6] = False
+ self._player.set_playlist('Album', self._album, self.model, _iter,
+ 5, 11)
+ self._player.set_playing(True)
+
+ @log
+ def _add_list_renderers(self):
+ """Create the ListView columns."""
+ list_widget = self.view.get_generic_view()
+
+ cols = list_widget.get_columns()
+ cols[0].set_min_width(100)
+ cols[0].set_max_width(200)
+ cells = cols[0].get_cells()
+ cells[2].set_visible(False)
+ cells[1].set_visible(False)
+
+ now_playing_symbol_renderer = Gtk.CellRendererPixbuf(xpad=0,
+ xalign=0.5,
+ yalign=0.5)
+
+ column_now_playing = Gtk.TreeViewColumn()
+ column_now_playing.set_fixed_width(48)
+ column_now_playing.pack_start(now_playing_symbol_renderer, False)
+ column_now_playing.set_cell_data_func(now_playing_symbol_renderer,
+ self._on_list_widget_icon_render,
+ None)
+ list_widget.insert_column(column_now_playing, 0)
+
+ type_renderer = Gd.StyledTextRenderer(
+ xpad=16,
+ ellipsize=Pango.EllipsizeMode.END,
+ xalign=0.0
+ )
+
+ list_widget.add_renderer(type_renderer, lambda *args: None, None)
+ cols[0].clear_attributes(type_renderer)
+ cols[0].add_attribute(type_renderer, 'markup', 0)
+
+ duration_renderer = Gd.StyledTextRenderer(
+ xpad=16,
+ ellipsize=Pango.EllipsizeMode.END,
+ xalign=1.0
+ )
+
+ duration_renderer.add_class('dim-label')
+ list_widget.add_renderer(duration_renderer, lambda *args: None, None)
+ cols[0].clear_attributes(duration_renderer)
+ cols[0].add_attribute(duration_renderer, 'markup', 1)
+
+ self._star_handler.add_star_renderers(list_widget, cols)
+
+ def _on_list_widget_icon_render(self, col, cell, model, _iter, data):
+ if not self._player.currentTrackUri:
+ cell.set_visible(False)
+ return
+
+ if model[_iter][10] == DiscoveryStatus.FAILED:
+ cell.set_property('icon-name', ERROR_ICON_NAME)
+ cell.set_visible(True)
+ elif model[_iter][5].get_url() == self._player.currentTrackUri:
+ cell.set_property('icon-name', NOW_PLAYING_ICON_NAME)
+ cell.set_visible(True)
+ else:
+ cell.set_visible(False)
+
+ @log
+ def _create_model(self):
+ """Create the ListStore model for this widget."""
+ self.model = Gtk.ListStore(
+ GObject.TYPE_STRING, # title
+ GObject.TYPE_STRING,
+ GObject.TYPE_STRING,
+ GObject.TYPE_STRING,
+ GdkPixbuf.Pixbuf, # icon
+ GObject.TYPE_OBJECT, # song object
+ GObject.TYPE_BOOLEAN, # item selected
+ GObject.TYPE_STRING,
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT, # icon shown
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
+ )
+
+ @log
+ def update(self, artist, album, item, header_bar, selection_toolbar):
+ """Update the album widget.
+
+ :param str artist: The artist name
+ :param str album: The album name
+ :param item: The grilo media item
+ :param header_bar: The header bar object
+ :param selection_toolbar: The selection toolbar object
+ """
+ self.selection_toolbar = selection_toolbar
+ self._header_bar = header_bar
+ self._album = album
+ self._ui.get_object('cover').set_from_surface(
+ self._loading_icon_surface)
+ self._cache.lookup(item, ArtSize.large, self._on_lookup, None)
+ self._duration = 0
+ self._create_model()
+ GLib.idle_add(grilo.populate_album_songs, item, self.add_item)
+ header_bar._select_button.connect(
+ 'toggled', self._on_header_select_button_toggled)
+ header_bar._cancel_button.connect(
+ 'clicked', self._on_header_cancel_button_clicked)
+ self.view.connect('view-selection-changed',
+ self._on_view_selection_changed)
+ self.view.set_model(self.model)
+ escaped_artist = GLib.markup_escape_text(artist)
+ escaped_album = GLib.markup_escape_text(album)
+ self._ui.get_object('artist_label').set_markup(escaped_artist)
+ self._ui.get_object('title_label').set_markup(escaped_album)
+ if (item.get_creation_date()):
+ self._ui.get_object('released_label_info').set_text(
+ str(item.get_creation_date().get_year()))
+ else:
+ self._ui.get_object('released_label_info').set_text('----')
+ self._player.connect('playlist-item-changed', self._update_model)
+
+ @log
+ def _on_view_selection_changed(self, widget):
+ items = self.view.get_selection()
+ self.selection_toolbar._add_to_playlist_button.set_sensitive(
+ len(items) > 0)
+ if len(items) > 0:
+ self._header_bar._selection_menu_label.set_text(
+ ngettext("Selected %d item", "Selected %d items",
+ len(items)) % len(items))
+ else:
+ self._header_bar._selection_menu_label.set_text(
+ _("Click on items to select them"))
+
+ @log
+ def _on_header_cancel_button_clicked(self, button):
+ """Cancel selection mode callback."""
+ self.view.set_selection_mode(False)
+ self._header_bar.set_selection_mode(False)
+ self._header_bar.header_bar.title = self._album
+
+ @log
+ def _on_header_select_button_toggled(self, button):
+ """Selection mode button clicked callback."""
+ if button.get_active():
+ self.view.set_selection_mode(True)
+ self._header_bar.set_selection_mode(True)
+ self._player.actionbar.set_visible(False)
+ self.selection_toolbar.actionbar.set_visible(True)
+ self.selection_toolbar._add_to_playlist_button.set_sensitive(False)
+ self._header_bar.header_bar.set_custom_title(
+ self._header_bar._selection_menu_button)
+ else:
+ self.view.set_selection_mode(False)
+ self._header_bar.set_selection_mode(False)
+ self._header_bar.title = self._album
+ self.selection_toolbar.actionbar.set_visible(False)
+ if(self._player.get_playback_status() != 2):
+ self._player.actionbar.set_visible(True)
+
+ @log
+ def add_item(self, source, prefs, track, remaining, data=None):
+ """Add a song to the item to album list.
+
+ :param source: The grilo source
+ :param prefs:
+ :param track: The grilo media object
+ :param remaining: Remaining number of items to add
+ :param data: User data
+ """
+ if track:
+ self._duration = self._duration + track.get_duration()
+ _iter = self.model.append()
+ title = utils.get_media_title(track)
+ escaped_title = GLib.markup_escape_text(title)
+ self.model[_iter][0, 1, 2, 3, 4, 5, 9] = [
+ escaped_title,
+ self._player.seconds_to_string(track.get_duration()),
+ '',
+ '',
+ None,
+ track,
+ bool(track.get_lyrics())
+ ]
+ self._ui.get_object('running_length_label_info').set_text(
+ _("%d min") % (int(self._duration / 60) + 1))
+
+ @log
+ def _on_lookup(self, surface, data=None):
+ """Albumart retrieved callback.
+
+ :param surface: The Cairo surface retrieved
+ :param path: The filesystem location the pixbuf
+ :param data: User data
+ """
+ if not surface:
+ surface = self._no_artwork_icon_surface
+ self._ui.get_object('cover').set_from_surface(surface)
+
+ @log
+ def _update_model(self, player, playlist, current_iter):
+ """Player changed callback.
+
+ :param player: The player object
+ :param playlist: The current playlist
+ :param current_iter: The current iter of the playlist model
+ """
+ # self is not our playlist, return
+ if (playlist != self.model):
+ return False
+
+ current_song = playlist[current_iter][5]
+ song_passed = False
+ _iter = playlist.get_iter_first()
+ self._duration = 0
+
+ while _iter:
+ song = playlist[_iter][5]
+ self._duration += song.get_duration()
+ escaped_title = GLib.markup_escape_text(utils.get_media_title(song))
+ if (song == current_song):
+ title = '<b>%s</b>' % escaped_title
+ song_passed = True
+ elif (song_passed):
+ title = '<span>%s</span>' % escaped_title
+ else:
+ title = '<span color=\'grey\'>%s</span>' % escaped_title
+ playlist[_iter][0] = title
+ _iter = playlist.iter_next(_iter)
+ self._ui.get_object('running_length_label_info').set_text(
+ _("%d min") % (int(self._duration / 60) + 1))
+
+ return False
diff --git a/gnomemusic/widgets/artistalbumswidget.py b/gnomemusic/widgets/artistalbumswidget.py
new file mode 100644
index 0000000..99a9f00
--- /dev/null
+++ b/gnomemusic/widgets/artistalbumswidget.py
@@ -0,0 +1,197 @@
+# Copyright (c) 2016 The GNOME Music Developers
+#
+# GNOME Music 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 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music 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 GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+import logging
+
+from gettext import gettext as _, ngettext
+from gi.repository import GLib, GObject, Gtk
+
+from gnomemusic import log
+from gnomemusic.widgets.artistalbumwidget import ArtistAlbumWidget
+import gnomemusic.utils as utils
+
+logger = logging.getLogger(__name__)
+
+
+class ArtistAlbumsWidget(Gtk.Box):
+
+ def __repr__(self):
+ return '<ArtistAlbumsWidget>'
+
+ @log
+ def __init__(self, artist, albums, player,
+ header_bar, selection_toolbar, window, selectionModeAllowed=False):
+ Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
+ self.player = player
+ self.artist = artist
+ self.albums = albums
+ self.window = window
+ self.selectionMode = False
+ self.selectionModeAllowed = selectionModeAllowed
+ self.selection_toolbar = selection_toolbar
+ self.header_bar = header_bar
+ self.ui = Gtk.Builder()
+ self.ui.add_from_resource('/org/gnome/Music/ArtistAlbumsWidget.ui')
+ self.set_border_width(0)
+ self.ui.get_object('artist').set_label(self.artist)
+ self.widgets = []
+
+ self.model = Gtk.ListStore(GObject.TYPE_STRING, # title
+ GObject.TYPE_STRING,
+ GObject.TYPE_STRING,
+ GObject.TYPE_BOOLEAN, # icon shown
+ GObject.TYPE_STRING, # icon
+ GObject.TYPE_OBJECT, # song object
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
+ )
+ self.row_changed_source_id = None
+
+ self._hbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+ self._albumBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
+ spacing=48)
+ self._scrolledWindow = Gtk.ScrolledWindow()
+ self._scrolledWindow.set_policy(
+ Gtk.PolicyType.NEVER,
+ Gtk.PolicyType.AUTOMATIC)
+ self._scrolledWindow.add(self._hbox)
+ self._hbox.pack_start(self.ui.get_object('ArtistAlbumsWidget'),
+ False, False, 0)
+ self._hbox.pack_start(self._albumBox, False, False, 16)
+ self._coverSizeGroup = Gtk.SizeGroup.new(Gtk.SizeGroupMode.HORIZONTAL)
+ self._songsGridSizeGroup = Gtk.SizeGroup.new(Gtk.SizeGroupMode.HORIZONTAL)
+ self.pack_start(self._scrolledWindow, True, True, 0)
+
+ self.hide()
+ self.window._init_loading_notification()
+
+ for album in albums:
+ is_last_album = False
+ if album == albums[-1]:
+ is_last_album = True
+ self.add_album(album, is_last_album)
+
+ self.player.connect('playlist-item-changed', self.update_model)
+
+ def _on_last_album_displayed(self, data=None):
+ self.window.notification.dismiss()
+ self.show_all()
+
+ @log
+ def add_album(self, album, is_last_album=False):
+ self.window.notification.set_timeout(0)
+ widget = ArtistAlbumWidget(
+ self.artist, album, self.player, self.model,
+ self.header_bar, self.selectionModeAllowed
+ )
+ self._coverSizeGroup.add_widget(widget.cover)
+ self._songsGridSizeGroup.add_widget(widget.songsGrid)
+ self._albumBox.pack_start(widget, False, False, 0)
+ self.widgets.append(widget)
+
+ if is_last_album:
+ widget.connect('tracks-loaded', self._on_last_album_displayed)
+
+ @log
+ def update_model(self, player, playlist, currentIter):
+ # this is not our playlist, return
+ if playlist != self.model:
+ # TODO, only clean once, but that can wait util we have clean
+ # the code a bit, and until the playlist refactoring.
+ # the overhead is acceptable for now
+ self.clean_model()
+ return False
+
+ currentSong = playlist.get_value(currentIter, 5)
+ song_passed = False
+ itr = playlist.get_iter_first()
+
+ while itr:
+ song = playlist.get_value(itr, 5)
+ song_widget = song.song_widget
+
+ if not song_widget.can_be_played:
+ itr = playlist.iter_next(itr)
+ continue
+
+ escaped_title = GLib.markup_escape_text(utils.get_media_title(song))
+ if (song == currentSong):
+ song_widget.now_playing_sign.show()
+ song_widget.title.set_markup('<b>%s</b>' % escaped_title)
+ song_passed = True
+ elif (song_passed):
+ song_widget.now_playing_sign.hide()
+ song_widget.title.set_markup('<span>%s</span>' % escaped_title)
+ else:
+ song_widget.now_playing_sign.hide()
+ song_widget.title.set_markup(
+ '<span color=\'grey\'>%s</span>' % escaped_title
+ )
+ itr = playlist.iter_next(itr)
+ return False
+
+ @log
+ def clean_model(self):
+ itr = self.model.get_iter_first()
+ while itr:
+ song = self.model.get_value(itr, 5)
+ song_widget = song.song_widget
+ escaped_title = GLib.markup_escape_text(utils.get_media_title(song))
+ if song_widget.can_be_played:
+ song_widget.now_playing_sign.hide()
+ song_widget.title.set_markup('<span>%s</span>' % escaped_title)
+ itr = self.model.iter_next(itr)
+ return False
+
+ @log
+ def set_selection_mode(self, selectionMode):
+ if self.selectionMode == selectionMode:
+ return
+ self.selectionMode = selectionMode
+ try:
+ if self.row_changed_source_id:
+ self.model.disconnect(self.row_changed_source_id)
+ self.row_changed_source_id = self.model.connect('row-changed', self._model_row_changed)
+ except Exception as e:
+ logger.warning("Exception while tracking row-changed: %s", e)
+
+ for widget in self.widgets:
+ widget.set_selection_mode(selectionMode)
+
+ @log
+ def _model_row_changed(self, model, path, _iter):
+ if not self.selectionMode:
+ return
+ selected_items = 0
+ for row in model:
+ if row[6]:
+ selected_items += 1
+ self.selection_toolbar\
+ ._add_to_playlist_button.set_sensitive(selected_items > 0)
+ if selected_items > 0:
+ self.header_bar._selection_menu_label.set_text(
+ ngettext("Selected %d item", "Selected %d items", selected_items) % selected_items)
+ else:
+ self.header_bar._selection_menu_label.set_text(_("Click on items to select them"))
+
diff --git a/gnomemusic/widgets/artistalbumwidget.py b/gnomemusic/widgets/artistalbumwidget.py
new file mode 100644
index 0000000..41016fa
--- /dev/null
+++ b/gnomemusic/widgets/artistalbumwidget.py
@@ -0,0 +1,217 @@
+# Copyright (c) 2016 The GNOME Music Developers
+#
+# GNOME Music 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 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music 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 GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+import logging
+
+from gettext import gettext as _
+from gi.repository import Gdk, Gio, GLib, GObject, Gtk
+
+from gnomemusic import log
+from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.grilo import grilo
+from gnomemusic.player import DiscoveryStatus
+from gnomemusic.playlists import Playlists
+import gnomemusic.utils as utils
+
+logger = logging.getLogger(__name__)
+
+NOW_PLAYING_ICON_NAME = 'media-playback-start-symbolic'
+ERROR_ICON_NAME = 'dialog-error-symbolic'
+
+try:
+ settings = Gio.Settings.new('org.gnome.Music')
+ MAX_TITLE_WIDTH = settings.get_int('max-width-chars')
+except Exception as e:
+ MAX_TITLE_WIDTH = 20
+ logger.error("Error on setting widget max-width-chars: %s", str(e))
+
+playlists = Playlists.get_default()
+
+
+class ArtistAlbumWidget(Gtk.Box):
+
+ __gsignals__ = {
+ 'tracks-loaded': (GObject.SignalFlags.RUN_FIRST, None, ()),
+ }
+
+ def __repr__(self):
+ return '<ArtistAlbumWidget>'
+
+ @log
+ def __init__(self, artist, album, player, model, header_bar, selectionModeAllowed):
+ Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
+
+ scale = self.get_scale_factor()
+ self._cache = AlbumArtCache(scale)
+
+ self._loading_icon_surface = DefaultIcon(scale).get(
+ DefaultIcon.Type.loading,
+ ArtSize.large)
+ self._no_artwork_icon_surface = DefaultIcon(scale).get(
+ DefaultIcon.Type.music,
+ ArtSize.large)
+
+ self.player = player
+ self.album = album
+ self.artist = artist
+ self.model = model
+ self.model.connect('row-changed', self._model_row_changed)
+ self.header_bar = header_bar
+ self.selectionMode = False
+ self.selectionModeAllowed = selectionModeAllowed
+ self.songs = []
+ self.ui = Gtk.Builder()
+ self.ui.add_from_resource('/org/gnome/Music/ArtistAlbumWidget.ui')
+
+ GLib.idle_add(self._update_album_art)
+
+ self.cover = self.ui.get_object('cover')
+ self.cover.set_from_surface(self._loading_icon_surface)
+ self.songsGrid = self.ui.get_object('grid1')
+ self.ui.get_object('title').set_label(album.get_title())
+ if album.get_creation_date():
+ self.ui.get_object('year').set_markup(
+ '<span color=\'grey\'>(%s)</span>' %
+ str(album.get_creation_date().get_year())
+ )
+ self.tracks = []
+ grilo.populate_album_songs(album, self.add_item)
+ self.pack_start(self.ui.get_object('ArtistAlbumWidget'), True, True, 0)
+
+ @log
+ def add_item(self, source, prefs, track, remaining, data=None):
+ if remaining == 0:
+ self.songsGrid.show_all()
+ self.emit("tracks-loaded")
+
+ if track:
+ self.tracks.append(track)
+ else:
+ for i, track in enumerate(self.tracks):
+ ui = Gtk.Builder()
+ ui.add_from_resource('/org/gnome/Music/TrackWidget.ui')
+ song_widget = ui.get_object('eventbox1')
+ self.songs.append(song_widget)
+ ui.get_object('num')\
+ .set_markup('<span color=\'grey\'>%d</span>'
+ % len(self.songs))
+ title = utils.get_media_title(track)
+ ui.get_object('title').set_text(title)
+ ui.get_object('title').set_alignment(0.0, 0.5)
+ ui.get_object('title').set_max_width_chars(MAX_TITLE_WIDTH)
+
+ self.songsGrid.attach(
+ song_widget,
+ int(i / (len(self.tracks) / 2)),
+ int(i % (len(self.tracks) / 2)), 1, 1
+ )
+ track.song_widget = song_widget
+ itr = self.model.append(None)
+ song_widget._iter = itr
+ song_widget.model = self.model
+ song_widget.title = ui.get_object('title')
+ song_widget.checkButton = ui.get_object('select')
+ song_widget.checkButton.set_visible(self.selectionMode)
+ song_widget.checkButton.connect(
+ 'toggled', self._check_button_toggled, song_widget
+ )
+ self.model.set(itr,
+ [0, 1, 2, 3, 5],
+ [title, '', '', False, track])
+ song_widget.now_playing_sign = ui.get_object('image1')
+ song_widget.now_playing_sign.set_from_icon_name(
+ NOW_PLAYING_ICON_NAME,
+ Gtk.IconSize.SMALL_TOOLBAR)
+ song_widget.now_playing_sign.set_no_show_all('True')
+ song_widget.now_playing_sign.set_alignment(1, 0.6)
+ song_widget.can_be_played = True
+ song_widget.connect('button-release-event',
+ self.track_selected)
+
+ @log
+ def _update_album_art(self):
+ self._cache.lookup(self.album, ArtSize.medium, self._get_album_cover,
+ None)
+
+ @log
+ def _get_album_cover(self, surface, data=None):
+ if not surface:
+ surface = self._no_artwork_icon_surface
+ self.cover.set_from_surface(surface)
+
+ @log
+ def track_selected(self, widget, event):
+ if not widget.can_be_played:
+ return
+
+ if not self.selectionMode and \
+ (event.button == Gdk.BUTTON_SECONDARY or
+ (event.button == 1 and event.state & Gdk.ModifierType.CONTROL_MASK)):
+ if self.selectionModeAllowed:
+ self.header_bar._select_button.set_active(True)
+ else:
+ return
+
+ if self.selectionMode:
+ self.model[widget._iter][6] = not self.model[widget._iter][6]
+ return
+
+ self.player.stop()
+ self.player.set_playlist('Artist', self.artist,
+ widget.model, widget._iter, 5, 6)
+ self.player.set_playing(True)
+
+ @log
+ def set_selection_mode(self, selectionMode):
+ if self.selectionMode == selectionMode:
+ return
+ self.selectionMode = selectionMode
+ for songWidget in self.songs:
+ songWidget.checkButton.set_visible(selectionMode)
+ if not selectionMode:
+ songWidget.model[songWidget._iter][6] = False
+
+ @log
+ def _check_button_toggled(self, button, songWidget):
+ if songWidget.model[songWidget._iter][6] != button.get_active():
+ songWidget.model[songWidget._iter][6] = button.get_active()
+
+ @log
+ def _model_row_changed(self, model, path, _iter):
+ if not self.selectionMode:
+ return
+ if not model[_iter][5]:
+ return
+ songWidget = model[_iter][5].song_widget
+ selected = model[_iter][6]
+
+ if model[_iter][11] == DiscoveryStatus.FAILED:
+ songWidget.now_playing_sign.set_from_icon_name(
+ ERROR_ICON_NAME,
+ Gtk.IconSize.SMALL_TOOLBAR)
+ songWidget.now_playing_sign.show()
+ songWidget.can_be_played = False
+
+ if selected != songWidget.checkButton.get_active():
+ songWidget.checkButton.set_active(selected)
diff --git a/gnomemusic/widgets/playlistdialog.py b/gnomemusic/widgets/playlistdialog.py
new file mode 100644
index 0000000..93d9d70
--- /dev/null
+++ b/gnomemusic/widgets/playlistdialog.py
@@ -0,0 +1,187 @@
+# Copyright (c) 2016 The GNOME Music Developers
+#
+# GNOME Music 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 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music 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 GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+from gi.repository import Gtk, Gd, GLib, Pango, Gio
+
+from gnomemusic import log
+from gnomemusic.grilo import grilo
+from gnomemusic.playlists import Playlists
+import gnomemusic.utils as utils
+
+
+class PlaylistDialog():
+
+ def __repr__(self):
+ return '<PlaylistDialog>'
+
+ @log
+ def __init__(self, parent):
+ self.ui = Gtk.Builder()
+ self.ui.add_from_resource('/org/gnome/Music/PlaylistDialog.ui')
+ self.dialog_box = self.ui.get_object('dialog1')
+ self.dialog_box.set_transient_for(parent)
+
+ self.view = self.ui.get_object('treeview1')
+ self.view.set_activate_on_single_click(False)
+ self.selection = self.ui.get_object('treeview-selection1')
+ self.selection.connect('changed', self._on_selection_changed)
+ self._add_list_renderers()
+ self.view.connect('row-activated', self._on_item_activated)
+
+ self.model = self.ui.get_object('liststore1')
+ self.populate()
+
+ self.title_bar = self.ui.get_object('headerbar1')
+ self.dialog_box.set_titlebar(self.title_bar)
+
+ self._cancel_button = self.ui.get_object('cancel-button')
+ self._select_button = self.ui.get_object('select-button')
+ self._select_button.set_sensitive(False)
+ self._cancel_button.connect('clicked', self._on_cancel_button_clicked)
+ self._select_button.connect('clicked', self._on_selection)
+
+ self._new_playlist_button = self.ui.get_object('new-playlist-button')
+ self._new_playlist_button.connect('clicked', self._on_editing_done)
+
+ self._new_playlist_entry = self.ui.get_object('new-playlist-entry')
+ self._new_playlist_entry.connect('changed',
+ self._on_new_playlist_entry_changed)
+ self._new_playlist_entry.connect('activate',
+ self._on_editing_done)
+ self._new_playlist_entry.connect('focus-in-event',
+ self._on_new_playlist_entry_focused)
+
+ self.playlist = Playlists.get_default()
+ self.playlist.connect('playlist-created', self._on_playlist_created)
+
+ @log
+ def get_selected(self):
+ _iter = self.selection.get_selected()[1]
+
+ if not _iter or self.model[_iter][1]:
+ return None
+
+ return self.model[_iter][2]
+
+ @log
+ def _add_list_renderers(self):
+ cols = Gtk.TreeViewColumn()
+ type_renderer = Gd.StyledTextRenderer(
+ xpad=8,
+ ypad=8,
+ ellipsize=Pango.EllipsizeMode.END,
+ xalign=0.0
+ )
+ cols.pack_start(type_renderer, True)
+ cols.add_attribute(type_renderer, "text", 0)
+ cols.set_cell_data_func(type_renderer, self._on_list_text_render)
+ self.view.append_column(cols)
+
+ @log
+ def populate(self):
+ if grilo.tracker:
+ GLib.idle_add(grilo.populate_playlists, 0, self._add_item)
+
+ @log
+ def _add_item(self, source, param, item, remaining=0, data=None):
+ if item:
+ self._add_item_to_model(item)
+
+ @log
+ def _add_item_to_model(self, item):
+ """Adds (non-static only) playlists to the model"""
+
+ # Don't show static playlists
+ if self.playlist.is_static_playlist(item):
+ return None
+
+ new_iter = self.model.append()
+ self.model.set(
+ new_iter,
+ [0, 1, 2],
+ [utils.get_media_title(item), False, item]
+ )
+ return new_iter
+
+ @log
+ def _on_list_text_render(self, col, cell, model, _iter, data):
+ editable = model.get_value(_iter, 1)
+ if editable:
+ cell.add_class("dim-label")
+ else:
+ cell.remove_class("dim-label")
+
+ @log
+ def _on_selection(self, select_button):
+ self.dialog_box.response(Gtk.ResponseType.ACCEPT)
+
+ @log
+ def _on_cancel_button_clicked(self, cancel_button):
+ self.dialog_box.response(Gtk.ResponseType.REJECT)
+
+ @log
+ def _on_item_activated(self, view, path, column):
+ self._new_playlist_entry.set_text("")
+ self._new_playlist_button.set_sensitive(False)
+ _iter = self.model.get_iter(path)
+ if self.model.get_value(_iter, 1):
+ self.view.set_cursor(path, column, True)
+ else:
+ self.dialog_box.response(Gtk.ResponseType.ACCEPT)
+
+ @log
+ def _on_selection_changed(self, selection):
+ model, _iter = self.selection.get_selected()
+
+ if _iter == None or self.model.get_value(_iter, 1):
+ self._select_button.set_sensitive(False)
+ else:
+ self._select_button.set_sensitive(True)
+
+
+ @log
+ def _on_editing_done(self, sender, data=None):
+ if self._new_playlist_entry.get_text() != '':
+ self.playlist.create_playlist(self._new_playlist_entry.get_text())
+
+ @log
+ def _on_playlist_created(self, playlists, item):
+ new_iter = self._add_item_to_model(item)
+ if new_iter and self.view.get_columns():
+ self.view.set_cursor(self.model.get_path(new_iter),
+ self.view.get_columns()[0], False)
+ self.view.row_activated(self.model.get_path(new_iter),
+ self.view.get_columns()[0])
+ self.dialog_box.response(Gtk.ResponseType.ACCEPT)
+
+ @log
+ def _on_new_playlist_entry_changed(self, editable, data=None):
+ if editable.get_text() != '':
+ self._new_playlist_button.set_sensitive(True)
+ else:
+ self._new_playlist_button.set_sensitive(False)
+
+ @log
+ def _on_new_playlist_entry_focused(self, editable, data=None):
+ self.selection.unselect_all()
diff --git a/gnomemusic/widgets/starhandlerwidget.py b/gnomemusic/widgets/starhandlerwidget.py
new file mode 100644
index 0000000..87d738b
--- /dev/null
+++ b/gnomemusic/widgets/starhandlerwidget.py
@@ -0,0 +1,129 @@
+# Copyright (c) 2016 The GNOME Music Developers
+#
+# GNOME Music 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 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music 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 GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+from gi.repository import GObject, Gtk
+
+from gnomemusic import log
+from gnomemusic.grilo import grilo
+from gnomemusic.playlists import Playlists, StaticPlaylists
+
+playlists = Playlists.get_default()
+
+
+class CellRendererClickablePixbuf(Gtk.CellRendererPixbuf):
+
+ __gsignals__ = {'clicked': (GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE,
+ (GObject.TYPE_STRING,))}
+ __gproperties__ = {
+ 'show_star': (GObject.TYPE_INT, 'Show star', 'show star',0 ,2 ,1 , GObject.ParamFlags.READWRITE)}
+
+ starIcon = 'starred-symbolic'
+ nonStarIcon = 'non-starred-symbolic'
+
+ def __repr__(self):
+ return '<CellRendererClickablePixbuf>'
+
+ def __init__(self, view, hidden=False, *args, **kwargs):
+ Gtk.CellRendererPixbuf.__init__(self, *args, **kwargs)
+ self.set_property('mode', Gtk.CellRendererMode.ACTIVATABLE)
+ self.set_property('xpad', 32)
+ self.set_property('icon_name', '')
+ self.view = view
+ self.hidden = hidden
+ self.show_star = 0
+
+ def do_activate(self, event, widget, path, background_area, cell_area, flags):
+ self.show_star = 0
+ self.emit('clicked', path)
+
+ def do_get_property(self, property):
+ if property.name == 'show-star':
+ return self.show_star
+
+ def do_set_property(self, property, value):
+ if property.name == 'show-star':
+ if self.show_star == 1:
+ self.set_property('icon_name', self.starIcon)
+ elif self.show_star == 0:
+ self.set_property('icon_name', self.nonStarIcon)
+ else:
+ self.set_property('icon_name', '')
+ self.show_star = value
+
+
+class StarHandlerWidget(object):
+ """Handles the treeview column for favorites (stars)."""
+
+ def __repr__(self):
+ return '<StarHandlerWidget>'
+
+ @log
+ def __init__(self, parent, star_index):
+ """Initialize.
+
+ :param parent: The parent widget
+ :param int star_index: The column of the stars
+ """
+ self.star_renderer_click = False
+ self._star_index = star_index
+ self._parent = parent
+
+ @log
+ def add_star_renderers(self, list_widget, cols, hidden=False):
+ """Adds the star renderer column
+
+ :param list_widget: The widget to add the favorites column
+ :param cols: List of the widgets GtkTreeViewColumns
+ :param hidden: Visible state of the column
+ """
+ star_renderer = CellRendererClickablePixbuf(self._parent.view,
+ hidden=hidden)
+ star_renderer.connect("clicked", self._on_star_toggled)
+ list_widget.add_renderer(star_renderer, lambda *args: None, None)
+
+ cols[0].clear_attributes(star_renderer)
+ cols[0].add_attribute(star_renderer, 'show_star', self._star_index)
+
+ @log
+ def _on_star_toggled(self, widget, path):
+ """Called if a star is clicked"""
+ try:
+ _iter = self._parent.model.get_iter(path)
+ except TypeError:
+ return
+
+ try:
+ if self._parent.model[_iter][9] == 2:
+ return
+ except AttributeError:
+ return
+
+ new_value = not self._parent.model[_iter][self._star_index]
+ self._parent.model[_iter][self._star_index] = new_value
+ song_item = self._parent.model[_iter][5]
+ grilo.toggle_favorite(song_item)
+ playlists.update_static_playlist(StaticPlaylists.Favorites)
+
+ # Use this flag to ignore the upcoming _on_item_activated call
+ self.star_renderer_click = True
diff --git a/gnomemusic/window.py b/gnomemusic/window.py
index cdea156..a1acbb7 100644
--- a/gnomemusic/window.py
+++ b/gnomemusic/window.py
@@ -45,7 +45,7 @@ from gnomemusic.views.emptysearchview import EmptySearchView
from gnomemusic.views.searchview import SearchView
from gnomemusic.views.songsview import SongsView
from gnomemusic.views.playlistview import PlaylistView
-import gnomemusic.widgets as Widgets
+from gnomemusic.widgets.playlistdialog import PlaylistDialog
from gnomemusic.playlists import Playlists
from gnomemusic.grilo import grilo
@@ -518,7 +518,7 @@ class Window(Gtk.ApplicationWindow):
if len(selected_tracks) < 1:
return
- add_to_playlist = Widgets.PlaylistDialog(self)
+ add_to_playlist = PlaylistDialog(self)
if add_to_playlist.dialog_box.run() == Gtk.ResponseType.ACCEPT:
playlist.add_to_playlist(
add_to_playlist.get_selected(),
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3b77d1f..0a754ce 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -24,7 +24,11 @@ gnomemusic/views/initialstateview.py
gnomemusic/views/playlistview.py
gnomemusic/views/searchview.py
gnomemusic/views/songsview.py
-gnomemusic/widgets.py
+gnomemusic/widgets/albumwidget.py
+gnomemusic/widgets/artistalbumswidget.py
+gnomemusic/widgets/artistalbumwidget.py
+gnomemusic/widgets/playlistdialog.py
+gnomemusic/widgets/starhandlerwidget.py
gnomemusic/window.py
[type: gettext/glade]data/AboutDialog.ui.in
[type: gettext/glade]data/AlbumWidget.ui
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]