Add "Last Read" column
Start counting blocks for progress (Not implemented)
This commit is contained in:
@@ -264,12 +264,12 @@ class EPUB:
|
|||||||
for this_chapter in chapters:
|
for this_chapter in chapters:
|
||||||
fallback_title = str(no_title_chapter)
|
fallback_title = str(no_title_chapter)
|
||||||
self.book['book_list'].append(
|
self.book['book_list'].append(
|
||||||
(fallback_title, this_chapter + ('<br>' * 8)))
|
(fallback_title, this_chapter + ('<br/>' * 8)))
|
||||||
no_title_chapter += 1
|
no_title_chapter += 1
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.book['book_list'].append(
|
self.book['book_list'].append(
|
||||||
(self.book['navpoint_dict'][i], chapter_data + ('<br>' * 8)))
|
(self.book['navpoint_dict'][i], chapter_data + ('<br/>' * 8)))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
fallback_title = str(no_title_chapter)
|
fallback_title = str(no_title_chapter)
|
||||||
self.book['book_list'].append(
|
self.book['book_list'].append(
|
||||||
@@ -303,14 +303,14 @@ def get_split_content(chapter_data, split_by):
|
|||||||
# As will all empty chapters
|
# As will all empty chapters
|
||||||
if bs_obj.text == '\n' or bs_obj.text == '' or count == 0:
|
if bs_obj.text == '\n' or bs_obj.text == '' or count == 0:
|
||||||
continue
|
continue
|
||||||
bs_obj_string = str(bs_obj).replace('">', '', 1) + ('<br>' * 8)
|
bs_obj_string = str(bs_obj).replace('">', '', 1) + ('<br/>' * 8)
|
||||||
|
|
||||||
return_list.append(
|
return_list.append(
|
||||||
(chapter_titles[count - 1], bs_obj_string))
|
(chapter_titles[count - 1], bs_obj_string))
|
||||||
xml_string = this_split[1]
|
xml_string = this_split[1]
|
||||||
|
|
||||||
bs_obj = BeautifulSoup(xml_string, 'lxml')
|
bs_obj = BeautifulSoup(xml_string, 'lxml')
|
||||||
bs_obj_string = str(bs_obj).replace('">', '', 1) + ('<br>' * 8)
|
bs_obj_string = str(bs_obj).replace('">', '', 1) + ('<br/>' * 8)
|
||||||
return_list.append(
|
return_list.append(
|
||||||
(chapter_titles[-1], bs_obj_string))
|
(chapter_titles[-1], bs_obj_string))
|
||||||
|
|
||||||
|
@@ -246,7 +246,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
if self.settings['main_window_headers']:
|
if self.settings['main_window_headers']:
|
||||||
for count, i in enumerate(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(count, int(i))
|
||||||
self.tableView.horizontalHeader().resizeSection(4, 1)
|
self.tableView.horizontalHeader().resizeSection(5, 1)
|
||||||
self.tableView.horizontalHeader().setStretchLastSection(True)
|
self.tableView.horizontalHeader().setStretchLastSection(True)
|
||||||
self.tableView.horizontalHeader().sectionClicked.connect(
|
self.tableView.horizontalHeader().sectionClicked.connect(
|
||||||
self.lib_ref.table_proxy_model.sort_table_columns)
|
self.lib_ref.table_proxy_model.sort_table_columns)
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import pickle
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtWidgets
|
from PyQt5 import QtCore, QtWidgets
|
||||||
@@ -68,7 +69,7 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
|
|||||||
def __init__(self, temp_dir, parent=None):
|
def __init__(self, temp_dir, parent=None):
|
||||||
super(TableProxyModel, self).__init__(parent)
|
super(TableProxyModel, self).__init__(parent)
|
||||||
self.header_data = [
|
self.header_data = [
|
||||||
None, 'Title', 'Author', 'Year', '%', 'Tags']
|
None, 'Title', 'Author', 'Year', 'Last Read', '%', 'Tags']
|
||||||
self.temp_dir = temp_dir
|
self.temp_dir = temp_dir
|
||||||
self.filter_text = None
|
self.filter_text = None
|
||||||
self.active_library_filters = None
|
self.active_library_filters = None
|
||||||
@@ -77,12 +78,13 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
|
|||||||
1: QtCore.Qt.UserRole, # Title
|
1: QtCore.Qt.UserRole, # Title
|
||||||
2: QtCore.Qt.UserRole + 1, # Author
|
2: QtCore.Qt.UserRole + 1, # Author
|
||||||
3: QtCore.Qt.UserRole + 2, # Year
|
3: QtCore.Qt.UserRole + 2, # Year
|
||||||
4: QtCore.Qt.UserRole + 7, # Position percentage
|
4: QtCore.Qt.UserRole + 12, # Last read
|
||||||
5: QtCore.Qt.UserRole + 4} # Tags
|
5: QtCore.Qt.UserRole + 7, # Position percentage
|
||||||
|
6: QtCore.Qt.UserRole + 4} # Tags
|
||||||
self.common_functions = ProxyModelsCommonFunctions(self)
|
self.common_functions = ProxyModelsCommonFunctions(self)
|
||||||
|
|
||||||
def columnCount(self, parent):
|
def columnCount(self, parent):
|
||||||
return 6
|
return 7
|
||||||
|
|
||||||
def headerData(self, column, orientation, role):
|
def headerData(self, column, orientation, role):
|
||||||
if role == QtCore.Qt.DisplayRole:
|
if role == QtCore.Qt.DisplayRole:
|
||||||
@@ -97,11 +99,12 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
|
|||||||
source_index = self.mapToSource(index)
|
source_index = self.mapToSource(index)
|
||||||
item = self.sourceModel().item(source_index.row(), 0)
|
item = self.sourceModel().item(source_index.row(), 0)
|
||||||
|
|
||||||
if role == QtCore.Qt.TextAlignmentRole and index.column() == 3:
|
if role == QtCore.Qt.TextAlignmentRole:
|
||||||
|
if index.column() in (3, 4):
|
||||||
return QtCore.Qt.AlignHCenter
|
return QtCore.Qt.AlignHCenter
|
||||||
|
|
||||||
if role == QtCore.Qt.DecorationRole:
|
if role == QtCore.Qt.DecorationRole:
|
||||||
if index.column() == 4:
|
if index.column() == 5:
|
||||||
return_pixmap = None
|
return_pixmap = None
|
||||||
|
|
||||||
file_exists = item.data(QtCore.Qt.UserRole + 5)
|
file_exists = item.data(QtCore.Qt.UserRole + 5)
|
||||||
@@ -136,11 +139,20 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
|
|||||||
return return_pixmap
|
return return_pixmap
|
||||||
|
|
||||||
elif role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
|
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 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:
|
else:
|
||||||
return QtCore.QVariant()
|
return QtCore.QVariant()
|
||||||
|
|
||||||
@@ -157,6 +169,20 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
|
|||||||
self.sort(0, sorting_order)
|
self.sort(0, sorting_order)
|
||||||
self.setSortRole(self.role_dictionary[column])
|
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:
|
class ProxyModelsCommonFunctions:
|
||||||
def __init__(self, parent_model):
|
def __init__(self, parent_model):
|
||||||
|
@@ -119,7 +119,7 @@ class Settings:
|
|||||||
'listViewBackground', self.parent.settings['listview_background'])
|
'listViewBackground', self.parent.settings['listview_background'])
|
||||||
|
|
||||||
table_headers = []
|
table_headers = []
|
||||||
for i in range(3):
|
for i in range(7):
|
||||||
table_headers.append(self.parent.tableView.horizontalHeader().sectionSize(i))
|
table_headers.append(self.parent.tableView.horizontalHeader().sectionSize(i))
|
||||||
self.settings.setValue('tableHeaders', table_headers)
|
self.settings.setValue('tableHeaders', table_headers)
|
||||||
self.settings.endGroup()
|
self.settings.endGroup()
|
||||||
|
@@ -36,6 +36,7 @@ class Tab(QtWidgets.QWidget):
|
|||||||
super(Tab, self).__init__(parent)
|
super(Tab, self).__init__(parent)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.metadata = metadata # Save progress data into this dictionary
|
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.masterLayout = QtWidgets.QHBoxLayout(self)
|
||||||
self.horzLayout = QtWidgets.QSplitter(self)
|
self.horzLayout = QtWidgets.QSplitter(self)
|
||||||
@@ -59,8 +60,6 @@ class Tab(QtWidgets.QWidget):
|
|||||||
# such as in the case of comic book files,
|
# such as in the case of comic book files,
|
||||||
# we want a QGraphicsView widget doing all the heavy lifting
|
# we want a QGraphicsView widget doing all the heavy lifting
|
||||||
# instead of a QTextBrowser
|
# instead of a QTextBrowser
|
||||||
self.are_we_doing_images_only = self.metadata['images_only']
|
|
||||||
|
|
||||||
if self.are_we_doing_images_only: # Boolean
|
if self.are_we_doing_images_only: # Boolean
|
||||||
self.contentView = PliantQGraphicsView(self.window(), self)
|
self.contentView = PliantQGraphicsView(self.window(), self)
|
||||||
self.contentView.loadImage(chapter_content)
|
self.contentView.loadImage(chapter_content)
|
||||||
@@ -209,9 +208,6 @@ class Tab(QtWidgets.QWidget):
|
|||||||
self.window().tabWidget.setCurrentWidget(previous_widget)
|
self.window().tabWidget.setCurrentWidget(previous_widget)
|
||||||
|
|
||||||
def generate_position(self, is_read=False):
|
def generate_position(self, is_read=False):
|
||||||
# TODO
|
|
||||||
# Calculate lines to incorporate into progress
|
|
||||||
|
|
||||||
total_chapters = len(self.metadata['content'])
|
total_chapters = len(self.metadata['content'])
|
||||||
|
|
||||||
current_chapter = 1
|
current_chapter = 1
|
||||||
@@ -220,9 +216,30 @@ class Tab(QtWidgets.QWidget):
|
|||||||
current_chapter = total_chapters
|
current_chapter = total_chapters
|
||||||
scroll_value = 1
|
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'] = {
|
self.metadata['position'] = {
|
||||||
'current_chapter': current_chapter,
|
'current_chapter': current_chapter,
|
||||||
'total_chapters': total_chapters,
|
'total_chapters': total_chapters,
|
||||||
|
'blocks_per_chapter': blocks_per_chapter,
|
||||||
|
'total_blocks': total_blocks,
|
||||||
'scroll_value': scroll_value,
|
'scroll_value': scroll_value,
|
||||||
'last_visible_text': None,
|
'last_visible_text': None,
|
||||||
'is_read': is_read}
|
'is_read': is_read}
|
||||||
|
Reference in New Issue
Block a user