#!/usr/bin/env python3 import os import database from PyQt5 import QtWidgets, QtGui, QtCore class Library: def __init__(self, parent): self.parent_window = parent self.proxy_model = None def generate_model(self): # TODO # Use QItemdelegates to show book read progress # The QlistView widget needs to be populated # with a model that inherits from QStandardItemModel self.parent_window.viewModel = QtGui.QStandardItemModel() books = database.DatabaseFunctions( self.parent_window.database_path).fetch_data( ('*',), 'books', {'Title': ''}, 'LIKE') if not books: print('Database returned nothing') return for i in books: # The database query returns a tuple with the following indices # Index 0 is the key ID is ignored book_title = i[1] book_author = i[2] book_year = i[3] book_cover = i[8] book_tags = i[6] book_path = i[4] book_progress = None # TODO # Leave at None for an untouched book # 'completed' for a completed book # whatever else is here can be used # to remember position all_metadata = { 'book_title': i[1], 'book_author': i[2], 'book_year': i[3], 'book_path': i[4], 'book_isbn': i[5], 'book_tags': i[6], 'book_hash': i[7]} tooltip_string = book_title + '\nAuthor: ' + book_author + '\nYear: ' + str(book_year) if book_tags: tooltip_string += ('\nTags: ' + book_tags) # This remarkably ugly hack is because the QSortFilterProxyModel # doesn't easily allow searching through multiple item roles search_workaround = book_title + ' ' + book_author if book_tags: search_workaround += book_tags # Generate book state for passing onto the QStyledItemDelegate def generate_book_state(book_path, book_progress): if not os.path.exists(book_path): return 'deleted' if book_progress: if book_progress == 'completed': return 'completed' else: return 'inprogress' else: return None book_state = generate_book_state(book_path, book_progress) # Generate image pixmap and then pass it to the widget # as a QIcon # Additional data can be set using an incrementing # QtCore.Qt.UserRole # QtCore.Qt.DisplayRole is the same as item.setText() # The model is a single row and has no columns img_pixmap = QtGui.QPixmap() img_pixmap.loadFromData(book_cover) img_pixmap = img_pixmap.scaled(420, 600, QtCore.Qt.IgnoreAspectRatio) item = QtGui.QStandardItem() item.setToolTip(tooltip_string) # The following order is needed to keep sorting working item.setData(book_title, QtCore.Qt.UserRole) item.setData(book_author, QtCore.Qt.UserRole + 1) item.setData(book_year, QtCore.Qt.UserRole + 2) item.setData(all_metadata, QtCore.Qt.UserRole + 3) item.setData(search_workaround, QtCore.Qt.UserRole + 4) item.setData(book_state, QtCore.Qt.UserRole + 5) item.setIcon(QtGui.QIcon(img_pixmap)) self.parent_window.viewModel.appendRow(item) def update_listView(self): self.proxy_model = QtCore.QSortFilterProxyModel() self.proxy_model.setSourceModel(self.parent_window.viewModel) self.proxy_model.setFilterRole(QtCore.Qt.UserRole + 4) self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) self.proxy_model.setFilterWildcard(self.parent_window.libraryToolBar.filterEdit.text()) self.parent_window.statusMessage.setText( str(self.proxy_model.rowCount()) + ' books') # Sorting according to roles and the drop down in the library self.proxy_model.setSortRole( QtCore.Qt.UserRole + self.parent_window.libraryToolBar.sortingBox.currentIndex()) self.proxy_model.sort(0) s = QtCore.QSize(160, 250) # Set icon sizing here self.parent_window.listView.setIconSize(s) self.parent_window.listView.setModel(self.proxy_model) class Settings: def __init__(self, parent): self.parent_window = parent self.settings = QtCore.QSettings('Lector', 'Lector') def read_settings(self): self.settings.beginGroup('mainWindow') self.parent_window.resize(self.settings.value( 'windowSize', QtCore.QSize(1299, 748))) self.parent_window.move(self.settings.value( 'windowPosition', QtCore.QPoint(286, 141))) self.settings.endGroup() self.settings.beginGroup('runtimeVariables') self.parent_window.last_open_path = self.settings.value( 'lastOpenPath', os.path.expanduser('~')) self.parent_window.database_path = self.settings.value( 'databasePath', QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.AppDataLocation)) self.settings.endGroup() def save_settings(self): self.settings.beginGroup('mainWindow') self.settings.setValue('windowSize', self.parent_window.size()) self.settings.setValue('windowPosition', self.parent_window.pos()) self.settings.endGroup() self.settings.beginGroup('runtimeVariables') self.settings.setValue('lastOpenPath', self.parent_window.last_open_path) self.settings.setValue('databasePath', self.parent_window.database_path) self.settings.endGroup()