7

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?

1
  • To my knowledge,this is not an existing functionality, but it may be something that can be scripted.
    – MGodby
    Dec 4, 2014 at 20:48

2 Answers 2

11

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.
17
  • This is perfect for what I need, except one thing: Can I make it so that it does this over my current background? i.e. instead of bg_color = "white" somehow make it overlay? I'll mark as solved either way. Thanks so much! Dec 4, 2014 at 23:09
  • Thanks again! It seems to work pretty well, however, if I add an apostrophe (but not a quotation mark) it doesn't seem to recognise that sentence, and will refuse to write it. Like this: i.imgur.com/NqoU2X3.gif Dec 4, 2014 at 23:41
  • also, is there a way to change alignment/ make two columns? Lot's of questions, but this is fantastic! Dec 4, 2014 at 23:51
  • I hadn't yet, but I did, and it doesn't work. Dec 5, 2014 at 6:07
  • @GuyfromAmsterdam the ' is easy to fix, I will update my answer later this morning. Dec 5, 2014 at 7:04
-1

I've modified the code above to put random quotes on the wallpaper every hour. Enjoy :) http://forraskod.blogspot.hu/2016/01/linux-hatterkep-veletlenszeru.html

#!/usr/bin/env python3

import subprocess
import os
import time
import random

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 = "80"            # text size (real size depends on the scale factor of your wallpaper)
border = 480           # space around your text blocks
columns = 1            # (max) number of columns
n_lines = 3          # (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(): # Read the file "notes" as specified above, display text in columns
    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)

def set_single_overlay(): # DEFAULT, read 1 line from "notes" file as specified above
    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 = []

    layer = curr_dir+"/"+"layer_1.png"
    #print(w)
    #print(h)
    create_section(w+"x"+h, text_1, 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)

print("Walltext started.")
print (curr_wall)
print (notes)

while True:
    text_1 = random.choice(open(notes).readlines())
    print(text_1)
    set_single_overlay()
    time.sleep(3600)

#    text_2 = read_text(notes)
#    if text_2 != text_1:
#        set_overlay()
2
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
    – Pilot6
    Jan 24, 2016 at 22:19
  • Good point, I'll update it.
    – Sicambria
    Jan 25, 2016 at 17:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .