Multiple fixes

Images are now center aligned
Better logging
This commit is contained in:
BasioMeusPuga
2019-02-10 23:43:17 +05:30
parent 3cd75807f9
commit 564db06179
8 changed files with 109 additions and 98 deletions

View File

@@ -302,9 +302,10 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
for count, i in enumerate(self.settings['main_window_headers']):
self.tableView.horizontalHeader().resizeSection(count, int(i))
self.tableView.horizontalHeader().resizeSection(5, 30)
self.tableView.horizontalHeader().setStretchLastSection(False)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.horizontalHeader().sectionClicked.connect(
self.lib_ref.tableProxyModel.sort_table_columns)
self.lib_ref.tableProxyModel.sort_table_columns(2)
self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tableView.customContextMenuRequested.connect(
self.generate_library_context_menu)
@@ -360,7 +361,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
def process_post_hoc_files(self, file_list, open_files_after_processing):
# Takes care of both dragged and dropped files
# As well as files sent as command line arguments
file_list = [i for i in file_list if os.path.exists(i)]
if not file_list:
return
@@ -390,7 +390,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# This allows for threading file opening
# Which should speed up multiple file opening
# especially @ application start
file_paths = [i for i in path_hash_dictionary]
for filename in path_hash_dictionary.items():
@@ -520,15 +519,15 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.thread.finished.connect(self.move_on)
self.thread.start()
def get_selection(self, library_widget):
def get_selection(self):
selected_indexes = None
if library_widget == self.listView:
if self.listView.isVisible():
selected_books = self.lib_ref.itemProxyModel.mapSelectionToSource(
self.listView.selectionModel().selection())
selected_indexes = [i.indexes()[0] for i in selected_books]
elif library_widget == self.tableView:
elif self.tableView.isVisible():
selected_books = self.tableView.selectionModel().selectedRows()
selected_indexes = [
self.lib_ref.tableProxyModel.mapToSource(i) for i in selected_books]
@@ -536,16 +535,10 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
return selected_indexes
def delete_books(self, selected_indexes=None):
if not selected_indexes:
# Get a list of QItemSelection objects
# What we're interested in is the indexes()[0] in each of them
# That gives a list of indexes from the view model
if self.listView.isVisible():
selected_indexes = self.get_selection(self.listView)
elif self.tableView.isVisible():
selected_indexes = self.get_selection(self.tableView)
# Get a list of QItemSelection objects
# What we're interested in is the indexes()[0] in each of them
# That gives a list of indexes from the view model
selected_indexes = self.get_selection()
if not selected_indexes:
return
@@ -572,10 +565,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.thread.start()
# Generate a message box to confirm deletion
selected_number = len(selected_indexes)
confirm_deletion = QtWidgets.QMessageBox()
deletion_prompt = self._translate(
'Main_UI', f'Delete {selected_number} book(s)?')
'Main_UI', f'Delete book(s)?')
confirm_deletion.setText(deletion_prompt)
confirm_deletion.setIcon(QtWidgets.QMessageBox.Question)
confirm_deletion.setWindowTitle(self._translate('Main_UI', 'Confirm deletion'))
@@ -770,6 +762,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
signal_sender = None
else:
signal_sender = self.sender().objectName()
self.profile_functions.modify_comic_view(
signal_sender, key_pressed)
@@ -805,7 +798,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# It's worth remembering that these are indexes of the libraryModel
# and NOT of the proxy models
selected_indexes = self.get_selection(self.sender())
selected_indexes = self.get_selection()
context_menu = QtWidgets.QMenu()

View File

