Implement sorting by last read
This commit is contained in:
1
TODO
1
TODO
@@ -45,6 +45,7 @@ TODO
|
||||
✓ Record progress
|
||||
Search document using QTextCursor?
|
||||
Use embedded fonts
|
||||
Cache multiple images
|
||||
Graphical themes
|
||||
Comic view keyboard shortcuts
|
||||
Comic view modes
|
||||
|
18
__main__.py
18
__main__.py
@@ -16,9 +16,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# TODO
|
||||
# Consider using sender().text() instead of sender().objectName()
|
||||
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
@@ -159,6 +156,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||
self.addToolBar(self.bookToolBar)
|
||||
|
||||
# Make the correct toolbar visible
|
||||
self.current_tab = self.tabWidget.currentIndex()
|
||||
self.tab_switch()
|
||||
self.tabWidget.currentChanged.connect(self.tab_switch)
|
||||
|
||||
@@ -481,6 +479,15 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||
self.resizeEvent()
|
||||
|
||||
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:
|
||||
|
||||
self.resizeEvent()
|
||||
@@ -539,6 +546,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||
self.database_path, [tab_metadata])
|
||||
self.thread.start()
|
||||
|
||||
self.tabWidget.widget(tab_index).update_last_accessed_time()
|
||||
self.tabWidget.removeTab(tab_index)
|
||||
|
||||
def set_toc_position(self, event=None):
|
||||
@@ -681,7 +689,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||
|
||||
self.tabWidget.setCurrentIndex(self.tabWidget.count() - 1)
|
||||
finishing_touches()
|
||||
|
||||
|
||||
# TODO
|
||||
# def dropEvent
|
||||
|
||||
@@ -892,7 +900,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||
checked = [i for i in directory_list if i[3] == QtCore.Qt.Checked]
|
||||
filter_list = list(map(generate_name, checked))
|
||||
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_all = QtWidgets.QAction('All', self.library_filter_menu)
|
||||
|
18
database.py
18
database.py
@@ -38,8 +38,8 @@ class DatabaseInit:
|
||||
# addition mode
|
||||
self.database.execute(
|
||||
"CREATE TABLE books \
|
||||
(id INTEGER PRIMARY KEY, Title TEXT, Author TEXT, Year INTEGER, DateAdded TEXT, \
|
||||
Path TEXT, Position BLOB, ISBN TEXT, Tags TEXT, Hash TEXT, \
|
||||
(id INTEGER PRIMARY KEY, Title TEXT, Author TEXT, Year INTEGER, DateAdded BLOB, \
|
||||
Path TEXT, Position BLOB, ISBN TEXT, Tags TEXT, Hash TEXT, LastAccessed BLOB,\
|
||||
Bookmarks BLOB, CoverImage BLOB)")
|
||||
|
||||
# CheckState is the standard QtCore.Qt.Checked / Unchecked
|
||||
@@ -167,18 +167,22 @@ class DatabaseFunctions:
|
||||
|
||||
self.close_database()
|
||||
|
||||
def modify_position(self, hash_position_pairs):
|
||||
for i in hash_position_pairs:
|
||||
def modify_position(self, hash_position_last_accessed):
|
||||
for i in hash_position_last_accessed:
|
||||
file_hash = i[0]
|
||||
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:
|
||||
self.database.execute(
|
||||
sql_command,
|
||||
[sqlite3.Binary(pickled_position), file_hash])
|
||||
[position_bin, last_accessed_bin, file_hash])
|
||||
except sqlite3.OperationalError:
|
||||
print('SQLite is in rebellion, Commander')
|
||||
return
|
||||
|
16
library.py
16
library.py
@@ -42,7 +42,7 @@ class Library:
|
||||
books = database.DatabaseFunctions(
|
||||
self.parent.database_path).fetch_data(
|
||||
('Title', 'Author', 'Year', 'DateAdded', 'Path',
|
||||
'Position', 'ISBN', 'Tags', 'Hash',),
|
||||
'Position', 'ISBN', 'Tags', 'Hash', 'LastAccessed'),
|
||||
'books',
|
||||
{'Title': ''},
|
||||
'LIKE')
|
||||
@@ -65,7 +65,7 @@ class Library:
|
||||
|
||||
books.append([
|
||||
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:
|
||||
return
|
||||
@@ -73,12 +73,12 @@ class Library:
|
||||
for i in books:
|
||||
# The database query returns (or the extension data is)
|
||||
# an iterable with the following indices:
|
||||
# Index 0 is the key ID is ignored
|
||||
title = i[0]
|
||||
author = i[1]
|
||||
year = i[2]
|
||||
path = i[4]
|
||||
tags = i[7]
|
||||
last_accessed = i[9]
|
||||
|
||||
try:
|
||||
date_added = pickle.loads(i[3])
|
||||
@@ -101,6 +101,7 @@ class Library:
|
||||
'isbn': i[6],
|
||||
'tags': tags,
|
||||
'hash': i[8],
|
||||
'last_accessed': last_accessed,
|
||||
'file_exists': file_exists}
|
||||
|
||||
tooltip_string = title + '\nAuthor: ' + author + '\nYear: ' + str(year)
|
||||
@@ -129,6 +130,7 @@ class Library:
|
||||
item.setData(position, QtCore.Qt.UserRole + 7)
|
||||
item.setData(False, QtCore.Qt.UserRole + 8) # Is the cover being displayed?
|
||||
item.setData(date_added, QtCore.Qt.UserRole + 9)
|
||||
item.setData(last_accessed, QtCore.Qt.UserRole + 12)
|
||||
item.setIcon(QtGui.QIcon(img_pixmap))
|
||||
self.view_model.appendRow(item)
|
||||
|
||||
@@ -182,7 +184,8 @@ class Library:
|
||||
self.proxy_model.invalidateFilter()
|
||||
self.proxy_model.setFilterParams(
|
||||
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.parent.libraryToolBar.searchBar.text())
|
||||
|
||||
@@ -200,7 +203,8 @@ class Library:
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 9}
|
||||
3: 9,
|
||||
4: 12}
|
||||
|
||||
# Sorting according to roles and the drop down in the library toolbar
|
||||
self.proxy_model.setSortRole(
|
||||
@@ -208,7 +212,7 @@ class Library:
|
||||
|
||||
# This can be expanded to other fields by appending to the list
|
||||
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
|
||||
|
||||
self.proxy_model.sort(0, sort_order)
|
||||
|
@@ -27,10 +27,12 @@ class ItemProxyModel(QtCore.QSortFilterProxyModel):
|
||||
super(ItemProxyModel, self).__init__(parent)
|
||||
self.filter_text = 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.active_library_filters = [i.lower() for i in active_library_filters]
|
||||
self.sorting_position = sorting_position
|
||||
|
||||
def filterAcceptsRow(self, row, parent):
|
||||
model = self.sourceModel()
|
||||
@@ -42,6 +44,10 @@ class ItemProxyModel(QtCore.QSortFilterProxyModel):
|
||||
tags = model.data(this_index, QtCore.Qt.UserRole + 4)
|
||||
directory_name = model.data(this_index, QtCore.Qt.UserRole + 10)
|
||||
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 directory_name not in self.active_library_filters:
|
||||
|
@@ -36,7 +36,9 @@ class BackGroundTabUpdate(QtCore.QThread):
|
||||
for i in self.all_metadata:
|
||||
file_hash = i['hash']
|
||||
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(
|
||||
self.database_path).modify_position(hash_position_pairs)
|
||||
|
31
widgets.py
31
widgets.py
@@ -333,7 +333,7 @@ class LibraryToolBar(QtWidgets.QToolBar):
|
||||
self.searchBar.setObjectName('searchBar')
|
||||
|
||||
# Sorter
|
||||
sorting_choices = ['Title', 'Author', 'Year', 'Newest']
|
||||
sorting_choices = ['Title', 'Author', 'Year', 'Newest', 'Last read']
|
||||
self.sortingBox = FixedComboBox(self)
|
||||
self.sortingBox.addItems(sorting_choices)
|
||||
self.sortingBox.setObjectName('sortingBox')
|
||||
@@ -374,10 +374,6 @@ class FixedPushButton(QtWidgets.QPushButton):
|
||||
|
||||
class Tab(QtWidgets.QWidget):
|
||||
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)
|
||||
self.parent = parent
|
||||
self.metadata = metadata # Save progress data into this dictionary
|
||||
@@ -387,10 +383,10 @@ class Tab(QtWidgets.QWidget):
|
||||
self.horzLayout.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.masterLayout.addWidget(self.horzLayout)
|
||||
|
||||
self.metadata['last_accessed'] = QtCore.QDateTime().currentDateTime()
|
||||
|
||||
position = self.metadata['position']
|
||||
|
||||
# TODO
|
||||
# Chapter position and vertical scrollbar position
|
||||
if position:
|
||||
current_chapter = position['current_chapter']
|
||||
else:
|
||||
@@ -461,6 +457,19 @@ class Tab(QtWidgets.QWidget):
|
||||
|
||||
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):
|
||||
if switch_widgets:
|
||||
previous_widget = self.window().tabWidget.currentWidget()
|
||||
@@ -489,7 +498,7 @@ class Tab(QtWidgets.QWidget):
|
||||
def generate_position(self):
|
||||
total_chapters = len(self.metadata['content'].keys())
|
||||
# TODO
|
||||
# Calculate lines
|
||||
# Calculate lines to incorporate into progress
|
||||
self.metadata['position'] = {
|
||||
'current_chapter': 1,
|
||||
'current_line': 0,
|
||||
@@ -754,9 +763,13 @@ class PliantWidgetsCommonFunctions():
|
||||
self.main_window = main_window
|
||||
|
||||
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:
|
||||
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_number = 0
|
||||
return
|
||||
|
Reference in New Issue
Block a user