Implement sorting by last read

This commit is contained in:
BasioMeusPuga
2018-02-21 01:05:15 +05:30
parent a65bd054be
commit 0b64fc3e8d
7 changed files with 67 additions and 29 deletions

1
TODO
View File

@@ -45,6 +45,7 @@ TODO
✓ Record progress ✓ Record progress
Search document using QTextCursor? Search document using QTextCursor?
Use embedded fonts Use embedded fonts
Cache multiple images
Graphical themes Graphical themes
Comic view keyboard shortcuts Comic view keyboard shortcuts
Comic view modes Comic view modes

View File

@@ -16,9 +16,6 @@
# 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/>.
# TODO
# Consider using sender().text() instead of sender().objectName()
import os import os
import sys import sys
import hashlib import hashlib
@@ -159,6 +156,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.addToolBar(self.bookToolBar) self.addToolBar(self.bookToolBar)
# Make the correct toolbar visible # Make the correct toolbar visible
self.current_tab = self.tabWidget.currentIndex()
self.tab_switch() self.tab_switch()
self.tabWidget.currentChanged.connect(self.tab_switch) self.tabWidget.currentChanged.connect(self.tab_switch)
@@ -481,6 +479,15 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.resizeEvent() self.resizeEvent()
def tab_switch(self): def tab_switch(self):
try:
if self.current_tab != 0:
self.tabWidget.widget(
self.current_tab).update_last_accessed_time()
except AttributeError:
pass
self.current_tab = self.tabWidget.currentIndex()
if self.tabWidget.currentIndex() == 0: if self.tabWidget.currentIndex() == 0:
self.resizeEvent() self.resizeEvent()
@@ -539,6 +546,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.database_path, [tab_metadata]) self.database_path, [tab_metadata])
self.thread.start() self.thread.start()
self.tabWidget.widget(tab_index).update_last_accessed_time()
self.tabWidget.removeTab(tab_index) self.tabWidget.removeTab(tab_index)
def set_toc_position(self, event=None): def set_toc_position(self, event=None):
@@ -892,7 +900,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
checked = [i for i in directory_list if i[3] == QtCore.Qt.Checked] checked = [i for i in directory_list if i[3] == QtCore.Qt.Checked]
filter_list = list(map(generate_name, checked)) filter_list = list(map(generate_name, checked))
filter_list.sort() filter_list.sort()
filter_list.append('Manually added') filter_list.append('Manually Added')
filter_actions = [QtWidgets.QAction(i, self.library_filter_menu) for i in filter_list] filter_actions = [QtWidgets.QAction(i, self.library_filter_menu) for i in filter_list]
filter_all = QtWidgets.QAction('All', self.library_filter_menu) filter_all = QtWidgets.QAction('All', self.library_filter_menu)

View File

