Bookmark creation and navigation, Cleanup

This commit is contained in:
BasioMeusPuga
2018-02-25 22:05:37 +05:30
parent 0b64fc3e8d
commit 7874838550
7 changed files with 112 additions and 42 deletions

9
TODO
View File

@@ -43,17 +43,17 @@ TODO
✓ View and hide toolbar actions in a list
✓ Line spacing
✓ Record progress
Bookmarks
Set context menu for definitions and the like
Search document using QTextCursor?
Use embedded fonts
Cache multiple images
Graphical themes
Comic view keyboard shortcuts
Comic view modes
Continuous paging
Double pages
Bookmarks
Pagination
Set context menu for definitions and the like
Use embedded fonts
Scrolling: Smooth / By Line
Filetypes:
✓ cbz, cbr support
@@ -72,4 +72,5 @@ TODO
✓ Include icons for emblems
Shift to logging instead of print statements
Bugs:
If there are files open and the database is deleted, TypeErrors result
If there are files open and the database is deleted, TypeErrors result
Closing a fullscreened contentView does not save settings

View File

@@ -334,7 +334,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
item.setData(True, QtCore.Qt.UserRole + 8)
def test_function(self):
print('Caesar si viveret, ad remum dareris')
# print('Caesar si viveret, ad remum dareris')
if self.tabWidget.currentIndex() != 0:
self.tabWidget.widget(self.tabWidget.currentIndex()).add_bookmark()
def resizeEvent(self, event=None):
if event:
@@ -376,7 +378,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
# Remember file addition modality
# If a file is added from here, it should not be removed
# from the libary in case of a database refresh
# Individually added files are not subject to library filtering
opened_files = QtWidgets.QFileDialog.getOpenFileNames(
self, 'Open file', self.settings['last_open_path'],

View File

@@ -19,7 +19,6 @@
import os
import pickle
import sqlite3
from PyQt5 import QtCore
@@ -163,28 +162,30 @@ class DatabaseFunctions:
return None
except (KeyError, sqlite3.OperationalError):
print('SQLite is in rebellion, Commander')
print('Commander, SQLite is in rebellion @ data fetching handling')
self.close_database()
def modify_position(self, hash_position_last_accessed):
for i in hash_position_last_accessed:
def modify_positional_data(self, positional_data):
for i in positional_data:
file_hash = i[0]
position = i[1]
last_accessed = i[2]
bookmarks = i[3]
position_bin = sqlite3.Binary(pickle.dumps(position))
last_accessed_bin = sqlite3.Binary(pickle.dumps(last_accessed))
bookmarks_bin = sqlite3.Binary(pickle.dumps(bookmarks))
sql_command = (
"UPDATE books SET Position = ?, LastAccessed = ? WHERE Hash = ?")
"UPDATE books SET Position = ?, LastAccessed = ?, Bookmarks = ? WHERE Hash = ?")
try:
self.database.execute(
sql_command,
[position_bin, last_accessed_bin, file_hash])
[position_bin, last_accessed_bin, bookmarks_bin, file_hash])
except sqlite3.OperationalError:
print('SQLite is in rebellion, Commander')
print('Commander, SQLite is in rebellion @ positional data handling')
return
self.database.commit()

View File

@@ -27,12 +27,12 @@ class ItemProxyModel(QtCore.QSortFilterProxyModel):
super(ItemProxyModel, self).__init__(parent)
self.filter_text = None
self.active_library_filters = None
self.sorting_position = None
self.sorting_box_position = None
def setFilterParams(self, filter_text, active_library_filters, sorting_position):
def setFilterParams(self, filter_text, active_library_filters, sorting_box_position):
self.filter_text = filter_text
self.active_library_filters = [i.lower() for i in active_library_filters]
self.sorting_position = sorting_position
self.sorting_box_position = sorting_box_position
def filterAcceptsRow(self, row, parent):
model = self.sourceModel()
@@ -46,7 +46,8 @@ class ItemProxyModel(QtCore.QSortFilterProxyModel):
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:
# Hide untouched files when sorting by last accessed
if self.sorting_box_position == 4 and not last_accessed:
return False
if self.active_library_filters:

