Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added tests/resources/example_multistaff.pdf
Binary file not shown.
34 changes: 34 additions & 0 deletions tests/timelines/pdf/test_pdf_timeline.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from pathlib import Path
from tilia.dirs import clear_tmp_path
from tilia.ui import commands
from tilia.timelines.timeline_kinds import TimelineKind
from unittest.mock import patch


class TestValidateComponentCreation:
Expand Down Expand Up @@ -74,3 +78,33 @@ def test_page_number_is_limited_by_page_total(self, tilia_state, pdf_tl):
tilia_state.current_time = 30
commands.execute("timeline.pdf.add")
assert pdf_tl[-1].get_data("page_number") == 2


class TestLoadPdf:
@patch("tilia.dirs.tmp_path", Path("tmp_path"))
def test_online_pdf(self, tls):
tls.create_timeline(
TimelineKind.PDF_TIMELINE,
path="https://s9.imslp.org/files/imglnks/usimg/0/04/IMSLP228371-WIMA.53e2-W.A.Moz.Ah_vous_dirai-je-Maman.pdf",
)

assert tls[0].is_pdf_valid
assert tls[0].page_total == 19
assert not tls[0].is_local

clear_tmp_path()

def test_local_pdf(self, tls, resources):
tls.create_timeline(
TimelineKind.PDF_TIMELINE,
path=(resources / "example_multistaff.pdf").as_posix(),
)

assert tls[0].is_pdf_valid
assert tls[0].page_total == 1
assert tls[0].is_local

def test_non_pdf(self, tls, resources):
tls.create_timeline(TimelineKind.PDF_TIMELINE, path="nonexistent.pdf")

assert not tls[0].is_pdf_valid
2 changes: 2 additions & 0 deletions tilia/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ def on_close(self) -> None:
return

post(Post.UI_EXIT, 0)
if settings.get("general", "clear_cache_on_exit"):
tilia.dirs.clear_tmp_path()

def load_media(
self,
Expand Down
30 changes: 29 additions & 1 deletion tilia/dirs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

autosaves_path = Path()
logs_path = Path()
tmp_path = Path()
_SITE_DATA_DIR = Path(platformdirs.site_data_dir(tilia.constants.APP_NAME))
_USER_DATA_DIR = Path(
platformdirs.user_data_dir(tilia.constants.APP_NAME, roaming=True)
Expand Down Expand Up @@ -39,19 +40,27 @@ def setup_logs_path(data_dir):
create_logs_dir(data_dir)


def setup_tmp_path(data_dir):
if not os.path.exists(tmp_path):
create_tmp_path(data_dir)


def setup_dirs() -> None:
os.chdir(os.path.dirname(__file__))

data_dir = setup_data_dir()

global autosaves_path, logs_path
global autosaves_path, logs_path, tmp_path

autosaves_path = Path(data_dir, "autosaves")
setup_autosaves_path(data_dir)

logs_path = Path(data_dir, "logs")
setup_logs_path(data_dir)

tmp_path = Path(data_dir, "tmp")
setup_tmp_path(data_dir)


def create_data_dir() -> Path:
try:
Expand All @@ -72,5 +81,24 @@ def create_logs_dir(data_dir: Path):
os.mkdir(Path(data_dir, "logs"))


def create_tmp_path(data_dir: Path):
os.mkdir(Path(data_dir, "tmp"))


def open_autosaves_dir():
open_with_os(autosaves_path)


def clear_tmp_path():
for root, dirs, files in os.walk(tmp_path, False):
r = Path(root)
for f in files:
try:
os.unlink(r / f)
except PermissionError: # file is in use
continue
for d in dirs: # dir is not empty
try:
os.rmdir(r / d)
except OSError:
continue
1 change: 1 addition & 0 deletions tilia/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class SettingsManager(QObject):
"timeline_background_color": "#EEE",
"loop_box_shade": "#78c0c0c0",
"prioritise_performance": "true",
"clear_cache_on_exit": "false",
},
"auto-save": {"max_stored_files": 100, "interval_(seconds)": 300},
"media_metadata": {
Expand Down
38 changes: 33 additions & 5 deletions tilia/timelines/pdf/timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

import functools

import httpx
import pypdf
from pathlib import Path
from urllib import parse


import tilia.dirs
from tilia.errors import display, LOAD_FILE_ERROR
from tilia.requests import get, Get
from tilia.settings import settings
from tilia.timelines.base.component.pointlike import scale_pointlike, crop_pointlike
Expand Down Expand Up @@ -54,18 +60,40 @@ def path(self):
return self._path

@path.setter
def path(self, value):
def path(self, value: str):
self._path = value
self.page_total = 0
self.is_local = True
self.is_pdf_valid = False
if checked_path := get(Get.VERIFIED_PATH, value):
self.page_total = 0
if parse.urlparse(value).scheme in ("http", "https"):
path = tilia.dirs.tmp_path / value.partition("://")[2]
if not path.exists() and not self._download_pdf(path, value):
return
self.is_local = False
self.page_total = len(pypdf.PdfReader(path).pages)
self.is_pdf_valid = True
self.tmp_path = path.as_posix()

elif checked_path := get(Get.VERIFIED_PATH, value):
try:
self.page_total = len(pypdf.PdfReader(checked_path).pages)
self._path = Path(checked_path).as_posix()
self.is_local = True
self.is_pdf_valid = True
self._path = checked_path
self.page_total = len(pypdf.PdfReader(checked_path).pages)

except FileNotFoundError:
return

def _download_pdf(self, path, url):
if not (response := httpx.get(url)).is_success:
display(LOAD_FILE_ERROR, url, response)
return False
path = tilia.dirs.tmp_path / url.partition("://")[2]
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "wb") as f:
f.write(response.content)
return True

def setup_blank_timeline(self):
self.create_component(ComponentKind.PDF_MARKER, time=0, page_number=1)

Expand Down
5 changes: 4 additions & 1 deletion tilia/ui/timelines/pdf/timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ def _handle_invalid_pdf(self):
def _load_pdf_file(self):
if not self.timeline.get_data("is_pdf_valid"):
self._handle_invalid_pdf()
self.pdf_document.load(self.get_data("path"))
if self.timeline.get_data("is_local"):
self.pdf_document.load(self.get_data("path"))
else:
self.pdf_document.load(self.get_data("tmp_path"))
self.pdf_view.update_window(
int(self.pdf_document.pagePointSize(0).height()),
int(self.pdf_document.pagePointSize(0).width()),
Expand Down
Loading