@@ -38,8 +38,8 @@ class DatabaseInit:
# addition mode # addition mode
self.database.execute( self.database.execute(
"CREATE TABLE books \ "CREATE TABLE books \
(id INTEGER PRIMARY KEY, Title TEXT, Author TEXT, Year INTEGER, DateAdded TEXT, \ (id INTEGER PRIMARY KEY, Title TEXT, Author TEXT, Year INTEGER, DateAdded BLOB, \
Path TEXT, Position BLOB, ISBN TEXT, Tags TEXT, Hash TEXT, \ Path TEXT, Position BLOB, ISBN TEXT, Tags TEXT, Hash TEXT, LastAccessed BLOB,\
Bookmarks BLOB, CoverImage BLOB)") Bookmarks BLOB, CoverImage BLOB)")
# CheckState is the standard QtCore.Qt.Checked / Unchecked # CheckState is the standard QtCore.Qt.Checked / Unchecked
@@ -167,18 +167,22 @@ class DatabaseFunctions:
self.close_database() self.close_database()
def modify_position(self, hash_position_pairs): def modify_position(self, hash_position_last_accessed):
for i in hash_position_pairs: for i in hash_position_last_accessed:
file_hash = i[0] file_hash = i[0]
position = i[1] position = i[1]
last_accessed = i[2]
pickled_position = pickle.dumps(position) position_bin = sqlite3.Binary(pickle.dumps(position))
last_accessed_bin = sqlite3.Binary(pickle.dumps(last_accessed))
sql_command = (
"UPDATE books SET Position = ?, LastAccessed = ? WHERE Hash = ?")
sql_command = "UPDATE books SET Position = ? WHERE Hash = ?"
try: try:
self.database.execute( self.database.execute(
sql_command, sql_command,
[sqlite3.Binary(pickled_position), file_hash]) [position_bin, last_accessed_bin, file_hash])
except sqlite3.OperationalError: except sqlite3.OperationalError:
print('SQLite is in rebellion, Commander') print('SQLite is in rebellion, Commander')
return return

View File

@@ -42,7 +42,7 @@ class Library:
books = database.DatabaseFunctions( books = database.DatabaseFunctions(
self.parent.database_path).fetch_data( self.parent.database_path).fetch_data(
('Title', 'Author', 'Year', 'DateAdded', 'Path', ('Title', 'Author', 'Year', 'DateAdded', 'Path',
'Position', 'ISBN', 'Tags', 'Hash',), 'Position', 'ISBN', 'Tags', 'Hash', 'LastAccessed'),
'books', 'books',
{'Title': ''}, {'Title': ''},
'LIKE') 'LIKE')
@@ -65,7 +65,7 @@ class Library:
books.append([ books.append([
i[1]['title'], i[1]['author'], i[1]['year'], current_qdatetime, i[1]['title'], i[1]['author'], i[1]['year'], current_qdatetime,
i[1]['path'], None, i[1]['isbn'], _tags, i[0]]) i[1]['path'], None, i[1]['isbn'], _tags, i[0], None])
else: else:
return return
@@ -73,12 +73,12 @@ class Library:
for i in books: for i in books:
# The database query returns (or the extension data is) # The database query returns (or the extension data is)
# an iterable with the following indices: # an iterable with the following indices:
# Index 0 is the key ID is ignored
title = i[0] title = i[0]
author = i[1] author = i[1]
year = i[2] year = i[2]
path = i[4] path = i[4]
tags = i[7] tags = i[7]
last_accessed = i[9]
try: try:
date_added = pickle.loads(i[3]) date_added = pickle.loads(i[3])
@@ -101,6 +101,7 @@ class Library:
'isbn': i[6], 'isbn': i[6],
'tags': tags, 'tags': tags,
'hash': i[8], 'hash': i[8],
'last_accessed': last_accessed,
'file_exists': file_exists} 'file_exists': file_exists}
tooltip_string = title + '\nAuthor: ' + author + '\nYear: ' + str(year) tooltip_string = title + '\nAuthor: ' + author + '\nYear: ' + str(year)
@@ -129,6 +130,7 @@ class Library:
item.setData(position, QtCore.Qt.UserRole + 7) item.setData(position, QtCore.Qt.UserRole + 7)
item.setData(False, QtCore.Qt.UserRole + 8) # Is the cover being displayed? item.setData(False, QtCore.Qt.UserRole + 8) # Is the cover being displayed?
item.setData(date_added, QtCore.Qt.UserRole + 9) item.setData(date_added, QtCore.Qt.UserRole + 9)
item.setData(last_accessed, QtCore.Qt.UserRole + 12)
item.setIcon(QtGui.QIcon(img_pixmap)) item.setIcon(QtGui.QIcon(img_pixmap))
self.view_model.appendRow(item) self.view_model.appendRow(item)
@@ -182,7 +184,8 @@ class Library:
self.proxy_model.invalidateFilter() self.proxy_model.invalidateFilter()
self.proxy_model.setFilterParams( self.proxy_model.setFilterParams(
self.parent.libraryToolBar.searchBar.text(), self.parent.libraryToolBar.searchBar.text(),
self.parent.active_library_filters) self.parent.active_library_filters,
self.parent.libraryToolBar.sortingBox.currentIndex())
self.proxy_model.setFilterFixedString( self.proxy_model.setFilterFixedString(
self.parent.libraryToolBar.searchBar.text()) self.parent.libraryToolBar.searchBar.text())
@@ -200,7 +203,8 @@ class Library:
0: 0, 0: 0,
1: 1, 1: 1,
2: 2, 2: 2,
3: 9} 3: 9,
4: 12}
# Sorting according to roles and the drop down in the library toolbar # Sorting according to roles and the drop down in the library toolbar
self.proxy_model.setSortRole( self.proxy_model.setSortRole(
@@ -208,7 +212,7 @@ class Library:
# This can be expanded to other fields by appending to the list # This can be expanded to other fields by appending to the list
sort_order = QtCore.Qt.AscendingOrder sort_order = QtCore.Qt.AscendingOrder
if self.parent.libraryToolBar.sortingBox.currentIndex() in [3]: if self.parent.libraryToolBar.sortingBox.currentIndex() in [3, 4]:
sort_order = QtCore.Qt.DescendingOrder sort_order = QtCore.Qt.DescendingOrder
self.proxy_model.sort(0, sort_order) self.proxy_model.sort(0, sort_order)

View File

@@ -27,10 +27,12 @@ class ItemProxyModel(QtCore.QSortFilterProxyModel):
super(ItemProxyModel, self).__init__(parent) super(ItemProxyModel, self).__init__(parent)
self.filter_text = None self.filter_text = None
self.active_library_filters = None self.active_library_filters = None
self.sorting_position = None
def setFilterParams(self, filter_text, active_library_filters): def setFilterParams(self, filter_text, active_library_filters, sorting_position):
self.filter_text = filter_text self.filter_text = filter_text
self.active_library_filters = [i.lower() for i in active_library_filters] self.active_library_filters = [i.lower() for i in active_library_filters]
self.sorting_position = sorting_position
def filterAcceptsRow(self, row, parent): def filterAcceptsRow(self, row, parent):
model = self.sourceModel() model = self.sourceModel()
@@ -42,6 +44,10 @@ class ItemProxyModel(QtCore.QSortFilterProxyModel):
tags = model.data(this_index, QtCore.Qt.UserRole + 4) tags = model.data(this_index, QtCore.Qt.UserRole + 4)
directory_name = model.data(this_index, QtCore.Qt.UserRole + 10) directory_name = model.data(this_index, QtCore.Qt.UserRole + 10)
directory_tags = model.data(this_index, QtCore.Qt.UserRole + 11) directory_tags = model.data(this_index, QtCore.Qt.UserRole + 11)
last_accessed = model.data(this_index, QtCore.Qt.UserRole + 12)
if self.sorting_position == 4 and not last_accessed:
return False
if self.active_library_filters: if self.active_library_filters:
if directory_name not in self.active_library_filters: if directory_name not in self.active_library_filters:

View File

@@ -36,7 +36,9 @@ class BackGroundTabUpdate(QtCore.QThread):
for i in self.all_metadata: for i in self.all_metadata:
file_hash = i['hash'] file_hash = i['hash']
position = i['position'] position = i['position']
hash_position_pairs.append([file_hash, position]) last_accessed = i['last_accessed']
hash_position_pairs.append([file_hash, position, last_accessed])
database.DatabaseFunctions( database.DatabaseFunctions(
self.database_path).modify_position(hash_position_pairs) self.database_path).modify_position(hash_position_pairs)

View File

@@ -333,7 +333,7 @@ class LibraryToolBar(QtWidgets.QToolBar):
self.searchBar.setObjectName('searchBar') self.searchBar.setObjectName('searchBar')
# Sorter # Sorter
sorting_choices = ['Title', 'Author', 'Year', 'Newest'] sorting_choices = ['Title', 'Author', 'Year', 'Newest', 'Last read']
self.sortingBox = FixedComboBox(self) self.sortingBox = FixedComboBox(self)
self.sortingBox.addItems(sorting_choices) self.sortingBox.addItems(sorting_choices)
self.sortingBox.setObjectName('sortingBox') self.sortingBox.setObjectName('sortingBox')
@@ -374,10 +374,6 @@ class FixedPushButton(QtWidgets.QPushButton):
class Tab(QtWidgets.QWidget): class Tab(QtWidgets.QWidget):
def __init__(self, metadata, parent=None): def __init__(self, metadata, parent=None):
# TODO
# Take hint from a position function argument to open the book
# at a specific page
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
@@ -387,10 +383,10 @@ class Tab(QtWidgets.QWidget):
self.horzLayout.setOrientation(QtCore.Qt.Horizontal) self.horzLayout.setOrientation(QtCore.Qt.Horizontal)
self.masterLayout.addWidget(self.horzLayout) self.masterLayout.addWidget(self.horzLayout)
self.metadata['last_accessed'] = QtCore.QDateTime().currentDateTime()
position = self.metadata['position'] position = self.metadata['position']
# TODO
# Chapter position and vertical scrollbar position
if position: if position:
current_chapter = position['current_chapter'] current_chapter = position['current_chapter']
else: else:
@@ -461,6 +457,19 @@ class Tab(QtWidgets.QWidget):
self.contentView.setFocus() self.contentView.setFocus()
def update_last_accessed_time(self):
self.metadata['last_accessed'] = QtCore.QDateTime().currentDateTime()
start_index = self.window().lib_ref.view_model.index(0, 0)
matching_item = self.window().lib_ref.view_model.match(
start_index,
QtCore.Qt.UserRole + 6,
self.metadata['hash'],
1, QtCore.Qt.MatchExactly)
self.window().lib_ref.view_model.setData(
matching_item[0], self.metadata['last_accessed'], QtCore.Qt.UserRole + 12)
def set_scroll_value(self, switch_widgets=True): def set_scroll_value(self, switch_widgets=True):
if switch_widgets: if switch_widgets:
previous_widget = self.window().tabWidget.currentWidget() previous_widget = self.window().tabWidget.currentWidget()
@@ -489,7 +498,7 @@ class Tab(QtWidgets.QWidget):
def generate_position(self): def generate_position(self):
total_chapters = len(self.metadata['content'].keys()) total_chapters = len(self.metadata['content'].keys())
# TODO # TODO
# Calculate lines # Calculate lines to incorporate into progress
self.metadata['position'] = { self.metadata['position'] = {
'current_chapter': 1, 'current_chapter': 1,
'current_line': 0, 'current_line': 0,
@@ -754,9 +763,13 @@ class PliantWidgetsCommonFunctions():
self.main_window = main_window self.main_window = main_window
def wheelEvent(self, event, are_we_doing_images_only): def wheelEvent(self, event, are_we_doing_images_only):
ignore_events = 20
if are_we_doing_images_only:
ignore_events = 10
if self.pw.ignore_wheel_event: if self.pw.ignore_wheel_event:
self.pw.ignore_wheel_event_number += 1 self.pw.ignore_wheel_event_number += 1
if self.pw.ignore_wheel_event_number > 20: if self.pw.ignore_wheel_event_number > ignore_events:
self.pw.ignore_wheel_event = False self.pw.ignore_wheel_event = False
self.pw.ignore_wheel_event_number = 0 self.pw.ignore_wheel_event_number = 0
return return