Thread safety, Disable toolbar context menu
This commit is contained in:
16
__main__.py
16
__main__.py
@@ -28,7 +28,6 @@
|
|||||||
Information dialog widget
|
Information dialog widget
|
||||||
Context menu: Cache, Read, Edit database, delete, Mark read/unread
|
Context menu: Cache, Read, Edit database, delete, Mark read/unread
|
||||||
Set focus to newly added file
|
Set focus to newly added file
|
||||||
Better way to thread than subprocess QThread
|
|
||||||
Reading:
|
Reading:
|
||||||
✓ Drop down for TOC
|
✓ Drop down for TOC
|
||||||
✓ Override the keypress event of the textedit
|
✓ Override the keypress event of the textedit
|
||||||
@@ -42,7 +41,7 @@
|
|||||||
✓ Selectable background color for QGraphicsView
|
✓ Selectable background color for QGraphicsView
|
||||||
✓ View modes for QGraphicsView
|
✓ View modes for QGraphicsView
|
||||||
✓ View and hide toolbar actions in a list
|
✓ View and hide toolbar actions in a list
|
||||||
Comic view kayboard shortcuts
|
Comic view keyboard shortcuts
|
||||||
Record progress
|
Record progress
|
||||||
Pagination
|
Pagination
|
||||||
Set context menu for definitions and the like
|
Set context menu for definitions and the like
|
||||||
@@ -113,8 +112,10 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.statusBar.addPermanentWidget(self.statusMessage)
|
self.statusBar.addPermanentWidget(self.statusMessage)
|
||||||
self.sorterProgress = QtWidgets.QProgressBar()
|
self.sorterProgress = QtWidgets.QProgressBar()
|
||||||
self.sorterProgress.setObjectName('sorterProgress')
|
self.sorterProgress.setObjectName('sorterProgress')
|
||||||
|
sorter.progressbar = self.sorterProgress # This is so that updates can be
|
||||||
|
# connected to setValue
|
||||||
self.statusBar.addWidget(self.sorterProgress)
|
self.statusBar.addWidget(self.sorterProgress)
|
||||||
self.sorterProgress.hide()
|
self.sorterProgress.setVisible(False)
|
||||||
|
|
||||||
# Init the QListView
|
# Init the QListView
|
||||||
self.lib_ref = Library(self)
|
self.lib_ref = Library(self)
|
||||||
@@ -247,10 +248,16 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
|
|
||||||
if my_file[0]:
|
if my_file[0]:
|
||||||
self.last_open_path = os.path.dirname(my_file[0][0])
|
self.last_open_path = os.path.dirname(my_file[0][0])
|
||||||
|
self.sorterProgress.setVisible(True)
|
||||||
|
self.statusMessage.setText('Adding books...')
|
||||||
self.thread = BackGroundBookAddition(self, my_file[0], self.database_path)
|
self.thread = BackGroundBookAddition(self, my_file[0], self.database_path)
|
||||||
self.thread.finished.connect(self.lib_ref.create_proxymodel)
|
self.thread.finished.connect(self.move_on)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
|
def move_on(self):
|
||||||
|
self.sorterProgress.setVisible(False)
|
||||||
|
self.lib_ref.create_proxymodel()
|
||||||
|
|
||||||
def delete_books(self):
|
def delete_books(self):
|
||||||
selected_books = self.listView.selectedIndexes()
|
selected_books = self.listView.selectedIndexes()
|
||||||
if selected_books:
|
if selected_books:
|
||||||
@@ -394,7 +401,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
file_paths,
|
file_paths,
|
||||||
'reading',
|
'reading',
|
||||||
self.database_path,
|
self.database_path,
|
||||||
self,
|
|
||||||
self.temp_dir.path()).initiate_threads()
|
self.temp_dir.path()).initiate_threads()
|
||||||
|
|
||||||
found_a_focusable_tab = False
|
found_a_focusable_tab = False
|
||||||
|
@@ -119,7 +119,11 @@ class DatabaseFunctions:
|
|||||||
pickled_position = pickle.dumps(position)
|
pickled_position = pickle.dumps(position)
|
||||||
|
|
||||||
sql_command = "UPDATE books SET Position = ? WHERE Hash = ?"
|
sql_command = "UPDATE books SET Position = ? WHERE Hash = ?"
|
||||||
|
try:
|
||||||
self.database.execute(sql_command, [sqlite3.Binary(pickled_position), file_hash])
|
self.database.execute(sql_command, [sqlite3.Binary(pickled_position), file_hash])
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
print('SQLite is in rebellion, Commander')
|
||||||
|
return
|
||||||
|
|
||||||
self.database.commit()
|
self.database.commit()
|
||||||
self.close_database()
|
self.close_database()
|
||||||
|
38
sorter.py
38
sorter.py
@@ -7,6 +7,7 @@ import os
|
|||||||
import pickle
|
import pickle
|
||||||
import hashlib
|
import hashlib
|
||||||
from multiprocessing.dummy import Pool
|
from multiprocessing.dummy import Pool
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
import database
|
import database
|
||||||
|
|
||||||
@@ -24,9 +25,22 @@ from parsers.epub import ParseEPUB
|
|||||||
from parsers.cbz import ParseCBZ
|
from parsers.cbz import ParseCBZ
|
||||||
from parsers.cbr import ParseCBR
|
from parsers.cbr import ParseCBR
|
||||||
|
|
||||||
|
progressbar = None # This is populated by __main__
|
||||||
|
|
||||||
|
|
||||||
|
# This is for thread safety
|
||||||
|
class UpdateProgress(QtCore.QObject):
|
||||||
|
update_signal = QtCore.pyqtSignal(int)
|
||||||
|
|
||||||
|
def connect_to_progressbar(self):
|
||||||
|
self.update_signal.connect(progressbar.setValue)
|
||||||
|
|
||||||
|
def update_progress(self, progress_percent):
|
||||||
|
self.update_signal.emit(progress_percent)
|
||||||
|
|
||||||
|
|
||||||
class BookSorter:
|
class BookSorter:
|
||||||
def __init__(self, file_list, mode, database_path, parent_window, temp_dir=None):
|
def __init__(self, file_list, mode, database_path, temp_dir=None):
|
||||||
# Have the GUI pass a list of files straight to here
|
# Have the GUI pass a list of files straight to here
|
||||||
# Then, on the basis of what is needed, pass the
|
# Then, on the basis of what is needed, pass the
|
||||||
# filenames to the requisite functions
|
# filenames to the requisite functions
|
||||||
@@ -40,20 +54,12 @@ class BookSorter:
|
|||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.database_path = database_path
|
self.database_path = database_path
|
||||||
self.temp_dir = temp_dir
|
self.temp_dir = temp_dir
|
||||||
self.parent_window = parent_window
|
|
||||||
if database_path:
|
if database_path:
|
||||||
self.database_hashes()
|
self.database_hashes()
|
||||||
|
|
||||||
# Maybe check why this isn't working the usual way
|
if self.mode == 'addition':
|
||||||
for i in self.parent_window.statusBar.children():
|
self.progress_emitter = UpdateProgress()
|
||||||
if i.objectName() == 'sorterProgress':
|
self.progress_emitter.connect_to_progressbar()
|
||||||
self.progressbar = i
|
|
||||||
if i.objectName() == 'statusMessage':
|
|
||||||
self.statuslabel = i
|
|
||||||
|
|
||||||
self.progressbar.show()
|
|
||||||
self.statuslabel.setText('Adding books...')
|
|
||||||
self.progressbar.setMaximum(self.statistics[1])
|
|
||||||
|
|
||||||
def database_hashes(self):
|
def database_hashes(self):
|
||||||
all_hashes = database.DatabaseFunctions(
|
all_hashes = database.DatabaseFunctions(
|
||||||
@@ -89,12 +95,14 @@ class BookSorter:
|
|||||||
# This should speed up addition for larger files
|
# This should speed up addition for larger files
|
||||||
# without compromising the integrity of the process
|
# without compromising the integrity of the process
|
||||||
first_bytes = current_book.read(1024 * 32) # First 32KB of the file
|
first_bytes = current_book.read(1024 * 32) # First 32KB of the file
|
||||||
salt = filename.encode()
|
salt = 'Caesar si viveret, ad remum dareris'.encode()
|
||||||
first_bytes += salt
|
first_bytes += salt
|
||||||
file_md5 = hashlib.md5(first_bytes).hexdigest()
|
file_md5 = hashlib.md5(first_bytes).hexdigest()
|
||||||
|
|
||||||
|
if self.mode == 'addition':
|
||||||
self.statistics[0] += 1
|
self.statistics[0] += 1
|
||||||
self.progressbar.setValue(self.statistics[0])
|
self.progress_emitter.update_progress(
|
||||||
|
self.statistics[0] * 100 // self.statistics[1])
|
||||||
|
|
||||||
# IF the file is NOT being loaded into the reader,
|
# IF the file is NOT being loaded into the reader,
|
||||||
# Do not allow addition in case the file is dupicated in the directory
|
# Do not allow addition in case the file is dupicated in the directory
|
||||||
@@ -179,6 +187,4 @@ class BookSorter:
|
|||||||
_pool.close()
|
_pool.close()
|
||||||
_pool.join()
|
_pool.join()
|
||||||
|
|
||||||
self.progressbar.hide()
|
|
||||||
self.statuslabel.setText('Populating table...')
|
|
||||||
return self.all_books
|
return self.all_books
|
||||||
|
@@ -23,6 +23,7 @@ class BookToolBar(QtWidgets.QToolBar):
|
|||||||
self.setMovable(False)
|
self.setMovable(False)
|
||||||
self.setIconSize(QtCore.QSize(22, 22))
|
self.setIconSize(QtCore.QSize(22, 22))
|
||||||
self.setFloatable(False)
|
self.setFloatable(False)
|
||||||
|
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
||||||
self.setObjectName("LibraryToolBar")
|
self.setObjectName("LibraryToolBar")
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
@@ -257,6 +258,7 @@ class LibraryToolBar(QtWidgets.QToolBar):
|
|||||||
self.setMovable(False)
|
self.setMovable(False)
|
||||||
self.setIconSize(QtCore.QSize(22, 22))
|
self.setIconSize(QtCore.QSize(22, 22))
|
||||||
self.setFloatable(False)
|
self.setFloatable(False)
|
||||||
|
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
||||||
self.setObjectName("LibraryToolBar")
|
self.setObjectName("LibraryToolBar")
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
@@ -735,8 +737,7 @@ class BackGroundBookAddition(QtCore.QThread):
|
|||||||
books = sorter.BookSorter(
|
books = sorter.BookSorter(
|
||||||
self.file_list,
|
self.file_list,
|
||||||
'addition',
|
'addition',
|
||||||
self.database_path,
|
self.database_path)
|
||||||
self.parent_window)
|
|
||||||
parsed_books = books.initiate_threads()
|
parsed_books = books.initiate_threads()
|
||||||
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
|
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
|
||||||
self.parent_window.lib_ref.generate_model('addition', parsed_books)
|
self.parent_window.lib_ref.generate_model('addition', parsed_books)
|
||||||
|
Reference in New Issue
Block a user