Skip to content

Instantly share code, notes, and snippets.

@blackle
Created June 6, 2024 02:12
Show Gist options
  • Save blackle/8380a76fa40bedccde4a66c2ff31bc82 to your computer and use it in GitHub Desktop.
Save blackle/8380a76fa40bedccde4a66c2ff31bc82 to your computer and use it in GitHub Desktop.
background management tool
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject, GLib
from gi.repository.GdkPixbuf import Pixbuf, InterpType
import subprocess, os, time, errno
from xdg_base_dirs import xdg_cache_home, xdg_config_home
import shutil
PROGNAME = "blackle_backgrounder"
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno != errno.EEXIST:
raise
feh_sizes = {
"Center": "--bg-center",
"Fill": "--bg-fill",
"Maximum": "--bg-max",
"Scale": "--bg-scale",
"Tile": "--bg-tile",
}
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Blackle's Backgrounder", resizable=True, default_height=500, default_width=510)
self.cache_directory = xdg_cache_home() / PROGNAME
self.config_directory = xdg_config_home() / PROGNAME
self.folder_file = self.config_directory / "folder"
mkdir_p(self.config_directory)
mkdir_p(self.cache_directory)
self.killed = False
try:
self.wallpaper_directory = open(self.folder_file, 'r').readline()
except:
if not self.change_folder():
self.killed = True
return
self.close_button = self.make_button("_Close", "window-close")
self.close_button.connect("clicked", Gtk.main_quit)
self.file_button = self.make_button("Change _Folder", "folder-open")
self.file_button.connect("clicked", self.change_folder_cb)
self.browser_info = Gtk.ListStore(Pixbuf, str)
self.image_browser = Gtk.IconView.new()
self.image_browser.set_model(self.browser_info)
self.image_browser.set_pixbuf_column(0)
self.image_browser.set_selection_mode(Gtk.SelectionMode.BROWSE)
#self.image_browser.set_columns(2)
self.image_browser.set_item_width(190)
self.image_browser.connect("selection-changed", self.update_wallpaper)
self.browser_scroll = Gtk.ScrolledWindow()
self.browser_scroll.add(self.image_browser)
#self.browser_scroll.set_size_request(502, 450)
self.style_combo = Gtk.ComboBoxText()
self.style_combo.connect("changed", self.update_wallpaper)
self.style_combo.set_entry_text_column(0)
for style in feh_sizes.keys():
self.style_combo.append_text(style)
self.style_combo.set_active(1)
self.blankbox = Gtk.Box()
self.main_table = Gtk.Table(n_rows=4, n_columns=2, homogeneous=False)
self.main_table.attach(self.style_combo, 0, 1, 1, 2, Gtk.AttachOptions.SHRINK, Gtk.AttachOptions.SHRINK, 4, 4)
self.main_table.attach(self.close_button, 3, 4, 1, 2, Gtk.AttachOptions.SHRINK, Gtk.AttachOptions.SHRINK, 4, 4)
self.main_table.attach(self.file_button, 2, 3, 1, 2, Gtk.AttachOptions.SHRINK, Gtk.AttachOptions.SHRINK, 4, 4)
self.main_table.attach(self.browser_scroll, 0, 4, 0, 1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 4, 4)
self.main_table.attach(self.blankbox, 1, 2, 1, 2, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.SHRINK, 4, 4)
self.add(self.main_table)
self.parse_directory()
def make_button(self, text, icon):
btn = Gtk.Button.new_with_mnemonic(text)
icon = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.BUTTON)
btn.set_image(icon)
btn.set_always_show_image(True)
return btn
def parse_directory(self):
os.chdir(self.wallpaper_directory)
self.filelist = os.listdir(".")
self.filelist.sort(key=lambda x: -os.path.getmtime(x))
self.thumbdict = dict()
self.iterator = 0
GLib.idle_add(self.loadmore, None)
def update_wallpaper(self, widget):
"""Update wallpaper using feh command (creates .fehbg which is useful)"""
style = self.style_combo.get_active_text()
command = feh_sizes.get(style, feh_sizes['Fill'])
try:
background = self.image_browser.get_selected_items()[0]
except:
return
path = self.browser_info[background][1]
subprocess.run(["feh", command, path])
def loadmore(self, derp):
"""Reduce startup time by using an idle signal to load wallpaper icons"""
file = self.filelist[self.iterator]
_, ext = os.path.splitext(file)
print(ext)
if ext.lower() in [".png", ".jpeg", ".jpg"]:
wallpaper = self.wallpaper_directory+"/"+file
thumb_path = file
self.thumbdict[thumb_path+".png"] = 0
thumb_path = self.cache_directory / (thumb_path+".png")
if not (os.path.exists(thumb_path) and os.path.getmtime(thumb_path) > os.path.getmtime(wallpaper)):
tempthumb = Pixbuf.new_from_file(wallpaper)
target_width = 220
target_height = 124
scale = min(
target_width / tempthumb.get_width(),
target_height / tempthumb.get_height()
)
tempthumb = tempthumb.scale_simple(tempthumb.get_width()*scale, tempthumb.get_height()*scale, InterpType.TILES)
self.browser_info.append([tempthumb, wallpaper])
print(str(thumb_path))
tempthumb.savev(str(thumb_path), "png")
else:
self.browser_info.append([Pixbuf.new_from_file(str(thumb_path)), wallpaper])
self.iterator += 1
if self.iterator >= len(self.filelist):
GLib.idle_add(self.clean_thumbnails, None)
else:
GLib.idle_add(self.loadmore, None)
def change_folder_cb(self, btn):
if self.change_folder():
self.browser_info.clear()
self.parse_directory()
def change_folder(self):
chooser = Gtk.FileChooserDialog(
title="Change Wallpaper Search Folder",
action=Gtk.FileChooserAction.SELECT_FOLDER
)
chooser.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
chooser.add_buttons(Gtk.STOCK_OPEN, Gtk.ResponseType.OK)
response = chooser.run()
if response == Gtk.ResponseType.OK:
self.wallpaper_directory = chooser.get_filename()
open(self.folder_file, "w").write(self.wallpaper_directory)
chooser.destroy()
else:
chooser.destroy()
return False
return True
def clean_thumbnails(self, btn):
os.chdir(self.cache_directory)
files = os.listdir(".")
for file in files:
if file not in self.thumbdict:
os.remove(file)
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
if not win.killed:
win.show_all()
Gtk.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment