Beispiel #1
0
 def _set_content(self, content, stream):
     """
         Set content
         @param content as string
         @param data as Gio.MemoryInputStream
     """
     if content is not None:
         self._content.set_markup(escape(content.decode('utf-8')))
         if stream is not None:
             scale = self._image.get_scale_factor()
             pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                        stream,
                        Lp().settings.get_value(
                                     'cover-size').get_int32() + 50 * scale,
                        -1,
                        True,
                        None)
             surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, None)
             del pixbuf
             self._image.set_from_surface(surface)
             del surface
             self._image.show()
         self.set_visible_child_name('widget')
     else:
         self._on_not_found()
     self._spinner.stop()
Beispiel #2
0
def getIcon(item, widget):
    wrapper = SurfaceWrapper(None)
    pixbuf = None
    if item is None:
        return wrapper

    if isinstance(item, CMenu.TreeDirectory):
        gicon = item.get_icon()
    elif isinstance(item, CMenu.TreeEntry):
        app_info = item.get_app_info()
        gicon = app_info.get_icon()
    else:
        return wrapper

    if gicon is None:
        return wrapper

    icon_theme = Gtk.IconTheme.get_default()
    size = 24 * widget.get_scale_factor()
    info = icon_theme.lookup_by_gicon(gicon, size, 0)
    if info is None:
        return wrapper
    try:
        pixbuf = info.load_icon()
    except GLib.GError:
        return wrapper
    if pixbuf is None:
        return wrapper
    if pixbuf.get_width() != size or pixbuf.get_height() != size:
        pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.HYPER)

    wrapper.surface = Gdk.cairo_surface_create_from_pixbuf (pixbuf, widget.get_scale_factor(), widget.get_window())
    return wrapper
    def set_image_internal(self, path):
        pixbuf = None
        scaled_max_size = self.max_size * self.get_scale_factor()

        try:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
        except GLib.Error as e:
            message = "Could not load pixbuf from '%s' for FramedImage: %s" % (path, e.message)
            error = True

        if pixbuf != None:
            if (pixbuf.get_height() > scaled_max_size or pixbuf.get_width() > scaled_max_size) or \
               (self.scale_up and (pixbuf.get_height() < scaled_max_size / 2 or pixbuf.get_width() < scaled_max_size / 2)):
                try:
                    pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path, scaled_max_size, scaled_max_size)
                except GLib.Error as e:
                    message = "Could not scale pixbuf from '%s' for FramedImage: %s" % (path, e.message)
                    error = True

        if pixbuf:
            surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf,
                                                           self.get_scale_factor(),
                                                           self.get_window())
            self.set_from_surface(surface)
            self.emit("surface-changed", surface)
        else:
            print(message)
            self.clear_image()
Beispiel #4
0
 def _set_content(self, content, stream):
     """
         Set content
         @param content as string
         @param data as Gio.MemoryInputStream
     """
     # Happens if widget is destroyed while loading content from the web
     if self.get_child_by_name('widget') is None:
         return
     if content is not None:
         self._content.set_markup(escape(content.decode('utf-8')))
         if stream is not None:
             scale = self._image.get_scale_factor()
             pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                        stream,
                        Lp().settings.get_value(
                                     'cover-size').get_int32() + 50 * scale,
                        -1,
                        True,
                        None)
             surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, None)
             del pixbuf
             self._image.set_from_surface(surface)
             del surface
             self._image_frame.show()
         self.set_visible_child_name('widget')
     else:
         self.set_visible_child_name('notfound')
Beispiel #5
0
 def __set_content(self, content, stream):
     """
         Set content
         @param content as string
         @param data as Gio.MemoryInputStream
     """
     if content is not None:
         self.__content.set_markup(
                           GLib.markup_escape_text(content.decode('utf-8')))
         if stream is not None:
             scale = self.__image.get_scale_factor()
             # Will happen if cache is broken or when reading empty files
             try:
                 pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                            stream,
                            Lp().settings.get_value(
                                     'cover-size').get_int32() + 50 * scale,
                            -1,
                            True,
                            None)
                 stream.close()
                 surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf,
                                                                scale,
                                                                None)
                 del pixbuf
                 self.__image.set_from_surface(surface)
                 del surface
                 self.__image.show()
             except:
                 pass
         self.set_visible_child_name('widget')
     else:
         self.__on_not_found()
     self._spinner.stop()
Beispiel #6
0
    def get_album_artwork(self, album, size):
        """
            Return a cairo surface for album_id, covers are cached as jpg.
            @param album as Album
            @param pixbuf size as int
            @return cairo surface
        """
        filename = self._get_album_cache_name(album)
        cache_path_jpg = "%s/%s_%s.jpg" % (self._CACHE_PATH, filename, size)
        pixbuf = None

        try:
            # Look in cache
            if os.path.exists(cache_path_jpg):
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(cache_path_jpg,
                                                                size,
                                                                size)
            else:
                # Use favorite folder artwork
                if pixbuf is None:
                    path = self.get_album_artwork_path(album)
                    # Look in album folder
                    if path is not None:
                        ratio = self._respect_ratio(path)
                        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path,
                                                                         size,
                                                                         size,
                                                                         ratio)
                # Use tags artwork
                if pixbuf is None and album.tracks:
                    try:
                        pixbuf = self.pixbuf_from_tags(
                                    album.tracks[0].path, size)
                    except Exception as e:
                        pass

                # Use folder artwork
                if pixbuf is None:
                    path = self.get_first_album_artwork(album)
                    # Look in album folder
                    if path is not None:
                        ratio = self._respect_ratio(path)
                        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path,
                                                                         size,
                                                                         size,
                                                                         ratio)
                # Use default artwork
                if pixbuf is None:
                    self.download_album_art(album.id)
                    return self._get_default_icon(size,
                                                  'folder-music-symbolic')
                else:
                    pixbuf.savev(cache_path_jpg, "jpeg", ["quality"], ["90"])
            surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, None)
            del pixbuf
            return surface

        except Exception as e:
            print(e)
            return self._get_default_icon(size, 'folder-music-symbolic')
