Error notifications

In application log viewer / database reset
Cleanup settings navigation
This commit is contained in:
BasioMeusPuga
2019-02-13 00:09:37 +05:30
parent fa030e3060
commit b1714b9674
12 changed files with 275 additions and 96 deletions

View File

@@ -11,6 +11,7 @@ Currently supports:
* cbr / cbz * cbr / cbz
## Contribute ## Contribute
[Paypal](https://www.paypal.me/supportlector)
Bitcoin: 17jaxj26vFJNqQ2hEVerbBV5fpTusfqFro Bitcoin: 17jaxj26vFJNqQ2hEVerbBV5fpTusfqFro
## Requirements ## Requirements

View File

@@ -34,9 +34,9 @@ from PyQt5 import QtWidgets, QtGui, QtCore
# Init logging # Init logging
# Must be done first and at the module level # Must be done first and at the module level
# or it won't work properly in case of the imports below # or it won't work properly in case of the imports below
from lector.logger import init_logging from lector.logger import init_logging, VERSION
logger = init_logging(sys.argv) logger = init_logging(sys.argv)
logger.log(60, 'Application started') logger.log(60, f'Lector {VERSION} - Application started')
from lector import database from lector import database
from lector import sorter from lector import sorter
@@ -127,6 +127,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# Statusbar widgets # Statusbar widgets
self.statusMessage.setObjectName('statusMessage') self.statusMessage.setObjectName('statusMessage')
self.statusBar.addPermanentWidget(self.statusMessage) self.statusBar.addPermanentWidget(self.statusMessage)
self.errorButton = QtWidgets.QPushButton(self.statusBar)
self.errorButton.setIcon(QtGui.QIcon(':/images/error.svg'))
self.errorButton.setFlat(True)
self.errorButton.setVisible(False)
self.errorButton.setToolTip('What hast thou done?')
self.errorButton.clicked.connect(self.show_errors)
self.statusBar.addPermanentWidget(self.errorButton)
self.sorterProgress = QtWidgets.QProgressBar() self.sorterProgress = QtWidgets.QProgressBar()
self.sorterProgress.setMaximumWidth(300) self.sorterProgress.setMaximumWidth(300)
self.sorterProgress.setObjectName('sorterProgress') self.sorterProgress.setObjectName('sorterProgress')
@@ -375,7 +382,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.settings, self.settings,
self.temp_dir.path()) self.temp_dir.path())
parsed_books = books.initiate_threads() parsed_books, errors = books.initiate_threads()
if not parsed_books and not open_files_after_processing: if not parsed_books and not open_files_after_processing:
return return
@@ -386,7 +393,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
if open_files_after_processing: if open_files_after_processing:
self.open_files(file_dict) self.open_files(file_dict)
self.move_on() self.move_on(errors)
def open_files(self, path_hash_dictionary): def open_files(self, path_hash_dictionary):
# file_paths is expected to be a dictionary # file_paths is expected to be a dictionary
@@ -461,45 +468,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.tabWidget.setCurrentIndex(self.tabWidget.count() - 1) self.tabWidget.setCurrentIndex(self.tabWidget.count() - 1)
def start_culling_timer(self):
if self.settings['perform_culling']:
self.culling_timer.start(30)
def resizeEvent(self, event=None):
if event:
# This implies a vertical resize event only
# We ain't about that lifestyle
if event.oldSize().width() == event.size().width():
return
# The hackiness of this hack is just...
default_size = 170 # This is size of the QIcon (160 by default) +
# minimum margin needed between thumbnails
# for n icons, the n + 1th icon will appear at > n +1.11875
# First, calculate the number of images per row
i = self.listView.viewport().width() / default_size
rem = i - int(i)
if rem >= .21875 and rem <= .9999:
num_images = int(i)
else:
num_images = int(i) - 1
# The rest is illustrated using informative variable names
space_occupied = num_images * default_size
# 12 is the scrollbar width
# Larger numbers keep reduce flickering but also increase
# the distance from the scrollbar
space_left = (
self.listView.viewport().width() - space_occupied - 19)
try:
layout_extra_space_per_image = space_left // num_images
self.listView.setGridSize(
QtCore.QSize(default_size + layout_extra_space_per_image, 250))
self.start_culling_timer()
except ZeroDivisionError: # Initial resize is ignored
return
def add_books(self): def add_books(self):
dialog_prompt = self._translate('Main_UI', 'Add books to database') dialog_prompt = self._translate('Main_UI', 'Add books to database')
ebooks_string = self._translate('Main_UI', 'eBooks') ebooks_string = self._translate('Main_UI', 'eBooks')
@@ -519,7 +487,8 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.statusMessage.setText(self._translate('Main_UI', 'Adding books...')) self.statusMessage.setText(self._translate('Main_UI', 'Adding books...'))
self.thread = BackGroundBookAddition( self.thread = BackGroundBookAddition(
opened_files[0], self.database_path, 'manual', self) opened_files[0], self.database_path, 'manual', self)
self.thread.finished.connect(self.move_on) self.thread.finished.connect(
lambda: self.move_on(self.thread.errors))
self.thread.start() self.thread.start()
def get_selection(self): def get_selection(self):
@@ -584,7 +553,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
if self.tabWidget.currentIndex() == 0: if self.tabWidget.currentIndex() == 0:
self.delete_books() self.delete_books()
def move_on(self): def move_on(self, errors=None):
self.settingsDialog.okButton.setEnabled(True) self.settingsDialog.okButton.setEnabled(True)
self.settingsDialog.okButton.setToolTip( self.settingsDialog.okButton.setToolTip(
self._translate('Main_UI', 'Save changes and start library scan')) self._translate('Main_UI', 'Save changes and start library scan'))
@@ -593,8 +562,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.sorterProgress.setVisible(False) self.sorterProgress.setVisible(False)
self.sorterProgress.setValue(0) self.sorterProgress.setValue(0)
if self.libraryToolBar.searchBar.text() == '': # The errors argument is a list and will only be present
self.statusBar.setVisible(False) # in case of addition and reading
if errors:
self.display_error_notification(errors)
else:
if self.libraryToolBar.searchBar.text() == '':
self.statusBar.setVisible(False)
self.lib_ref.update_proxymodels() self.lib_ref.update_proxymodels()
self.lib_ref.generate_library_tags() self.lib_ref.generate_library_tags()
@@ -735,6 +709,20 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.open_files(path) self.open_files(path)
def display_error_notification(self, errors):
self.statusBar.setVisible(True)
self.errorButton.setVisible(True)
def show_errors(self):
# TODO
# Create a separate viewing area for errors
# before showing the log
self.show_settings(3)
self.settingsDialog.aboutTabWidget.setCurrentIndex(1)
self.errorButton.setVisible(False)
self.statusBar.setVisible(False)
def statusbar_visibility(self): def statusbar_visibility(self):
if self.sender() == self.libraryToolBar.searchBar: if self.sender() == self.libraryToolBar.searchBar:
if self.libraryToolBar.searchBar.text() == '': if self.libraryToolBar.searchBar.text() == '':
@@ -745,12 +733,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
def show_settings(self, stacked_widget_index): def show_settings(self, stacked_widget_index):
if not self.settingsDialog.isVisible(): if not self.settingsDialog.isVisible():
self.settingsDialog.show() self.settingsDialog.show()
self.settingsDialog.okButton.setVisible(False)
index = self.settingsDialog.listModel.index( index = self.settingsDialog.listModel.index(
stacked_widget_index, 0) stacked_widget_index, 0)
self.settingsDialog.listView.setCurrentIndex(index) self.settingsDialog.listView.setCurrentIndex(index)
self.settingsDialog.stackedWidget.setCurrentIndex(
stacked_widget_index)
else: else:
self.settingsDialog.hide() self.settingsDialog.hide()
@@ -983,6 +968,45 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.start_culling_timer() self.start_culling_timer()
def start_culling_timer(self):
if self.settings['perform_culling']:
self.culling_timer.start(30)
def resizeEvent(self, event=None):
if event:
# This implies a vertical resize event only
# We ain't about that lifestyle
if event.oldSize().width() == event.size().width():
return
# The hackiness of this hack is just...
default_size = 170 # This is size of the QIcon (160 by default) +
# minimum margin needed between thumbnails
# for n icons, the n + 1th icon will appear at > n +1.11875
# First, calculate the number of images per row
i = self.listView.viewport().width() / default_size
rem = i - int(i)
if rem >= .21875 and rem <= .9999:
num_images = int(i)
else:
num_images = int(i) - 1
# The rest is illustrated using informative variable names
space_occupied = num_images * default_size
# 12 is the scrollbar width
# Larger numbers keep reduce flickering but also increase
# the distance from the scrollbar
space_left = (
self.listView.viewport().width() - space_occupied - 19)
try:
layout_extra_space_per_image = space_left // num_images
self.listView.setGridSize(
QtCore.QSize(default_size + layout_extra_space_per_image, 250))
self.start_culling_timer()
except ZeroDivisionError: # Initial resize is ignored
return
def closeEvent(self, event=None): def closeEvent(self, event=None):
if event: if event:
event.ignore() event.ignore()