View File

@@ -110,13 +110,14 @@ class BookSorter:
def database_entry_for_book(self, file_hash):
database_return = database.DatabaseFunctions(
self.database_path).fetch_data(
('DateAdded', 'Position', 'Bookmarks'),
('Position', 'Bookmarks'),
'books',
{'Hash': file_hash},
'EQUALS')[0]
book_data = []
for i in database_return:
# All of these values are pickled and stored
if i:
book_data.append(pickle.loads(i))
else:
@@ -214,12 +215,9 @@ class BookSorter:
content['Invalid'] = 'Possible Parse Error'
book_data = self.database_entry_for_book(file_md5)
position = book_data[0]
bookmarks = book_data[1]
date_added = book_data[0]
position = book_data[1]
bookmarks = book_data[2]
this_book[file_md5]['date_added'] = date_added
this_book[file_md5]['position'] = position
this_book[file_md5]['bookmarks'] = bookmarks
this_book[file_md5]['content'] = content

View File

@@ -37,11 +37,13 @@ class BackGroundTabUpdate(QtCore.QThread):
file_hash = i['hash']
position = i['position']
last_accessed = i['last_accessed']
bookmarks = i['bookmarks']
hash_position_pairs.append([file_hash, position, last_accessed])
hash_position_pairs.append(
[file_hash, position, last_accessed, bookmarks])
database.DatabaseFunctions(
self.database_path).modify_position(hash_position_pairs)
self.database_path).modify_positional_data(hash_position_pairs)
class BackGroundBookAddition(QtCore.QThread):

View File