Beispiel #7
0
    def _on_artwork_draw(self, image, ctx):
        """
            Draw rounded image
            @param image as Gtk.Image
            @param ctx as cairo.Context
        """
        pixbuf = image.get_pixbuf()
        if pixbuf is None:
            return

        surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, image.get_scale_factor(), None)
        ctx.translate(2, 2)
        size = ArtSize.ARTIST_SMALL * 2 - 4
        ctx.new_sub_path()
        radius = size / 2
        ctx.arc(size / 2, size / 2, radius, 0, 2 * pi)
        ctx.set_source_rgb(1, 1, 1)
        ctx.fill_preserve()
        ctx.set_line_width(2)
        ctx.set_source_rgba(0, 0, 0, 0.3)
        ctx.stroke_preserve()
        ctx.set_source_surface(surface, 0, 0)
        ctx.clip()
        ctx.paint()
        return True
Beispiel #8
0
 def _add_pixbuf(self, stream):
     """
         Add stream to the view
     """
     try:
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream, ArtSize.MONSTER, ArtSize.MONSTER, True, None)
         image = Gtk.Image()
         image.get_style_context().add_class("cover-frame")
         image.set_property("halign", Gtk.Align.CENTER)
         image.set_property("valign", Gtk.Align.CENTER)
         self._orig_pixbufs[image] = pixbuf
         # Scale preserving aspect ratio
         width = pixbuf.get_width()
         height = pixbuf.get_height()
         if width > height:
             height = height * ArtSize.BIG * self.get_scale_factor() / width
             width = ArtSize.BIG * self.get_scale_factor()
         else:
             width = width * ArtSize.BIG * self.get_scale_factor() / height
             height = ArtSize.BIG * self.get_scale_factor()
         scaled_pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR)
         del pixbuf
         surface = Gdk.cairo_surface_create_from_pixbuf(scaled_pixbuf, self.get_scale_factor(), None)
         del scaled_pixbuf
         image.set_from_surface(surface)
         del surface
         image.show()
         self._view.add(image)
     except Exception as e:
         print(e)
         pass
     if self._stack.get_visible_child_name() == "spinner":
         self._spinner.stop()
         self._stack.set_visible_child_name("logo")
Beispiel #9
0
def set_icon_from_pixbuf_with_scale(icon, pixbuf, scale=1):
    if scale == 1 or scale is None or pixbuf is None:
        icon.set_from_pixbuf(pixbuf)
        return None

    surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, None)
    icon.set_from_surface(surface)
    return None
Beispiel #10
0
    def _cache_hit(self, klass, pixbuf):
        surface = Gdk.cairo_surface_create_from_pixbuf(
            pixbuf, self._scale, None)
        surface = _make_icon_frame(surface, self._size, self._scale)
        self._surface = surface
        self._set_grilo_thumbnail_path()

        self.emit('finished')
Beispiel #11
0
 def get_default_icon(self, icon_name, size, scale):
     """
         Construct an empty cover album,
         code forked Gnome Music, see copyright header
         @param icon_name as str
         @param size as int
         @param scale factor as int
         @return pixbuf as cairo.Surface
     """
     try:
         # First look in cache
         cache_path_jpg = self._get_default_icon_path(size, icon_name)
         f = Lio.File.new_for_path(cache_path_jpg)
         if f.query_exists():
             pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                                                             cache_path_jpg,
                                                             size,
                                                             size,
                                                             False)
         else:
             # get a small pixbuf with the given path
             icon_size = size / 4
             icon = Gtk.IconTheme.get_default().load_icon(icon_name,
                                                          icon_size, 0)
             # create an empty pixbuf with the requested size
             pixbuf = GdkPixbuf.Pixbuf.new(icon.get_colorspace(),
                                           True,
                                           icon.get_bits_per_sample(),
                                           size,
                                           size)
             pixbuf.fill(0xffffffff)
             icon.composite(pixbuf,
                            icon_size * 3 / 2,
                            icon_size * 3 / 2,
                            icon_size,
                            icon_size,
                            icon_size * 3 / 2,
                            icon_size * 3 / 2,
                            1, 1,
                            GdkPixbuf.InterpType.NEAREST, 255)
             # Gdk < 3.15 was missing save method
             # > 3.15 is missing savev method
             try:
                 pixbuf.save(cache_path_jpg, "jpeg",
                             ["quality"], [str(Lp().settings.get_value(
                                           'cover-quality').get_int32())])
             except:
                 pixbuf.savev(cache_path_jpg, "jpeg",
                              ["quality"], [str(Lp().settings.get_value(
                                           'cover-quality').get_int32())])
         surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, None)
         del pixbuf
         return surface
     except:
         return self.get_default_icon('computer-fail-symbolic',
                                      ArtSize.MEDIUM,
                                      scale)
Beispiel #12
0
    def __set_artwork(self):
        """
            Set artist artwork
        """
        artwork_height = 0
        if Lp().settings.get_value('artist-artwork'):
            if len(self._artist_ids) == 1 and\
                    Lp().settings.get_value('artist-artwork'):
                artist = Lp().artists.get_name(self._artist_ids[0])
                size = ArtSize.ARTIST_SMALL * 2 * self.__scale_factor
                for suffix in ["lastfm", "spotify", "wikipedia"]:
                    uri = InfoCache.get_artwork(artist, suffix, size)
                    if uri is not None:
                        f = Lio.File.new_for_path(uri)
                        (status, data, tag) = f.load_contents(None)
                        stream = Gio.MemoryInputStream.new_from_data(data,
                                                                     None)
                        pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                                                       stream,
                                                                       size,
                                                                       size,
                                                                       True,
                                                                       None)
                        stream.close()
                        surface = Gdk.cairo_surface_create_from_pixbuf(
                                            pixbuf, self.__scale_factor, None)
                        del pixbuf
                        self.__artwork.set_from_surface(surface)
                        del surface
                        artwork_height = ArtSize.ARTIST_SMALL * 2
                        self.__artwork.get_style_context().remove_class(
                                                                'artwork-icon')
                        self.__artwork.show()
                        self.__artwork_box.show()
                        break
            # Add a default icon
            if len(self._artist_ids) == 1 and artwork_height == 0:
                self.__artwork.set_from_icon_name(
                                            'avatar-default-symbolic',
                                            Gtk.IconSize.DND)
                artwork_height = 32
                self.__artwork.get_style_context().add_class('artwork-icon')
                self.__artwork.show()
                self.__artwork_box.show()

        # Create an self.__empty widget with header height
        ctx = self.__label.get_pango_context()
        layout = Pango.Layout.new(ctx)
        layout.set_text("a", 1)
        # Font scale 2
        font_height = int(layout.get_pixel_size()[1]) * 2

        if artwork_height > font_height:
            self.__empty.set_property('height-request', artwork_height)
        else:
            self.__empty.set_property('height-request', font_height)
