Update readme
Begin logging Account for fb2 books without covers
This commit is contained in:
21
README.md
21
README.md
@@ -10,19 +10,30 @@ Currently supports:
|
|||||||
* azw / azw3 / azw4
|
* azw / azw3 / azw4
|
||||||
* cbr / cbz
|
* cbr / cbz
|
||||||
|
|
||||||
Support for a bunch of other formats is coming. Please see the TODO for additional information.
|
## Donate to support development
|
||||||
|
Bitcoin: 17jaxj26vFJNqQ2hEVerbBV5fpTusfqFro
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
### Needed
|
||||||
| Package | Version tested |
|
| Package | Version tested |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Qt5 | 5.10.1 |
|
| Qt5 | 5.10.1 |
|
||||||
| Python | 3.6 |
|
| Python | 3.6 |
|
||||||
| PyQt5 | 5.10.1 |
|
| PyQt5 | 5.10.1 |
|
||||||
|
| python-lxml | 4.3.0 |
|
||||||
| python-beautifulsoup4 | 4.6.0 |
|
| python-beautifulsoup4 | 4.6.0 |
|
||||||
|
|
||||||
|
### Optional
|
||||||
|
| Package | Version tested |
|
||||||
|
| --- | --- |
|
||||||
| poppler-qt5 | 0.61.1 |
|
| poppler-qt5 | 0.61.1 |
|
||||||
| python-poppler-qt5 | 0.24.2 |
|
| python-poppler-qt5 | 0.24.2 |
|
||||||
|
|
||||||
poppler-qt5 and python-poppler-qt5 are optional.
|
## Support
|
||||||
|
When reporting issues:
|
||||||
|
* Include the log `~/.local/share/Lector/Lector.log` AND terminal output.
|
||||||
|
* If you're having trouble with a book while the rest of the application / other books work, please link to a copy of the book itself.
|
||||||
|
* If nothing is working, please make sure the requirements mentioned above are all installed, and are at least at the version mentioned.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
### Manual
|
### Manual
|
||||||
@@ -85,12 +96,6 @@ Please keep the translations short. There's only so much space for UI elements.
|
|||||||
### Settings window
|
### Settings window
|
||||||

|