View File

@@ -14,20 +14,24 @@
# 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/>.
VERSION = '0.4.nowGIT'
import os import os
import logging import logging
from PyQt5 import QtCore from PyQt5 import QtCore
location_prefix = os.path.join(
QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.AppDataLocation),
'Lector')
logger_filename = os.path.join(location_prefix, 'Lector.log')
def init_logging(cli_arguments): def init_logging(cli_arguments):
# This needs a separate 'Lector' in the os.path.join because # This needs a separate 'Lector' in the os.path.join because
# application name isn't explicitly set in this module # application name isn't explicitly set in this module
location_prefix = os.path.join(
QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.AppDataLocation),
'Lector')
os.makedirs(location_prefix, exist_ok=True) os.makedirs(location_prefix, exist_ok=True)
logger_filename = os.path.join(location_prefix, 'Lector.log')
log_level = 30 # Warning and above log_level = 30 # Warning and above
# Set log level according to command line arguments # Set log level according to command line arguments

View File

@@ -343,4 +343,3 @@ class MostExcellentFileSystemModel(QtWidgets.QFileSystemModel):
for i in deletable: for i in deletable:
del self.tag_data[i] del self.tag_data[i]

View File

@@ -10,6 +10,7 @@
<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:&nbsp;<a href="https://github.com/BasioMeusPuga/Lector">https://github.com/BasioMeusPuga/Lector</a></p> <p>Page:&nbsp;<a href="https://github.com/BasioMeusPuga/Lector">https://github.com/BasioMeusPuga/Lector</a></p>
<p>License: GPLv3&nbsp;<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&nbsp;<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 (Paypal): <a href="https://www.paypal.me/supportlector">https://www.paypal.me/supportlector</p>
<p>Donate (Bitcoin): 17jaxj26vFJNqQ2hEVerbBV5fpTusfqFro</p> <p>Donate (Bitcoin): 17jaxj26vFJNqQ2hEVerbBV5fpTusfqFro</p>
<p>&nbsp;</p></body> <p>&nbsp;</p></body>
</html> </html>