Beispiel #13
0
    def get_radio_artwork(self, name, size):
        """
            Return a cairo surface for radio name
            @param radio name as string
            @param pixbuf size as int
            @return cairo surface
        """
        filename = self._get_radio_cache_name(name)
        cache_path_png = "%s/%s_%s.png" % (self._CACHE_PATH, filename, size)
        pixbuf = None

        try:
            # Look in cache
            if os.path.exists(cache_path_png):
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(cache_path_png,
                                                                size,
                                                                size)
            else:
                path = self._get_radio_art_path(name)
                if path is not None:
                    pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                                                  True,
                                                  8,
                                                  size,
                                                  size)
                    pixbuf.fill(0xffffffff)
                    cover = GdkPixbuf.Pixbuf.new_from_file_at_size(path,
                                                                   size,
                                                                   size)
                    cover_width = cover.get_width()
                    cover_height = cover.get_height()
                    cover.composite(pixbuf,
                                    (size-cover_width)/2,
                                    (size-cover_height)/2,
                                    cover_width,
                                    cover_height,
                                    (size-cover_width)/2,
                                    (size-cover_height)/2,
                                    1,
                                    1,
                                    GdkPixbuf.InterpType.HYPER,
                                    255)
            if pixbuf is None:
                return self._get_default_icon(
                                             size,
                                             'audio-input-microphone-symbolic')
            pixbuf.savev(cache_path_png, "png", [None], [None])
            surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, None)
            del pixbuf
            return surface

        except Exception as e:
            print(e)
            return self._get_default_icon(size,
                                          'audio-input-microphone-symbolic')
Beispiel #14
0
 def set_cover(self, pixbuf):
     """
         Set cover
         @param pixbuf as GdkPixbuf.Pixbuf
     """
     surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf,
                                                    self.get_scale_factor(),
                                                    None)
     del pixbuf
     self.__cover.set_from_surface(surface)
     del surface
Beispiel #15
0
def _make_icon_frame(pixbuf, art_size=None, scale=1):
    border = 3 * scale
    degrees = pi / 180
    radius = 3 * scale

    ratio = pixbuf.get_height() / pixbuf.get_width()

    # Scale down the image according to the biggest axis
    if ratio > 1:
        w = int(art_size.width / ratio * scale)
        h = art_size.height * scale
    else:
        w = art_size.width * scale
        h = int(art_size.height * ratio * scale)

    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
    ctx = cairo.Context(surface)

    # draw outline
    ctx.new_sub_path()
    ctx.arc(w - radius, radius, radius - 0.5, -90 * degrees, 0 * degrees)
    ctx.arc(w - radius, h - radius, radius - 0.5, 0 * degrees, 90 * degrees)
    ctx.arc(radius, h - radius, radius - 0.5, 90 * degrees, 180 * degrees)
    ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees)
    ctx.close_path()
    ctx.set_line_width(0.6)
    ctx.set_source_rgb(0.2, 0.2, 0.2)
    ctx.stroke_preserve()

    # fill the center
    ctx.set_source_rgb(1, 1, 1)
    ctx.fill()

    matrix = cairo.Matrix()
    matrix.scale(pixbuf.get_width() / (w - border * 2),
                 pixbuf.get_height() / (h - border * 2))
    matrix.translate(-border, -border)

    # paste the scaled pixbuf in the center
    Gdk.cairo_set_source_pixbuf(ctx, pixbuf, 0, 0)
    pattern = ctx.get_source()
    pattern.set_matrix(matrix)
    ctx.rectangle(border, border, w - border * 2, h - border * 2)
    ctx.fill()

    border_pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, w, h)

    surface = Gdk.cairo_surface_create_from_pixbuf(border_pixbuf,
                                                   scale,
                                                   None)

    return surface
Beispiel #16
0
def get_pbosf_for_pixbuf(widget, pixbuf):
    """Returns a cairo surface or the same pixbuf,
    let's call it PixbufOrSurface..
    """

    if hasattr(Gdk, "cairo_surface_create_from_pixbuf"):
        scale_factor = widget.get_scale_factor()
        # Don't create a surface if we don't have to
        if scale_factor == 1:
            return pixbuf
        return Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale_factor, widget.get_window())
    else:
        return pixbuf
Beispiel #17
0
 def show_image(self, uri, pbuf):
     """ Show the loaded image and switch to it on the view """
     self.uri = uri
     self.page_loading.stop()
     try:
         surface = Gdk.cairo_surface_create_from_pixbuf(
             pbuf,
             self.get_scale_factor(),
             self.get_window())
         self.page_image.set_from_surface(surface)
     except Exception as e:
         print(e)
         self.page_image.set_from_pixbuf(pbuf)
     self.stack.set_visible_child_name("page-image")
Beispiel #18
0
 def get_album_artwork2(self, uri, size):
     """
         Return a cairo surface with borders for uri
         No cache usage
         @param uri as string
         @param size as int
         @return cairo surface
     """
     pixbuf = self.pixbuf_from_tags(GLib.filename_from_uri(uri)[0], size)
     if pixbuf is not None:
         surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, None)
         del pixbuf
         return surface
     else:
         return self._get_default_icon(size, 'folder-music-symbolic')
