Improved PDF handling

This commit is contained in:
Deniz Şafak
2025-05-09 17:36:49 +03:00
parent 22086793ae
commit ac8907041a
2 changed files with 50 additions and 58 deletions
+1
View File
@@ -3,6 +3,7 @@
- Ignore chapter markers and single newlines when calculating text length, improving the accuracy of the text length calculation. - Ignore chapter markers and single newlines when calculating text length, improving the accuracy of the text length calculation.
- Prevent cancellation if process is at 99%, ensuring the process is not interrupted at the last moment. - Prevent cancellation if process is at 99%, ensuring the process is not interrupted at the last moment.
- Improved process handling for subpprocess calls, ensuring better management of subprocesses. - Improved process handling for subpprocess calls, ensuring better management of subprocesses.
- Improved PDF handling, ignoring empty pages/chapters and better chapter handling.
- Added `.opus` as output format for generated audio files. - Added `.opus` as output format for generated audio files.
- Added "Playing..." indicator for "Preview" button in the voice mixer. - Added "Playing..." indicator for "Preview" button in the voice mixer.
+47 -56
View File
@@ -934,6 +934,7 @@ class HandlerDialog(QDialog):
def _build_pdf_tree(self): def _build_pdf_tree(self):
outline = self.pdf_doc.get_toc() outline = self.pdf_doc.get_toc()
self.has_pdf_bookmarks = bool(outline) self.has_pdf_bookmarks = bool(outline)
self.bookmark_items_map = {}
if not outline: if not outline:
self._build_pdf_pages_tree() self._build_pdf_pages_tree()
@@ -976,20 +977,23 @@ class HandlerDialog(QDialog):
else self.pdf_doc.resolve_link(page)[0] else self.pdf_doc.resolve_link(page)[0]
) )
page_id = f"page_{page_num+1}" page_id = f"page_{page_num+1}"
# attach chapters on same page under original
if page_num in self.bookmark_items_map:
orig = self.bookmark_items_map[page_num]
child = QTreeWidgetItem(orig, [f"{title} (Same page)"])
child.setData(0, Qt.UserRole, page_id)
child.setFlags(child.flags() & ~Qt.ItemIsUserCheckable)
continue
bookmark_item = QTreeWidgetItem(parent_item, [title]) bookmark_item = QTreeWidgetItem(parent_item, [title])
bookmark_item.setData(0, Qt.UserRole, page_id) bookmark_item.setData(0, Qt.UserRole, page_id)
bookmark_item.setFlags( # only allow checking if this chapter has content
bookmark_item.flags() | Qt.ItemIsUserCheckable if self.content_lengths.get(page_id, 0) > 0:
) bookmark_item.setFlags(bookmark_item.flags() | Qt.ItemIsUserCheckable)
bookmark_item.setCheckState( bookmark_item.setCheckState(0, Qt.Checked if page_id in self.checked_chapters else Qt.Unchecked)
0, else:
( bookmark_item.setFlags(bookmark_item.flags() & ~Qt.ItemIsUserCheckable)
Qt.Checked # map for uncategorized pages
if page_id in self.checked_chapters self.bookmark_items_map[page_num] = bookmark_item
else Qt.Unchecked
),
)
added_pages.add(page_num) added_pages.add(page_num)
@@ -1012,30 +1016,39 @@ class HandlerDialog(QDialog):
page_item = QTreeWidgetItem(bookmark_item, [page_title]) page_item = QTreeWidgetItem(bookmark_item, [page_title])
page_item.setData(0, Qt.UserRole, page_id) page_item.setData(0, Qt.UserRole, page_id)
# only allow checking if this sub-page has content
if self.content_lengths.get(page_id, 0) > 0:
page_item.setFlags(page_item.flags() | Qt.ItemIsUserCheckable) page_item.setFlags(page_item.flags() | Qt.ItemIsUserCheckable)
page_item.setCheckState( page_item.setCheckState(0, Qt.Checked if page_id in self.checked_chapters else Qt.Unchecked)
0, else:
( page_item.setFlags(page_item.flags() & ~Qt.ItemIsUserCheckable)
Qt.Checked
if page_id in self.checked_chapters
else Qt.Unchecked
),
)
added_pages.add(sub_page_num) added_pages.add(sub_page_num)
if len(entry) > 3 and isinstance(entry[3], list):
build_outline_tree(entry[3], bookmark_item)
build_outline_tree(outline, self.treeWidget) build_outline_tree(outline, self.treeWidget)
covered_pages = set(added_pages) covered_pages = set(added_pages)
# attach any pages without direct bookmarks under nearest preceding chapter
uncategorized_pages = [ uncategorized_pages = [i for i in range(len(self.pdf_doc)) if i not in covered_pages]
i for i in range(len(self.pdf_doc)) if i not in covered_pages for page_num in uncategorized_pages:
] # find nearest previous bookmark
if uncategorized_pages: prev_nums = [n for n in sorted(self.bookmark_items_map) if n < page_num]
self._add_other_pages(uncategorized_pages) parent_item = self.bookmark_items_map[prev_nums[-1]] if prev_nums else self.treeWidget
page_id = f"page_{page_num+1}"
title = f"Page {page_num+1}"
text = self.content_texts.get(page_id, "").strip()
if text:
first = text.split("\n", 1)[0].strip()
if first and len(first) < 100:
title += f" - {first}"
page_item = QTreeWidgetItem(parent_item, [title])
page_item.setData(0, Qt.UserRole, page_id)
# only allow checking if uncategorized page has content
if self.content_lengths.get(page_id, 0) > 0:
page_item.setFlags(page_item.flags() | Qt.ItemIsUserCheckable)
page_item.setCheckState(0, Qt.Checked if page_id in self.checked_chapters else Qt.Unchecked)
else:
page_item.setFlags(page_item.flags() & ~Qt.ItemIsUserCheckable)
def _build_pdf_pages_tree(self): def _build_pdf_pages_tree(self):
pages_item = QTreeWidgetItem(self.treeWidget, ["Pages"]) pages_item = QTreeWidgetItem(self.treeWidget, ["Pages"])
@@ -1056,34 +1069,12 @@ class HandlerDialog(QDialog):
page_item = QTreeWidgetItem(pages_item, [page_title]) page_item = QTreeWidgetItem(pages_item, [page_title])
page_item.setData(0, Qt.UserRole, page_id) page_item.setData(0, Qt.UserRole, page_id)
# only allow checking if standalone page has content
if self.content_lengths.get(page_id, 0) > 0:
page_item.setFlags(page_item.flags() | Qt.ItemIsUserCheckable) page_item.setFlags(page_item.flags() | Qt.ItemIsUserCheckable)
page_item.setCheckState( page_item.setCheckState(0, Qt.Checked if page_id in self.checked_chapters else Qt.Unchecked)
0, Qt.Checked if page_id in self.checked_chapters else Qt.Unchecked else:
) page_item.setFlags(page_item.flags() & ~Qt.ItemIsUserCheckable)
def _add_other_pages(self, uncategorized_pages):
other_pages = QTreeWidgetItem(self.treeWidget, ["Other Pages"])
other_pages.setFlags(other_pages.flags() & ~Qt.ItemIsUserCheckable)
font = other_pages.font(0)
font.setBold(True)
other_pages.setFont(0, font)
for page_num in uncategorized_pages:
page_id = f"page_{page_num+1}"
page_title = f"Page {page_num+1}"
page_text = self.content_texts.get(page_id, "").strip()
if page_text:
first_line = page_text.split("\n", 1)[0].strip()
if first_line and len(first_line) < 100:
page_title += f" - {first_line}"
page_item = QTreeWidgetItem(other_pages, [page_title])
page_item.setData(0, Qt.UserRole, page_id)
page_item.setFlags(page_item.flags() | Qt.ItemIsUserCheckable)
page_item.setCheckState(
0, Qt.Checked if page_id in self.checked_chapters else Qt.Unchecked
)
def _are_provided_checks_relevant(self): def _are_provided_checks_relevant(self):
if not self.checked_chapters: if not self.checked_chapters: