[gnome-music/wip/mschraal/artrework: 22/23] searchview: Use cairo surface instead of pixbuf
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/artrework: 22/23] searchview: Use cairo surface instead of pixbuf
- Date: Tue, 23 Jan 2018 00:41:26 +0000 (UTC)
commit 9c37772f920353422c6928409803b8c1c5947c84
Author: Marinus Schraal <mschraal gnome org>
Date: Sat Jan 20 17:04:00 2018 +0100
searchview: Use cairo surface instead of pixbuf
Surfaces support HiDPI images in Gtk.TreeView.
FIXME: Still a warning being generated
gnomemusic/albumartcache.py | 67 ++++++++++++-----------------------------
gnomemusic/views/baseview.py | 12 ++------
gnomemusic/views/searchview.py | 68 ++++++++++++++++++++++++++++--------------
3 files changed, 66 insertions(+), 81 deletions(-)
---
diff --git a/gnomemusic/albumartcache.py b/gnomemusic/albumartcache.py
index da41b2c..2a1bca0 100644
--- a/gnomemusic/albumartcache.py
+++ b/gnomemusic/albumartcache.py
@@ -206,6 +206,10 @@ class DefaultIcon(GObject.GObject):
class Art(GObject.GObject):
+ __gsignals__ = {
+ 'finished': (GObject.SignalFlags.RUN_FIRST, None, ())
+ }
+
_blacklist = {}
_cache_queue = Queue()
_embedded_queue = Queue()
@@ -235,7 +239,7 @@ class Art(GObject.GObject):
self._scale = scale
@log
- def _start_art_lookup(self):
+ def lookup(self):
if self._in_blacklist():
self._no_art_available()
return
@@ -260,6 +264,8 @@ class Art(GObject.GObject):
surface = _make_icon_frame(pixbuf, self._size, self._scale)
self._surface = surface
+ self.emit('finished')
+
def _embedded_art_found(self, klass):
self._embedded_queue.pop()
@@ -297,6 +303,8 @@ class Art(GObject.GObject):
self._surface = DefaultIcon().get(
DefaultIcon.Type.music, self._size, self._scale)
+ self.emit('finished')
+
def _add_to_blacklist(self):
album = utils.get_album_title(self._media)
artist = utils.get_artist_name(self._media)
@@ -318,6 +326,15 @@ class Art(GObject.GObject):
return False
+ @GObject.Property
+ @log
+ def surface(self):
+ if self._surface is None:
+ self._surface = DefaultIcon().get(
+ DefaultIcon.Type.loading, self._size, self._scale)
+
+ return self._surface
+
class ArtImage(Art):
@@ -356,54 +373,8 @@ class ArtImage(Art):
self._image.set_from_surface(self._surface)
- self._start_art_lookup()
-
-
-class ArtPixbuf(Art):
-
- __gsignals__ = {
- 'finished': (GObject.SignalFlags.RUN_FIRST, None, ())
- }
-
- def __init__(self, size, media, scale=1):
- super().__init__(size, media, scale)
-
- self._iter = None
+ self.lookup()
- def _cache_hit(self, klass, pixbuf):
- super()._cache_hit(klass, pixbuf)
-
- self.emit('finished')
-
- def _no_art_available(self):
- super()._no_art_available()
-
- self.emit('finished')
-
- @GObject.Property
- @log
- def pixbuf(self):
- return Gdk.pixbuf_get_from_surface(
- self._surface, 0, 0, self._surface.get_width(),
- self._surface.get_height())
-
- @pixbuf.setter
- @log
- def pixbuf(self, pixbuf):
- self._surface = DefaultIcon().get(
- DefaultIcon.Type.loading, self._size, self._scale)
-
- self._start_art_lookup()
-
- @GObject.Property(type=Gtk.TreeIter)
- @log
- def iter(self):
- return self._iter
-
- @iter.setter
- @log
- def iter(self, iter_):
- self._iter = iter_
# 1. libmediaart
# 2 embedded -> libmediaart
diff --git a/gnomemusic/views/baseview.py b/gnomemusic/views/baseview.py
index 83cbcea..7b2ac36 100644
--- a/gnomemusic/views/baseview.py
+++ b/gnomemusic/views/baseview.py
@@ -26,7 +26,7 @@ from gettext import gettext as _, ngettext
from gi.repository import Gd, Gdk, GdkPixbuf, GObject, Gtk
from gnomemusic import log
-from gnomemusic.albumartcache import Art, ArtPixbuf
+from gnomemusic.albumartcache import Art
from gnomemusic.grilo import grilo
from gnomemusic.widgets.starhandlerwidget import StarHandlerWidget
import gnomemusic.utils as utils
@@ -227,24 +227,16 @@ class BaseView(Gtk.Stack):
itr = self.model.append(None)
- pixbuf = GdkPixbuf.Pixbuf()
- art = ArtPixbuf(Art.Size.MEDIUM, item)
- art.pixbuf = pixbuf
-
- self.model[itr][0, 1, 2, 3, 4, 5, 7, 9] = [
+ self.model[itr][0, 1, 2, 3, 5, 7, 9] = [
str(item.get_id()),
'',
title,
artist,
- art,
item,
0,
False
]
- art.iter = itr
- art.connect('finished', self._retrieval_finished)
-
@log
def _on_lookup_ready(self, surface, itr):
if surface:
diff --git a/gnomemusic/views/searchview.py b/gnomemusic/views/searchview.py
index b46b6f1..7f04d86 100644
--- a/gnomemusic/views/searchview.py
+++ b/gnomemusic/views/searchview.py
@@ -25,7 +25,7 @@
from gettext import gettext as _
from gi.repository import Gd, GdkPixbuf, GObject, Grl, Gtk, Pango
-from gnomemusic.albumartcache import Art, ArtPixbuf
+from gnomemusic.albumartcache import Art
from gnomemusic.grilo import grilo
from gnomemusic import log
from gnomemusic.player import DiscoveryStatus
@@ -188,8 +188,11 @@ class SearchView(BaseView):
self._add_item(source, None, item, 0, [self.model, 'song'])
@log
- def _retrieval_finished(self, klass):
- self.model[klass.iter][4] = klass.pixbuf
+ def _retrieval_finished(self, klass, model, _iter):
+ if not model[_iter][13]:
+ return
+
+ model[_iter][13] = klass.surface
@log
def _add_item(self, source, param, item, remaining=0, data=None):
@@ -235,18 +238,11 @@ class SearchView(BaseView):
except:
pass
- # FIXME: HiDPI icon lookups return a surface that can't be
- # scaled by GdkPixbuf, so it results in a * scale factor sized
- # icon for the search view.
_iter = None
- scale = self._view.get_scale_factor()
- pixbuf = GdkPixbuf.Pixbuf()
- art = ArtPixbuf(Art.Size.SMALL, item, scale)
- art.pixbuf = pixbuf
if category == 'album':
_iter = self.model.insert_with_values(
- self._head_iters[group], -1, [0, 2, 3, 4, 5, 9, 11],
- [str(item.get_id()), title, artist, art.pixbuf, item, 2,
+ self._head_iters[group], -1, [0, 2, 3, 5, 9, 11],
+ [str(item.get_id()), title, artist, item, 2,
category])
elif category == 'song':
# FIXME: source specific hack
@@ -255,14 +251,14 @@ class SearchView(BaseView):
else:
fav = item.get_favourite()
_iter = self.model.insert_with_values(
- self._head_iters[group], -1, [0, 2, 3, 4, 5, 9, 11],
- [str(item.get_id()), title, artist, art.pixbuf, item, fav,
+ self._head_iters[group], -1, [0, 2, 3, 5, 9, 11],
+ [str(item.get_id()), title, artist, item, fav,
category])
else:
if not artist.casefold() in self._artists:
_iter = self.model.insert_with_values(
- self._head_iters[group], -1, [0, 2, 4, 5, 9, 11],
- [str(item.get_id()), artist, art.pixbuf, item, 2,
+ self._head_iters[group], -1, [0, 2, 5, 9, 11],
+ [str(item.get_id()), artist, item, 2,
category])
self._artists[artist.casefold()] = {
'iter': _iter,
@@ -272,8 +268,13 @@ class SearchView(BaseView):
# FIXME: Figure out why iter can be None here, seems illogical.
if _iter is not None:
- art.iter = _iter
- art.connect('finished', self._retrieval_finished)
+ scale = self._view.get_scale_factor()
+ art = Art(Art.Size.SMALL, item, scale)
+ self.model[_iter][13] = art.surface
+ art.connect(
+ 'finished', self._retrieval_finished, self.model, _iter)
+ art.lookup()
+
if self.model.iter_n_children(self._head_iters[group]) == 1:
path = self.model.get_path(self._head_iters[group])
@@ -294,13 +295,31 @@ class SearchView(BaseView):
title_renderer, self._on_list_widget_title_render, None)
cols[0].add_attribute(title_renderer, 'text', 2)
- self._star_handler.add_star_renderers(list_widget, cols[0])
+ # Add our own surface renderer, instead of the one provided by
+ # Gd. This avoids us having to set the model to a cairo.Surface
+ # which is currently not a working solution in pygobject.
+ # https://gitlab.gnome.org/GNOME/pygobject/issues/155
+ pixbuf_renderer = Gtk.CellRendererPixbuf(
+ xalign=0.5, yalign=0.5, xpad=12, ypad=2)
+ list_widget.add_renderer(
+ pixbuf_renderer, self._on_list_widget_pixbuf_renderer, None)
+ cols[0].add_attribute(pixbuf_renderer, 'surface', 13)
+ self._star_handler.add_star_renderers(list_widget, cols[0])
cells = cols[0].get_cells()
cols[0].reorder(cells[0], -1)
+ cols[0].reorder(cells[4], 1)
cols[0].set_cell_data_func(
cells[0], self._on_list_widget_selection_render, None)
+ @log
+ def _on_list_widget_pixbuf_renderer(self, col, cell, model, _iter, data):
+ if not model[_iter][13]:
+ return
+
+ cell.set_property("surface", model[_iter][13])
+
+ @log
def _on_list_widget_selection_render(self, col, cell, model, _iter, data):
if (self._view.get_selection_mode()
and model.iter_parent(_iter) is not None):
@@ -308,11 +327,13 @@ class SearchView(BaseView):
else:
cell.set_visible(False)
+ @log
def _on_list_widget_title_render(self, col, cell, model, _iter, data):
cells = col.get_cells()
- cells[0].set_visible(model.iter_parent(_iter) is not None)
+ cells[0].set_visible(False)
cells[1].set_visible(model.iter_parent(_iter) is not None)
- cells[2].set_visible(model.iter_parent(_iter) is None)
+ cells[2].set_visible(model.iter_parent(_iter) is not None)
+ cells[3].set_visible(model.iter_parent(_iter) is None)
@log
def populate(self):
@@ -455,7 +476,7 @@ class SearchView(BaseView):
GObject.TYPE_STRING,
GObject.TYPE_STRING, # item title or header text
GObject.TYPE_STRING, # artist for albums and songs
- GdkPixbuf.Pixbuf, # album art
+ GdkPixbuf.Pixbuf, # Gd placeholder album art
GObject.TYPE_OBJECT, # item
GObject.TYPE_BOOLEAN,
GObject.TYPE_INT,
@@ -463,7 +484,8 @@ class SearchView(BaseView):
GObject.TYPE_INT,
GObject.TYPE_BOOLEAN,
GObject.TYPE_STRING, # type
- GObject.TYPE_INT
+ GObject.TYPE_INT,
+ object # album art surface
)
self._filter_model = self.model.filter_new(None)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]