From fc2fcb5361bbbbb0b071f4b0589fd0e1a5540f33 Mon Sep 17 00:00:00 2001 From: BasioMeusPuga Date: Fri, 16 Mar 2018 14:46:47 +0530 Subject: [PATCH] Add "Last Read" column Start counting blocks for progress (Not implemented) --- ePub/read_epub.py | 8 ++++---- lector/__main__.py | 2 +- lector/models.py | 44 +++++++++++++++++++++++++++++++++++--------- lector/settings.py | 2 +- lector/widgets.py | 27 ++++++++++++++++++++++----- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/ePub/read_epub.py b/ePub/read_epub.py index 2786451..fed3875 100644 --- a/ePub/read_epub.py +++ b/ePub/read_epub.py @@ -264,12 +264,12 @@ class EPUB: for this_chapter in chapters: fallback_title = str(no_title_chapter) self.book['book_list'].append( - (fallback_title, this_chapter + ('
' * 8))) + (fallback_title, this_chapter + ('
' * 8))) no_title_chapter += 1 else: try: self.book['book_list'].append( - (self.book['navpoint_dict'][i], chapter_data + ('
' * 8))) + (self.book['navpoint_dict'][i], chapter_data + ('
' * 8))) except KeyError: fallback_title = str(no_title_chapter) self.book['book_list'].append( @@ -303,14 +303,14 @@ def get_split_content(chapter_data, split_by): # As will all empty chapters if bs_obj.text == '\n' or bs_obj.text == '' or count == 0: continue - bs_obj_string = str(bs_obj).replace('">', '', 1) + ('
' * 8) + bs_obj_string = str(bs_obj).replace('">', '', 1) + ('
' * 8) return_list.append( (chapter_titles[count - 1], bs_obj_string)) xml_string = this_split[1] bs_obj = BeautifulSoup(xml_string, 'lxml') - bs_obj_string = str(bs_obj).replace('">', '', 1) + ('
' * 8) + bs_obj_string = str(bs_obj).replace('">', '', 1) + ('
' * 8) return_list.append( (chapter_titles[-1], bs_obj_string)) diff --git a/lector/__main__.py b/lector/__main__.py index 023e477..8862d7c 100755 --- a/lector/__main__.py +++ b/lector/__main__.py @@ -246,7 +246,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): if self.settings['main_window_headers']: for count, i in enumerate(self.settings['main_window_headers']): self.tableView.horizontalHeader().resizeSection(count, int(i)) - self.tableView.horizontalHeader().resizeSection(4, 1) + self.tableView.horizontalHeader().resizeSection(5, 1) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.horizontalHeader().sectionClicked.connect( self.lib_ref.table_proxy_model.sort_table_columns) diff --git a/lector/models.py b/lector/models.py index 2554290..074ae68 100644 --- a/lector/models.py +++ b/lector/models.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import pickle import pathlib from PyQt5 import QtCore, QtWidgets @@ -68,7 +69,7 @@ class TableProxyModel(QtCore.QSortFilterProxyModel): def __init__(self, temp_dir, parent=None): super(TableProxyModel, self).__init__(parent) self.header_data = [ - None, 'Title', 'Author', 'Year', '%', 'Tags'] + None, 'Title', 'Author', 'Year', 'Last Read', '%', 'Tags'] self.temp_dir = temp_dir self.filter_text = None self.active_library_filters = None @@ -77,12 +78,13 @@ class TableProxyModel(QtCore.QSortFilterProxyModel): 1: QtCore.Qt.UserRole, # Title 2: QtCore.Qt.UserRole + 1, # Author 3: QtCore.Qt.UserRole + 2, # Year - 4: QtCore.Qt.UserRole + 7, # Position percentage - 5: QtCore.Qt.UserRole + 4} # Tags + 4: QtCore.Qt.UserRole + 12, # Last read + 5: QtCore.Qt.UserRole + 7, # Position percentage + 6: QtCore.Qt.UserRole + 4} # Tags self.common_functions = ProxyModelsCommonFunctions(self) def columnCount(self, parent): - return 6 + return 7 def headerData(self, column, orientation, role): if role == QtCore.Qt.DisplayRole: @@ -97,11 +99,12 @@ class TableProxyModel(QtCore.QSortFilterProxyModel): source_index = self.mapToSource(index) item = self.sourceModel().item(source_index.row(), 0) - if role == QtCore.Qt.TextAlignmentRole and index.column() == 3: - return QtCore.Qt.AlignHCenter + if role == QtCore.Qt.TextAlignmentRole: + if index.column() in (3, 4): + return QtCore.Qt.AlignHCenter if role == QtCore.Qt.DecorationRole: - if index.column() == 4: + if index.column() == 5: return_pixmap = None file_exists = item.data(QtCore.Qt.UserRole + 5) @@ -136,11 +139,20 @@ class TableProxyModel(QtCore.QSortFilterProxyModel): return return_pixmap elif role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: - if index.column() in (0, 4): # Cover and Status + if index.column() in (0, 5): # Cover and Status return QtCore.QVariant() - return item.data(self.role_dictionary[index.column()]) + if index.column() == 4: + last_accessed_time = item.data(self.role_dictionary[index.column()]) + if last_accessed_time: + last_accessed = last_accessed_time + if not isinstance(last_accessed_time, QtCore.QDateTime): + last_accessed = pickle.loads(last_accessed_time) + right_now = QtCore.QDateTime().currentDateTime() + time_diff = last_accessed.msecsTo(right_now) + return self.time_convert(time_diff // 1000) + return item.data(self.role_dictionary[index.column()]) else: return QtCore.QVariant() @@ -157,6 +169,20 @@ class TableProxyModel(QtCore.QSortFilterProxyModel): self.sort(0, sorting_order) self.setSortRole(self.role_dictionary[column]) + def time_convert(self, seconds): + seconds = int(seconds) + m, s = divmod(seconds, 60) + h, m = divmod(m, 60) + d, h = divmod(h, 24) + + if d > 0: + return f'{d}d' + if h > 0: + return f'{h}h' + if m > 0: + return f'{m}m' + else: + return '<1m' class ProxyModelsCommonFunctions: def __init__(self, parent_model): diff --git a/lector/settings.py b/lector/settings.py index c90efff..6d2baf2 100644 --- a/lector/settings.py +++ b/lector/settings.py @@ -119,7 +119,7 @@ class Settings: 'listViewBackground', self.parent.settings['listview_background']) table_headers = [] - for i in range(3): + for i in range(7): table_headers.append(self.parent.tableView.horizontalHeader().sectionSize(i)) self.settings.setValue('tableHeaders', table_headers) self.settings.endGroup() diff --git a/lector/widgets.py b/lector/widgets.py index 8ae43db..f9b4571 100644 --- a/lector/widgets.py +++ b/lector/widgets.py @@ -36,6 +36,7 @@ class Tab(QtWidgets.QWidget): super(Tab, self).__init__(parent) self.parent = parent self.metadata = metadata # Save progress data into this dictionary + self.are_we_doing_images_only = self.metadata['images_only'] self.masterLayout = QtWidgets.QHBoxLayout(self) self.horzLayout = QtWidgets.QSplitter(self) @@ -59,8 +60,6 @@ class Tab(QtWidgets.QWidget): # such as in the case of comic book files, # we want a QGraphicsView widget doing all the heavy lifting # instead of a QTextBrowser - self.are_we_doing_images_only = self.metadata['images_only'] - if self.are_we_doing_images_only: # Boolean self.contentView = PliantQGraphicsView(self.window(), self) self.contentView.loadImage(chapter_content) @@ -209,9 +208,6 @@ class Tab(QtWidgets.QWidget): self.window().tabWidget.setCurrentWidget(previous_widget) def generate_position(self, is_read=False): - # TODO - # Calculate lines to incorporate into progress - total_chapters = len(self.metadata['content']) current_chapter = 1 @@ -220,9 +216,30 @@ class Tab(QtWidgets.QWidget): current_chapter = total_chapters scroll_value = 1 + # TODO + # Use this to generate position + + # Generate block count @ time of first read + # Blocks are indexed from 0 up + blocks_per_chapter = [] + total_blocks = 0 + + if not self.are_we_doing_images_only: + for i in self.metadata['content']: + chapter_html = i[1] + + textDocument = QtGui.QTextDocument(None) + textDocument.setHtml(chapter_html) + block_count = textDocument.blockCount() + + blocks_per_chapter.append(block_count) + total_blocks += block_count + self.metadata['position'] = { 'current_chapter': current_chapter, 'total_chapters': total_chapters, + 'blocks_per_chapter': blocks_per_chapter, + 'total_blocks': total_blocks, 'scroll_value': scroll_value, 'last_visible_text': None, 'is_read': is_read}