Beispiel #19
0
 def _get_default_icon(self, size, icon_name):
     """
         Construct an empty cover album,
         code forked Gnome Music, see copyright header
         @param size as int
         @param icon_name as str
         @return pixbuf as Gdk.Pixbuf
     """
     # First look in cache
     cache_path_jpg = self._get_default_icon_path(size, icon_name)
     if os.path.exists(cache_path_jpg):
         pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(cache_path_jpg,
                                                          size,
                                                          size,
                                                          False)
     else:
         # get a small pixbuf with the given path
         icon_size = size / 4
         icon = Gtk.IconTheme.get_default().load_icon(icon_name,
                                                      icon_size, 0)
         # create an empty pixbuf with the requested size
         pixbuf = GdkPixbuf.Pixbuf.new(icon.get_colorspace(),
                                       True,
                                       icon.get_bits_per_sample(),
                                       size,
                                       size)
         pixbuf.fill(0xffffffff)
         icon.composite(pixbuf,
                        icon_size * 3 / 2,
                        icon_size * 3 / 2,
                        icon_size,
                        icon_size,
                        icon_size * 3 / 2,
                        icon_size * 3 / 2,
                        1, 1,
                        GdkPixbuf.InterpType.NEAREST, 255)
         # Gdk < 3.15 was missing save method
         # > 3.15 is missing savev method
         try:
             pixbuf.save(cache_path_jpg, "jpeg",
                         ["quality"], ["90"])
         except:
             pixbuf.savev(cache_path_jpg, "jpeg",
                          ["quality"], ["90"])
     surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, None)
     del pixbuf
     return surface
Beispiel #20
0
 def _set_image(self, image, stream):
     """
         Set image with stream
         @param image as Gtk.Image
         @param stream as Gio.MemoryInputStream
     """
     pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream,
                                                        ArtSize.MEDIUM,
                                                        ArtSize.MEDIUM,
                                                        True,
                                                        None)
     surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf,
                                                    0,
                                                    None)
     del pixbuf
     image.set_from_surface(surface)
     del surface
Beispiel #21
0
 def _add_pixbuf(self, pixbuf):
     """
         Add pixbuf to the view
         @param pixbuf as Gdk.Pixbuf
     """
     image = Gtk.Image()
     self._orig_pixbufs[image] = pixbuf
     scaled_pixbuf = pixbuf.scale_simple(
         ArtSize.BIG * self.get_scale_factor(), ArtSize.BIG * self.get_scale_factor(), 2
     )
     del pixbuf
     surface = Gdk.cairo_surface_create_from_pixbuf(scaled_pixbuf, 0, None)
     del scaled_pixbuf
     image.set_from_surface(surface)
     del surface
     image.show()
     self._view.add(image)
Beispiel #22
0
 def get_album_artwork2(self, uri, size, scale):
     """
         Return a cairo surface with borders for uri
         No cache usage
         @param uri as string
         @param size as int
         @param scale as int
         @return cairo surface
     """
     size *= scale
     pixbuf = self.pixbuf_from_tags(uri, size)
     if pixbuf is not None:
         surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, None)
         del pixbuf
         return surface
     else:
         return self.get_default_icon('folder-music-symbolic', size, scale)
Beispiel #23
0
 def _add_pixbuf(self, monster, big):
     """
         Add pixbuf to the view
         @param monster as Gdk.Pixbuf
         @param big as Gdk.Pixbuf
     """
     image = Gtk.Image()
     self._monster_pixbufs[image] = monster
     surface = Gdk.cairo_surface_create_from_pixbuf(big,
                                                    0,
                                                    None)
     del monster
     del big
     image.set_from_surface(surface)
     del surface
     image.show()
     self._view.add(image)
Beispiel #24
0
    def create_image(self, image_name=None, scale_ratio=1, window=None):
        """
            The function creates a image from name defined in image_name
        """
        size = 48 * scale_ratio
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(image_name, -1, size, True)
        image = Gtk.Image()

        # Creating the cairo surface is necessary for proper scaling on HiDPI
        try:
            surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale_ratio, window)
            image.set_from_surface(surface)

        # Fallback for GTK+ older than 3.10
        except AttributeError:
            image.set_from_pixbuf(pixbuf)

        return image
Beispiel #25
0
 def do_own_render(self, ctx, widget, cell_area, size):
     surface = None
     alpha = False
     if self.rowid in self._surfaces.keys():
         surface = self._surfaces[self.rowid]
     if surface is None:
         for suffix in ["lastfm", "spotify", "wikipedia"]:
             uri = InfoCache.get_artwork(self.artist, suffix, size)
             if uri is not None:
                 pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(uri,
                                                                 size,
                                                                 size)
                 surface = Gdk.cairo_surface_create_from_pixbuf(
                                                  pixbuf,
                                                  widget.get_scale_factor(),
                                                  None)
                 self._surfaces[self.rowid] = surface
                 del pixbuf
                 break
     if surface is None:
         alpha = True
         surface = Gtk.IconTheme.get_default().load_surface(
                                          'media-optical-cd-audio-symbolic',
                                          ArtSize.ARTIST_SMALL,
                                          1,
                                          widget.get_window(),
                                          0)
     ctx.translate(cell_area.x, cell_area.y)
     ctx.new_sub_path()
     radius = ArtSize.ARTIST_SMALL / 2
     ctx.arc(ArtSize.ARTIST_SMALL/2, ArtSize.ARTIST_SMALL/2,
             radius, 0, 2 * pi)
     ctx.set_source_rgb(1, 1, 1)
     ctx.fill_preserve()
     ctx.set_line_width(2)
     ctx.set_source_rgba(0, 0, 0, 0.3)
     ctx.stroke_preserve()
     ctx.set_source_surface(surface, 0, 0)
     ctx.clip()
     if alpha:
         ctx.paint_with_alpha(0.5)
     else:
         ctx.paint()
