Improve fb2 parsing

Miscellaneous fixes to navigation
This commit is contained in:
BasioMeusPuga
2019-02-03 23:55:33 +05:30
parent d1662b47d9
commit 91ca1e2190
7 changed files with 67 additions and 32 deletions

12
TODO
View File

@@ -2,8 +2,9 @@ TODO
General: General:
✓ Internationalization ✓ Internationalization
✓ Application icon ✓ Application icon
✓ .desktop file ✓ .desktop file
Flatpak and AppImage support ✓ Shift to logging instead of print statements
Flatpak and AppImage support
Options: Options:
✓ Automatic library management ✓ Automatic library management
✓ Recursive file addition ✓ Recursive file addition
@@ -93,9 +94,13 @@ TODO
Last line in QTextBrowser should never be cut off Last line in QTextBrowser should never be cut off
Does image alignment need to be centered? Does image alignment need to be centered?
Bookmark name for a page that's not on the TOC or has nothing before Bookmark name for a page that's not on the TOC or has nothing before
Screen position still keeps jumping when inside a paragraph
Better recursion needed for fb2 toc
Secondary: Secondary:
The cover page needs to be marked separately Special formatting for each chapter's title
Create covers for books without them
Signal end of chapter with some text
Graphical themes Graphical themes
Change focus rectangle dimensions Change focus rectangle dimensions
Universal Ctrl + Tab Universal Ctrl + Tab
@@ -103,7 +108,6 @@ TODO
Goodreads API: Ratings, Read, Recommendations Goodreads API: Ratings, Read, Recommendations
Get ISBN using python-isbnlib Get ISBN using python-isbnlib
Use embedded fonts + CSS Use embedded fonts + CSS
Shift to logging instead of print statements
txt, doc, chm support txt, doc, chm support
Include icons for filetype emblems Include icons for filetype emblems
Comic view modes Comic view modes

View File

@@ -724,7 +724,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# The set_content method is universal # The set_content method is universal
# It's going to do position tracking # It's going to do position tracking
current_tab = self.tabWidget.currentWidget() current_tab = self.tabWidget.currentWidget()
current_tab.set_content(required_position) current_tab.set_content(required_position, False, True)
def library_doubleclick(self, index): def library_doubleclick(self, index):
sender = self.sender().objectName() sender = self.sender().objectName()

View File

@@ -737,7 +737,7 @@ class PliantWidgetsCommonFunctions:
return direction return direction
current_tab.set_content( current_tab.set_content(
current_position + direction + get_modifier(), True) current_position + direction + get_modifier(), True, True)
# Set page position depending on if the chapter number is increasing or decreasing # Set page position depending on if the chapter number is increasing or decreasing
if direction == 1 or was_button_pressed: if direction == 1 or was_button_pressed:
@@ -853,7 +853,7 @@ class PliantWidgetsCommonFunctions:
def set_toc_position(tocTree): def set_toc_position(tocTree):
currentIndex = tocTree.currentIndex() currentIndex = tocTree.currentIndex()
required_position = currentIndex.data(QtCore.Qt.UserRole) required_position = currentIndex.data(QtCore.Qt.UserRole)
self.pw.parent.set_content(required_position, True) self.pw.parent.set_content(required_position, True, True)
# Create the Combobox / Treeview combination # Create the Combobox / Treeview combination
tocComboBox = QtWidgets.QComboBox() tocComboBox = QtWidgets.QComboBox()

View File

@@ -220,7 +220,7 @@ class Bookmarks:
if is_parent: if is_parent:
chapter_number = self.parent.bookmarkProxyModel.data( chapter_number = self.parent.bookmarkProxyModel.data(
index, QtCore.Qt.UserRole) index, QtCore.Qt.UserRole)
self.parentTab.set_content(chapter_number, True) self.parentTab.set_content(chapter_number, True, True)
return return
chapter = self.parent.bookmarkProxyModel.data( chapter = self.parent.bookmarkProxyModel.data(
@@ -228,7 +228,7 @@ class Bookmarks:
cursor_position = self.parent.bookmarkProxyModel.data( cursor_position = self.parent.bookmarkProxyModel.data(
index, QtCore.Qt.UserRole + 1) index, QtCore.Qt.UserRole + 1)
self.parentTab.set_content(chapter, True) self.parentTab.set_content(chapter, True, True)
if not self.parentTab.are_we_doing_images_only: if not self.parentTab.are_we_doing_images_only:
self.parentTab.set_cursor_position(cursor_position) self.parentTab.set_cursor_position(cursor_position)
@@ -500,7 +500,7 @@ class Search:
cursor_position = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 2) cursor_position = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 2)
search_term = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 4) search_term = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 4)
self.parentTab.set_content(chapter_number, True) self.parentTab.set_content(chapter_number, True, True)
if not self.parentTab.are_we_doing_images_only: if not self.parentTab.are_we_doing_images_only:
self.parentTab.set_cursor_position( self.parentTab.set_cursor_position(
cursor_position, len(search_term)) cursor_position, len(search_term))

View File

@@ -64,8 +64,8 @@ class ParseFB2:
toc = [] toc = []
content = [] content = []
for count, i in enumerate(self.book['book_list']): for count, i in enumerate(self.book['book_list']):
toc.append((1, i[0], count + 1)) toc.append((i[0], i[1], count + 1))
content.append(i[1]) content.append(i[2])
# Return toc, content, images_only # Return toc, content, images_only
return toc, content, False return toc, content, False

View File

