Multiple fixes
MuPDF import error Definition text color Database logging
This commit is contained in:
5
TODO
5
TODO
@@ -97,10 +97,15 @@ TODO
|
|||||||
Bookmark name for a page that's not on the TOC and has nothing before
|
Bookmark name for a page that's not on the TOC and has nothing before
|
||||||
Screen position still keeps jumping when inside a paragraph
|
Screen position still keeps jumping when inside a paragraph
|
||||||
Better recursion needed for fb2 toc
|
Better recursion needed for fb2 toc
|
||||||
|
Search results should ignore punctuation
|
||||||
|
Keep text size for annotations
|
||||||
|
|
||||||
Secondary:
|
Secondary:
|
||||||
|
Definitions dialog needs to respond to escape
|
||||||
|
Zoom slider for comics
|
||||||
Tab tooltip
|
Tab tooltip
|
||||||
Additional Settings:
|
Additional Settings:
|
||||||
|
Find definitions on Google
|
||||||
Disable progressbar - 20% book addition speed improvement
|
Disable progressbar - 20% book addition speed improvement
|
||||||
Disable cover loading when reading - Saves ~2M / book
|
Disable cover loading when reading - Saves ~2M / book
|
||||||
Special formatting for each chapter's title
|
Special formatting for each chapter's title
|
||||||
|
@@ -21,13 +21,13 @@ import webbrowser
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import fitz
|
import fitz
|
||||||
|
from lector.parsers.pdf import render_pdf_page
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
from lector.rarfile import rarfile
|
from lector.rarfile import rarfile
|
||||||
from lector.parsers.pdf import render_pdf_page
|
|
||||||
from lector.threaded import BackGroundCacheRefill
|
from lector.threaded import BackGroundCacheRefill
|
||||||
from lector.annotations import AnnotationPlacement
|
from lector.annotations import AnnotationPlacement
|
||||||
|
|
||||||
@@ -501,13 +501,17 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
QtWidgets.QTextBrowser.mouseReleaseEvent(self, event)
|
QtWidgets.QTextBrowser.mouseReleaseEvent(self, event)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.place_annotation(self.current_annotation)
|
||||||
|
self.toggle_annotation_mode()
|
||||||
|
|
||||||
|
def place_annotation(self, annotation):
|
||||||
current_chapter = self.parent.metadata['position']['current_chapter']
|
current_chapter = self.parent.metadata['position']['current_chapter']
|
||||||
cursor = self.textCursor()
|
cursor = self.textCursor()
|
||||||
cursor_start = cursor.selectionStart()
|
cursor_start = cursor.selectionStart()
|
||||||
cursor_end = cursor.selectionEnd()
|
cursor_end = cursor.selectionEnd()
|
||||||
annotation_type = 'text_markup'
|
annotation_type = 'text_markup'
|
||||||
applicable_to = 'text'
|
applicable_to = 'text'
|
||||||
annotation_components = self.current_annotation['components']
|
annotation_components = annotation['components']
|
||||||
|
|
||||||
self.annotator.set_current_annotation(
|
self.annotator.set_current_annotation(
|
||||||
annotation_type, annotation_components)
|
annotation_type, annotation_components)
|
||||||
@@ -520,7 +524,7 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
# Maybe use annotation name for a consolidated annotation list
|
# Maybe use annotation name for a consolidated annotation list
|
||||||
|
|
||||||
this_annotation = {
|
this_annotation = {
|
||||||
'name': self.current_annotation['name'],
|
'name': annotation['name'],
|
||||||
'applicable_to': applicable_to,
|
'applicable_to': applicable_to,
|
||||||
'type': annotation_type,
|
'type': annotation_type,
|
||||||
'cursor': (cursor_start, cursor_end),
|
'cursor': (cursor_start, cursor_end),
|
||||||
@@ -533,8 +537,6 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
self.annotation_dict[current_chapter] = []
|
self.annotation_dict[current_chapter] = []
|
||||||
self.annotation_dict[current_chapter].append(this_annotation)
|
self.annotation_dict[current_chapter].append(this_annotation)
|
||||||
|
|
||||||
self.toggle_annotation_mode()
|
|
||||||
|
|
||||||
def generate_textbrowser_context_menu(self, position):
|
def generate_textbrowser_context_menu(self, position):
|
||||||
selection = self.textCursor().selection()
|
selection = self.textCursor().selection()
|
||||||
selection = selection.toPlainText()
|
selection = selection.toPlainText()
|
||||||
@@ -552,6 +554,7 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
searchWikipediaAction = searchYoutubeAction = 'Does anyone know something funny in Latin?'
|
searchWikipediaAction = searchYoutubeAction = 'Does anyone know something funny in Latin?'
|
||||||
searchAction = searchGoogleAction = bookmarksToggleAction = 'TODO Insert Latin Joke'
|
searchAction = searchGoogleAction = bookmarksToggleAction = 'TODO Insert Latin Joke'
|
||||||
deleteAnnotationAction = editAnnotationNoteAction = 'Latin quote 2. Electric Boogaloo.'
|
deleteAnnotationAction = editAnnotationNoteAction = 'Latin quote 2. Electric Boogaloo.'
|
||||||
|
annotationActions = []
|
||||||
|
|
||||||
if self.parent.is_fullscreen:
|
if self.parent.is_fullscreen:
|
||||||
fsToggleAction = contextMenu.addAction(
|
fsToggleAction = contextMenu.addAction(
|
||||||
@@ -566,13 +569,18 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
|
|
||||||
if selection and selection != '':
|
if selection and selection != '':
|
||||||
first_selected_word = selection.split()[0]
|
first_selected_word = selection.split()[0]
|
||||||
|
elided_selection = selection
|
||||||
|
if len(elided_selection) > 15:
|
||||||
|
elided_selection = elided_selection[:15] + '...'
|
||||||
|
|
||||||
define_string = self._translate('PliantQTextBrowser', 'Define')
|
define_string = self._translate('PliantQTextBrowser', 'Define')
|
||||||
defineAction = contextMenu.addAction(
|
defineAction = contextMenu.addAction(
|
||||||
self.main_window.QImageFactory.get_image('view-readermode'),
|
self.main_window.QImageFactory.get_image('view-readermode'),
|
||||||
f'{define_string} "{first_selected_word}"')
|
f'{define_string} "{first_selected_word}"')
|
||||||
|
|
||||||
search_submenu_string = self._translate('PliantQTextBrowser', 'Search for')
|
search_submenu_string = self._translate('PliantQTextBrowser', 'Search for')
|
||||||
searchSubMenu = contextMenu.addMenu(search_submenu_string + f' "{selection}"')
|
searchSubMenu = contextMenu.addMenu(
|
||||||
|
search_submenu_string + f' "{elided_selection}"')
|
||||||
searchSubMenu.setIcon(self.main_window.QImageFactory.get_image('search'))
|
searchSubMenu.setIcon(self.main_window.QImageFactory.get_image('search'))
|
||||||
|
|
||||||
searchAction = searchSubMenu.addAction(
|
searchAction = searchSubMenu.addAction(
|
||||||
@@ -588,6 +596,26 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
searchYoutubeAction = searchSubMenu.addAction(
|
searchYoutubeAction = searchSubMenu.addAction(
|
||||||
QtGui.QIcon(':/images/Youtube.png'),
|
QtGui.QIcon(':/images/Youtube.png'),
|
||||||
'Youtube')
|
'Youtube')
|
||||||
|
|
||||||
|
# Allow adding new annotation from the context menu
|
||||||
|
if not annotation_is_present:
|
||||||
|
annotation_string = self._translate('PliantQTextBrowser', 'Annotate')
|
||||||
|
annotationSubmenu = contextMenu.addMenu(annotation_string)
|
||||||
|
annotationSubmenu.setIcon(
|
||||||
|
self.main_window.QImageFactory.get_image('annotate'))
|
||||||
|
|
||||||
|
saved_annotations = self.parent.main_window.settings['annotations']
|
||||||
|
if not saved_annotations:
|
||||||
|
nope = annotationSubmenu.addAction('<No annotations set>')
|
||||||
|
nope.setEnabled(False)
|
||||||
|
|
||||||
|
for i in saved_annotations:
|
||||||
|
this_action = QtWidgets.QAction(i['name'])
|
||||||
|
# Does not require / support a role
|
||||||
|
this_action.setData(i)
|
||||||
|
annotationActions.append(this_action)
|
||||||
|
annotationSubmenu.addAction(this_action)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
searchAction = contextMenu.addAction(
|
searchAction = contextMenu.addAction(
|
||||||
self.main_window.QImageFactory.get_image('search'),
|
self.main_window.QImageFactory.get_image('search'),
|
||||||
@@ -639,10 +667,12 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
webbrowser.open_new_tab(
|
webbrowser.open_new_tab(
|
||||||
f'https://www.youtube.com/results?search_query={selection}')
|
f'https://www.youtube.com/results?search_query={selection}')
|
||||||
|
|
||||||
|
if action in annotationActions:
|
||||||
|
self.place_annotation(action.data())
|
||||||
|
|
||||||
if action == editAnnotationNoteAction:
|
if action == editAnnotationNoteAction:
|
||||||
self.common_functions.annotation_specific(
|
self.common_functions.annotation_specific(
|
||||||
'note', 'text', current_chapter, cursor_at_mouse.position())
|
'note', 'text', current_chapter, cursor_at_mouse.position())
|
||||||
|
|
||||||
if action == deleteAnnotationAction:
|
if action == deleteAnnotationAction:
|
||||||
self.common_functions.annotation_specific(
|
self.common_functions.annotation_specific(
|
||||||
'delete', 'text', current_chapter, cursor_at_mouse.position())
|
'delete', 'text', current_chapter, cursor_at_mouse.position())
|
||||||
|
@@ -210,8 +210,9 @@ class DatabaseFunctions:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except (KeyError, sqlite3.OperationalError):
|
except Exception as e:
|
||||||
logger.critical('SQLite is in wretched rebellion @ data fetching handling')
|
error_string = 'SQLite is in wretched rebellion @ data fetching handling'
|
||||||
|
logger.critical(error_string + f' {type(e).__name__} Arguments: {e.args}')
|
||||||
|
|
||||||
def fetch_covers_only(self, hash_list):
|
def fetch_covers_only(self, hash_list):
|
||||||
parameter_marks = ','.join(['?' for i in hash_list])
|
parameter_marks = ','.join(['?' for i in hash_list])
|
||||||
@@ -243,8 +244,9 @@ class DatabaseFunctions:
|
|||||||
try:
|
try:
|
||||||
self.database.execute(
|
self.database.execute(
|
||||||
sql_command, update_data)
|
sql_command, update_data)
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError as e:
|
||||||
logger.critical('SQLite is in wretched rebellion @ metadata handling')
|
error_string = 'SQLite is in wretched rebellion @ metadata handling'
|
||||||
|
logger.critical(error_string + f' {type(e).__name__} Arguments: {e.args}')
|
||||||
|
|
||||||
self.database.commit()
|
self.database.commit()
|
||||||
self.database.close()
|
self.database.close()
|
||||||
|
@@ -86,12 +86,15 @@ class DefinitionsUI(QtWidgets.QDialog, definitions.Ui_Dialog):
|
|||||||
if response.getcode() == 200:
|
if response.getcode() == 200:
|
||||||
return_json = json.loads(response.read())
|
return_json = json.loads(response.read())
|
||||||
return return_json
|
return return_json
|
||||||
except (urllib.error.HTTPError, urllib.error.URLError):
|
except Exception as e:
|
||||||
|
this_error = f'API access error'
|
||||||
|
logger.exception(this_error + f' {type(e).__name__} Arguments: {e.args}')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def find_definition(self, word):
|
def find_definition(self, word):
|
||||||
word_root_json = self.api_call(self.root_url, word)
|
word_root_json = self.api_call(self.root_url, word)
|
||||||
if not word_root_json:
|
if not word_root_json:
|
||||||
|
logger.error('Word root json noped out: ' + word)
|
||||||
self.set_text(word, None, None, True)
|
self.set_text(word, None, None, True)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -100,6 +103,7 @@ class DefinitionsUI(QtWidgets.QDialog, definitions.Ui_Dialog):
|
|||||||
|
|
||||||
definition_json = self.api_call(self.define_url, word_root)
|
definition_json = self.api_call(self.define_url, word_root)
|
||||||
if not definition_json:
|
if not definition_json:
|
||||||
|
logger.error('Definition json noped out: ' + word_root)
|
||||||
self.set_text(word, None, None, True)
|
self.set_text(word, None, None, True)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -118,7 +122,7 @@ class DefinitionsUI(QtWidgets.QDialog, definitions.Ui_Dialog):
|
|||||||
this_definition = j['definitions'][0].capitalize()
|
this_definition = j['definitions'][0].capitalize()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# The API also reports crossReferenceMarkers here
|
# The API also reports crossReferenceMarkers here
|
||||||
pass
|
this_definition = '<Not found>'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
definitions[category].add(this_definition)
|
definitions[category].add(this_definition)
|
||||||
@@ -163,10 +167,21 @@ class DefinitionsUI(QtWidgets.QDialog, definitions.Ui_Dialog):
|
|||||||
self.parent.get_color()
|
self.parent.get_color()
|
||||||
background = self.parent.settings['dialog_background']
|
background = self.parent.settings['dialog_background']
|
||||||
|
|
||||||
|
# Calculate inverse color for the background so that
|
||||||
|
# the text doesn't look blank
|
||||||
|
r, g, b, alpha = background.getRgb()
|
||||||
|
inv_average = 255 - (r + g + b) // 3
|
||||||
|
if 100 < inv_average < 150:
|
||||||
|
inv_average = 255
|
||||||
|
|
||||||
|
foreground = QtGui.QColor(
|
||||||
|
inv_average, inv_average, inv_average, alpha)
|
||||||
|
|
||||||
self.setStyleSheet(
|
self.setStyleSheet(
|
||||||
"QDialog {{background-color: {0}}}".format(background.name()))
|
"QDialog {{background-color: {0}}}".format(background.name()))
|
||||||
self.definitionView.setStyleSheet(
|
self.definitionView.setStyleSheet(
|
||||||
"QTextBrowser {{background-color: {0}}}".format(background.name()))
|
"QTextBrowser {{color:{0}; background-color: {1}}}".format(
|
||||||
|
foreground.name(), background.name()))
|
||||||
|
|
||||||
if not set_initial:
|
if not set_initial:
|
||||||
self.show()
|
self.show()
|
||||||
|
@@ -24,7 +24,11 @@ from PyQt5 import QtCore, QtGui
|
|||||||
|
|
||||||
from lector import sorter
|
from lector import sorter
|
||||||
from lector import database
|
from lector import database
|
||||||
from lector.parsers.pdf import render_pdf_page
|
|
||||||
|
try:
|
||||||
|
from lector.parsers.pdf import render_pdf_page
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@@ -450,6 +450,8 @@ class Tab(QtWidgets.QWidget):
|
|||||||
if tocBox_readjust:
|
if tocBox_readjust:
|
||||||
self.set_tocBox_index(required_position, None)
|
self.set_tocBox_index(required_position, None)
|
||||||
|
|
||||||
|
self.contentView.setFocus()
|
||||||
|
|
||||||
def set_tocBox_index(self, current_position=None, tocBox=None):
|
def set_tocBox_index(self, current_position=None, tocBox=None):
|
||||||
# Get current position from the metadata dictionary
|
# Get current position from the metadata dictionary
|
||||||
# in case it isn't specified
|
# in case it isn't specified
|
||||||
|
Reference in New Issue
Block a user