114 lines
3.7 KiB
Python
114 lines
3.7 KiB
Python
from pathlib import Path
|
|
from datatypes import *
|
|
from typing import cast, Any
|
|
from util import rofi
|
|
import pydbus
|
|
import subprocess
|
|
import fitz
|
|
|
|
|
|
def get_section_pdf() -> PDFSection:
|
|
page_ref: PDFPage = get_page_pdf()
|
|
with fitz.Document(page_ref.filepath) as doc:
|
|
toc = [FitzBookmark(*x) for x in cast(Any, doc).get_toc()]
|
|
page_headers = [x for x in toc if x.page == page_ref.page]
|
|
|
|
rofi_res = rofi([f"{x.title}" for x in page_headers], prompt="Select header: ")
|
|
if rofi_res is None or rofi_res.index is None:
|
|
raise RuntimeError("No header was selected.")
|
|
else:
|
|
selected_header = page_headers[rofi_res.index]
|
|
return PDFSection(filepath=page_ref.filepath, title=selected_header.title)
|
|
|
|
|
|
def get_destination_pdf() -> PDFDestination:
|
|
page_ref: PDFPage = get_page_pdf()
|
|
with fitz.Document(page_ref.filepath) as doc:
|
|
destinations = cast(FitzDestinations, cast(Any, doc).resolve_names())
|
|
page_dests = {
|
|
k: x
|
|
for k, x in destinations.items()
|
|
if cast(Any, x)["page"] + 1 == page_ref.page
|
|
}
|
|
|
|
rofi_res = rofi(
|
|
[f"{k}" for k, _ in page_dests.items()], prompt="Select named destination: "
|
|
)
|
|
if rofi_res is None or rofi_res.index is None:
|
|
raise RuntimeError("No destination was selected.")
|
|
else:
|
|
selected_header = [x for x in page_dests.items()][rofi_res.index]
|
|
return PDFDestination(filepath=page_ref.filepath, name=selected_header[0])
|
|
|
|
|
|
def get_page_pdf() -> PDFPage:
|
|
"""Find current page of focused PDF reader window.
|
|
|
|
Returns
|
|
-------
|
|
`PDFPage` reference to the current page.
|
|
"""
|
|
try:
|
|
res = subprocess.run(
|
|
["xdotool", "getactivewindow"], capture_output=True, text=True
|
|
)
|
|
window_id: WindowId = WindowId(int(res.stdout))
|
|
res = subprocess.run(
|
|
["xdotool", "getactivewindow", "getwindowpid"],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
pid: ProcessId = ProcessId(int(res.stdout))
|
|
except OSError as e:
|
|
raise Exception("Please install `xdotool`.") from e
|
|
except subprocess.CalledProcessError as e:
|
|
raise Exception(
|
|
"Could not get current active window ID. Is a window focused right now?"
|
|
)
|
|
|
|
try:
|
|
res = subprocess.run(
|
|
["xprop", "-id", str(window_id), "WM_CLASS"], capture_output=True, text=True
|
|
)
|
|
# WM_CLASS(STRING) = "org.pwmt.zathura", "Zathura"
|
|
wm_class: list[str] = [
|
|
i.strip('"\n') for i in res.stdout.split(" = ")[-1].split(", ")
|
|
]
|
|
except OSError as e:
|
|
raise Exception("Please install `xprop`.") from e
|
|
except subprocess.CalledProcessError as e:
|
|
raise Exception("Could not get focused window class.") from e
|
|
|
|
match wm_class[0]:
|
|
case "Zathura":
|
|
return get_page_zathura(pid)
|
|
case "org.pwmt.zathura":
|
|
return get_page_zathura(pid)
|
|
case _:
|
|
raise Exception(
|
|
f"Can not retrieve pdf data from this type of window {wm_class}."
|
|
)
|
|
|
|
|
|
def get_page_zathura(pid: ProcessId) -> PDFPage:
|
|
"""Given the PID of a Zathura instance, find which page of which file it's on.
|
|
|
|
Parameters
|
|
----------
|
|
pid
|
|
Process ID of the Zathura instance to retrieve the reference from.
|
|
|
|
Returns
|
|
-------
|
|
`PDFPage` that the Zathura instance is currently on.
|
|
"""
|
|
|
|
bus = pydbus.SessionBus()
|
|
obj = bus.get(f"org.pwmt.zathura.PID-{pid}", "/org/pwmt/zathura")
|
|
|
|
filename: str = obj.filename
|
|
# zathura returns 0-indexed pages
|
|
pagenumber: PageNumber = obj.pagenumber + 1
|
|
|
|
return PDFPage(filepath=Path(filename), page=pagenumber)
|