Beispiel #26
0
    def get_radio_artwork(self, name, size, scale):
        """
            Return a cairo surface for radio name
            @param radio name as string
            @param pixbuf size as int
            @param scale factor as int
            @return cairo surface
        """
        size *= scale
        filename = self.__get_radio_cache_name(name)
        cache_path_png = "%s/%s_%s.png" % (self._CACHE_PATH, filename, size)
        pixbuf = None

        try:
            # Look in cache
            f = Gio.File.new_for_path(cache_path_png)
            if f.query_exists():
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(cache_path_png,
                                                                size,
                                                                size)
            else:
                path = self.__get_radio_art_path(name)
                if path is not None:
                    pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path,
                                                                    size,
                                                                    size)
            if pixbuf is None:
                return self.get_default_icon(
                                             'audio-input-microphone-symbolic',
                                             size,
                                             scale)
            pixbuf.savev(cache_path_png, "png", [None], [None])
            surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, None)
            del pixbuf
            return surface

        except Exception as e:
            print(e)
            return self.get_default_icon('audio-input-microphone-symbolic',
                                         size,
                                         scale)
Beispiel #27
0
 def _add_pixbuf(self, data):
     """
         Add pixbuf to the view
         @param data as bytes
     """
     try:
         stream = Gio.MemoryInputStream.new_from_data(data, None)
         if stream is not None:
             monster = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                 stream, ArtSize.MONSTER,
                 ArtSize.MONSTER,
                 True,
                 None)
         stream = Gio.MemoryInputStream.new_from_data(data, None)
         if stream is not None:
             big = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                 stream, ArtSize.BIG,
                 ArtSize.BIG,
                 True,
                 None)
         image = Gtk.Image()
         image.get_style_context().add_class('cover-frame')
         image.set_property('halign', Gtk.Align.CENTER)
         image.set_property('valign', Gtk.Align.CENTER)
         self._datas[image] = data
         surface = Gdk.cairo_surface_create_from_pixbuf(big,
                                                        0,
                                                        None)
         del monster
         del big
         image.set_from_surface(surface)
         del surface
         image.show()
         self._view.add(image)
     except Exception as e:
         print("ArtworkSearch::_add_pixbuf: %s" % e)
     # Remove spinner if exist
     if self._stack.get_visible_child_name() == 'spinner':
         self._spinner.stop()
         self._label.set_text(_("Select artwork"))
         self._stack.set_visible_child_name('main')
Beispiel #28
0
 def _add_pixbuf(self, stream):
     """
         Add stream to the view
     """
     try:
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
             stream, ArtSize.MONSTER,
             ArtSize.MONSTER,
             True,
             None)
         image = Gtk.Image()
         self._orig_pixbufs[image] = pixbuf
         # Scale preserving aspect ratio
         width = pixbuf.get_width()
         height = pixbuf.get_height()
         if width > height:
             height = height*ArtSize.BIG*self.get_scale_factor()/width
             width = ArtSize.BIG*self.get_scale_factor()
         else:
             width = width*ArtSize.BIG*self.get_scale_factor()/height
             height = ArtSize.BIG*self.get_scale_factor()
         scaled_pixbuf = pixbuf.scale_simple(width,
                                             height,
                                             GdkPixbuf.InterpType.BILINEAR)
         del pixbuf
         surface = Gdk.cairo_surface_create_from_pixbuf(scaled_pixbuf,
                                                        0,
                                                        None)
         del scaled_pixbuf
         image.set_from_surface(surface)
         del surface
         image.show()
         self._view.add(image)
     except Exception as e:
         print(e)
         pass
     # Remove spinner if exist
     if self._spinner is not None:
         self._stack.set_visible_child(self._logo)
         self._stack.clean_old_views(self._logo)
         self._spinner = None
Beispiel #29
0
 def _add_pixbuf(self, monster, big):
     """
         Add pixbuf to the view
         @param monster as Gdk.Pixbuf
         @param big as Gdk.Pixbuf
     """
     if monster is None or big is None:
         return
     image = Gtk.Image()
     image.get_style_context().add_class('cover-frame')
     image.set_property('halign', Gtk.Align.CENTER)
     image.set_property('valign', Gtk.Align.CENTER)
     self._monster_pixbufs[image] = monster
     surface = Gdk.cairo_surface_create_from_pixbuf(big,
                                                    0,
                                                    None)
     del monster
     del big
     image.set_from_surface(surface)
     del surface
     image.show()
     self._view.add(image)
    def _on_artwork_draw(self, image, ctx):
        """
            Draw rounded image
            @param image as Gtk.Image
            @param ctx as cairo.Context
        """
        # Update image if scale factor changed
        if self.__scale_factor != image.get_scale_factor():
            self.__scale_factor = image.get_scale_factor()
            self.__set_artwork()
        if not image.is_drawable():
            return

        if image.props.surface is None:
            pixbuf = image.get_pixbuf()
            if pixbuf is None:
                return
            surface = Gdk.cairo_surface_create_from_pixbuf(
                                                         pixbuf,
                                                         self.__scale_factor,
                                                         None)
            del pixbuf
        else:
            surface = image.props.surface

        ctx.translate(2, 2)
        size = ArtSize.ARTIST_SMALL * 2 - 4
        ctx.new_sub_path()
        radius = size / 2
        ctx.arc(size/2, size/2, radius, 0, 2 * pi)
        ctx.set_source_rgb(1, 1, 1)
        ctx.fill_preserve()
        ctx.set_line_width(2)
        ctx.set_source_rgba(0, 0, 0, 0.3)
        ctx.stroke_preserve()
        ctx.set_source_surface(surface, 0, 0)
        ctx.clip()
        ctx.paint()
        return True