@@ -241,6 +241,7 @@ class ViewProfileModification:
self.format_contentView()
def modify_comic_view(self, signal_sender, key_pressed):
comic_profile = self.main_window.comic_profile
current_tab = self.tabWidget.widget(self.tabWidget.currentIndex())
self.bookToolBar.fitWidth.setChecked(False)
@@ -248,34 +249,35 @@ class ViewProfileModification:
self.bookToolBar.originalSize.setChecked(False)
if signal_sender == 'zoomOut' or key_pressed == QtCore.Qt.Key_Minus:
self.comic_profile['zoom_mode'] = 'manualZoom'
self.comic_profile['padding'] += 50
comic_profile['zoom_mode'] = 'manualZoom'
comic_profile['padding'] += 50
# This prevents infinite zoom out
if self.comic_profile['padding'] * 2 > current_tab.contentView.viewport().width():
self.comic_profile['padding'] -= 50
if comic_profile['padding'] * 2 > current_tab.contentView.viewport().width():
comic_profile['padding'] -= 50
if signal_sender == 'zoomIn' or key_pressed in (QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal):
self.comic_profile['zoom_mode'] = 'manualZoom'
self.comic_profile['padding'] -= 50
if signal_sender == 'zoomIn' or key_pressed in (
QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal):
comic_profile['zoom_mode'] = 'manualZoom'
comic_profile['padding'] -= 50
# This prevents infinite zoom in
if self.comic_profile['padding'] < 0:
self.comic_profile['padding'] = 0
if comic_profile['padding'] < 0:
comic_profile['padding'] = 0
if signal_sender == 'fitWidth' or key_pressed == QtCore.Qt.Key_W:
self.comic_profile['zoom_mode'] = 'fitWidth'
self.comic_profile['padding'] = 0
comic_profile['zoom_mode'] = 'fitWidth'
comic_profile['padding'] = 0
self.bookToolBar.fitWidth.setChecked(True)
# Padding in the following cases is decided by
# the image pixmap loaded by the widget
if signal_sender == 'bestFit' or key_pressed == QtCore.Qt.Key_B:
self.comic_profile['zoom_mode'] = 'bestFit'
comic_profile['zoom_mode'] = 'bestFit'
self.bookToolBar.bestFit.setChecked(True)
if signal_sender == 'originalSize' or key_pressed == QtCore.Qt.Key_O:
self.comic_profile['zoom_mode'] = 'originalSize'
comic_profile['zoom_mode'] = 'originalSize'
self.bookToolBar.originalSize.setChecked(True)
self.format_contentView()
@@ -290,7 +292,6 @@ class ViewProfileModification:
if current_metadata['images_only']:
background = self.comic_profile['background']
padding = self.comic_profile['padding']
zoom_mode = self.comic_profile['zoom_mode']
if zoom_mode == 'fitWidth':
@@ -304,7 +305,7 @@ class ViewProfileModification:
'background-color: %s' % background.name())
current_tab.format_view(
None, None, None, background, padding, None, None)
None, None, None, background, None, None, None)
else:
profile_index = self.bookToolBar.profileBox.currentIndex()

View File

@@ -27,11 +27,7 @@ class ParsePDF:
self.book = None
def read_book(self):
try:
self.book = fitz.open(self.filename)
return True
except RuntimeError:
return False
self.book = fitz.open(self.filename)
def generate_metadata(self):
title = self.book.metadata['title']

View File

@@ -17,7 +17,6 @@
# TODO
# See if inserting chapters not in the toc.ncx can be avoided
# Account for stylesheets... eventually
# Everything needs logging
import os
import zipfile
@@ -40,6 +39,7 @@ class EPUB:
self.zip_file = None
self.file_list = None
self.opf_dict = None
self.cover_image_name = None
self.split_chapters = {}
self.metadata = None
@@ -89,7 +89,7 @@ class EPUB:
return i
# If the file isn't found
logging.error(filename + ' not found in ' + self.book_filename)
logger.error(filename + ' not found in ' + self.book_filename)
return False
def generate_toc(self):
@@ -247,25 +247,19 @@ class EPUB:
toc_chapters = [
unquote(i[2].split('#')[0]) for i in self.content]
# TODO
# This totally borks the order
last_valid_index = -2 # Yes, but why?
for i in spine_final:
if not i in toc_chapters:
previous_chapter = spine_final[spine_final.index(i) - 1]
try:
spine_index = spine_final.index(i)
if spine_index == 0: # Or chapter insertion circles back to the end
previous_chapter_toc_index = -1
else:
previous_chapter = spine_final[spine_final.index(i) - 1]
previous_chapter_toc_index = toc_chapters.index(previous_chapter)
# In case of 2+ consecutive missing chapters
last_valid_index = previous_chapter_toc_index
except ValueError:
last_valid_index += 1
# Chapters are currently named None
# Blank chapters will later be removed
# and the None will be replaced by a number
toc_chapters.insert(
previous_chapter_toc_index + 1, i)
self.content.insert(
last_valid_index + 1, [1, None, i])
previous_chapter_toc_index + 1, [1, None, i])
# Parse split chapters as below
# They can be picked up during the iteration through the toc
@@ -334,28 +328,42 @@ class EPUB:
chapter_title = i[1]
if not chapter_title:
chapter_title = unnamed_chapter_title
unnamed_chapter_title += 1
content_copy.append((
i[0], str(chapter_title), i[2]))
unnamed_chapter_title += 1
self.content = content_copy
# TODO
# This can probably be circumvented by shifting the extraction
# to this module and simply getting the path to the cover
# Get cover image and put it in its place
# I imagine this involves saying nasty things to it
# There's no point shifting this to the parser
# The performance increase is negligible
cover_image = self.generate_book_cover()
if cover_image:
cover_path = os.path.join(
self.temp_dir, os.path.basename(self.book_filename)) + ' - cover'
with open(cover_path, 'wb') as cover_temp:
cover_temp.write(cover_image)
# There's probably some rationale to doing an insert here
# But a replacement seems... neater
self.content.insert(
0, (1, 'Cover', f'<center><img src="{cover_path}" alt="Cover"></center>'))
# This is probably stupid, but I can't stand the idea of
# having to look at two book covers
cover_replacement_conditions = (
self.cover_image_name.lower() + '.jpg' in self.content[0][2].lower(),
self.cover_image_name.lower() + '.png' in self.content[0][2].lower(),
'cover' in self.content[0][1].lower())
if True in cover_replacement_conditions:
logger.info(
f'Replacing cover {cover_replacement_conditions}: {self.book_filename}')
self.content[0] = (
1, 'Cover',
f'<center><img src="{cover_path}" alt="Cover"></center>')
else:
logger.info('Adding cover: ' + self.book_filename)
self.content.insert(
0,
(1, 'Cover',
f'<center><img src="{cover_path}" alt="Cover"></center>'))
def generate_metadata(self):
book_metadata = self.opf_dict['package']['metadata']
@@ -443,6 +451,8 @@ class EPUB:
if i['@media-type'].split('/')[0] == 'image' and
'cover' in i['@id']][0]
book_cover = self.zip_file.read(self.find_file(cover_image))
self.cover_image_name = os.path.splitext(
os.path.basename(cover_image))[0]
except:
pass

