Ubuntu – Make a text file the automatically updated background

backgroundnotesscriptswallpaper

I want to make a "to-do" list my wallpaper. I was hoping to be able to write a text file, save it, and have the background be updated each time I edit file. Is this possible?

Best Answer

The script below watches a textfile that you can edit. If the file is changed, it will create a new layer over your wallpaper with the text of the file.

Options

you can define:

  • text size
  • text color
  • number of columns
  • (max) number of lines per column
  • border width (around the text blocks)

How to use

The script uses Imagemagick, you might have to install it first:

sudo apt-get install imagemagick

Then:

  • Copy the script below into an empty file and save it as walltext.py.
  • Edit, if you want specific settings, the options in the head section of the script.
  • Into the same folder, copy the wallpaper of your choice , name it (exactly) original.jpg

    N.B.- It is important that the proportions of your wallpaper match the proportions of your screen's resolution, else the text will not be positioned properly.
  • In the same folder, create an empty textfile named (exactly) notes.txt. This is the file to make your todolist or whatever you'd like to have on your screen.

Run the script by the command:

python3 /path/to/walltext.py

Now start editing your text file. Every five seconds, the wallpaper is updated if needed (after you saved the changes):

Examples

1 column, max 30 lines per column

enter image description here

2 columns, max 20 lines per column

enter image description here

3 columns, max 10 lines per column

enter image description here

The script

#!/usr/bin/env python3

import subprocess
import os
import time

curr_dir = os.path.dirname(os.path.realpath(__file__))
curr_wall = curr_dir+"/"+"original.jpg"
notes = curr_dir+"/"+"notes.txt"

#--
text_color = "white"   # text color
size = "20"            # text size (real size depends on the scale factor of your wallpaper)
border = 120           # space around your text blocks
columns = 2            # (max) number of columns
n_lines = 10           # (max) number of lines per column
#--

def run_command(cmd):
    subprocess.call(["/bin/bash", "-c", cmd])

def get_value(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").strip()

def read_text(file):
    with open(file) as src:
        return [l.strip() for l in src.readlines()]

def slice_lines(lines, n_lines, columns):
    markers = [i for i in range(len(lines)) if i % n_lines == 0]
    last = len(lines); markers = markers+[last] if markers[-1] != last else markers
    textblocks = [lines[markers[i]:markers[i+1]] for i in range(len(markers)-1)]
    filled_blocks = len(textblocks)
    if filled_blocks < columns:
        for n in range(columns - filled_blocks):
            textblocks.insert(len(textblocks), [])
    for i in range(columns):
        textblocks[i] = ("\n").join(textblocks[i])
    return textblocks[:columns]

def create_section(psize, text, layer):
    run_command("convert -background none -fill "+text_color+" -border "+str(border)+\
                  " -bordercolor none -pointsize "+size+" -size "+psize+\
                  " caption:"+'"'+text+'" '+layer)

def combine_sections(layers):
    run_command("convert "+image_1+" "+image_2+" "+"+append "+span_image)
    pass

def set_overlay():
    boxes = slice_lines(read_text(notes), n_lines, columns)
    resolution = get_value('identify -format "%wx%h" '+curr_wall).split("x")
    w = str(int(int(resolution[0])/columns)-2*border)
    h = str(int(resolution[1])-2*border)
    layers = []
    for i in range(len(boxes)):
        layer = curr_dir+"/"+"layer_"+str(i+1)+".png"
        create_section(w+"x"+h, boxes[i], layer)
        layers.append(layer)
    run_command("convert "+(" ").join(layers)+" "+"+append "+curr_dir+"/"+"layer_span.png")
    wall_img = curr_dir+"/"+"walltext.jpg"
    run_command("convert "+curr_wall+" "+curr_dir+"/"+"layer_span.png"+" -background None -layers merge "+wall_img)
    run_command("gsettings set org.gnome.desktop.background picture-uri file:///"+wall_img)
    for img in [img for img in os.listdir(curr_dir) if img.startswith("layer_")]:
        os.remove(curr_dir+"/"+img)

while True:
    text_1 = read_text(notes)
    time.sleep(5)
    text_2 = read_text(notes)
    if text_2 != text_1:
        set_overlay()

Notes

  • More options can be added to the script, more info on Imagemagick's options can be found here.