@@ -386,7 +386,6 @@ class Tab(QtWidgets.QWidget):
self.metadata['last_accessed'] = QtCore.QDateTime().currentDateTime()
position = self.metadata['position']
if position:
current_chapter = position['current_chapter']
else:
@@ -420,10 +419,10 @@ class Tab(QtWidgets.QWidget):
self.contentView.setHtml(chapter_content)
self.contentView.setReadOnly(True)
temp_hidden_button = QtWidgets.QToolButton(self)
temp_hidden_button.setVisible(False)
temp_hidden_button.clicked.connect(self.set_scroll_value)
temp_hidden_button.animateClick(100)
tempHiddenButton = QtWidgets.QToolButton(self)
tempHiddenButton.setVisible(False)
tempHiddenButton.clicked.connect(self.set_scroll_value)
tempHiddenButton.animateClick(100)
# The following are common to both the text browser and
# the graphics view
@@ -437,12 +436,18 @@ class Tab(QtWidgets.QWidget):
self.dockWidget = QtWidgets.QDockWidget(self)
self.dockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable)
self.dockWidget.setFloating(False)
self.dockListWidget = QtWidgets.QListWidget()
self.dockListWidget.setResizeMode(QtWidgets.QListWidget.Adjust)
self.dockListWidget.setMaximumWidth(350)
self.dockWidget.setWidget(self.dockListWidget)
self.dockWidget.hide()
self.dockListView = QtWidgets.QListView(self.dockWidget)
self.dockListView.setResizeMode(QtWidgets.QListWidget.Adjust)
self.dockListView.setMaximumWidth(350)
self.dockListView.clicked.connect(self.navigate_to_bookmark)
self.dockWidget.setWidget(self.dockListView)
self.bookmark_model = QtGui.QStandardItemModel()
self.generate_bookmark_model()
self.dockListView.setModel(self.bookmark_model)
self.generate_keyboard_shortcuts()
self.horzLayout.addWidget(self.contentView)
@@ -470,21 +475,25 @@ class Tab(QtWidgets.QWidget):
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, search_data=None):
if switch_widgets:
previous_widget = self.window().tabWidget.currentWidget()
self.window().tabWidget.setCurrentWidget(self)
scroll_position = (
self.metadata['position']['scroll_value'] *
self.contentView.verticalScrollBar().maximum())
scroll_value = self.metadata['position']['scroll_value']
if search_data:
scroll_value = search_data[0]
# Scroll a little ahead
# This avoids confusion with potentially duplicate phrases
# And the found result is at the top of the window
self.contentView.verticalScrollBar().setValue(scroll_position * 1.1)
scroll_position = scroll_value * self.contentView.verticalScrollBar().maximum() * 1.1
self.contentView.verticalScrollBar().setValue(scroll_position)
last_visible_text = self.metadata['position']['last_visible_text']
if search_data:
last_visible_text = search_data[1]
if last_visible_text:
self.contentView.find(last_visible_text)
@@ -501,7 +510,6 @@ class Tab(QtWidgets.QWidget):
# Calculate lines to incorporate into progress
self.metadata['position'] = {
'current_chapter': 1,
'current_line': 0,
'total_chapters': total_chapters,
'scroll_value': 0,
'last_visible_text': None}
@@ -579,6 +587,10 @@ class Tab(QtWidgets.QWidget):
block_format.setLineHeight(
line_spacing, QtGui.QTextBlockFormat.ProportionalHeight)
# TODO
# Give options for alignment
# block_format.setAlignment(QtCore.Qt.AlignJustify)
# Also for padding
# Using setViewPortMargins for this disables scrolling in the margins
block_format.setLeftMargin(padding)
@@ -605,6 +617,47 @@ class Tab(QtWidgets.QWidget):
else:
self.dockWidget.show()
def add_bookmark(self):
chapter, scroll_position, visible_text = self.contentView.record_scroll_position(True)
description = 'New bookmark'
search_data = (scroll_position, visible_text)
self.metadata['bookmarks'].append([
chapter, search_data, description])
self.add_bookmark_to_model(description, chapter, search_data)
def generate_bookmark_model(self):
bookmarks = self.metadata['bookmarks']
if not bookmarks:
self.metadata['bookmarks'] = []
return
# TODO
# Replace this with proxy model sorting
bookmarks.sort(key=lambda x: x[0])
for i in bookmarks:
self.add_bookmark_to_model(i[2], i[0], i[1])
def add_bookmark_to_model(self, description, chapter, search_data):
bookmark = QtGui.QStandardItem()
bookmark.setData(description, QtCore.Qt.DisplayRole)
bookmark.setData(chapter, QtCore.Qt.UserRole)
bookmark.setData(search_data, QtCore.Qt.UserRole + 1)
self.bookmark_model.appendRow(bookmark)
def navigate_to_bookmark(self, index):
if not index.isValid():
return
chapter = self.bookmark_model.data(index, QtCore.Qt.UserRole)
search_data = self.bookmark_model.data(index, QtCore.Qt.UserRole + 1)
self.window().bookToolBar.tocBox.setCurrentIndex(chapter - 1)
self.set_scroll_value(False, search_data)
def hide_mouse(self):
self.contentView.setCursor(QtCore.Qt.BlankCursor)
@@ -629,11 +682,18 @@ class PliantQGraphicsView(QtWidgets.QGraphicsView):
self.image_pixmap = None
self.ignore_wheel_event = False
self.ignore_wheel_event_number = 0
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self.common_functions = PliantWidgetsCommonFunctions(
self, self.main_window)
self.setMouseTracking(True)
def loadImage(self, image_path):
# TODO
# Cache 4 images
# For single page view: 1 before, 2 after
# For double page view: 1 before, 1 after
# Image panning with mouse
self.image_pixmap = QtGui.QPixmap()
self.image_pixmap.load(image_path)
self.resizeEvent()
@@ -731,7 +791,7 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
else:
QtWidgets.QTextEdit.keyPressEvent(self, event)
def record_scroll_position(self):
def record_scroll_position(self, return_as_bookmark=False):
vertical = self.verticalScrollBar().value()
maximum = self.verticalScrollBar().maximum()
@@ -747,7 +807,13 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
if len(visible_text) > 50:
visible_text = visible_text[:51]
self.parent.metadata['position']['last_visible_text'] = visible_text
if return_as_bookmark:
return (self.parent.metadata['position']['current_chapter'],
self.parent.metadata['position']['scroll_value'],
visible_text)
else:
self.parent.metadata['position']['last_visible_text'] = visible_text
# def mouseMoveEvent(self, event):
# TODO