View File

@@ -124,8 +124,8 @@ class BookSorter:
self.queue = Manager().Queue()
self.processed_books = []
# if self.work_mode == 'addition':
progress_object_generator()
if self.work_mode == 'addition':
progress_object_generator()
def database_hashes(self):
all_hashes_and_paths = database.DatabaseFunctions(
@@ -140,9 +140,6 @@ class BookSorter:
i[0]: i[1] for i in all_hashes_and_paths}
def database_entry_for_book(self, file_hash):
# TODO
# This will probably look a whole lot better with a namedtuple
database_return = database.DatabaseFunctions(
self.database_path).fetch_data(
('Title', 'Author', 'Year', 'ISBN', 'Tags',
@@ -187,7 +184,8 @@ class BookSorter:
or os.path.exists(self.hashes_and_paths[file_md5])):
if not self.hashes_and_paths[file_md5] == filename:
warning_string = f'{os.path.basename(filename)} is already in database'
warning_string = (
f'{os.path.basename(filename)} is already in database')
logger.warning(warning_string)
return
@@ -214,8 +212,9 @@ class BookSorter:
try:
book_ref.read_book()
except:
logger.error('Error initializing: ' + filename)
except Exception as e:
this_error = f'Error initializing: {filename} {type(e).__name__} Arguments: {e.args}'
logger.exception(this_error)
return
this_book = {}
@@ -227,8 +226,10 @@ class BookSorter:
if self.work_mode == 'addition':
try:
metadata = book_ref.generate_metadata()
except:
logger.error('Metadata generation error: ' + filename)
except Exception as e:
this_error = (
f'Metadata generation error: {filename} {type(e).__name__} Arguments: {e.args}')
logger.exception(this_error)
return
title = metadata.title
@@ -255,16 +256,24 @@ class BookSorter:
if self.work_mode == 'reading':
try:
book_breakdown = book_ref.generate_content()
except KeyboardInterrupt:
logger.error('Content generation error: ' + filename)
except Exception as e:
this_error = (
f'Content generation error: {filename} {type(e).__name__} Arguments: {e.args}')
logger.exception(this_error)
return
toc = book_breakdown[0]
content = book_breakdown[1]
images_only = book_breakdown[2]
book_data = self.database_entry_for_book(file_md5)
title = book_data[0]
try:
book_data = self.database_entry_for_book(file_md5)
except TypeError:
logger.error(
f'Database error: {filename}. Re-add book to program')
return
title = book_data[0].replace('&', '&&')
author = book_data[1]
year = book_data[2]
isbn = book_data[3]

View File

@@ -521,30 +521,37 @@ class Tab(QtWidgets.QWidget):
'center': QtCore.Qt.AlignCenter,
'justify': QtCore.Qt.AlignJustify}
# Adjusted for books without covers
current_position = self.metadata['position']['current_chapter']
chapter_name = self.metadata['toc'][current_position - 1][1]
if current_position == 1 and chapter_name == 'Cover':
block_format.setAlignment(
QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
else:
block_format.setAlignment(alignment_dict[text_alignment])
# Also for padding
# Using setViewPortMargins for this disables scrolling in the margins
block_format.setLeftMargin(padding)
block_format.setRightMargin(padding)
this_cursor = self.contentView.textCursor()
this_cursor.movePosition(QtGui.QTextCursor.Start, 0, 1)
this_cursor.setPosition(QtGui.QTextCursor.Start)
# Iterate over the entire document block by block
# The document ends when the cursor position can no longer be incremented
while True:
# So this fixes the stupid repetitive iteration
# I was doing over the entire thing
# It also allows for all images to be center aligned.
# Magic. *jazz hands*
block_text = this_cursor.block().text().strip()
try:
# Object replacement char - Seems to work with images
if ord(block_text) == 65532:
block_format.setAlignment(
QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
else:
raise TypeError
except TypeError:
block_format.setAlignment(alignment_dict[text_alignment])
# Iterate over the entire document block by block
# The document ends when the cursor position can no longer be incremented
old_position = this_cursor.position()
this_cursor.mergeBlockFormat(block_format)
this_cursor.movePosition(QtGui.QTextCursor.NextBlock, 0, 1)
this_cursor.movePosition(
QtGui.QTextCursor.NextBlock, QtGui.QTextCursor.MoveAnchor)
new_position = this_cursor.position()
if old_position == new_position:
break