Use of background-image CSS with PyGTK

I’ve written some GUI code in PyGTK that involves a CSS background-image from this URL, as well as background-images from other URLs.
https://www.gravatar.com/avatar/f83cbebd822015762b2bd15617fa3147.jpg?d=mm&w=100&h=100

The code works great when I run the python file in the terminal on Ubuntu. But after I snap it, install the snap, and then run the app (still on Ubuntu), the image will not show up. Everything else works fine. I can do background-colors and all kinds of other things with great success, but the background-images are never displayed.

Any thoughts on what might be going on and how I can make it work?

Can you share your snapcraft.yaml file? that will make it easy to figure out few things.

Here is my YAML file, with names changed to protect the innocent.

name: myamazingapp
base: core18
version: '2.1.6'
title: 'myamazingapp'
summary: 'myamazingapp summary'
icon: 'myamazingapp.svg'
grade: stable
confinement: strict

# https://snapcraft.io/docs/supported-interfaces
plugs:
    network:
    network-bind:
    desktop:
    desktop-legacy:
    x11:
    unity7:
    gsettings:

hooks:
    install:
        plugs: [network, network-bind]
    remove:
        plugs: [network, network-bind]

apps:
    myamazingapp:
        # The terminal command a user would use to launch the app
        command: bin/desktop-launch python3 $SNAP/main.py &
        desktop: usr/share/applications/myamazingapp.desktop
        autostart: myamazingapp.desktop
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1

parts:
    desktop-gtk3:
        build-packages:
            - build-essential
            - libgtk-3-dev
        make-parameters:
            - FLAVOR=gtk3
        plugin: make
        source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
        source-subdir: gtk
        stage-packages:
            - libxkbcommon0
            - dmz-cursor-theme
            - adwaita-icon-theme
            - gnome-themes-standard
            - shared-mime-info
            - libgtk-3-0
            - libgdk-pixbuf2.0-0
            - libglib2.0-bin
            - libgtk-3-bin
            - libappindicator3-1
            - locales-all
            - xdg-user-dirs
            - ibus-gtk3
            - libibus-1.0-5
            - fcitx-frontend-gtk3
    copy-stuff:
        plugin: dump
        source: .
    copy-desktop-icon-etc:
        plugin: dump
        source: snap/gui
        organize:
            # https://developer.gnome.org/integration-guide/stable/icons.html.en
            myamazingapp.desktop: usr/share/applications/myamazingapp.desktop
    myamazingapp:
        plugin: python
        python-version: python3
        source: .
        python-packages:
            - setproctitle
        build-packages:
            - coreutils
            - python3-requests
        stage-packages:
            - coreutils
            - libssl-dev
            - libjpeg-dev
            - libtiff-dev
            - libsdl1.2-dev
            - libnotify-dev
            - freeglut3
            - ibus-gtk3
            - zlib1g
            - libsm6
            - libpulse0
            - libslang2
            - libsdl1.2debian
            - wmctrl
            - gir1.2-gtk-3.0
            - gir1.2-appindicator3-0.1
            - python3-gi
            - gir1.2-wnck-3.0
            - libcanberra-gtk-module
            - libcanberra-gtk3-module
            - x11-utils
            - python3-requests
        requirements:
            - /root/project/requirements.txt

You just need network plug in order to have network access for your snapped application.

Learn more about how to add interfaces here

As my YAML file shows, I have the network plug. Unless I did it wrong…?

I don’t know why you need this section.

Normally for your app to have network access permission, you just declare plugs under apps.

First, I apologize. I had removed some parts of my actual YAML file that I saw as unrelated to my question, including my hooks. I did this primarily to make things easier for anyone assisting me, but it may have had the opposite effect.

Having said that, I tried my app again without the lonely plugs section that you suggested I remove, but keeping the hooks section that initially appeared to be pointless. The hooks section still is needed, given the fact that I do have some hooks that need network access.

With the new YAML without the plugs section, nothing changed regarding the CSS images (or any other functionality of the app as far as I can tell). Here is the actual new YAML, though I have changed the name, summary, and description of the app, removed some comments, and removed the actual bash code in my hooks.

name: myamazingapp
base: core18
version: '2.1.6'
title: 'myamazingapp'
summary: 'myamazingapp summary'
description: |
    An elaborate and thorough description. An elaborate and thorough description. An elaborate and thorough description. An elaborate and thorough description.
    An elaborate and thorough description. An elaborate and thorough description. An elaborate and thorough description. An elaborate and thorough description.
    An elaborate and thorough description. An elaborate and thorough description. An elaborate and thorough description.
icon: 'myamazingapp.svg'
grade: stable
confinement: strict

hooks:
    install:
        plugs: [network, network-bind]
    remove:
        plugs: [network, network-bind]