|
||||||
|
|
||||||
## Reporting issues
|
|
||||||
When reporting issues:
|
|
||||||
|
|
||||||
* If you're having trouble with a book while the rest of the application / other books work, please link to a copy of the book itself.
|
|
||||||
* If nothing is working, please make sure the requirements mentioned above are all installed, and are at least at the version mentioned.
|
|
||||||
|
|
||||||
## Attributions
|
## Attributions
|
||||||
* [KindleUnpack](https://github.com/kevinhendricks/KindleUnpack)
|
* [KindleUnpack](https://github.com/kevinhendricks/KindleUnpack)
|
||||||
* [rarfile](https://github.com/markokr/rarfile)
|
* [rarfile](https://github.com/markokr/rarfile)
|
||||||
|
@@ -19,9 +19,12 @@
|
|||||||
import os
|
import os
|
||||||
import gc
|
import gc
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
import hashlib
|
import hashlib
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
# This allows for the program to be launched from the
|
# This allows for the program to be launched from the
|
||||||
# dir where it's been copied instead of needing to be
|
# dir where it's been copied instead of needing to be
|
||||||
# installed
|
# installed
|
||||||
@@ -29,7 +32,20 @@ install_dir = os.path.realpath(__file__)
|
|||||||
install_dir = pathlib.Path(install_dir).parents[1]
|
install_dir = pathlib.Path(install_dir).parents[1]
|
||||||
sys.path.append(str(install_dir))
|
sys.path.append(str(install_dir))
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
# Initialize logging
|
||||||
|
# This is outside the UI declaration to allow sharing
|
||||||
|
# the object across modules without explicit redeclaration
|
||||||
|
logger_filename = os.path.join(
|
||||||
|
QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.AppDataLocation),
|
||||||
|
'Lector',
|
||||||
|
'Lector.log')
|
||||||
|
logging.basicConfig(
|
||||||
|
filename=logger_filename,
|
||||||
|
filemode='a',
|
||||||
|
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
|
||||||
|
datefmt='%H:%M:%S',
|
||||||
|
level=logging.ERROR)
|
||||||
|
logger = logging.getLogger('lector.main')
|
||||||
|
|
||||||
from lector import database
|
from lector import database
|
||||||
from lector import sorter
|
from lector import sorter
|
||||||
@@ -240,7 +256,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
|
|
||||||
# Get list of available parsers
|
# Get list of available parsers
|
||||||
self.available_parsers = '*.' + ' *.'.join(sorter.available_parsers)
|
self.available_parsers = '*.' + ' *.'.join(sorter.available_parsers)
|
||||||
print('Available parsers: ' + self.available_parsers)
|
logger.info('Available parsers: ' + self.available_parsers)
|
||||||
|
|
||||||
# The Library tab gets no button
|
# The Library tab gets no button
|
||||||
self.tabWidget.tabBar().setTabButton(
|
self.tabWidget.tabBar().setTabButton(
|
||||||
@@ -407,7 +423,8 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
if not file_paths:
|
if not file_paths:
|
||||||
return
|
return
|
||||||
|
|
||||||
print('Attempting to open: ' + ', '.join(file_paths))
|
logger.info(
|
||||||
|
'Attempting to open: ' + ', '.join(file_paths))
|
||||||
|
|
||||||
contents = sorter.BookSorter(
|
contents = sorter.BookSorter(
|
||||||
file_paths,
|
file_paths,
|
||||||
@@ -420,13 +437,18 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
# Notification feedback in case all books return nothing
|
# Notification feedback in case all books return nothing
|
||||||
|
|
||||||
if not contents:
|
if not contents:
|
||||||
|
logger.error('No parseable files found')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
successfully_opened = []
|
||||||
for i in contents:
|
for i in contents:
|
||||||
# New tabs are created here
|
# New tabs are created here
|
||||||
# Initial position adjustment is carried out by the tab itself
|
# Initial position adjustment is carried out by the tab itself
|
||||||
file_data = contents[i]
|
file_data = contents[i]
|
||||||
Tab(file_data, self)
|
Tab(file_data, self)
|
||||||
|
successfully_opened.append(file_data['path'])
|
||||||
|
logger.info(
|
||||||
|
'Successfully opened: ' + ', '.join(file_paths))
|
||||||
|
|
||||||
if self.settings['last_open_tab'] == 'library':
|
if self.settings['last_open_tab'] == 'library':
|
||||||
self.tabWidget.setCurrentIndex(0)
|
self.tabWidget.setCurrentIndex(0)
|
||||||
@@ -1041,7 +1063,8 @@ def main():
|
|||||||
translations_out_string = '(Translations found)'
|
translations_out_string = '(Translations found)'
|
||||||
if not translations_found:
|
if not translations_found:
|
||||||
translations_out_string = '(No translations found)'
|
translations_out_string = '(No translations found)'
|
||||||
print(f'Locale: {QtCore.QLocale.system().name()}', translations_out_string)
|
log_string = f'Locale: {QtCore.QLocale.system().name()}' + translations_out_string
|
||||||
|
logger.info(log_string)
|
||||||
|
|
||||||
form = MainUI()
|
form = MainUI()
|
||||||
form.show()
|
form.show()
|
||||||
@@ -1050,4 +1073,5 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
logger.info('Application start')
|
||||||
main()
|
main()
|
||||||
|
@@ -14,10 +14,14 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
from lector.resources import annotationswindow
|
from lector.resources import annotationswindow
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AnnotationsUI(QtWidgets.QDialog, annotationswindow.Ui_Dialog):
|
class AnnotationsUI(QtWidgets.QDialog, annotationswindow.Ui_Dialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
|
import logging
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -29,6 +30,8 @@ from lector.rarfile import rarfile
|
|||||||
from lector.threaded import BackGroundCacheRefill
|
from lector.threaded import BackGroundCacheRefill
|
||||||
from lector.annotations import AnnotationPlacement
|
from lector.annotations import AnnotationPlacement
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PliantQGraphicsView(QtWidgets.QGraphicsView):
|
class PliantQGraphicsView(QtWidgets.QGraphicsView):
|
||||||
def __init__(self, filepath, main_window, parent=None):
|
def __init__(self, filepath, main_window, parent=None):
|
||||||
@@ -124,7 +127,7 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
|
|||||||
return bigPixmap
|
return bigPixmap
|
||||||
|
|
||||||
def generate_image_cache(current_page):
|
def generate_image_cache(current_page):
|
||||||
print('Building image cache')
|
logger.info('(Re)building image cache')
|
||||||
current_page_index = all_pages.index(current_page)
|
current_page_index = all_pages.index(current_page)
|
||||||
|
|
||||||
# Image caching for single and double page views
|
# Image caching for single and double page views
|
||||||
@@ -491,7 +494,7 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
selected_index = self.parent.annotationListView.currentIndex()
|
selected_index = self.parent.annotationListView.currentIndex()
|
||||||
self.current_annotation = self.parent.annotationModel.data(
|
self.current_annotation = self.parent.annotationModel.data(
|
||||||
selected_index, QtCore.Qt.UserRole)
|
selected_index, QtCore.Qt.UserRole)
|
||||||
print('Current annotation: ' + self.current_annotation['name'])
|
logger.info('Selected annotation: ' + + self.current_annotation['name'])
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
def mouseReleaseEvent(self, event):
|
||||||
# This takes care of annotation placement
|
# This takes care of annotation placement
|
||||||
|
@@ -17,9 +17,12 @@
|
|||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DatabaseInit:
|
class DatabaseInit:
|
||||||
def __init__(self, location_prefix):
|
def __init__(self, location_prefix):
|
||||||
@@ -81,7 +84,8 @@ class DatabaseInit:
|
|||||||
for i in self.books_table_columns.items():
|
for i in self.books_table_columns.items():
|
||||||
if i[0] not in database_columns:
|
if i[0] not in database_columns:
|
||||||
commit_required = True
|
commit_required = True
|
||||||
print(f'Database: Adding column "{i[0]}"')
|
info_string = f'Database: Adding column "{i[0]}"'
|
||||||
|
logger.info(info_string)
|
||||||
sql_command = f"ALTER TABLE books ADD COLUMN {i[0]} {i[1]}"
|
sql_command = f"ALTER TABLE books ADD COLUMN {i[0]} {i[1]}"
|
||||||
self.database.execute(sql_command)
|
self.database.execute(sql_command)
|
||||||
|
|
||||||
@@ -208,7 +212,7 @@ class DatabaseFunctions:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
except (KeyError, sqlite3.OperationalError):
|
except (KeyError, sqlite3.OperationalError):
|
||||||
print('SQLite is in wretched rebellion @ data fetching handling')
|
logger.critical('SQLite is in wretched rebellion @ data fetching handling')
|
||||||
|
|
||||||
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])
|
||||||
@@ -241,7 +245,7 @@ class DatabaseFunctions:
|
|||||||
self.database.execute(
|
self.database.execute(
|
||||||
sql_command, update_data)
|
sql_command, update_data)
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
print('SQLite is in wretched rebellion @ metadata handling')
|
logger.critical('SQLite is in wretched rebellion @ metadata handling')
|
||||||
|
|
||||||
self.database.commit()
|
self.database.commit()
|
||||||
self.database.close()
|
self.database.close()
|
||||||
|
@@ -15,14 +15,20 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PyQt5 import QtMultimedia
|
from PyQt5 import QtMultimedia
|
||||||
multimedia_available = True
|
multimedia_available = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print('QtMultimedia not found. Sounds will not play.')
|
error_string = 'QtMultimedia not found. Sounds will not play.'
|
||||||
|
print(error_string)
|
||||||
|
logger.error(error_string)
|
||||||
multimedia_available = False
|
multimedia_available = False
|
||||||
|
|
||||||
from lector.resources import definitions
|
from lector.resources import definitions
|
||||||
|
@@ -14,9 +14,14 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
from lector.resources import pie_chart
|
from lector.resources import pie_chart
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LibraryDelegate(QtWidgets.QStyledItemDelegate):
|
class LibraryDelegate(QtWidgets.QStyledItemDelegate):
|
||||||
def __init__(self, temp_dir, parent=None):
|
def __init__(self, temp_dir, parent=None):
|
||||||
|
@@ -14,12 +14,16 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
from lector import database
|
from lector import database
|
||||||
from lector.settings import Settings
|
from lector.settings import Settings
|
||||||
from lector.resources import resources
|
from lector.resources import resources
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class QImageFactory:
|
class QImageFactory:
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from PyQt5 import QtGui, QtCore
|
from PyQt5 import QtGui, QtCore
|
||||||
@@ -23,6 +24,8 @@ from PyQt5 import QtGui, QtCore
|
|||||||
from lector import database
|
from lector import database
|
||||||
from lector.models import TableProxyModel, ItemProxyModel
|
from lector.models import TableProxyModel, ItemProxyModel
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Library:
|
class Library:
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
@@ -47,7 +50,7 @@ class Library:
|
|||||||
'LIKE')
|
'LIKE')
|
||||||
|
|
||||||
if not books:
|
if not books:
|
||||||
print('Database returned nothing')
|
logger.error('Database returned nothing')
|
||||||
return
|
return
|
||||||
|
|
||||||
elif mode == 'addition':
|
elif mode == 'addition':
|
||||||
@@ -320,7 +323,7 @@ class Library:
|
|||||||
addition_mode = item_metadata['addition_mode']
|
addition_mode = item_metadata['addition_mode']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
addition_mode = 'automatic'
|
addition_mode = 'automatic'
|
||||||
print('Libary: Error setting addition mode for prune')
|
logger.error('Libary: Error setting addition mode for prune')
|
||||||
|
|
||||||
if (book_path not in valid_paths and
|
if (book_path not in valid_paths and
|
||||||
(addition_mode != 'manual' or addition_mode is None)):
|
(addition_mode != 'manual' or addition_mode is None)):
|
||||||
|
@@ -14,12 +14,16 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
from lector import database
|
from lector import database
|
||||||
from lector.widgets import PliantQGraphicsScene
|
from lector.widgets import PliantQGraphicsScene
|
||||||
from lector.resources import metadata
|
from lector.resources import metadata
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MetadataUI(QtWidgets.QDialog, metadata.Ui_Dialog):
|
class MetadataUI(QtWidgets.QDialog, metadata.Ui_Dialog):
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
|
@@ -14,11 +14,14 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtWidgets
|
from PyQt5 import QtCore, QtWidgets
|
||||||
from lector.resources import pie_chart
|
from lector.resources import pie_chart
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BookmarkProxyModel(QtCore.QSortFilterProxyModel):
|
class BookmarkProxyModel(QtCore.QSortFilterProxyModel):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@@ -19,10 +19,13 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from lector.rarfile import rarfile
|
from lector.rarfile import rarfile
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ParseCOMIC:
|
class ParseCOMIC:
|
||||||
def __init__(self, filename, *args):
|
def __init__(self, filename, *args):
|
||||||
|
@@ -16,9 +16,12 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
|
import logging
|
||||||
|
|
||||||
from lector.readers.read_epub import EPUB
|
from lector.readers.read_epub import EPUB
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ParseEPUB:
|
class ParseEPUB:
|
||||||
def __init__(self, filename, temp_dir, file_md5):
|
def __init__(self, filename, temp_dir, file_md5):
|
||||||
|
@@ -15,9 +15,12 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
from lector.readers.read_fb2 import FB2
|
from lector.readers.read_fb2 import FB2
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ParseFB2:
|
class ParseFB2:
|
||||||
def __init__(self, filename, temp_dir, file_md5):
|
def __init__(self, filename, temp_dir, file_md5):
|
||||||
|
@@ -21,10 +21,13 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import zipfile
|
import zipfile
|
||||||
|
import logging
|
||||||
|
|
||||||
from lector.readers.read_epub import EPUB
|
from lector.readers.read_epub import EPUB
|
||||||
import lector.KindleUnpack.kindleunpack as KindleUnpack
|
import lector.KindleUnpack.kindleunpack as KindleUnpack
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ParseMOBI:
|
class ParseMOBI:
|
||||||
def __init__(self, filename, temp_dir, file_md5):
|
def __init__(self, filename, temp_dir, file_md5):
|
||||||
|
@@ -20,12 +20,15 @@
|
|||||||
|
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
import popplerqt5
|
import popplerqt5
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ParsePDF:
|
class ParsePDF:
|
||||||
def __init__(self, filename, *args):
|
def __init__(self, filename, *args):
|
||||||
|
@@ -15,11 +15,14 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
import zipfile
|
import zipfile
|
||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EPUB:
|
class EPUB:
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
@@ -189,7 +192,7 @@ class EPUB:
|
|||||||
if biggest_image:
|
if biggest_image:
|
||||||
self.book['cover'] = self.read_from_zip(biggest_image)
|
self.book['cover'] = self.read_from_zip(biggest_image)
|
||||||
else:
|
else:
|
||||||
print('No cover found for: ' + self.filename)
|
logger.error('No cover found for: ' + self.filename)
|
||||||
|
|
||||||
# Parse spine and arrange chapter paths acquired from the opf
|
# Parse spine and arrange chapter paths acquired from the opf
|
||||||
# according to the order IN THE SPINE
|
# according to the order IN THE SPINE
|
||||||
|
@@ -17,9 +17,12 @@
|
|||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
import zipfile
|
import zipfile
|
||||||
|
import logging
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class FB2:
|
class FB2:
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
@@ -83,7 +86,9 @@ class FB2:
|
|||||||
for i in cover_image_data:
|
for i in cover_image_data:
|
||||||
if cover_image_name.endswith(i.get('id')):
|
if cover_image_name.endswith(i.get('id')):
|
||||||
self.book['cover'] = base64.decodebytes(i.text.encode())
|
self.book['cover'] = base64.decodebytes(i.text.encode())
|
||||||
except AttributeError:
|
except (AttributeError, TypeError):
|
||||||
|
# Catch TypeError in case no images exist in the book
|
||||||
|
logger.error('No cover found for: ' + self.filename)
|
||||||
self.book['cover'] = None
|
self.book['cover'] = None
|
||||||
|
|
||||||
def parse_chapters(self, temp_dir):
|
def parse_chapters(self, temp_dir):
|
||||||
|
@@ -10,5 +10,6 @@
|
|||||||
<p>Author: BasioMeusPuga <a href="mailto:disgruntled.mob@gmail.com">disgruntled.mob@gmail.com</a></p>
|
<p>Author: BasioMeusPuga <a href="mailto:disgruntled.mob@gmail.com">disgruntled.mob@gmail.com</a></p>
|
||||||
<p>Page: <a href="https://github.com/BasioMeusPuga/Lector">https://github.com/BasioMeusPuga/Lector</a></p>
|
<p>Page: <a href="https://github.com/BasioMeusPuga/Lector">https://github.com/BasioMeusPuga/Lector</a></p>
|
||||||
<p>License: GPLv3 <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">https://www.gnu.org/licenses/gpl-3.0.en.html</a></p>
|
<p>License: GPLv3 <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">https://www.gnu.org/licenses/gpl-3.0.en.html</a></p>
|
||||||
|
<p>Donate (Bitcoin): 17jaxj26vFJNqQ2hEVerbBV5fpTusfqFro</p>
|
||||||
<p> </p></body>
|
<p> </p></body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -17,10 +17,13 @@
|
|||||||
# Keep in mind that all integer / boolean settings are returned as strings
|
# Keep in mind that all integer / boolean settings are returned as strings
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui
|
from PyQt5 import QtCore, QtGui
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import copy
|
import copy
|
||||||
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||||
@@ -30,6 +31,8 @@ from lector.threaded import BackGroundBookSearch, BackGroundBookAddition
|
|||||||
from lector.resources import settingswindow
|
from lector.resources import settingswindow
|
||||||
from lector.settings import Settings
|
from lector.settings import Settings
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
|
class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@@ -189,7 +192,7 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
|
|||||||
self.main_window.generate_library_filter_menu(paths)
|
self.main_window.generate_library_filter_menu(paths)
|
||||||
directory_data = {}
|
directory_data = {}
|
||||||
if not paths:
|
if not paths:
|
||||||
print('Database: No paths for settings...')
|
logger.error('Database: No paths for settings...')
|
||||||
else:
|
else:
|
||||||
# Convert to the dictionary format that is
|
# Convert to the dictionary format that is
|
||||||
# to be fed into the QFileSystemModel
|
# to be fed into the QFileSystemModel
|
||||||
|
@@ -36,6 +36,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import pickle
|
import pickle
|
||||||
|
import logging
|
||||||
import hashlib
|
import hashlib
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
@@ -53,6 +54,8 @@ from lector.parsers.mobi import ParseMOBI
|
|||||||
from lector.parsers.fb2 import ParseFB2
|
from lector.parsers.fb2 import ParseFB2
|
||||||
from lector.parsers.comicbooks import ParseCOMIC
|
from lector.parsers.comicbooks import ParseCOMIC
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
sorter = {
|
sorter = {
|
||||||
'epub': ParseEPUB,
|
'epub': ParseEPUB,
|
||||||
'mobi': ParseMOBI,
|
'mobi': ParseMOBI,
|
||||||
@@ -70,7 +73,9 @@ try:
|
|||||||
from lector.parsers.pdf import ParsePDF
|
from lector.parsers.pdf import ParsePDF
|
||||||
sorter['pdf'] = ParsePDF
|
sorter['pdf'] = ParsePDF
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print('python-poppler-qt5 is not installed. Pdf files will not work.')
|
error_string = 'python-poppler-qt5 is not installed. Pdf files will not work.'
|
||||||
|
print(error_string)
|
||||||
|
logger.error(error_string)
|
||||||
|
|
||||||
available_parsers = [i for i in sorter]
|
available_parsers = [i for i in sorter]
|
||||||
progressbar = None # This is populated by __main__
|
progressbar = None # This is populated by __main__
|
||||||
@@ -194,7 +199,7 @@ class BookSorter:
|
|||||||
# None values are accounted for here
|
# None values are accounted for here
|
||||||
is_valid = book_ref.read_book()
|
is_valid = book_ref.read_book()
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
print('Cannot parse: ' + filename)
|
logger.error('Cannot parse:' + filename)
|
||||||
return
|
return
|
||||||
|
|
||||||
if book_ref.book:
|
if book_ref.book:
|
||||||
@@ -311,7 +316,8 @@ class BookSorter:
|
|||||||
return_books[j] = i[j]
|
return_books[j] = i[j]
|
||||||
|
|
||||||
del self.processed_books
|
del self.processed_books
|
||||||
print('Finished processing in', time.time() - start_time)
|
processing_time = str(time.time() - start_time)
|
||||||
|
logger.info('Finished processing in:' + processing_time)
|
||||||
return return_books
|
return return_books
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from multiprocessing.dummy import Pool
|
from multiprocessing.dummy import Pool
|
||||||
@@ -24,6 +25,8 @@ from PyQt5 import QtCore, QtGui
|
|||||||
from lector import sorter
|
from lector import sorter
|
||||||
from lector import database
|
from lector import database
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BackGroundTabUpdate(QtCore.QThread):
|
class BackGroundTabUpdate(QtCore.QThread):
|
||||||
def __init__(self, database_path, all_metadata, parent=None):
|
def __init__(self, database_path, all_metadata, parent=None):
|
||||||
|
@@ -14,8 +14,12 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtCore
|
from PyQt5 import QtWidgets, QtCore
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BookToolBar(QtWidgets.QToolBar):
|
class BookToolBar(QtWidgets.QToolBar):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
@@ -28,6 +29,8 @@ from lector.sorter import resize_image
|
|||||||
from lector.threaded import BackGroundTextSearch
|
from lector.threaded import BackGroundTextSearch
|
||||||
from lector.contentwidgets import PliantQGraphicsView, PliantQTextBrowser
|
from lector.contentwidgets import PliantQGraphicsView, PliantQTextBrowser
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Tab(QtWidgets.QWidget):
|
class Tab(QtWidgets.QWidget):
|
||||||
def __init__(self, metadata, main_window, parent=None):
|
def __init__(self, metadata, main_window, parent=None):
|
||||||
|
Reference in New Issue
Block a user