@@ -92,18 +92,50 @@ class FB2:
self.book['cover'] = None self.book['cover'] = None
def parse_chapters(self, temp_dir): def parse_chapters(self, temp_dir):
for i in self.xml.find_all('section'): # TODO
this_title = '<No title>' # Check what's up with recursion levels
for j in i: # Why is the TypeError happening in get_title
if j.name == 'title':
this_title = j.getText(separator=' ')
this_title = this_title.replace('\n', '').strip()
# This comes later because the tag is changed in place
title_xml = j.unwrap()
break
self.book['book_list'].append( def get_title(element):
[this_title, str(title_xml) + str(i)]) this_title = '<No title>'
title_xml = '<No title xml>'
try:
for i in element:
if i.name == 'title':
this_title = i.getText(separator=' ')
this_title = this_title.replace('\n', '').strip()
title_xml = str(i.unwrap())
break
except TypeError:
return None, None
return this_title, title_xml
def recursor(level, element):
children = element.findChildren('section', recursive=False)
if not children and level != 1:
this_title, title_xml = get_title(element)
self.book['book_list'].append(
[level, this_title, title_xml + str(element)])
else:
for i in children:
recursor(level + 1, i)
first_element = self.xml.find('section') # Recursive find
siblings = list(first_element.findNextSiblings('section', recursive=False))
siblings.insert(0, first_element)
for this_element in siblings:
this_title, title_xml = get_title(this_element)
# Do not add chapter content in case it has sections
# inside it. This prevents having large Book sections that
# have duplicated content
section_children = this_element.findChildren('section')
chapter_text = str(this_element)
if section_children:
chapter_text = this_title
self.book['book_list'].append([1, this_title, chapter_text])
recursor(1, this_element)
# Extract all images to the temp_dir # Extract all images to the temp_dir
for i in self.xml.find_all('binary'): for i in self.xml.find_all('binary'):
@@ -113,7 +145,7 @@ class FB2:
replacement_string = f'<p></p><img src=\"{image_path}\"' replacement_string = f'<p></p><img src=\"{image_path}\"'
for j in self.book['book_list']: for j in self.book['book_list']:
j[1] = j[1].replace( j[2] = j[2].replace(
image_string, replacement_string) image_string, replacement_string)
try: try:
image_data = base64.decodebytes(i.text.encode()) image_data = base64.decodebytes(i.text.encode())
@@ -128,4 +160,4 @@ class FB2:
with open(cover_path, 'wb') as outimage: with open(cover_path, 'wb') as outimage:
outimage.write(self.book['cover']) outimage.write(self.book['cover'])
self.book['book_list'].insert( self.book['book_list'].insert(
0, ('Cover', f'<center><img src="{cover_path}" alt="Cover"></center>')) 0, (1, 'Cover', f'<center><img src="{cover_path}" alt="Cover"></center>'))

View File

@@ -109,7 +109,7 @@ class Tab(QtWidgets.QWidget):
self.hiddenButton.clicked.connect(self.set_cursor_position) self.hiddenButton.clicked.connect(self.set_cursor_position)
# All content must be set through this function # All content must be set through this function
self.set_content(current_chapter, True) self.set_content(current_chapter, True, False)
if not self.are_we_doing_images_only: if not self.are_we_doing_images_only:
# Setting this later breaks cursor positioning for search results # Setting this later breaks cursor positioning for search results
self.hiddenButton.animateClick(50) self.hiddenButton.animateClick(50)
@@ -249,7 +249,7 @@ class Tab(QtWidgets.QWidget):
# Finally, to make sure the cover image isn't # Finally, to make sure the cover image isn't
# scrolled halfway through on first open, # scrolled halfway through on first open,
if self.main_window.bookToolBar.tocBox.currentIndex() == 0: if self.metadata['position']['current_chapter'] == 1:
self.contentView.verticalScrollBar().setValue(0) self.contentView.verticalScrollBar().setValue(0)
def generate_position(self, is_read=False): def generate_position(self, is_read=False):
@@ -266,10 +266,8 @@ class Tab(QtWidgets.QWidget):
if not self.are_we_doing_images_only: if not self.are_we_doing_images_only:
for i in self.metadata['content']: for i in self.metadata['content']:
chapter_html = i[1]
textDocument = QtGui.QTextDocument(None) textDocument = QtGui.QTextDocument(None)
textDocument.setHtml(chapter_html) textDocument.setHtml(i)
block_count = textDocument.blockCount() block_count = textDocument.blockCount()
blocks_per_chapter.append(block_count) blocks_per_chapter.append(block_count)
@@ -418,7 +416,7 @@ class Tab(QtWidgets.QWidget):
self.mouse_hide_timer.start(2000) self.mouse_hide_timer.start(2000)
self.contentView.setFocus() self.contentView.setFocus()
def set_content(self, required_position, tocBox_readjust=False): def set_content(self, required_position, tocBox_readjust=False, record_position=False):
# All content changes must come through here # All content changes must come through here
# This function will decide how to relate # This function will decide how to relate
# entries in the toc to the actual content # entries in the toc to the actual content
@@ -433,7 +431,8 @@ class Tab(QtWidgets.QWidget):
# Update the metadata dictionary to save position # Update the metadata dictionary to save position
self.metadata['position']['current_chapter'] = required_position self.metadata['position']['current_chapter'] = required_position
self.metadata['position']['is_read'] = False if record_position:
self.contentView.record_position()
if self.are_we_doing_images_only: if self.are_we_doing_images_only:
self.contentView.loadImage(required_content) self.contentView.loadImage(required_content)