apps:
    myamazingapp:
        # The terminal command a user would use to launch the app
        command: bin/desktop-launch python3 $SNAP/main.py &
        desktop: usr/share/applications/myamazingapp.desktop
        autostart: myamazingapp.desktop
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    about:
        command: bin/desktop-launch python3 $SNAP/main.py About &
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    diagnostics:
        command: bin/desktop-launch python3 $SNAP/main.py Diagnostics &
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    exclusions:
        command: bin/desktop-launch python3 $SNAP/main.py Exclusions &
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    settings:
        command: bin/desktop-launch python3 $SNAP/main.py Settings &
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    menu:
        command: bin/desktop-launch python3 $SNAP/main.py Menu &
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    debug:
        command: bin/desktop-launch python3 $SNAP/main.py Debug
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    debug-about:
        command: bin/desktop-launch python3 $SNAP/main.py Debug About
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    debug-diagnostics:
        command: bin/desktop-launch python3 $SNAP/main.py Debug Diagnostics
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    debug-exclusions:
        command: bin/desktop-launch python3 $SNAP/main.py Debug Exclusions
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    debug-settings:
        command: bin/desktop-launch python3 $SNAP/main.py Debug Settings
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1
    debug-menu:
        command: bin/desktop-launch python3 $SNAP/main.py Debug Menu
        plugs:
            - network
            - network-bind
            - desktop
            - desktop-legacy
            - x11
            - unity7
            - gsettings
        environment:
            DISABLE_WAYLAND: 1

parts:
    install-hook:
        plugin: nil
        override-build: |
            cat > myfile << 'EOF'
            #!/bin/bash
            MY BASH SCRIPT GOES HERE
            EOF
            install -D myfile $SNAPCRAFT_PART_INSTALL/snap/hooks/install
    remove-hook:
        plugin: nil
        build-packages:
            - wget
        stage-packages:
            - wget
        override-build: |
            cat > myfile << 'EOF'
            #!/bin/bash
            MY BASH SCRIPT GOES HERE
            EOF
            install -D myfile $SNAPCRAFT_PART_INSTALL/snap/hooks/remove
    desktop-gtk3:
        build-packages:
            - build-essential
            - libgtk-3-dev
        make-parameters:
            - FLAVOR=gtk3
        plugin: make
        source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
        source-subdir: gtk
        stage-packages:
            - libxkbcommon0
            - dmz-cursor-theme
            - adwaita-icon-theme
            - gnome-themes-standard
            - shared-mime-info
            - libgtk-3-0
            - libgdk-pixbuf2.0-0
            - libglib2.0-bin
            - libgtk-3-bin
            - libappindicator3-1
            - locales-all
            - xdg-user-dirs
            - ibus-gtk3
            - libibus-1.0-5
            - fcitx-frontend-gtk3
    copy-stuff:
        plugin: dump
        source: .
    copy-desktop-icon-etc:
        plugin: dump
        source: snap/gui
        organize:
            myamazingapp.desktop: usr/share/applications/myamazingapp.desktop
    myamazingapp:
        plugin: python
        python-version: python3
        source: .
        python-packages:
            - setproctitle
        build-packages:
            - coreutils
            - python3-requests
        stage-packages:
            - coreutils
            - libssl-dev
            - libjpeg-dev
            - libtiff-dev
            - libsdl1.2-dev
            - libnotify-dev
            - freeglut3
            - ibus-gtk3
            - zlib1g
            - libsm6
            - libpulse0
            - libslang2
            - libsdl1.2debian
            - wmctrl
            - gir1.2-gtk-3.0
            - gir1.2-appindicator3-0.1
            - python3-gi
            - gir1.2-wnck-3.0
            - libcanberra-gtk-module
            - libcanberra-gtk3-module
            - x11-utils
            - python3-requests
        requirements:
            - /root/project/requirements.txt

In that case I don’t think there is anything wrong in your snapcraft file, last thing i would suggest you is check if your snapped app is not trying to write to locations that are out of scope of the permitted ones : https://snapcraft.io/docs/debug-snaps

To check that run sudo snappy-debug in a terminal before starting your app and look for any permission denial message. Learn more about snappy-debug here

Thanks for your help. I saw no write location errors in snappy-debug, nor did I see anything else that seemed related to the background-image issues.

I decided I would just download all the images before displaying them and save them in SNAP_USER_COMMON. That seems to be working properly for me, though it makes the app slower than I wanted. I guess my problem had something to do with the remote URL rather than the local URL, but I still don’t know what the problem was exactly.

What is used to actually perform the download?

When I was having the initial problem, I wasn’t downloading it. I was using CSS like:
#elementID {background-image: url("https://www.gravatar.com/avatar/f83cbebd822015762b2bd15617fa3147.jpg?d=mm&w=100&h=100");}

It worked fine when I ran the python file in terminal, but would not display the image when I ran it as an installed snap.

Now I’m downloading the images using this code:

def downloadImage(self, url, newLocation):
    r = requests.get(url, stream=True)
    if r.status_code == 200:
        r.raw.decode_content = True
        with open(newLocation, 'wb') as f:
            copyfileobj(r.raw, f)

There are several images that need to be downloaded before the window can be displayed. I guess maybe I could do the downloads in threads or something. Do you have a faster method in mind?

This won’t work as css property for a widget. Qt’s styling engine do not resolve remote URLs, as there is no network stack attached to it. You need to have the resources either on your local system or inside a Qt resource file.

1 Like