View File

@@ -15,7 +15,7 @@
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QListView" name="listView"> <widget class="SaysHelloWhenClicked" name="listView">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding"> <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@@ -610,15 +610,39 @@ Reopen book to see changes</string>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="aboutPage"> <widget class="QWidget" name="aboutPage">
<layout class="QGridLayout" name="gridLayout_6"> <layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTextBrowser" name="aboutBox"> <widget class="QTabWidget" name="aboutTabWidget">
<property name="openExternalLinks"> <property name="currentIndex">
<bool>true</bool> <number>0</number>
</property>
<property name="openLinks">
<bool>false</bool>
</property> </property>
<widget class="QWidget" name="aboutTab">
<attribute name="title">
<string>About</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QTextBrowser" name="aboutBox">
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="openLinks">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="logTab">
<attribute name="title">
<string>Log</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="logBox"/>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@@ -627,6 +651,20 @@ Reopen book to see changes</string>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_10"> <layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QPushButton" name="resetButton">
<property name="text">
<string>Reset Application</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearLogButton">
<property name="text">
<string>Clear Log</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@@ -660,6 +698,13 @@ Reopen book to see changes</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>SaysHelloWhenClicked</class>
<extends>QListView</extends>
<header>lector.widgets</header>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View File

@@ -14,7 +14,7 @@ class Ui_Dialog(object):
Dialog.resize(1139, 612) Dialog.resize(1139, 612)
self.gridLayout = QtWidgets.QGridLayout(Dialog) self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName("gridLayout")
self.listView = QtWidgets.QListView(Dialog) self.listView = SaysHelloWhenClicked(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@@ -304,17 +304,39 @@ class Ui_Dialog(object):
self.stackedWidget.addWidget(self.annotationsPage) self.stackedWidget.addWidget(self.annotationsPage)
self.aboutPage = QtWidgets.QWidget() self.aboutPage = QtWidgets.QWidget()
self.aboutPage.setObjectName("aboutPage") self.aboutPage.setObjectName("aboutPage")
self.gridLayout_6 = QtWidgets.QGridLayout(self.aboutPage) self.gridLayout_9 = QtWidgets.QGridLayout(self.aboutPage)
self.gridLayout_9.setObjectName("gridLayout_9")
self.aboutTabWidget = QtWidgets.QTabWidget(self.aboutPage)
self.aboutTabWidget.setObjectName("aboutTabWidget")
self.aboutTab = QtWidgets.QWidget()
self.aboutTab.setObjectName("aboutTab")
self.gridLayout_6 = QtWidgets.QGridLayout(self.aboutTab)
self.gridLayout_6.setObjectName("gridLayout_6") self.gridLayout_6.setObjectName("gridLayout_6")
self.aboutBox = QtWidgets.QTextBrowser(self.aboutPage) self.aboutBox = QtWidgets.QTextBrowser(self.aboutTab)
self.aboutBox.setOpenExternalLinks(True) self.aboutBox.setOpenExternalLinks(True)
self.aboutBox.setOpenLinks(False) self.aboutBox.setOpenLinks(False)
self.aboutBox.setObjectName("aboutBox") self.aboutBox.setObjectName("aboutBox")
self.gridLayout_6.addWidget(self.aboutBox, 0, 0, 1, 1) self.gridLayout_6.addWidget(self.aboutBox, 0, 0, 1, 1)
self.aboutTabWidget.addTab(self.aboutTab, "")
self.logTab = QtWidgets.QWidget()
self.logTab.setObjectName("logTab")
self.gridLayout_10 = QtWidgets.QGridLayout(self.logTab)
self.gridLayout_10.setObjectName("gridLayout_10")
self.logBox = QtWidgets.QPlainTextEdit(self.logTab)
self.logBox.setObjectName("logBox")
self.gridLayout_10.addWidget(self.logBox, 0, 0, 1, 1)
self.aboutTabWidget.addTab(self.logTab, "")
self.gridLayout_9.addWidget(self.aboutTabWidget, 0, 0, 1, 1)
self.stackedWidget.addWidget(self.aboutPage) self.stackedWidget.addWidget(self.aboutPage)
self.verticalLayout_4.addWidget(self.stackedWidget) self.verticalLayout_4.addWidget(self.stackedWidget)
self.horizontalLayout_10 = QtWidgets.QHBoxLayout() self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
self.horizontalLayout_10.setObjectName("horizontalLayout_10") self.horizontalLayout_10.setObjectName("horizontalLayout_10")
self.resetButton = QtWidgets.QPushButton(Dialog)
self.resetButton.setObjectName("resetButton")
self.horizontalLayout_10.addWidget(self.resetButton)
self.clearLogButton = QtWidgets.QPushButton(Dialog)
self.clearLogButton.setObjectName("clearLogButton")
self.horizontalLayout_10.addWidget(self.clearLogButton)
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_10.addItem(spacerItem3) self.horizontalLayout_10.addItem(spacerItem3)
self.okButton = QtWidgets.QPushButton(Dialog) self.okButton = QtWidgets.QPushButton(Dialog)
@@ -328,6 +350,7 @@ class Ui_Dialog(object):
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.tabWidget.setCurrentIndex(0) self.tabWidget.setCurrentIndex(0)
self.aboutTabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):
@@ -371,6 +394,11 @@ class Ui_Dialog(object):
self.moveDown.setToolTip(_translate("Dialog", "Move Down")) self.moveDown.setToolTip(_translate("Dialog", "Move Down"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.textTab), _translate("Dialog", "Text")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.textTab), _translate("Dialog", "Text"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.imageTab), _translate("Dialog", "Image")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.imageTab), _translate("Dialog", "Image"))
self.aboutTabWidget.setTabText(self.aboutTabWidget.indexOf(self.aboutTab), _translate("Dialog", "About"))
self.aboutTabWidget.setTabText(self.aboutTabWidget.indexOf(self.logTab), _translate("Dialog", "Log"))
self.resetButton.setText(_translate("Dialog", "Reset Application"))
self.clearLogButton.setText(_translate("Dialog", "Clear Log"))
self.okButton.setText(_translate("Dialog", "Scan Library")) self.okButton.setText(_translate("Dialog", "Scan Library"))
self.cancelButton.setText(_translate("Dialog", "Close")) self.cancelButton.setText(_translate("Dialog", "Close"))
from lector.widgets import SaysHelloWhenClicked

View File

@@ -30,6 +30,7 @@ from lector.models import MostExcellentFileSystemModel
from lector.threaded import BackGroundBookSearch, BackGroundBookAddition 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
from lector.logger import logger_filename, VERSION
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -55,7 +56,10 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
install_dir = pathlib.Path(install_dir).parents[1] install_dir = pathlib.Path(install_dir).parents[1]
aboutfile_path = os.path.join(install_dir, 'lector', 'resources', 'about.html') aboutfile_path = os.path.join(install_dir, 'lector', 'resources', 'about.html')
with open(aboutfile_path) as about_html: with open(aboutfile_path) as about_html:
self.aboutBox.setHtml(about_html.read()) html = about_html.readlines()
html.insert(
8, f'<h3 style="text-align: center;">v{VERSION}</h3>\n')
self.aboutBox.setHtml(''.join(html))
self.paths = None self.paths = None
self.thread = None self.thread = None
@@ -120,7 +124,7 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.largeIncrementBox.valueChanged.connect(self.change_increment) self.largeIncrementBox.valueChanged.connect(self.change_increment)
# Generate the QStandardItemModel for the listView # Generate the QStandardItemModel for the listView
self.listModel = QtGui.QStandardItemModel() self.listModel = QtGui.QStandardItemModel(self.listView)
library_string = self._translate('SettingsUI', 'Library') library_string = self._translate('SettingsUI', 'Library')
switches_string = self._translate('SettingsUI', 'Switches') switches_string = self._translate('SettingsUI', 'Switches')
@@ -143,7 +147,9 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.main_window.QImageFactory.get_image(this_icon)) self.main_window.QImageFactory.get_image(this_icon))
self.listModel.appendRow(item) self.listModel.appendRow(item)
self.listView.setModel(self.listModel) self.listView.setModel(self.listModel)
self.listView.clicked.connect(self.page_switch)
# Custom signal to account for page changes
self.listView.newIndexSignal.connect(self.list_index_changed)
# Annotation related buttons # Annotation related buttons
# Icon names # Icon names
@@ -175,11 +181,37 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
# Generate the filesystem treeView # Generate the filesystem treeView
self.generate_tree() self.generate_tree()
# About... About
self.aboutTabWidget.setDocumentMode(True)
self.aboutTabWidget.setContentsMargins(0, 0, 0, 0)
self.logBox.setReadOnly(True)
# About buttons
self.resetButton.clicked.connect(self.delete_database)
self.clearLogButton.clicked.connect(self.clear_log)
# Hide the image annotation tab # Hide the image annotation tab
# TODO # TODO
# Maybe get off your lazy ass and write something for this # Maybe get off your lazy ass and write something for this
self.tabWidget.setContentsMargins(0, 0, 0, 0)
self.tabWidget.tabBar().setVisible(False) self.tabWidget.tabBar().setVisible(False)
def list_index_changed(self, index):
switch_to = index.row()
self.stackedWidget.setCurrentIndex(switch_to)
valid_buttons = {
0: (self.okButton,),
3: (self.resetButton, self.clearLogButton),}
for i in valid_buttons:
if i == switch_to:
for j in valid_buttons[i]:
j.setVisible(True)
else:
for j in valid_buttons[i]:
j.setVisible(False)
def generate_tree(self): def generate_tree(self):
# Fetch all directories in the database # Fetch all directories in the database
paths = database.DatabaseFunctions( paths = database.DatabaseFunctions(
@@ -203,7 +235,8 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
'check_state': i[3]} 'check_state': i[3]}
self.filesystemModel = MostExcellentFileSystemModel(directory_data) self.filesystemModel = MostExcellentFileSystemModel(directory_data)
self.filesystemModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Dirs) self.filesystemModel.setFilter(
QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Dirs)
self.treeView.setModel(self.filesystemModel) self.treeView.setModel(self.filesystemModel)
# TODO # TODO
@@ -216,7 +249,8 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
# Set the treeView and QFileSystemModel to its desired state # Set the treeView and QFileSystemModel to its desired state
selected_paths = [ selected_paths = [
i for i in directory_data if directory_data[i]['check_state'] == QtCore.Qt.Checked] i for i in directory_data
if directory_data[i]['check_state'] == QtCore.Qt.Checked]
expand_paths = set() expand_paths = set()
for i in selected_paths: for i in selected_paths:
@@ -270,7 +304,6 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.show() self.show()
treeViewIndex = self.listModel.index(0, 0) treeViewIndex = self.listModel.index(0, 0)
self.listView.setCurrentIndex(treeViewIndex) self.listView.setCurrentIndex(treeViewIndex)
self.page_switch(treeViewIndex)
return return
except AttributeError: except AttributeError:
pass pass
@@ -317,16 +350,10 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
# We now create a new thread to put those files into the database # We now create a new thread to put those files into the database
self.thread = BackGroundBookAddition( self.thread = BackGroundBookAddition(
self.thread.valid_files, self.database_path, 'automatic', self.main_window) self.thread.valid_files, self.database_path, 'automatic', self.main_window)
self.thread.finished.connect(self.main_window.move_on) self.thread.finished.connect(
lambda: self.main_window.move_on(self.thread.errors))
self.thread.start() self.thread.start()
def page_switch(self, index):
self.stackedWidget.setCurrentIndex(index.row())
if index.row() == 0:
self.okButton.setVisible(True)
else:
self.okButton.setVisible(False)
def cancel_pressed(self): def cancel_pressed(self):
self.filesystemModel.tag_data = copy.deepcopy(self.tag_data_copy) self.filesystemModel.tag_data = copy.deepcopy(self.tag_data_copy)
self.hide() self.hide()
@@ -336,8 +363,15 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
event.accept() event.accept()
def showEvent(self, event): def showEvent(self, event):
# Load log into the plainTextEdit
with open(logger_filename) as infile:
log_text = infile.read()
self.logBox.setPlainText(log_text)
# Annotation preview
self.format_preview() self.format_preview()
# Make copy of tags in case of a nope.jpg
self.tag_data_copy = copy.deepcopy(self.filesystemModel.tag_data) self.tag_data_copy = copy.deepcopy(self.filesystemModel.tag_data)
event.accept() event.accept()
def no_more_settings(self): def no_more_settings(self):
@@ -497,3 +531,30 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
annotations_out.append(annotation_data) annotations_out.append(annotation_data)
self.main_window.settings['annotations'] = annotations_out self.main_window.settings['annotations'] = annotations_out
def delete_database(self):
def ifcontinue(box_button):
if box_button.text() != '&Yes':
return
database_filename = os.path.join(
self.main_window.database_path, 'Lector.db')
os.remove(database_filename)
QtWidgets.qApp.exit()
# Generate a message box to confirm deletion
confirm_deletion = QtWidgets.QMessageBox()
deletion_prompt = self._translate(
'SettingsUI', f'Delete database and exit?')
confirm_deletion.setText(deletion_prompt)
confirm_deletion.setIcon(QtWidgets.QMessageBox.Critical)
confirm_deletion.setWindowTitle(self._translate('SettingsUI', 'Confirm'))
confirm_deletion.setStandardButtons(
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
confirm_deletion.buttonClicked.connect(ifcontinue)
confirm_deletion.show()
confirm_deletion.exec_()
def clear_log(self):
self.logBox.clear()
open(logger_filename, 'w').close()

View File

@@ -123,6 +123,7 @@ class BookSorter:
self.threading_completed = [] self.threading_completed = []
self.queue = Manager().Queue() self.queue = Manager().Queue()
self.errors = Manager().list()
self.processed_books = [] self.processed_books = []
if self.work_mode == 'addition': if self.work_mode == 'addition':
@@ -214,8 +215,9 @@ class BookSorter:
try: try:
book_ref.read_book() book_ref.read_book()
except Exception as e: except Exception as e:
this_error = f'Error initializing: {filename} {type(e).__name__} Arguments: {e.args}' this_error = f'Error initializing: {filename}'
logger.exception(this_error) self.errors.append(this_error)
logger.exception(this_error + f' {type(e).__name__} Arguments: {e.args}')
return return
this_book = {} this_book = {}
@@ -228,9 +230,9 @@ class BookSorter:
try: try:
metadata = book_ref.generate_metadata() metadata = book_ref.generate_metadata()
except Exception as e: except Exception as e:
this_error = ( this_error = f'Metadata generation error: {filename}'
f'Metadata generation error: {filename} {type(e).__name__} Arguments: {e.args}') self.errors.append(this_error)
logger.exception(this_error) logger.exception(this_error + f' {type(e).__name__} Arguments: {e.args}')
return return
title = metadata.title title = metadata.title
@@ -257,9 +259,9 @@ class BookSorter:
try: try:
book_breakdown = book_ref.generate_content() book_breakdown = book_ref.generate_content()
except Exception as e: except Exception as e:
this_error = ( this_error = f'Content generation error: {filename}'
f'Content generation error: {filename} {type(e).__name__} Arguments: {e.args}') self.errors.append(this_error)
logger.exception(this_error) logger.exception(this_error + f' {type(e).__name__} Arguments: {e.args}')
return return
toc = book_breakdown[0] toc = book_breakdown[0]
@@ -347,7 +349,8 @@ class BookSorter:
del self.processed_books del self.processed_books
processing_time = str(time.time() - start_time) processing_time = str(time.time() - start_time)
logger.info('Finished processing in ' + processing_time) logger.info('Finished processing in ' + processing_time)
return return_books
return return_books, self.errors
def progress_object_generator(): def progress_object_generator():

View File

@@ -55,6 +55,7 @@ class BackGroundBookAddition(QtCore.QThread):
self.database_path = database_path self.database_path = database_path
self.addition_mode = addition_mode self.addition_mode = addition_mode
self.main_window = main_window self.main_window = main_window
self.errors = []
self.prune_required = True self.prune_required = True
if self.addition_mode == 'manual': if self.addition_mode == 'manual':
@@ -68,7 +69,7 @@ class BackGroundBookAddition(QtCore.QThread):
self.main_window.settings, self.main_window.settings,
self.main_window.temp_dir.path()) self.main_window.temp_dir.path())
parsed_books = books.initiate_threads() parsed_books, self.errors = books.initiate_threads()
self.main_window.lib_ref.generate_model('addition', parsed_books, False) self.main_window.lib_ref.generate_model('addition', parsed_books, False)
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books) database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)

