Refactor sideDock
This commit is contained in:
@@ -462,7 +462,8 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||
|
||||
def add_bookmark(self):
|
||||
if self.tabWidget.currentIndex() != 0:
|
||||
self.tabWidget.widget(self.tabWidget.currentIndex()).add_bookmark()
|
||||
current_tab = self.tabWidget.currentWidget()
|
||||
current_tab.sideDock.bookmarks.add_bookmark()
|
||||
|
||||
def resizeEvent(self, event=None):
|
||||
if event:
|
||||
|
@@ -482,15 +482,15 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
||||
self.parent.sideDock.setWindowOpacity(.95)
|
||||
|
||||
self.current_annotation = None
|
||||
self.parent.annotationListView.clearSelection()
|
||||
self.parent.sideDock.annotations.annotationListView.clearSelection()
|
||||
|
||||
else:
|
||||
self.annotation_mode = True
|
||||
self.viewport().setCursor(QtCore.Qt.IBeamCursor)
|
||||
self.parent.sideDock.hide()
|
||||
|
||||
selected_index = self.parent.annotationListView.currentIndex()
|
||||
self.current_annotation = self.parent.annotationModel.data(
|
||||
selected_index = self.parent.sideDock.annotations.annotationListView.currentIndex()
|
||||
self.current_annotation = self.parent.sideDock.annotationModel.data(
|
||||
selected_index, QtCore.Qt.UserRole)
|
||||
logger.info('Selected annotation: ' + self.current_annotation['name'])
|
||||
|
||||
@@ -619,14 +619,14 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
||||
action = contextMenu.exec_(self.sender().mapToGlobal(position))
|
||||
|
||||
if action == addBookMarkAction:
|
||||
self.parent.add_bookmark(cursor_at_mouse.position())
|
||||
self.parent.sideDock.bookmarks.add_bookmark(cursor_at_mouse.position())
|
||||
|
||||
if action == defineAction:
|
||||
self.main_window.definitionDialog.find_definition(selection)
|
||||
|
||||
if action == searchAction:
|
||||
if selection and selection != '':
|
||||
self.parent.searchLineEdit.setText(selection)
|
||||
self.parent.sideDock.search.searchLineEdit.setText(selection)
|
||||
self.parent.toggle_side_dock(2, True)
|
||||
|
||||
if action == searchGoogleAction:
|
||||
|
@@ -14,9 +14,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import uuid
|
||||
|
||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||
|
||||
from lector.models import BookmarkProxyModel
|
||||
from lector.threaded import BackGroundTextSearch
|
||||
|
||||
|
||||
class PliantDockWidget(QtWidgets.QDockWidget):
|
||||
@@ -26,6 +29,27 @@ class PliantDockWidget(QtWidgets.QDockWidget):
|
||||
self.notes_only = notes_only
|
||||
self.contentView = contentView
|
||||
self.current_annotation = None
|
||||
self.parent = parent
|
||||
|
||||
# Models
|
||||
# The following models belong to the sideDock
|
||||
# bookmarkModel, bookmarkProxyModel
|
||||
# annotationModel
|
||||
# searchResultsModel
|
||||
self.bookmarkModel = None
|
||||
self.bookmarkProxyModel = None
|
||||
self.annotationModel = None
|
||||
self.searchResultsModel = None
|
||||
|
||||
# References
|
||||
# All widgets belong to these
|
||||
self.bookmarks = None
|
||||
self.annotations = None
|
||||
self.search = None
|
||||
|
||||
# Widgets
|
||||
# Except this one
|
||||
self.sideDockTabWidget = None
|
||||
|
||||
def showEvent(self, event=None):
|
||||
viewport_topRight = self.contentView.mapToGlobal(
|
||||
@@ -60,96 +84,434 @@ class PliantDockWidget(QtWidgets.QDockWidget):
|
||||
def set_annotation(self, annotation):
|
||||
self.current_annotation = annotation
|
||||
|
||||
def populate(self):
|
||||
self.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable)
|
||||
self.setTitleBarWidget(QtWidgets.QWidget(self)) # Removes titlebar
|
||||
self.sideDockTabWidget = QtWidgets.QTabWidget(self)
|
||||
self.setWidget(self.sideDockTabWidget)
|
||||
|
||||
# This order is important
|
||||
self.bookmarkModel = QtGui.QStandardItemModel(self)
|
||||
self.bookmarkProxyModel = BookmarkProxyModel(self)
|
||||
self.bookmarks = Bookmarks(self)
|
||||
self.bookmarks.generate_bookmark_model()
|
||||
|
||||
if not self.parent.are_we_doing_images_only:
|
||||
self.annotationModel = QtGui.QStandardItemModel(self)
|
||||
self.annotations = Annotations(self)
|
||||
self.annotations.generate_annotation_model()
|
||||
|
||||
self.searchResultsModel = QtGui.QStandardItemModel(self)
|
||||
self.search = Search(self)
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.hide()
|
||||
|
||||
# Ignoring this event prevents application closure when everything is fullscreened
|
||||
# Ignoring this event prevents application closure
|
||||
# when everything is fullscreened
|
||||
event.ignore()
|
||||
|
||||
|
||||
# TODO
|
||||
# Maybe subclass PliantDockWidget for this
|
||||
def populate_sideDock(tabWidget):
|
||||
tabWidget.sideDock.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable)
|
||||
tabWidget.sideDock.setTitleBarWidget(QtWidgets.QWidget())
|
||||
tabWidget.sideDockTabWidget = QtWidgets.QTabWidget()
|
||||
tabWidget.sideDock.setWidget(tabWidget.sideDockTabWidget)
|
||||
# For the following classes, the parent is the sideDock
|
||||
# The parentTab is the parent... tab. So self.parent.parent
|
||||
class Bookmarks:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.parentTab = self.parent.parent
|
||||
self.bookmarkTreeView = QtWidgets.QTreeView(self.parent)
|
||||
self._translate = QtCore.QCoreApplication.translate
|
||||
self.bookmarks_string = self._translate('SideDock', 'Bookmarks')
|
||||
|
||||
# Bookmark tree view and model
|
||||
tabWidget.bookmarkTreeView = QtWidgets.QTreeView(tabWidget)
|
||||
tabWidget.bookmarkTreeView.setHeaderHidden(True)
|
||||
tabWidget.bookmarkTreeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
tabWidget.bookmarkTreeView.customContextMenuRequested.connect(
|
||||
tabWidget.generate_bookmark_context_menu)
|
||||
tabWidget.bookmarkTreeView.clicked.connect(tabWidget.navigate_to_bookmark)
|
||||
bookmarks_string = tabWidget._translate('Tab', 'Bookmarks')
|
||||
tabWidget.sideDockTabWidget.addTab(tabWidget.bookmarkTreeView, bookmarks_string)
|
||||
self.create_widgets()
|
||||
|
||||
tabWidget.bookmarkModel = QtGui.QStandardItemModel(tabWidget)
|
||||
tabWidget.bookmarkProxyModel = BookmarkProxyModel(tabWidget)
|
||||
tabWidget.generate_bookmark_model()
|
||||
def create_widgets(self):
|
||||
self.bookmarkTreeView.setHeaderHidden(True)
|
||||
self.bookmarkTreeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.bookmarkTreeView.customContextMenuRequested.connect(
|
||||
self.generate_bookmark_context_menu)
|
||||
self.bookmarkTreeView.clicked.connect(self.navigate_to_bookmark)
|
||||
|
||||
# Annotation list view and model
|
||||
# Leave this without a parent or it shows up in the image viewer
|
||||
tabWidget.annotationListView = QtWidgets.QListView()
|
||||
tabWidget.annotationListView.setEditTriggers(QtWidgets.QListView.NoEditTriggers)
|
||||
tabWidget.annotationListView.doubleClicked.connect(tabWidget.contentView.toggle_annotation_mode)
|
||||
annotations_string = tabWidget._translate('Tab', 'Annotations')
|
||||
# Add widget to side dock
|
||||
self.parent.sideDockTabWidget.addTab(
|
||||
self.bookmarkTreeView, self.bookmarks_string)
|
||||
|
||||
tabWidget.annotationModel = QtGui.QStandardItemModel(tabWidget)
|
||||
tabWidget.generate_annotation_model()
|
||||
def add_bookmark(self, position=None):
|
||||
identifier = uuid.uuid4().hex[:10]
|
||||
description = self._translate('SideDock', 'New bookmark')
|
||||
|
||||
# Search view and model
|
||||
tabWidget.searchLineEdit = QtWidgets.QLineEdit()
|
||||
tabWidget.searchLineEdit.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||
tabWidget.searchLineEdit.setClearButtonEnabled(True)
|
||||
search_string = tabWidget._translate('Tab', 'Search')
|
||||
tabWidget.searchLineEdit.setPlaceholderText(search_string)
|
||||
if self.parentTab.are_we_doing_images_only:
|
||||
chapter = self.parentTab.metadata['position']['current_chapter']
|
||||
cursor_position = 0
|
||||
else:
|
||||
chapter, cursor_position = self.parent.contentView.record_position(True)
|
||||
if position: # Should be the case when called from the context menu
|
||||
cursor_position = position
|
||||
|
||||
search_book_string = tabWidget._translate('Tab', 'Search entire book')
|
||||
tabWidget.searchBookButton = QtWidgets.QToolButton()
|
||||
tabWidget.searchBookButton.setIcon(
|
||||
tabWidget.main_window.QImageFactory.get_image('view-readermode'))
|
||||
tabWidget.searchBookButton.setToolTip(search_book_string)
|
||||
tabWidget.searchBookButton.setCheckable(True)
|
||||
tabWidget.searchBookButton.setAutoRaise(True)
|
||||
self.parentTab.metadata['bookmarks'][identifier] = {
|
||||
'chapter': chapter,
|
||||
'cursor_position': cursor_position,
|
||||
'description': description}
|
||||
|
||||
case_sensitive_string = tabWidget._translate('Tab', 'Match case')
|
||||
tabWidget.caseSensitiveSearchButton = QtWidgets.QToolButton()
|
||||
tabWidget.caseSensitiveSearchButton.setIcon(
|
||||
tabWidget.main_window.QImageFactory.get_image('search-case'))
|
||||
tabWidget.caseSensitiveSearchButton.setToolTip(case_sensitive_string)
|
||||
tabWidget.caseSensitiveSearchButton.setCheckable(True)
|
||||
tabWidget.caseSensitiveSearchButton.setAutoRaise(True)
|
||||
self.parent.setVisible(True)
|
||||
self.parent.sideDockTabWidget.setCurrentIndex(0)
|
||||
self.add_bookmark_to_model(
|
||||
description, chapter, cursor_position, identifier, True)
|
||||
|
||||
match_word_string = tabWidget._translate('Tab', 'Match word')
|
||||
tabWidget.matchWholeWordButton = QtWidgets.QToolButton()
|
||||
tabWidget.matchWholeWordButton.setIcon(
|
||||
tabWidget.main_window.QImageFactory.get_image('search-word'))
|
||||
tabWidget.matchWholeWordButton.setToolTip(match_word_string)
|
||||
tabWidget.matchWholeWordButton.setCheckable(True)
|
||||
tabWidget.matchWholeWordButton.setAutoRaise(True)
|
||||
def add_bookmark_to_model(
|
||||
self, description, chapter_number, cursor_position,
|
||||
identifier, new_bookmark=False):
|
||||
|
||||
tabWidget.searchOptionsLayout = QtWidgets.QHBoxLayout()
|
||||
tabWidget.searchOptionsLayout.setContentsMargins(0, 3, 0, 0)
|
||||
tabWidget.searchOptionsLayout.addWidget(tabWidget.searchLineEdit)
|
||||
tabWidget.searchOptionsLayout.addWidget(tabWidget.searchBookButton)
|
||||
tabWidget.searchOptionsLayout.addWidget(tabWidget.caseSensitiveSearchButton)
|
||||
tabWidget.searchOptionsLayout.addWidget(tabWidget.matchWholeWordButton)
|
||||
def edit_new_bookmark(parent_item):
|
||||
new_child = parent_item.child(parent_item.rowCount() - 1, 0)
|
||||
source_index = self.parent.bookmarkModel.indexFromItem(new_child)
|
||||
edit_index = self.bookmarkTreeView.model().mapFromSource(source_index)
|
||||
self.parent.activateWindow()
|
||||
self.bookmarkTreeView.setFocus()
|
||||
self.bookmarkTreeView.setCurrentIndex(edit_index)
|
||||
self.bookmarkTreeView.edit(edit_index)
|
||||
|
||||
# Leave this without a parent or it shows up in the image viewer
|
||||
tabWidget.searchResultsTreeView = QtWidgets.QTreeView()
|
||||
tabWidget.searchResultsTreeView.setHeaderHidden(True)
|
||||
tabWidget.searchResultsTreeView.setEditTriggers(QtWidgets.QTreeView.NoEditTriggers)
|
||||
tabWidget.searchResultsTreeView.clicked.connect(tabWidget.navigate_to_search_result)
|
||||
def get_chapter_name(chapter_number):
|
||||
for i in reversed(self.parentTab.metadata['toc']):
|
||||
if i[2] <= chapter_number:
|
||||
return i[1]
|
||||
return 'Unknown'
|
||||
|
||||
tabWidget.searchTabLayout = QtWidgets.QVBoxLayout()
|
||||
tabWidget.searchTabLayout.addLayout(tabWidget.searchOptionsLayout)
|
||||
tabWidget.searchTabLayout.addWidget(tabWidget.searchResultsTreeView)
|
||||
tabWidget.searchTabLayout.setContentsMargins(0, 0, 0, 0)
|
||||
tabWidget.searchTabWidget = QtWidgets.QWidget()
|
||||
tabWidget.searchTabWidget.setLayout(tabWidget.searchTabLayout)
|
||||
bookmark = QtGui.QStandardItem()
|
||||
bookmark.setData(False, QtCore.Qt.UserRole + 10) # Is Parent
|
||||
bookmark.setData(chapter_number, QtCore.Qt.UserRole) # Chapter number
|
||||
bookmark.setData(cursor_position, QtCore.Qt.UserRole + 1) # Cursor Position
|
||||
bookmark.setData(identifier, QtCore.Qt.UserRole + 2) # Identifier
|
||||
bookmark.setData(description, QtCore.Qt.DisplayRole) # Description
|
||||
bookmark_chapter_name = get_chapter_name(chapter_number)
|
||||
|
||||
if not tabWidget.are_we_doing_images_only:
|
||||
tabWidget.sideDockTabWidget.addTab(tabWidget.searchTabWidget, search_string)
|
||||
tabWidget.sideDockTabWidget.addTab(tabWidget.annotationListView, annotations_string)
|
||||
for i in range(self.parent.bookmarkModel.rowCount()):
|
||||
parentIndex = self.parent.bookmarkModel.index(i, 0)
|
||||
parent_chapter_number = parentIndex.data(QtCore.Qt.UserRole)
|
||||
parent_chapter_name = parentIndex.data(QtCore.Qt.DisplayRole)
|
||||
|
||||
# This prevents duplication of the bookmark in the new
|
||||
# navigation model
|
||||
if ((parent_chapter_number <= chapter_number) and
|
||||
(parent_chapter_name == bookmark_chapter_name)):
|
||||
bookmarkParent = self.parent.bookmarkModel.itemFromIndex(parentIndex)
|
||||
bookmarkParent.appendRow(bookmark)
|
||||
if new_bookmark:
|
||||
edit_new_bookmark(bookmarkParent)
|
||||
return
|
||||
|
||||
# In case no parent item exists
|
||||
bookmarkParent = QtGui.QStandardItem()
|
||||
bookmarkParent.setData(True, QtCore.Qt.UserRole + 10) # Is Parent
|
||||
bookmarkParent.setFlags(bookmarkParent.flags() & ~QtCore.Qt.ItemIsEditable) # Is Editable
|
||||
bookmarkParent.setData(get_chapter_name(chapter_number), QtCore.Qt.DisplayRole)
|
||||
bookmarkParent.setData(chapter_number, QtCore.Qt.UserRole)
|
||||
|
||||
bookmarkParent.appendRow(bookmark)
|
||||
self.parent.bookmarkModel.appendRow(bookmarkParent)
|
||||
if new_bookmark:
|
||||
edit_new_bookmark(bookmarkParent)
|
||||
|
||||
def navigate_to_bookmark(self, index):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
is_parent = self.parent.bookmarkProxyModel.data(
|
||||
index, QtCore.Qt.UserRole + 10)
|
||||
if is_parent:
|
||||
chapter_number = self.parent.bookmarkProxyModel.data(
|
||||
index, QtCore.Qt.UserRole)
|
||||
self.parentTab.set_content(chapter_number, True)
|
||||
return
|
||||
|
||||
chapter = self.parent.bookmarkProxyModel.data(
|
||||
index, QtCore.Qt.UserRole)
|
||||
cursor_position = self.parent.bookmarkProxyModel.data(
|
||||
index, QtCore.Qt.UserRole + 1)
|
||||
|
||||
self.parentTab.set_content(chapter, True)
|
||||
if not self.parentTab.are_we_doing_images_only:
|
||||
self.parentTab.set_cursor_position(cursor_position)
|
||||
|
||||
def generate_bookmark_model(self):
|
||||
for i in self.parentTab.metadata['bookmarks'].items():
|
||||
description = i[1]['description']
|
||||
chapter = i[1]['chapter']
|
||||
cursor_position = i[1]['cursor_position']
|
||||
identifier = i[0]
|
||||
self.add_bookmark_to_model(
|
||||
description, chapter, cursor_position, identifier)
|
||||
|
||||
self.generate_bookmark_proxy_model()
|
||||
|
||||
def generate_bookmark_proxy_model(self):
|
||||
self.parent.bookmarkProxyModel.setSourceModel(self.parent.bookmarkModel)
|
||||
self.parent.bookmarkProxyModel.setSortCaseSensitivity(False)
|
||||
self.parent.bookmarkProxyModel.setSortRole(QtCore.Qt.UserRole)
|
||||
self.parent.bookmarkProxyModel.sort(0)
|
||||
self.bookmarkTreeView.setModel(self.parent.bookmarkProxyModel)
|
||||
|
||||
def generate_bookmark_context_menu(self, position):
|
||||
index = self.bookmarkTreeView.indexAt(position)
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
is_parent = self.parent.bookmarkProxyModel.data(
|
||||
index, QtCore.Qt.UserRole + 10)
|
||||
if is_parent:
|
||||
return
|
||||
|
||||
bookmarkMenu = QtWidgets.QMenu()
|
||||
editAction = bookmarkMenu.addAction(
|
||||
self.parentTab.main_window.QImageFactory.get_image('edit-rename'),
|
||||
self._translate('Tab', 'Edit'))
|
||||
deleteAction = bookmarkMenu.addAction(
|
||||
self.parentTab.main_window.QImageFactory.get_image('trash-empty'),
|
||||
self._translate('Tab', 'Delete'))
|
||||
|
||||
action = bookmarkMenu.exec_(
|
||||
self.bookmarkTreeView.mapToGlobal(position))
|
||||
|
||||
if action == editAction:
|
||||
self.bookmarkTreeView.edit(index)
|
||||
|
||||
if action == deleteAction:
|
||||
child_index = self.parent.bookmarkProxyModel.mapToSource(index)
|
||||
parent_index = child_index.parent()
|
||||
child_rows = self.parent.bookmarkModel.itemFromIndex(parent_index).rowCount()
|
||||
delete_uuid = self.parent.bookmarkModel.data(
|
||||
child_index, QtCore.Qt.UserRole + 2)
|
||||
|
||||
self.parentTab.metadata['bookmarks'].pop(delete_uuid)
|
||||
|
||||
self.parent.bookmarkModel.removeRow(child_index.row(), child_index.parent())
|
||||
if child_rows == 1:
|
||||
self.parent.bookmarkModel.removeRow(parent_index.row())
|
||||
|
||||
|
||||
class Annotations:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.parentTab = self.parent.parent
|
||||
self.annotationListView = QtWidgets.QListView(self.parent)
|
||||
self._translate = QtCore.QCoreApplication.translate
|
||||
self.annotations_string = self._translate('SideDock', 'Annotations')
|
||||
|
||||
self.create_widgets()
|
||||
|
||||
def create_widgets(self):
|
||||
self.annotationListView.setEditTriggers(QtWidgets.QListView.NoEditTriggers)
|
||||
self.annotationListView.doubleClicked.connect(
|
||||
self.parent.contentView.toggle_annotation_mode)
|
||||
|
||||
# Add widget to side dock
|
||||
self.parent.sideDockTabWidget.addTab(
|
||||
self.annotationListView, self.annotations_string)
|
||||
|
||||
def generate_annotation_model(self):
|
||||
# TODO
|
||||
# Annotation previews will require creation of a
|
||||
# QStyledItemDelegate
|
||||
|
||||
saved_annotations = self.parent.main_window.settings['annotations']
|
||||
if not saved_annotations:
|
||||
return
|
||||
|
||||
# Create annotation model
|
||||
for i in saved_annotations:
|
||||
item = QtGui.QStandardItem()
|
||||
item.setText(i['name'])
|
||||
item.setData(i, QtCore.Qt.UserRole)
|
||||
self.parent.annotationModel.appendRow(item)
|
||||
self.annotationListView.setModel(self.parent.annotationModel)
|
||||
|
||||
|
||||
class Search:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.parentTab = self.parent.parent
|
||||
|
||||
self.searchThread = BackGroundTextSearch()
|
||||
self.searchOptionsLayout = QtWidgets.QHBoxLayout()
|
||||
self.searchTabLayout = QtWidgets.QVBoxLayout()
|
||||
self.searchTimer = QtCore.QTimer(self.parent)
|
||||
self.searchLineEdit = QtWidgets.QLineEdit(self.parent)
|
||||
self.searchBookButton = QtWidgets.QToolButton(self.parent)
|
||||
self.caseSensitiveSearchButton = QtWidgets.QToolButton(self.parent)
|
||||
self.matchWholeWordButton = QtWidgets.QToolButton(self.parent)
|
||||
self.searchResultsTreeView = QtWidgets.QTreeView(self.parent)
|
||||
|
||||
self.create_widgets()
|
||||
|
||||
def create_widgets(self):
|
||||
self.searchThread.finished.connect(self.generate_search_result_model)
|
||||
|
||||
self.searchTimer.setSingleShot(True)
|
||||
self.searchTimer.timeout.connect(self.set_search_options)
|
||||
|
||||
self.searchLineEdit.textChanged.connect(
|
||||
lambda: self.searchLineEdit.setStyleSheet(
|
||||
QtWidgets.QLineEdit.styleSheet(self.parent)))
|
||||
self.searchLineEdit.textChanged.connect(
|
||||
lambda: self.searchTimer.start(500))
|
||||
self.searchBookButton.clicked.connect(
|
||||
lambda: self.searchTimer.start(100))
|
||||
self.caseSensitiveSearchButton.clicked.connect(
|
||||
lambda: self.searchTimer.start(100))
|
||||
self.matchWholeWordButton.clicked.connect(
|
||||
lambda: self.searchTimer.start(100))
|
||||
|
||||
self.searchLineEdit.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||
self.searchLineEdit.setClearButtonEnabled(True)
|
||||
self._translate = QtCore.QCoreApplication.translate
|
||||
self.search_string = self._translate('SideDock', 'Search')
|
||||
self.searchLineEdit.setPlaceholderText(self.search_string)
|
||||
|
||||
search_book_string = self._translate('SideDock', 'Search entire book')
|
||||
|
||||
self.searchBookButton.setIcon(
|
||||
self.parent.main_window.QImageFactory.get_image('view-readermode'))
|
||||
self.searchBookButton.setToolTip(search_book_string)
|
||||
self.searchBookButton.setCheckable(True)
|
||||
self.searchBookButton.setAutoRaise(True)
|
||||
self.searchBookButton.setIconSize(QtCore.QSize(20, 20))
|
||||
|
||||
case_sensitive_string = self._translate('SideDock', 'Match case')
|
||||
|
||||
self.caseSensitiveSearchButton.setIcon(
|
||||
self.parent.main_window.QImageFactory.get_image('search-case'))
|
||||
self.caseSensitiveSearchButton.setToolTip(case_sensitive_string)
|
||||
self.caseSensitiveSearchButton.setCheckable(True)
|
||||
self.caseSensitiveSearchButton.setAutoRaise(True)
|
||||
self.caseSensitiveSearchButton.setIconSize(QtCore.QSize(20, 20))
|
||||
|
||||
match_word_string = self._translate('SideDock', 'Match word')
|
||||
self.matchWholeWordButton.setIcon(
|
||||
self.parent.main_window.QImageFactory.get_image('search-word'))
|
||||
self.matchWholeWordButton.setToolTip(match_word_string)
|
||||
self.matchWholeWordButton.setCheckable(True)
|
||||
self.matchWholeWordButton.setAutoRaise(True)
|
||||
self.matchWholeWordButton.setIconSize(QtCore.QSize(20, 20))
|
||||
|
||||
self.searchOptionsLayout.setContentsMargins(0, 3, 0, 0)
|
||||
self.searchOptionsLayout.addWidget(self.searchLineEdit)
|
||||
self.searchOptionsLayout.addWidget(self.searchBookButton)
|
||||
self.searchOptionsLayout.addWidget(self.caseSensitiveSearchButton)
|
||||
self.searchOptionsLayout.addWidget(self.matchWholeWordButton)
|
||||
|
||||
self.searchResultsTreeView.setHeaderHidden(True)
|
||||
self.searchResultsTreeView.setEditTriggers(
|
||||
QtWidgets.QTreeView.NoEditTriggers)
|
||||
self.searchResultsTreeView.clicked.connect(
|
||||
self.navigate_to_search_result)
|
||||
|
||||
self.searchTabLayout.addLayout(self.searchOptionsLayout)
|
||||
self.searchTabLayout.addWidget(self.searchResultsTreeView)
|
||||
self.searchTabLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.searchTabWidget = QtWidgets.QWidget(self.parent)
|
||||
self.searchTabWidget.setLayout(self.searchTabLayout)
|
||||
|
||||
# Add widget to side dock
|
||||
self.parent.sideDockTabWidget.addTab(
|
||||
self.searchTabWidget, self.search_string)
|
||||
|
||||
def set_search_options(self):
|
||||
def generate_title_content_pair(required_chapters):
|
||||
title_content_list = []
|
||||
for i in self.parentTab.metadata['toc']:
|
||||
if i[2] in required_chapters:
|
||||
title_content_list.append(
|
||||
(i[1], self.parentTab.metadata['content'][i[2] - 1], i[2]))
|
||||
return title_content_list
|
||||
|
||||
# Select either the current chapter or all chapters
|
||||
# Function name is descriptive
|
||||
chapter_numbers = (self.parentTab.metadata['position']['current_chapter'],)
|
||||
if self.searchBookButton.isChecked():
|
||||
chapter_numbers = [i + 1 for i in range(len(self.parentTab.metadata['content']))]
|
||||
search_content = generate_title_content_pair(chapter_numbers)
|
||||
|
||||
self.searchThread.set_search_options(
|
||||
search_content,
|
||||
self.searchLineEdit.text(),
|
||||
self.caseSensitiveSearchButton.isChecked(),
|
||||
self.matchWholeWordButton.isChecked())
|
||||
self.searchThread.start()
|
||||
|
||||
def generate_search_result_model(self):
|
||||
self.parent.searchResultsModel.clear()
|
||||
search_results = self.searchThread.search_results
|
||||
for i in search_results:
|
||||
parentItem = QtGui.QStandardItem()
|
||||
parentItem.setData(True, QtCore.Qt.UserRole) # Is parent?
|
||||
parentItem.setData(i, QtCore.Qt.UserRole + 3) # Display text for label
|
||||
|
||||
for j in search_results[i]:
|
||||
childItem = QtGui.QStandardItem(parentItem)
|
||||
childItem.setData(False, QtCore.Qt.UserRole) # Is parent?
|
||||
childItem.setData(j[3], QtCore.Qt.UserRole + 1) # Chapter index
|
||||
childItem.setData(j[0], QtCore.Qt.UserRole + 2) # Cursor Position
|
||||
childItem.setData(j[1], QtCore.Qt.UserRole + 3) # Display text for label
|
||||
childItem.setData(j[2], QtCore.Qt.UserRole + 4) # Search term
|
||||
parentItem.appendRow(childItem)
|
||||
self.parent.searchResultsModel.appendRow(parentItem)
|
||||
|
||||
self.searchResultsTreeView.setModel(self.parent.searchResultsModel)
|
||||
self.searchResultsTreeView.expandToDepth(1)
|
||||
|
||||
# Reset stylesheet in case something is found
|
||||
if search_results:
|
||||
self.searchLineEdit.setStyleSheet(
|
||||
QtWidgets.QLineEdit.styleSheet(self.parent))
|
||||
|
||||
# Or set to Red in case nothing is found
|
||||
if not search_results and len(self.searchLineEdit.text()) > 2:
|
||||
self.searchLineEdit.setStyleSheet("QLineEdit {color: red;}")
|
||||
|
||||
# We'll be putting in labels instead of making a delegate
|
||||
# QLabels can understand RTF, and they also have the somewhat
|
||||
# distinct advantage of being a lot less work than a delegate
|
||||
|
||||
def generate_label(index):
|
||||
label_text = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 3)
|
||||
labelWidget = PliantLabelWidget(index, self.navigate_to_search_result)
|
||||
labelWidget.setText(label_text)
|
||||
self.searchResultsTreeView.setIndexWidget(index, labelWidget)
|
||||
|
||||
for parent_iter in range(self.parent.searchResultsModel.rowCount()):
|
||||
parentItem = self.parent.searchResultsModel.item(parent_iter)
|
||||
parentIndex = self.parent.searchResultsModel.index(parent_iter, 0)
|
||||
generate_label(parentIndex)
|
||||
|
||||
for child_iter in range(parentItem.rowCount()):
|
||||
childIndex = self.parent.searchResultsModel.index(child_iter, 0, parentIndex)
|
||||
generate_label(childIndex)
|
||||
|
||||
def navigate_to_search_result(self, index):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
is_parent = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole)
|
||||
if is_parent:
|
||||
return
|
||||
|
||||
chapter_number = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 1)
|
||||
cursor_position = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 2)
|
||||
search_term = self.parent.searchResultsModel.data(index, QtCore.Qt.UserRole + 4)
|
||||
|
||||
self.parentTab.set_content(chapter_number, True)
|
||||
if not self.parentTab.are_we_doing_images_only:
|
||||
self.parentTab.set_cursor_position(
|
||||
cursor_position, len(search_term))
|
||||
|
||||
|
||||
class PliantLabelWidget(QtWidgets.QLabel):
|
||||
# This is a hack to get clickable / editable appearance
|
||||
# search results in the tree view.
|
||||
|
||||
def __init__(self, index, navigate_to_search_result):
|
||||
super(PliantLabelWidget, self).__init__()
|
||||
self.index = index
|
||||
self.navigate_to_search_result = navigate_to_search_result
|
||||
|
||||
def mousePressEvent(self, QMouseEvent):
|
||||
self.navigate_to_search_result(self.index)
|
||||
QtWidgets.QLabel.mousePressEvent(self, QMouseEvent)
|
||||
|
@@ -27,23 +27,19 @@ class BookmarkProxyModel(QtCore.QSortFilterProxyModel):
|
||||
def __init__(self, parent=None):
|
||||
super(BookmarkProxyModel, self).__init__(parent)
|
||||
self.parent = parent
|
||||
self.parentTab = self.parent.parent
|
||||
self.filter_text = None
|
||||
|
||||
def setFilterParams(self, filter_text):
|
||||
self.filter_text = filter_text
|
||||
|
||||
def filterAcceptsRow(self, row, parent):
|
||||
# TODO
|
||||
# Connect this to the search bar
|
||||
return True
|
||||
|
||||
def setData(self, index, value, role):
|
||||
if role == QtCore.Qt.EditRole:
|
||||
source_index = self.mapToSource(index)
|
||||
identifier = self.sourceModel().data(source_index, QtCore.Qt.UserRole + 2)
|
||||
|
||||
self.sourceModel().setData(source_index, value, QtCore.Qt.DisplayRole)
|
||||
self.parent.metadata['bookmarks'][identifier]['description'] = value
|
||||
self.parentTab.metadata['bookmarks'][identifier]['description'] = value
|
||||
|
||||
return True
|
||||
|
||||
|
@@ -19,14 +19,12 @@
|
||||
# Double page, Continuous etc
|
||||
|
||||
import os
|
||||
import uuid
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||
|
||||
from lector.sorter import resize_image
|
||||
from lector.threaded import BackGroundTextSearch
|
||||
from lector.dockwidgets import PliantDockWidget, populate_sideDock
|
||||
from lector.dockwidgets import PliantDockWidget
|
||||
from lector.contentwidgets import PliantQGraphicsView, PliantQTextBrowser
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -137,13 +135,14 @@ class Tab(QtWidgets.QWidget):
|
||||
self.contentView.setVerticalScrollBarPolicy(
|
||||
QtCore.Qt.ScrollBarAsNeeded)
|
||||
|
||||
# Create a common dock for annotations and bookmarks
|
||||
# It is populated by the following method
|
||||
self.sideDock = PliantDockWidget(self.main_window, False, self.contentView)
|
||||
populate_sideDock(self)
|
||||
# Create a common dock for bookmarks, annotations, and search
|
||||
self.sideDock = PliantDockWidget(
|
||||
self.main_window, False, self.contentView, self)
|
||||
self.sideDock.populate()
|
||||
|
||||
# Create the annotation notes dock
|
||||
self.annotationNoteDock = PliantDockWidget(self.main_window, True, self.contentView)
|
||||
self.annotationNoteDock = PliantDockWidget(
|
||||
self.main_window, True, self.contentView, self)
|
||||
self.annotationNoteDock.setWindowTitle(self._translate('Tab', 'Note'))
|
||||
self.annotationNoteDock.setFeatures(QtWidgets.QDockWidget.DockWidgetClosable)
|
||||
self.annotationNoteDock.hide()
|
||||
@@ -166,29 +165,6 @@ class Tab(QtWidgets.QWidget):
|
||||
self.annotationNoteDock.setWindowOpacity(.95)
|
||||
self.sideDock.hide()
|
||||
|
||||
# Create search references
|
||||
if not self.are_we_doing_images_only:
|
||||
self.searchResultsModel = None
|
||||
|
||||
self.searchThread = BackGroundTextSearch()
|
||||
self.searchThread.finished.connect(self.generate_search_result_model)
|
||||
|
||||
self.searchTimer = QtCore.QTimer()
|
||||
self.searchTimer.setSingleShot(True)
|
||||
self.searchTimer.timeout.connect(self.set_search_options)
|
||||
|
||||
self.searchLineEdit.textChanged.connect(
|
||||
lambda: self.searchLineEdit.setStyleSheet(
|
||||
QtWidgets.QLineEdit.styleSheet(self)))
|
||||
self.searchLineEdit.textChanged.connect(
|
||||
lambda: self.searchTimer.start(500))
|
||||
self.searchBookButton.clicked.connect(
|
||||
lambda: self.searchTimer.start(100))
|
||||
self.caseSensitiveSearchButton.clicked.connect(
|
||||
lambda: self.searchTimer.start(100))
|
||||
self.matchWholeWordButton.clicked.connect(
|
||||
lambda: self.searchTimer.start(100))
|
||||
|
||||
# Create tab in the central tab widget
|
||||
title = self.metadata['title']
|
||||
if self.main_window.settings['attenuate_titles'] and len(title) > 30:
|
||||
@@ -214,17 +190,17 @@ class Tab(QtWidgets.QWidget):
|
||||
|
||||
def toggle_side_dock(self, tab_required, override_hide=False):
|
||||
if (self.sideDock.isVisible()
|
||||
and self.sideDockTabWidget.currentIndex() == tab_required
|
||||
and self.sideDock.sideDockTabWidget.currentIndex() == tab_required
|
||||
and not override_hide):
|
||||
self.sideDock.hide()
|
||||
elif not self.sideDock.isVisible():
|
||||
self.sideDock.show()
|
||||
if tab_required == 2:
|
||||
self.sideDock.activateWindow()
|
||||
self.searchLineEdit.setFocus()
|
||||
self.searchLineEdit.selectAll()
|
||||
self.sideDock.search.searchLineEdit.setFocus()
|
||||
self.sideDock.search.searchLineEdit.selectAll()
|
||||
|
||||
self.sideDockTabWidget.setCurrentIndex(tab_required)
|
||||
self.sideDock.sideDockTabWidget.setCurrentIndex(tab_required)
|
||||
|
||||
def update_last_accessed_time(self):
|
||||
self.metadata['last_accessed'] = QtCore.QDateTime().currentDateTime()
|
||||
@@ -238,7 +214,8 @@ class Tab(QtWidgets.QWidget):
|
||||
|
||||
try:
|
||||
self.main_window.lib_ref.libraryModel.setData(
|
||||
matching_item[0], self.metadata['last_accessed'], QtCore.Qt.UserRole + 12)
|
||||
matching_item[0],
|
||||
self.metadata['last_accessed'], QtCore.Qt.UserRole + 12)
|
||||
except IndexError: # The file has been deleted
|
||||
pass
|
||||
|
||||
@@ -329,17 +306,20 @@ class Tab(QtWidgets.QWidget):
|
||||
|
||||
ksToggleBookmarks = QtWidgets.QShortcut(
|
||||
QtGui.QKeySequence('Ctrl+B'), self.contentView)
|
||||
ksToggleBookmarks.activated.connect(lambda: self.toggle_side_dock(0))
|
||||
ksToggleBookmarks.activated.connect(
|
||||
lambda: self.toggle_side_dock(0))
|
||||
|
||||
# Shortcuts not required for comic view functionality
|
||||
if not self.are_we_doing_images_only:
|
||||
ksToggleAnnotations = QtWidgets.QShortcut(
|
||||
QtGui.QKeySequence('Ctrl+N'), self.contentView)
|
||||
ksToggleAnnotations.activated.connect(lambda: self.toggle_side_dock(1))
|
||||
ksToggleAnnotations.activated.connect(
|
||||
lambda: self.toggle_side_dock(1))
|
||||
|
||||
ksToggleSearch = QtWidgets.QShortcut(
|
||||
QtGui.QKeySequence('Ctrl+F'), self.contentView)
|
||||
ksToggleSearch.activated.connect(lambda: self.toggle_side_dock(2))
|
||||
ksToggleSearch.activated.connect(
|
||||
lambda: self.toggle_side_dock(2))
|
||||
|
||||
def generate_toc_model(self):
|
||||
# The toc list is:
|
||||
@@ -548,7 +528,8 @@ class Tab(QtWidgets.QWidget):
|
||||
|
||||
current_index = self.main_window.bookToolBar.tocBox.currentIndex()
|
||||
if current_index == 0:
|
||||
block_format.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
|
||||
block_format.setAlignment(
|
||||
QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter)
|
||||
else:
|
||||
block_format.setAlignment(alignment_dict[text_alignment])
|
||||
|
||||
@@ -570,259 +551,6 @@ class Tab(QtWidgets.QWidget):
|
||||
if old_position == new_position:
|
||||
break
|
||||
|
||||
def generate_annotation_model(self):
|
||||
# TODO
|
||||
# Annotation previews will require creation of a
|
||||
# QStyledItemDelegate
|
||||
|
||||
saved_annotations = self.main_window.settings['annotations']
|
||||
if not saved_annotations:
|
||||
return
|
||||
|
||||
# Create annotation model
|
||||
for i in saved_annotations:
|
||||
item = QtGui.QStandardItem()
|
||||
item.setText(i['name'])
|
||||
item.setData(i, QtCore.Qt.UserRole)
|
||||
self.annotationModel.appendRow(item)
|
||||
self.annotationListView.setModel(self.annotationModel)
|
||||
|
||||
def add_bookmark(self, position=None):
|
||||
identifier = uuid.uuid4().hex[:10]
|
||||
description = self._translate('Tab', 'New bookmark')
|
||||
|
||||
if self.are_we_doing_images_only:
|
||||
chapter = self.metadata['position']['current_chapter']
|
||||
cursor_position = 0
|
||||
else:
|
||||
chapter, cursor_position = self.contentView.record_position(True)
|
||||
if position: # Should be the case when called from the context menu
|
||||
cursor_position = position
|
||||
|
||||
self.metadata['bookmarks'][identifier] = {
|
||||
'chapter': chapter,
|
||||
'cursor_position': cursor_position,
|
||||
'description': description}
|
||||
|
||||
self.sideDock.setVisible(True)
|
||||
self.sideDockTabWidget.setCurrentIndex(0)
|
||||
self.add_bookmark_to_model(
|
||||
description, chapter, cursor_position, identifier, True)
|
||||
|
||||
def add_bookmark_to_model(
|
||||
self, description, chapter_number, cursor_position,
|
||||
identifier, new_bookmark=False):
|
||||
|
||||
def edit_new_bookmark(parent_item):
|
||||
new_child = parent_item.child(parent_item.rowCount() - 1, 0)
|
||||
source_index = self.bookmarkModel.indexFromItem(new_child)
|
||||
edit_index = self.bookmarkTreeView.model().mapFromSource(source_index)
|
||||
self.sideDock.activateWindow()
|
||||
self.bookmarkTreeView.setFocus()
|
||||
self.bookmarkTreeView.setCurrentIndex(edit_index)
|
||||
self.bookmarkTreeView.edit(edit_index)
|
||||
|
||||
def get_chapter_name(chapter_number):
|
||||
for i in reversed(self.metadata['toc']):
|
||||
if i[2] <= chapter_number:
|
||||
return i[1]
|
||||
return 'Unknown'
|
||||
|
||||
bookmark = QtGui.QStandardItem()
|
||||
bookmark.setData(False, QtCore.Qt.UserRole + 10) # Is Parent
|
||||
bookmark.setData(chapter_number, QtCore.Qt.UserRole) # Chapter number
|
||||
bookmark.setData(cursor_position, QtCore.Qt.UserRole + 1) # Cursor Position
|
||||
bookmark.setData(identifier, QtCore.Qt.UserRole + 2) # Identifier
|
||||
bookmark.setData(description, QtCore.Qt.DisplayRole) # Description
|
||||
bookmark_chapter_name = get_chapter_name(chapter_number)
|
||||
|
||||
for i in range(self.bookmarkModel.rowCount()):
|
||||
parentIndex = self.bookmarkModel.index(i, 0)
|
||||
parent_chapter_number = parentIndex.data(QtCore.Qt.UserRole)
|
||||
parent_chapter_name = parentIndex.data(QtCore.Qt.DisplayRole)
|
||||
|
||||
# This prevents duplication of the bookmark in the new
|
||||
# navigation model
|
||||
if ((parent_chapter_number <= chapter_number) and
|
||||
(parent_chapter_name == bookmark_chapter_name)):
|
||||
bookmarkParent = self.bookmarkModel.itemFromIndex(parentIndex)
|
||||
bookmarkParent.appendRow(bookmark)
|
||||
if new_bookmark:
|
||||
edit_new_bookmark(bookmarkParent)
|
||||
return
|
||||
|
||||
# In case no parent item exists
|
||||
bookmarkParent = QtGui.QStandardItem()
|
||||
bookmarkParent.setData(True, QtCore.Qt.UserRole + 10) # Is Parent
|
||||
bookmarkParent.setFlags(bookmarkParent.flags() & ~QtCore.Qt.ItemIsEditable) # Is Editable
|
||||
bookmarkParent.setData(get_chapter_name(chapter_number), QtCore.Qt.DisplayRole)
|
||||
bookmarkParent.setData(chapter_number, QtCore.Qt.UserRole)
|
||||
|
||||
bookmarkParent.appendRow(bookmark)
|
||||
self.bookmarkModel.appendRow(bookmarkParent)
|
||||
if new_bookmark:
|
||||
edit_new_bookmark(bookmarkParent)
|
||||
|
||||
def navigate_to_bookmark(self, index):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
is_parent = self.bookmarkProxyModel.data(index, QtCore.Qt.UserRole + 10)
|
||||
if is_parent:
|
||||
chapter_number = self.bookmarkProxyModel.data(index, QtCore.Qt.UserRole)
|
||||
self.set_content(chapter_number, True)
|
||||
return
|
||||
|
||||
chapter = self.bookmarkProxyModel.data(index, QtCore.Qt.UserRole)
|
||||
cursor_position = self.bookmarkProxyModel.data(index, QtCore.Qt.UserRole + 1)
|
||||
|
||||
self.set_content(chapter, True)
|
||||
if not self.are_we_doing_images_only:
|
||||
self.set_cursor_position(cursor_position)
|
||||
|
||||
def generate_bookmark_model(self):
|
||||
for i in self.metadata['bookmarks'].items():
|
||||
description = i[1]['description']
|
||||
chapter = i[1]['chapter']
|
||||
cursor_position = i[1]['cursor_position']
|
||||
identifier = i[0]
|
||||
self.add_bookmark_to_model(
|
||||
description, chapter, cursor_position, identifier)
|
||||
|
||||
self.generate_bookmark_proxy_model()
|
||||
|
||||
def generate_bookmark_proxy_model(self):
|
||||
self.bookmarkProxyModel.setSourceModel(self.bookmarkModel)
|
||||
self.bookmarkProxyModel.setSortCaseSensitivity(False)
|
||||
self.bookmarkProxyModel.setSortRole(QtCore.Qt.UserRole)
|
||||
self.bookmarkProxyModel.sort(0)
|
||||
self.bookmarkTreeView.setModel(self.bookmarkProxyModel)
|
||||
|
||||
def generate_bookmark_context_menu(self, position):
|
||||
index = self.bookmarkTreeView.indexAt(position)
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
is_parent = self.bookmarkProxyModel.data(index, QtCore.Qt.UserRole + 10)
|
||||
if is_parent:
|
||||
return
|
||||
|
||||
bookmarkMenu = QtWidgets.QMenu()
|
||||
editAction = bookmarkMenu.addAction(
|
||||
self.main_window.QImageFactory.get_image('edit-rename'),
|
||||
self._translate('Tab', 'Edit'))
|
||||
deleteAction = bookmarkMenu.addAction(
|
||||
self.main_window.QImageFactory.get_image('trash-empty'),
|
||||
self._translate('Tab', 'Delete'))
|
||||
|
||||
action = bookmarkMenu.exec_(
|
||||
self.bookmarkTreeView.mapToGlobal(position))
|
||||
|
||||
if action == editAction:
|
||||
self.bookmarkTreeView.edit(index)
|
||||
|
||||
if action == deleteAction:
|
||||
child_index = self.bookmarkProxyModel.mapToSource(index)
|
||||
parent_index = child_index.parent()
|
||||
child_rows = self.bookmarkModel.itemFromIndex(parent_index).rowCount()
|
||||
delete_uuid = self.bookmarkModel.data(
|
||||
child_index, QtCore.Qt.UserRole + 2)
|
||||
|
||||
self.metadata['bookmarks'].pop(delete_uuid)
|
||||
|
||||
self.bookmarkModel.removeRow(child_index.row(), child_index.parent())
|
||||
if child_rows == 1:
|
||||
self.bookmarkModel.removeRow(parent_index.row())
|
||||
|
||||
def set_search_options(self):
|
||||
def generate_title_content_pair(required_chapters):
|
||||
title_content_list = []
|
||||
for i in self.metadata['toc']:
|
||||
if i[2] in required_chapters:
|
||||
title_content_list.append(
|
||||
(i[1], self.metadata['content'][i[2] - 1], i[2]))
|
||||
return title_content_list
|
||||
|
||||
# Select either the current chapter or all chapters
|
||||
# Function name is descriptive
|
||||
chapter_numbers = (self.metadata['position']['current_chapter'],)
|
||||
if self.searchBookButton.isChecked():
|
||||
chapter_numbers = [i + 1 for i in range(len(self.metadata['content']))]
|
||||
search_content = generate_title_content_pair(chapter_numbers)
|
||||
|
||||
self.searchThread.set_search_options(
|
||||
search_content,
|
||||
self.searchLineEdit.text(),
|
||||
self.caseSensitiveSearchButton.isChecked(),
|
||||
self.matchWholeWordButton.isChecked())
|
||||
self.searchThread.start()
|
||||
|
||||
def generate_search_result_model(self):
|
||||
self.searchResultsModel = QtGui.QStandardItemModel()
|
||||
search_results = self.searchThread.search_results
|
||||
for i in search_results:
|
||||
parentItem = QtGui.QStandardItem()
|
||||
parentItem.setData(True, QtCore.Qt.UserRole) # Is parent?
|
||||
parentItem.setData(i, QtCore.Qt.UserRole + 3) # Display text for label
|
||||
|
||||
for j in search_results[i]:
|
||||
childItem = QtGui.QStandardItem(parentItem)
|
||||
childItem.setData(False, QtCore.Qt.UserRole) # Is parent?
|
||||
childItem.setData(j[3], QtCore.Qt.UserRole + 1) # Chapter index
|
||||
childItem.setData(j[0], QtCore.Qt.UserRole + 2) # Cursor Position
|
||||
childItem.setData(j[1], QtCore.Qt.UserRole + 3) # Display text for label
|
||||
childItem.setData(j[2], QtCore.Qt.UserRole + 4) # Search term
|
||||
parentItem.appendRow(childItem)
|
||||
self.searchResultsModel.appendRow(parentItem)
|
||||
|
||||
self.searchResultsTreeView.setModel(self.searchResultsModel)
|
||||
self.searchResultsTreeView.expandToDepth(1)
|
||||
|
||||
# Reset stylesheet in case something is found
|
||||
if search_results:
|
||||
self.searchLineEdit.setStyleSheet(
|
||||
QtWidgets.QLineEdit.styleSheet(self))
|
||||
|
||||
# Or set to Red in case nothing is found
|
||||
if not search_results and len(self.searchLineEdit.text()) > 2:
|
||||
self.searchLineEdit.setStyleSheet("QLineEdit {color: red;}")
|
||||
|
||||
# We'll be putting in labels instead of making a delegate
|
||||
# QLabels can understand RTF, and they also have the somewhat
|
||||
# distinct advantage of being a lot less work than a delegate
|
||||
|
||||
def generate_label(index):
|
||||
label_text = self.searchResultsModel.data(index, QtCore.Qt.UserRole + 3)
|
||||
labelWidget = PliantLabelWidget(index, self.navigate_to_search_result)
|
||||
labelWidget.setText(label_text)
|
||||
self.searchResultsTreeView.setIndexWidget(index, labelWidget)
|
||||
|
||||
for parent_iter in range(self.searchResultsModel.rowCount()):
|
||||
parentItem = self.searchResultsModel.item(parent_iter)
|
||||
parentIndex = self.searchResultsModel.index(parent_iter, 0)
|
||||
generate_label(parentIndex)
|
||||
|
||||
for child_iter in range(parentItem.rowCount()):
|
||||
childIndex = self.searchResultsModel.index(child_iter, 0, parentIndex)
|
||||
generate_label(childIndex)
|
||||
|
||||
def navigate_to_search_result(self, index):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
is_parent = self.searchResultsModel.data(index, QtCore.Qt.UserRole)
|
||||
if is_parent:
|
||||
return
|
||||
|
||||
chapter_number = self.searchResultsModel.data(index, QtCore.Qt.UserRole + 1)
|
||||
cursor_position = self.searchResultsModel.data(index, QtCore.Qt.UserRole + 2)
|
||||
search_term = self.searchResultsModel.data(index, QtCore.Qt.UserRole + 4)
|
||||
|
||||
self.set_content(chapter_number, True)
|
||||
if not self.are_we_doing_images_only:
|
||||
self.set_cursor_position(
|
||||
cursor_position, len(search_term))
|
||||
|
||||
def hide_mouse(self):
|
||||
self.contentView.viewport().setCursor(QtCore.Qt.BlankCursor)
|
||||
|
||||
@@ -839,20 +567,6 @@ class Tab(QtWidgets.QWidget):
|
||||
self.main_window.closeEvent()
|
||||
|
||||
|
||||
class PliantLabelWidget(QtWidgets.QLabel):
|
||||
# This is a hack to get clickable / editable appearance
|
||||
# search results in the tree view.
|
||||
|
||||
def __init__(self, index, navigate_to_search_result):
|
||||
super(PliantLabelWidget, self).__init__()
|
||||
self.index = index
|
||||
self.navigate_to_search_result = navigate_to_search_result
|
||||
|
||||
def mousePressEvent(self, QMouseEvent):
|
||||
self.navigate_to_search_result(self.index)
|
||||
QtWidgets.QLabel.mousePressEvent(self, QMouseEvent)
|
||||
|
||||
|
||||
class PliantQGraphicsScene(QtWidgets.QGraphicsScene):
|
||||
def __init__(self, parent=None):
|
||||
super(PliantQGraphicsScene, self).__init__(parent)
|
||||
@@ -933,7 +647,8 @@ class DragDropTableView(QtWidgets.QTableView):
|
||||
self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
|
||||
self.setFrameShape(QtWidgets.QFrame.Box)
|
||||
self.setFrameShadow(QtWidgets.QFrame.Plain)
|
||||
self.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
|
||||
self.setSizeAdjustPolicy(
|
||||
QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
|
||||
self.setEditTriggers(
|
||||
QtWidgets.QAbstractItemView.DoubleClicked |
|
||||
QtWidgets.QAbstractItemView.EditKeyPressed |
|
||||
|
Reference in New Issue
Block a user