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?
2 Answers
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
2 columns, max 20 lines per column
3 columns, max 10 lines per column
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.
-
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
-
-
@GuyfromAmsterdam the ' is easy to fix, I will update my answer later this morning. Dec 5, 2014 at 7:04
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()
-
1While 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– Pilot6Jan 24, 2016 at 22:19
-