View File

@@ -683,3 +683,19 @@ class DragDropTableView(QtWidgets.QTableView):
event.acceptProposedAction() event.acceptProposedAction()
else: else:
super(DragDropTableView, self).dropEvent(event) super(DragDropTableView, self).dropEvent(event)
class SaysHelloWhenClicked(QtWidgets.QListView):
# Signal declarations must be outside the constructor
# The argument is the type of the data emitted
newIndexSignal = QtCore.pyqtSignal(QtCore.QModelIndex)
def __init__(self, parent):
super(SaysHelloWhenClicked, self).__init__(parent)
self.parent = parent
def currentChanged(self, index, previous_index):
if not index.isValid():
return
self.newIndexSignal.emit(index)

View File

@@ -1,14 +1,10 @@
import codecs import codecs
from os import path from os import path
from setuptools import setup, find_packages from setuptools import setup, find_packages
from lector.logger import VERSION
HERE = path.abspath(path.dirname(__file__)) HERE = path.abspath(path.dirname(__file__))
MAJOR_VERSION = '0'
MINOR_VERSION = '4'
MICRO_VERSION = '1'
VERSION = "{}.{}.{}".format(MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION)
# Get the long description from the README file # Get the long description from the README file
with codecs.open(path.join(HERE, 'README.md'), encoding='utf-8') as f: with codecs.open(path.join(HERE, 'README.md'), encoding='utf-8') as f:
LONG_DESC = f.read() LONG_DESC = f.read()
@@ -73,6 +69,6 @@ setup(
extras_require={ extras_require={
'dev': DEV_DEPS, 'dev': DEV_DEPS,
'test': TEST_DEPS, 'test': TEST_DEPS,
'PDF': ['python-poppler-qt5'] 'PDF': ['pymupdf']
}, },
) )