Beispiel #31
0
    def __init__(self, book, size, scale, bordered=False, square=False):
        """
        :param size: the size for the longer side of the image
        :param bordered: should there be a border around the album art?
        :param square: should the widget be always a square?
        """
        super().__init__()

        self.book = book
        self.selected = False
        self.signal_ids = []
        self.play_signal_ids = []

        # the event box is used for mouse enter and leave signals
        self.event_box = Gtk.EventBox()
        self.event_box.set_property("halign", Gtk.Align.CENTER)
        self.event_box.set_property("valign", Gtk.Align.CENTER)

        # scale the book cover to a fix size.
        pixbuf = artwork_cache.get_cover_pixbuf(book, scale, size)

        # box is the main container for the album art
        self.set_halign(Gtk.Align.CENTER)
        self.set_valign(Gtk.Align.CENTER)

        # img contains the album art
        img = Gtk.Image()
        img.set_halign(Gtk.Align.CENTER)
        img.set_valign(Gtk.Align.CENTER)
        if bordered:
            img.get_style_context().add_class("bordered")
        surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, None)
        img.set_from_surface(surface)

        self.play_box = Gtk.EventBox()

        # on click we want to play the audio book
        self.play_signal_ids.append(
            self.play_box.connect("button-press-event",
                                  self._on_play_button_press))
        self.play_box.set_property("halign", Gtk.Align.CENTER)
        self.play_box.set_property("valign", Gtk.Align.CENTER)
        self.play_box.set_tooltip_text(_("Play this book"))

        # play_color is an overlay for the play button
        # with this it should be visible on any album art color
        play_image = GdkPixbuf.Pixbuf.new_from_resource(
            "/de/geigi/cozy/play_background.svg")
        if square:
            play_image = play_image.scale_simple(size - 10, size - 10,
                                                 GdkPixbuf.InterpType.BILINEAR)
        if size < 100:
            self.icon_size = Gtk.IconSize.LARGE_TOOLBAR
        else:
            self.icon_size = Gtk.IconSize.DIALOG
        self.play_button = Gtk.Image.new_from_icon_name(
            "media-playback-start-symbolic", self.icon_size)
        self.play_button.set_property("halign", Gtk.Align.CENTER)
        self.play_button.set_property("valign", Gtk.Align.CENTER)
        self.play_button.get_style_context().add_class("white")

        # this is the main overlay for the album art
        # we need to create field for the overlays
        # to change the opacity of them on mouse over/leave events
        self.overlay = Gtk.Overlay.new()

        # this is the play symbol overlay
        self.play_overlay = Gtk.Overlay.new()

        # this is for the play button animation
        self.play_revealer = Gtk.Revealer()
        self.play_revealer.set_transition_type(
            Gtk.RevealerTransitionType.CROSSFADE)
        self.play_revealer.set_transition_duration(300)
        self.play_revealer.add(self.play_overlay)
        self.play_revealer.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK)
        self.play_revealer.add_events(Gdk.EventMask.LEAVE_NOTIFY_MASK)

        # this grid has a background color to act as a visible overlay
        color = Gtk.Grid()
        color.set_property("halign", Gtk.Align.CENTER)
        color.set_property("valign", Gtk.Align.CENTER)

        if square:
            self.set_size_request(size, size)

            smaller_width = size - pixbuf.get_width()
            if smaller_width > 1:
                self.event_box.set_margin_left(smaller_width / 2)

        # assemble play overlay
        self.play_box.add(self.play_button)
        self.play_overlay.add(self.play_box)

        # assemble overlay with album art
        self.overlay.add(img)
        self.overlay.add_overlay(self.play_revealer)

        # assemble overlay color
        color.add(self.overlay)
        self.event_box.add(color)
        self.add(self.event_box)

        # connect signals
        self.play_signal_ids.append(
            self.play_box.connect("enter-notify-event",
                                  self._on_play_enter_notify))
        self.play_signal_ids.append(
            self.play_box.connect("leave-notify-event",
                                  self._on_play_leave_notify))
        # connect mouse events to the event box
        self.signal_ids.append(
            self.event_box.connect("enter-notify-event",
                                   self._on_enter_notify))
        self.signal_ids.append(
            self.event_box.connect("leave-notify-event",
                                   self._on_leave_notify))
Beispiel #32
0
 def op_blur(self, source_pixbuf, blur_algo, blur_radius):
     surface = Gdk.cairo_surface_create_from_pixbuf(source_pixbuf, 0, None)
     bs = utilities_fast_blur(surface, blur_radius, blur_algo)
     bp = Gdk.pixbuf_get_from_surface(bs, 0, 0, bs.get_width(),
                                      bs.get_height())
     self.get_image().set_temp_pixbuf(bp)
Beispiel #33
0
    def surface_for_path(self, path, scale):
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)

        return Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale)
Beispiel #34
0
    def set_image_from_item(self, image, item, store=None, size=64):
        """ Set the GtkImage if possible """
        icon_name = item.get_icon_name()
        if icon_name:
            image.set_from_icon_name(icon_name, Gtk.IconSize.INVALID)
            return

        # Grab app bits
        id = item.get_id()
        app = self.get_store_variant(store, id)

        # No app? Set default icon for hidpi support.
        if not app:
            self.set_fallback_icon(image)
            return

        size = size * self.scale_factor
        original_size = size

        # No icon?
        icon = self.find_icon(app, size, size)
        if not icon:
            size /= self.scale_factor
            icon = self.find_icon(app, size, size)
        if not icon:
            self.set_fallback_icon(image)
            return

        # Find out what kind of icon this is
        kind = icon.get_kind()
        if kind == As.IconKind.STOCK:
            image.set_from_icon_name(icon.get_name(), Gtk.IconSize.INVALID)
            return

        # We're dealing with an unknown
        if kind == As.IconKind.UNKNOWN or kind == As.IconKind.REMOTE:
            self.set_fallback_icon(image)
            return

        icon.set_scale(self.scale_factor)
        # Try to load the cached/available icon
        try:
            if not icon.load(As.IconLoadFlags.SEARCH_SIZE):
                self.set_fallback_icon(image)
                return
        except Exception as e:
            print("Should not happen: {}".format(e))
            self.set_fallback_icon(image)
            return

        # At this point we're dealing with pixbufs
        pbuf = icon.get_pixbuf()

        # Ensure we upscale on HiDPI
        if pbuf.get_height() != original_size:
            pbuf = pbuf.scale_simple(original_size, original_size,
                                     GdkPixbuf.InterpType.BILINEAR)

        if self.scale_factor == 1:
            image.set_from_pixbuf(pbuf)
            return

        window = self.window.get_window()
        if not window:
            self.set_fallback_icon(image)
            return

        try:
            surface = Gdk.cairo_surface_create_from_pixbuf(
                pbuf, self.scale_factor, window)
            image.set_from_surface(surface)
        except Exception as e:
            print(e)
            self.set_fallback_icon(image)
Beispiel #35
0
 def data_func_surface(self, column, cell, model, iter_, *args):
     pixbuf = model.get_value(iter_, CHANNEL_LOGO)
     surface = Gdk.cairo_surface_create_from_pixbuf(
         pixbuf, self.window.get_scale_factor())
     cell.set_property("surface", surface)
Beispiel #36
0
 def refresh_channel_logo(self, channel, image):
     pixbuf = self.get_pixbuf(channel.logo_path)
     surface = Gdk.cairo_surface_create_from_pixbuf(
         pixbuf, self.window.get_scale_factor())
     image.set_from_surface(surface)
Beispiel #37
0
    def paint_menu(self, paint_background, paint_selected, paint_activated,
                   page_number):

        coordinates = []

        if self.sf is None:
            self.sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, 720, int(self.y))
            self.cr = cairo.Context(self.sf)

        if self.cached_menu_font != self.entry_font:
            # memorize the font sizes
            (fontname, fontstyle, fontslant,
             fontsize) = self.get_font_params(self.entry_font)
            self.cr.select_font_face(fontname, fontslant, fontstyle)
            self.cr.set_font_size(fontsize)
            extents = self.cr.font_extents()
            self.cached_menu_size = extents[2]
            self.cached_menu_font = self.entry_font

        if paint_background:
            extra_pixbuf = GdkPixbuf.Pixbuf.new_from_file(
                self.background_picture)
            extra_x = float(extra_pixbuf.get_width())
            extra_y = float(extra_pixbuf.get_height())

            self.cr.save()
            self.cr.scale(720.0 / extra_x, self.y / extra_y)

            surface = Gdk.cairo_surface_create_from_pixbuf(
                extra_pixbuf, 1, None)
            self.cr.set_source_surface(surface, 0, 0)
            self.cr.paint()
            self.cr.restore()
            hmargin = self.title_horizontal * 720.0 / 100.0
            self.write_text(self.title_text, "title", 0 + hmargin,
                            720 + hmargin,
                            self.title_vertical * self.y / 100.0, "center")
#         else:
#             self.cr.set_source_rgb(1.0,1.0,1.0)
#             self.cr.paint()

        top_margin_p = self.y * self.margin_top / 100.0
        bottom_margin_p = self.y * self.margin_bottom / 100.0
        left_margin_p = 720.0 * self.margin_left / 100.0
        right_margin_p = 720.0 * self.margin_right / 100.0

        entry_height = self.cached_menu_size + self.entry_vertical_margin * 2.0 + self.entry_separation
        entries_per_page = int(
            (self.y - top_margin_p - bottom_margin_p) / entry_height)
        if (self.play_all_c):
            entries_per_page -= 1
        n_entries = len(self.title_list)
        if (n_entries > entries_per_page):
            paint_arrows = True
            entries_per_page -= 1
        else:
            paint_arrows = False

        self.pages = int(n_entries / entries_per_page)
        if (n_entries == 0) or ((n_entries % entries_per_page) != 0):
            self.pages += 1
        if (page_number >= self.pages) and (page_number > 0):
            page_number -= 1

        if self.wcurrent_page is not None:
            self.wcurrent_page.set_text(
                _("Page %(X)d of %(Y)d") % {
                    "X": page_number + 1,
                    "Y": self.pages
                })
        xl = left_margin_p
        xr = 720.0 - right_margin_p
        y = top_margin_p + entry_height / 2.0
        height = (self.cached_menu_size + self.entry_vertical_margin) / 2.0

        if (self.play_all_c):
            coordinates.append([xl, y - height, xr, y + height, "play_all"])
            if paint_background:
                self.paint_base(xl, xr, y, 0)
                self.write_text("Play All", "menu_entry", xl, xr, y,
                                self.position_horizontal)
            if paint_selected:
                self.write_text("Play All", "menu_entry_selected", xl, xr, y,
                                self.position_horizontal)
            if paint_activated:
                self.write_text("Play All", "menu_entry_activated", xl, xr, y,
                                self.position_horizontal)
            y += entry_height

        for entry in self.title_list[page_number *
                                     entries_per_page:(page_number + 1) *
                                     entries_per_page]:
            coordinates.append([xl, y - height, xr, y + height, "entry"])
            text = entry[0].title_name
            if paint_background:
                self.paint_base(xl, xr, y, 0)
                self.write_text(text, "menu_entry", xl, xr, y,
                                self.position_horizontal)
            if paint_selected:
                self.write_text(text, "menu_entry_selected", xl, xr, y,
                                self.position_horizontal)
            if paint_activated:
                self.write_text(text, "menu_entry_activated", xl, xr, y,
                                self.position_horizontal)
            y += entry_height

        if paint_arrows:
            if page_number == 0:
                coordinates.append([xl, y - height, xr, y + height, "right"])
                if paint_background:
                    self.paint_base(xl, xr, y, 0)
                    self.paint_arrow(xl, xr, y, "menu_entry", False)
                if paint_selected:
                    self.paint_arrow(xl, xr, y, "menu_entry_selected", False)
                if paint_activated:
                    self.paint_arrow(xl, xr, y, "menu_entry_activated", False)
            elif page_number == (self.pages - 1):
                coordinates.append([xl, y - height, xr, y + height, "left"])
                if paint_background:
                    self.paint_base(xl, xr, y, 0)
                    self.paint_arrow(xl, xr, y, "menu_entry", True)
                if paint_selected:
                    self.paint_arrow(xl, xr, y, "menu_entry_selected", True)
                if paint_activated:
                    self.paint_arrow(xl, xr, y, "menu_entry_activated", True)
            else:
                med = (xl + xr) / 2.0
                coordinates.append([xl, y - height, med, y + height, "left"])
                coordinates.append([med, y - height, xr, y + height, "right"])
                if paint_background:
                    self.paint_base(xl, xr, y, 1)
                    self.paint_base(xl, xr, y, 2)
                    self.paint_arrow(med, xr, y, "menu_entry", False)
                    self.paint_arrow(xl, med, y, "menu_entry", True)
                if paint_selected:
                    self.paint_arrow(med, xr, y, "menu_entry_selected", False)
                    self.paint_arrow(xl, med, y, "menu_entry_selected", True)
                if paint_activated:
                    self.paint_arrow(med, xr, y, "menu_entry_activated", False)
                    self.paint_arrow(xl, med, y, "menu_entry_activated", True)
        return coordinates
Beispiel #38
0
 def use_stable_pixbuf(self):
     # print('image/384: use_stable_pixbuf')
     self.surface = Gdk.cairo_surface_create_from_pixbuf(
         self.main_pixbuf, 0, None)
Beispiel #39
0
	def op_blur(self, source_pixbuf, blur_algo, blur_direction, radius):
		surface = Gdk.cairo_surface_create_from_pixbuf(source_pixbuf, 0, None)
		surface.set_device_scale(self.scale_factor(), self.scale_factor())
		bs = utilities_blur_surface(surface, radius, blur_algo, blur_direction)
		bp = Gdk.pixbuf_get_from_surface(bs, 0, 0, bs.get_width(), bs.get_height())
		self.get_image().set_temp_pixbuf(bp)
Beispiel #40
0
    def get_album_artwork(self, album, size, scale):
        """
            Return a cairo surface for album_id, covers are cached as jpg.
            @param album as Album
            @param pixbuf size as int
            @param scale factor as int
            @return cairo surface
        """
        size *= scale
        filename = self.get_album_cache_name(album)
        cache_path_jpg = "%s/%s_%s.jpg" % (self._CACHE_PATH, filename, size)
        pixbuf = None

        try:
            # Look in cache
            f = Lio.File.new_for_path(cache_path_jpg)
            if f.query_exists():
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(cache_path_jpg,
                                                                size,
                                                                size)
            else:
                # Use favorite folder artwork
                if pixbuf is None:
                    uri = self.get_album_artwork_uri(album)
                    data = None
                    if uri is not None:
                        f = Lio.File.new_for_uri(uri)
                        (status, data, tag) = f.load_contents(None)
                        ratio = self._respect_ratio(uri)
                        stream = Gio.MemoryInputStream.new_from_data(data,
                                                                     None)
                        pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                                                       stream,
                                                                       size,
                                                                       size,
                                                                       ratio,
                                                                       None)
                        stream.close()
                # Use tags artwork
                if pixbuf is None and album.tracks:
                    try:
                        pixbuf = self.pixbuf_from_tags(
                                    album.tracks[0].uri, size)
                    except Exception as e:
                        print("AlbumArt::get_album_artwork()", e)

                # Use folder artwork
                if pixbuf is None and album.uri != "":
                    uri = self.get_first_album_artwork(album)
                    # Look in album folder
                    if uri is not None:
                        f = Lio.File.new_for_uri(uri)
                        (status, data, tag) = f.load_contents(None)
                        ratio = self._respect_ratio(uri)
                        stream = Gio.MemoryInputStream.new_from_data(data,
                                                                     None)
                        pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                                                       stream,
                                                                       size,
                                                                       size,
                                                                       ratio,
                                                                       None)
                        stream.close()
                # Use default artwork
                if pixbuf is None:
                    self.cache_album_art(album.id)
                    return self.get_default_icon("folder-music-symbolic",
                                                 size,
                                                 scale)
                else:
                    pixbuf.savev(cache_path_jpg, "jpeg", ["quality"],
                                 [str(Lp().settings.get_value(
                                                "cover-quality").get_int32())])
            surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, None)
            del pixbuf
            return surface

        except Exception as e:
            print("AlbumArt::get_album_artwork()", e)
            return self.get_default_icon("folder-music-symbolic", size, scale)
Beispiel #41
0
 def set_picture_from_file(self, path):
     pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
         path, -1, FLAG_SIZE * self.scale)
     surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, self.scale)
     self.button_image.set_from_surface(surface)
Beispiel #42
0
    def set_book(self, book):
        """
        Display the given book in the book overview.
        """
        if self.book and self.book.id == book.id:
            self.update_time()
            return
        self.book = Book.get(Book.id == book.id)

        if player.is_playing(
        ) and self.ui.titlebar.current_book and self.book.id == self.ui.titlebar.current_book.id:
            self.play_book_button.set_image(self.pause_img)
        else:
            self.play_book_button.set_image(self.play_img)

        self.name_label.set_text(book.name)
        self.author_label.set_text(book.author)

        self.update_offline_status()

        pixbuf = artwork_cache.get_cover_pixbuf(
            book, self.ui.window.get_scale_factor(), 250)
        if pixbuf:
            surface = Gdk.cairo_surface_create_from_pixbuf(
                pixbuf, self.ui.window.get_scale_factor(), None)
            self.cover_img.set_from_surface(surface)
        else:
            self.cover_img.set_from_icon_name("book-open-variant-symbolic",
                                              Gtk.IconSize.DIALOG)
            self.cover_img.props.pixel_size = 250

        self.duration = get_book_duration(book)
        self.speed = self.book.playback_speed
        self.total_label.set_text(
            tools.seconds_to_human_readable(self.duration / self.speed))

        self.last_played_label.set_text(
            tools.past_date_to_human_readable(book.last_played))

        self.published_label.set_visible(False)
        self.published_text.set_visible(False)

        # track list
        # This box contains all track content
        self.track_box = Gtk.Box()
        self.track_box.set_orientation(Gtk.Orientation.VERTICAL)
        self.track_box.set_halign(Gtk.Align.START)
        self.track_box.set_valign(Gtk.Align.START)
        self.track_box.props.margin = 8

        disk_number = -1
        first_disk_element = None
        disk_count = 0

        for track in get_tracks(book):
            # Insert disk headers
            if track.disk != disk_number:
                disc_element = DiskElement(track.disk)
                self.track_box.add(disc_element)
                if disk_number == -1:
                    first_disk_element = disc_element
                    if track.disk < 2:
                        first_disk_element.set_hidden(True)
                else:
                    first_disk_element.show_all()
                    disc_element.show_all()

                disk_number = track.disk
                disk_count += 1

            track_element = TrackElement(track, self)
            self.track_box.add(track_element)
            track_element.show_all()

        tools.remove_all_children(self.track_list_container)
        self.track_box.show()
        self.track_box.set_halign(Gtk.Align.FILL)
        self.track_list_container.add(self.track_box)

        self._mark_current_track()
        self.update_time()