diff --git a/__main__.py b/__main__.py index fda65f3..0a39bf4 100755 --- a/__main__.py +++ b/__main__.py @@ -55,7 +55,6 @@ import os import sys -import shutil from PyQt5 import QtWidgets, QtGui, QtCore @@ -63,7 +62,8 @@ import mainwindow import database import sorter -from widgets import LibraryToolBar, BookToolBar, Tab, LibraryDelegate, BackGroundTabUpdate +from widgets import LibraryToolBar, BookToolBar, Tab +from widgets import LibraryDelegate, BackGroundTabUpdate, BackGroundBookAddition from library import Library from settings import Settings @@ -80,6 +80,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): # Create the database in case it doesn't exist database.DatabaseInit(self.database_path) + # Background Thread + self.thread = None + # Create and right align the statusbar label widget self.statusMessage = QtWidgets.QLabel() self.statusMessage.setObjectName('statusMessage') @@ -96,8 +99,8 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): self.libraryToolBar = LibraryToolBar(self) self.libraryToolBar.addButton.triggered.connect(self.add_books) self.libraryToolBar.deleteButton.triggered.connect(self.delete_books) - self.libraryToolBar.searchBar.textChanged.connect(self.only_update_listview) - self.libraryToolBar.sortingBox.activated.connect(self.only_update_listview) + self.libraryToolBar.searchBar.textChanged.connect(self.lib_ref.update_proxymodel) + self.libraryToolBar.sortingBox.activated.connect(self.lib_ref.update_proxymodel) self.addToolBar(self.libraryToolBar) # Book toolbar @@ -125,9 +128,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): self.tab_switch() self.tabWidget.currentChanged.connect(self.tab_switch) - # Background Thread - self.thread = None - # For fullscreening purposes self.current_contentView = None @@ -188,22 +188,16 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): def add_books(self): # TODO # Maybe expand this to traverse directories recursively - self.statusMessage.setText('Adding books...') - - # TODO # Generate list of available parsers + my_file = QtWidgets.QFileDialog.getOpenFileNames( self, 'Open file', self.last_open_path, "eBooks (*.epub *.mobi *.aws *.txt *.pdf *.fb2 *.djvu *.cbz)") + if my_file[0]: - self.listView.setEnabled(False) - self.last_open_path = os.path.dirname(my_file[0][0]) - books = sorter.BookSorter(my_file[0], 'addition', self.database_path) - parsed_books = books.initiate_threads() - database.DatabaseFunctions(self.database_path).add_to_database(parsed_books) - self.listView.setEnabled(True) - self.viewModel = None - self.reload_listview() + self.thread = BackGroundBookAddition(self, my_file[0], self.database_path) + self.thread.finished.connect(self.lib_ref.create_proxymodel) + self.thread.start() def delete_books(self): selected_books = self.listView.selectedIndexes() @@ -233,14 +227,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): msg_box.show() msg_box.exec_() - def only_update_listview(self): - self.lib_ref.update_proxymodel() - def reload_listview(self): if not self.viewModel: - self.lib_ref.generate_model() - self.lib_ref.create_proxymodel() - self.lib_ref.update_proxymodel() + self.lib_ref.generate_model('build') def tab_switch(self): if self.tabWidget.currentIndex() == 0: diff --git a/library.py b/library.py index 3dcefe0..2e86312 100644 --- a/library.py +++ b/library.py @@ -13,25 +13,54 @@ class Library: self.parent_window = parent self.proxy_model = None - def generate_model(self): + def generate_model(self, mode, parsed_books=None): # The QlistView widget needs to be populated # with a model that inherits from QStandardItemModel # self.parent_window.viewModel = QtGui.QStandardItemModel() - self.parent_window.viewModel = MyAbsModel() - books = database.DatabaseFunctions( - self.parent_window.database_path).fetch_data( - ('*',), - 'books', - {'Title': ''}, - 'LIKE') + if mode == 'build': + self.parent_window.viewModel = MyAbsModel() - if not books: - print('Database returned nothing') + books = database.DatabaseFunctions( + self.parent_window.database_path).fetch_data( + ('*',), + 'books', + {'Title': ''}, + 'LIKE') + + if not books: + print('Database returned nothing') + return + + + elif mode == 'addition': + # Assumes parent_window.viewModel already exists and may be extended + # Because any additional books have already been added to the + # database using background threads + + books = [] + for i in parsed_books: + parsed_title = parsed_books[i]['title'] + parsed_author = parsed_books[i]['author'] + parsed_year = parsed_books[i]['year'] + parsed_path = parsed_books[i]['path'] + parsed_position = None + parsed_isbn = parsed_books[i]['isbn'] + parsed_tags = None + parsed_hash = i + parsed_cover = parsed_books[i]['cover_image'] + + books.append([ + None, parsed_title, parsed_author, parsed_year, parsed_path, + parsed_position, parsed_isbn, parsed_tags, parsed_hash, parsed_cover]) + + else: return + for i in books: - # The database query returns a tuple with the following indices + # The database query returns (or the extension data is) + # an iterable with the following indices: # Index 0 is the key ID is ignored title = i[1] author = i[2] @@ -54,6 +83,9 @@ class Library: 'tags': tags, 'hash': i[8]} + # import pprint + # pprint.pprint(all_metadata) + tooltip_string = title + '\nAuthor: ' + author + '\nYear: ' + str(year) if tags: tooltip_string += ('\nTags: ' + tags) @@ -89,12 +121,15 @@ class Library: item.setIcon(QtGui.QIcon(img_pixmap)) self.parent_window.viewModel.appendRow(item) + self.create_proxymodel() + def create_proxymodel(self): self.proxy_model = QtCore.QSortFilterProxyModel() self.proxy_model.setSourceModel(self.parent_window.viewModel) s = QtCore.QSize(160, 250) # Set icon sizing here self.parent_window.listView.setIconSize(s) self.parent_window.listView.setModel(self.proxy_model) + self.update_proxymodel() def update_proxymodel(self): self.proxy_model.setFilterRole(QtCore.Qt.UserRole + 4) diff --git a/sorter.py b/sorter.py index 3029001..552b904 100644 --- a/sorter.py +++ b/sorter.py @@ -33,6 +33,7 @@ class BookSorter: # Parsing for the reader proper # Caching upon closing self.file_list = file_list + self.statistics = [0, (len(file_list))] self.all_books = {} self.database_path = database_path self.hashes = [] @@ -73,6 +74,11 @@ class BookSorter: with open(filename, 'rb') as current_book: file_md5 = hashlib.md5(current_book.read()).hexdigest() + # TODO + # Make use of this + # self.statistics[0] += 1 + # print(self.statistics) + # IF the file is NOT being loaded into the reader, # Do not allow addition in case the file is dupicated in the directory # OR is already in the database @@ -109,7 +115,8 @@ class BookSorter: cover_image = book_ref.get_cover_image() # TODO if not cover_image: - pass + with open('resources/NotFound.png', 'rb') as stand_in: + cover_image = stand_in.read() self.all_books[file_md5] = { 'title': title, diff --git a/widgets.py b/widgets.py index a6a0d2a..adfb764 100644 --- a/widgets.py +++ b/widgets.py @@ -6,6 +6,7 @@ from PyQt5 import QtWidgets, QtGui, QtCore import pie_chart import database +import sorter class BookToolBar(QtWidgets.QToolBar): @@ -390,4 +391,18 @@ class BackGroundTabUpdate(QtCore.QThread): temp_dir = self.tab_metadata['temp_dir'] if temp_dir: - shutil.rmtree(temp_dir) \ No newline at end of file + shutil.rmtree(temp_dir) + + +class BackGroundBookAddition(QtCore.QThread): + def __init__(self, parent_window, file_list, database_path, parent=None): + super(BackGroundBookAddition, self).__init__(parent) + self.parent_window = parent_window + self.file_list = file_list + self.database_path = database_path + + def run(self): + books = sorter.BookSorter(self.file_list, 'addition', self.database_path) + parsed_books = books.initiate_threads() + database.DatabaseFunctions(self.database_path).add_to_database(parsed_books) + self.parent_window.lib_ref.generate_model('addition', parsed_books)