73 lines
2.0 KiB
Python
73 lines
2.0 KiB
Python
import contextlib
|
|
import dataclasses
|
|
import plistlib
|
|
import sqlite3
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
DB_PATH = Path("~/Library/Application Support/Dock/desktoppicture.db").expanduser()
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class SpaceInfo:
|
|
uuid: str
|
|
image_path: Optional[Path]
|
|
data_id: Optional[Path]
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def get_connection() -> sqlite3.Connection:
|
|
con = sqlite3.connect(str(DB_PATH))
|
|
con.row_factory = sqlite3.Row
|
|
yield con
|
|
con.close()
|
|
|
|
|
|
def get_current_wallpapers() -> list[SpaceInfo]:
|
|
sql = """
|
|
select distinct s.space_uuid, pr.key, d.rowid, d.value from preferences pr
|
|
left join payload d on d.rowid = pr.data_id
|
|
left join pictures p on p.rowid = pr.picture_id
|
|
inner join spaces s on s.rowid = p.space_id
|
|
where key = 1
|
|
|
|
order by space_uuid, key
|
|
"""
|
|
spaces = list_spaces()
|
|
|
|
with get_connection() as con:
|
|
cur = con.execute(sql)
|
|
|
|
space_props = {}
|
|
for i, row in enumerate(cur):
|
|
space_uuid = row["space_uuid"]
|
|
data_id = row["rowid"]
|
|
image_path = row["value"]
|
|
|
|
if image_path:
|
|
image_path = Path(image_path).expanduser()
|
|
space_props[space_uuid] = SpaceInfo(uuid=space_uuid, image_path=image_path, data_id=data_id)
|
|
return [space_props.get(id, SpaceInfo(uuid="", image_path=None, data_id=None)) for id in spaces]
|
|
|
|
|
|
def read_plist(plist_path):
|
|
with plist_path.open("rb") as f:
|
|
return plistlib.load(f)
|
|
|
|
|
|
def list_spaces():
|
|
spaces_plist_path = Path("~/Library/Preferences/com.apple.spaces.plist").expanduser()
|
|
data = read_plist(spaces_plist_path)
|
|
spaces = data["SpacesDisplayConfiguration"]["Management Data"]["Monitors"][0]["Spaces"]
|
|
return [s["uuid"] for s in spaces]
|
|
|
|
|
|
def set_wallpaper(image_path: Path):
|
|
script = f'tell application "Finder" to set desktop picture to "{image_path.expanduser().resolve()}" as POSIX file'
|
|
subprocess.run(["osascript", "-e", script], check=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pass
|