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 |     ✓ Shift focus to the tab that has the book open | ||||||
|     ✓ Search bar in toolbar |     ✓ Search bar in toolbar | ||||||
|     ✓ Drop down for TOC (book view) |     ✓ Drop down for TOC (book view) | ||||||
|  |     ✓ Image reflow | ||||||
|  |  | ||||||
|     mobi support |     mobi support | ||||||
|     txt, doc support |     txt, doc support | ||||||
| @@ -37,6 +38,7 @@ import database | |||||||
| import book_parser | import book_parser | ||||||
|  |  | ||||||
| from widgets import LibraryToolBar, BookToolBar, Tab | from widgets import LibraryToolBar, BookToolBar, Tab | ||||||
|  | from main_subclasses import Settings, Library | ||||||
|  |  | ||||||
|  |  | ||||||
| class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | ||||||
| @@ -87,11 +89,10 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): | |||||||
|  |  | ||||||
|         # ListView |         # ListView | ||||||
|         # self.listView.setSpacing(0) |         # 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.verticalScrollBar().setSingleStep(7) | ||||||
|         self.listView.doubleClicked.connect(self.list_doubleclick) |         self.listView.doubleClicked.connect(self.list_doubleclick) | ||||||
|         self.reload_listview() |         self.reload_listview() | ||||||
|         self.resizeEvent() |  | ||||||
|  |  | ||||||
|         # Keyboard shortcuts |         # Keyboard shortcuts | ||||||
|         self.exit_all = QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+Q'), self) |         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 |         # Maybe expand this to traverse directories recursively | ||||||
|         self.statusMessage.setText('Adding books...') |         self.statusMessage.setText('Adding books...') | ||||||
|         my_file = QtWidgets.QFileDialog.getOpenFileNames( |         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]: |         if my_file[0]: | ||||||
|             self.listView.setEnabled(False) |             self.listView.setEnabled(False) | ||||||
|             self.last_open_path = os.path.dirname(my_file[0][0]) |             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() |         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(): | def main(): | ||||||
|     app = QtWidgets.QApplication(sys.argv) |     app = QtWidgets.QApplication(sys.argv) | ||||||
|     app.setApplicationName('Lector')  # This is needed for QStandardPaths |     app.setApplicationName('Lector')  # This is needed for QStandardPaths | ||||||
|                                       # and my own hubris |                                       # and my own hubris | ||||||
|     form = MainUI() |     form = MainUI() | ||||||
|     form.show() |     form.show() | ||||||
|  |     form.resizeEvent() | ||||||
|     app.exec_() |     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