Separate module for subclasses
This commit is contained in:
		
							
								
								
									
										135
									
								
								__main__.py
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								__main__.py
									
									
									
									
									
								
							| @@ -10,6 +10,7 @@ | ||||
|     ✓ Shift focus to the tab that has the book open | ||||
|     ✓ Search bar in toolbar | ||||
|     ✓ Drop down for TOC (book view) | ||||
|     ✓ Image reflow | ||||
|  | ||||
|     mobi support | ||||
|     txt, doc support | ||||
| @@ -37,6 +38,7 @@ import database | ||||
| import book_parser | ||||
|  | ||||
| from widgets import LibraryToolBar, BookToolBar, Tab | ||||
| from main_subclasses import Settings, Library | ||||
|  | ||||
|  | ||||
| class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | ||||
| @@ -87,11 +89,10 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | ||||
|  | ||||
|         # ListView | ||||
|         # self.listView.setSpacing(0) | ||||
|         self.listView.setGridSize(QtCore.QSize(175, 250)) | ||||
|         self.listView.setGridSize(QtCore.QSize(175, 240)) | ||||
|         self.listView.verticalScrollBar().setSingleStep(7) | ||||
|         self.listView.doubleClicked.connect(self.list_doubleclick) | ||||
|         self.reload_listview() | ||||
|         self.resizeEvent() | ||||
|  | ||||
|         # Keyboard shortcuts | ||||
|         self.exit_all = QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+Q'), self) | ||||
| @@ -127,7 +128,8 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | ||||
|         # Maybe expand this to traverse directories recursively | ||||
|         self.statusMessage.setText('Adding books...') | ||||
|         my_file = QtWidgets.QFileDialog.getOpenFileNames( | ||||
|             self, 'Open file', self.last_open_path, "eBooks (*.epub *.mobi *.txt)") | ||||
|             self, 'Open file', self.last_open_path, | ||||
|             "eBooks (*.epub *.mobi *.aws *.txt *.pdf *.fb2 *.djvu)") | ||||
|         if my_file[0]: | ||||
|             self.listView.setEnabled(False) | ||||
|             self.last_open_path = os.path.dirname(my_file[0][0]) | ||||
| @@ -232,138 +234,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | ||||
|         QtWidgets.qApp.exit() | ||||
|  | ||||
|  | ||||
| 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] | ||||
|             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 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.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() | ||||
|  | ||||
|  | ||||
| def main(): | ||||
|     app = QtWidgets.QApplication(sys.argv) | ||||
|     app.setApplicationName('Lector')  # This is needed for QStandardPaths | ||||
|                                       # and my own hubris | ||||
|     form = MainUI() | ||||
|     form.show() | ||||
|     form.resizeEvent() | ||||
|     app.exec_() | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										131
									
								
								main_subclasses.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								main_subclasses.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| #!/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] | ||||
|             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 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.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() | ||||
		Reference in New Issue
	
	Block a user