QGraphicsView for image browsing
This commit is contained in:
25
__main__.py
25
__main__.py
@@ -34,6 +34,8 @@
|
|||||||
✓ Keep fontsize and margins consistent - Let page increase in length
|
✓ Keep fontsize and margins consistent - Let page increase in length
|
||||||
✓ Fullscreening
|
✓ Fullscreening
|
||||||
✓ Remember open tabs
|
✓ Remember open tabs
|
||||||
|
Special Keyboard shortcuts and view modes for QGraphicsView
|
||||||
|
Selectable background color for QGraphicsView
|
||||||
Record progress
|
Record progress
|
||||||
Pagination
|
Pagination
|
||||||
Set context menu for definitions and the like
|
Set context menu for definitions and the like
|
||||||
@@ -286,11 +288,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.tabWidget.removeTab(tab_index)
|
self.tabWidget.removeTab(tab_index)
|
||||||
|
|
||||||
def set_toc_position(self, event=None):
|
def set_toc_position(self, event=None):
|
||||||
chapter_name = self.bookToolBar.tocBox.currentText()
|
|
||||||
current_tab = self.tabWidget.widget(self.tabWidget.currentIndex())
|
current_tab = self.tabWidget.widget(self.tabWidget.currentIndex())
|
||||||
required_content = current_tab.metadata['content'][chapter_name]
|
|
||||||
|
|
||||||
# We're also updating the underlying model to have real-time
|
# We're updating the underlying model to have real-time
|
||||||
# updates on the read status
|
# updates on the read status
|
||||||
|
|
||||||
# Set a baseline model index in case the item gets deleted
|
# Set a baseline model index in case the item gets deleted
|
||||||
@@ -314,14 +314,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.viewModel.setData(
|
self.viewModel.setData(
|
||||||
model_index, current_tab.metadata['position'], QtCore.Qt.UserRole + 7)
|
model_index, current_tab.metadata['position'], QtCore.Qt.UserRole + 7)
|
||||||
|
|
||||||
# current_tab.contentView.verticalScrollBar().setValue(0)
|
current_tab.chapter_change()
|
||||||
current_tab.contentView.clear()
|
|
||||||
current_tab.contentView.setHtml(required_content)
|
|
||||||
|
|
||||||
def set_fullscreen(self):
|
def set_fullscreen(self):
|
||||||
current_tab = self.tabWidget.currentIndex()
|
current_tab = self.tabWidget.currentIndex()
|
||||||
current_tab_widget = self.tabWidget.widget(current_tab)
|
current_tab_widget = self.tabWidget.widget(current_tab)
|
||||||
self.current_contentView = current_tab_widget.findChildren(QtWidgets.QTextBrowser)[0]
|
self.current_contentView = current_tab_widget.findChildren(
|
||||||
|
(QtWidgets.QTextBrowser, QtWidgets.QGraphicsView))[0]
|
||||||
|
|
||||||
self.current_contentView.setWindowFlags(QtCore.Qt.Window)
|
self.current_contentView.setWindowFlags(QtCore.Qt.Window)
|
||||||
self.current_contentView.setWindowState(QtCore.Qt.WindowFullScreen)
|
self.current_contentView.setWindowState(QtCore.Qt.WindowFullScreen)
|
||||||
@@ -458,16 +457,8 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Change contentView to match new settings
|
# Change contentView to match new settings
|
||||||
current_tab = self.tabWidget.currentIndex()
|
current_tab = self.tabWidget.widget(self.tabWidget.currentIndex())
|
||||||
current_tab_widget = self.tabWidget.widget(current_tab)
|
current_tab.format_view(font, font_size, foreground, background, padding)
|
||||||
current_contentView = current_tab_widget.findChildren(QtWidgets.QTextBrowser)[0]
|
|
||||||
|
|
||||||
# This allows for the scrollbar to always be at the edge of the screen
|
|
||||||
current_contentView.setViewportMargins(padding, 0, padding, 0)
|
|
||||||
|
|
||||||
current_contentView.setStyleSheet(
|
|
||||||
"QTextEdit {{font-family: {0}; font-size: {1}px; color: {2}; background-color: {3}}}".format(
|
|
||||||
font, font_size, foreground, background))
|
|
||||||
|
|
||||||
def reset_profile(self):
|
def reset_profile(self):
|
||||||
current_profile_index = self.bookToolBar.profileBox.currentIndex()
|
current_profile_index = self.bookToolBar.profileBox.currentIndex()
|
||||||
|
@@ -93,7 +93,7 @@ class ParseCBZ:
|
|||||||
page_name = 'Page ' + str(count)
|
page_name = 'Page ' + str(count)
|
||||||
image_path = os.path.join(extract_path, image_dir, i)
|
image_path = os.path.join(extract_path, image_dir, i)
|
||||||
|
|
||||||
# contents[page_name] = image_path
|
contents[page_name] = image_path
|
||||||
contents[page_name] = "<img src='%s' align='middle'/>" % image_path
|
# contents[page_name] = "<img src='%s' align='middle'/>" % image_path
|
||||||
|
|
||||||
return contents, file_settings
|
return contents, file_settings
|
||||||
|
155
widgets.py
155
widgets.py
@@ -274,28 +274,14 @@ class Tab(QtWidgets.QWidget):
|
|||||||
# Take hint from a position function argument to open the book
|
# Take hint from a position function argument to open the book
|
||||||
# at a specific page
|
# at a specific page
|
||||||
|
|
||||||
# The content display widget is currently a QTextBrowser
|
|
||||||
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.gridLayout = QtWidgets.QGridLayout(self)
|
self.gridLayout = QtWidgets.QGridLayout(self)
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
self.contentView = PliantQTextBrowser(self.window())
|
|
||||||
self.contentView.setFrameShape(QtWidgets.QFrame.NoFrame)
|
|
||||||
self.contentView.setObjectName("contentView")
|
|
||||||
self.contentView.verticalScrollBar().setSingleStep(7)
|
|
||||||
self.contentView.setHorizontalScrollBarPolicy(
|
|
||||||
QtCore.Qt.ScrollBarAlwaysOff)
|
|
||||||
|
|
||||||
self.scroll_past_end_tries = 0
|
|
||||||
|
|
||||||
title = self.metadata['title']
|
|
||||||
position = self.metadata['position']
|
position = self.metadata['position']
|
||||||
relative_path_root = self.metadata['temp_dir']
|
|
||||||
relative_paths = []
|
|
||||||
for i in os.walk(relative_path_root):
|
|
||||||
relative_paths.append(os.path.join(relative_path_root, i[0]))
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
# Chapter position and vertical scrollbar position
|
# Chapter position and vertical scrollbar position
|
||||||
@@ -307,13 +293,42 @@ class Tab(QtWidgets.QWidget):
|
|||||||
|
|
||||||
chapter_name = list(self.metadata['content'])[current_chapter - 1]
|
chapter_name = list(self.metadata['content'])[current_chapter - 1]
|
||||||
chapter_content = self.metadata['content'][chapter_name]
|
chapter_content = self.metadata['content'][chapter_name]
|
||||||
self.contentView.setSearchPaths(relative_paths)
|
|
||||||
self.contentView.setOpenLinks(False) # Change this when HTML navigation works
|
# The content display widget is, by default a QTextBrowser
|
||||||
self.contentView.setHtml(chapter_content)
|
# In case the incoming data is only images
|
||||||
|
# such as in the case of comic book files,
|
||||||
|
# we want a QGraphicsView widget doing all the heavy lifting
|
||||||
|
# instead of a QTextBrowser
|
||||||
|
self.are_we_doing_images_only = self.metadata['images_only']
|
||||||
|
|
||||||
|
if self.are_we_doing_images_only: # Boolean
|
||||||
|
self.contentView = PliantQGraphicsView(self.window())
|
||||||
|
self.contentView.loadImage(chapter_content)
|
||||||
|
self.setStyleSheet("background-color: black;")
|
||||||
|
else:
|
||||||
|
self.contentView = PliantQTextBrowser(self.window())
|
||||||
|
|
||||||
|
relative_path_root = self.metadata['temp_dir']
|
||||||
|
relative_paths = []
|
||||||
|
for i in os.walk(relative_path_root):
|
||||||
|
relative_paths.append(os.path.join(relative_path_root, i[0]))
|
||||||
|
self.contentView.setSearchPaths(relative_paths)
|
||||||
|
|
||||||
|
self.contentView.setOpenLinks(False) # Change this when HTML navigation works
|
||||||
|
self.contentView.setHtml(chapter_content)
|
||||||
|
|
||||||
|
# The following are common to both the text browser and
|
||||||
|
# the graphics view
|
||||||
|
self.contentView.setFrameShape(QtWidgets.QFrame.NoFrame)
|
||||||
|
self.contentView.setObjectName("contentView")
|
||||||
|
self.contentView.verticalScrollBar().setSingleStep(7)
|
||||||
|
self.contentView.setHorizontalScrollBarPolicy(
|
||||||
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
|
||||||
self.generate_keyboard_shortcuts()
|
self.generate_keyboard_shortcuts()
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.contentView, 0, 0, 1, 1)
|
self.gridLayout.addWidget(self.contentView, 0, 0, 1, 1)
|
||||||
|
title = self.metadata['title']
|
||||||
self.parent.addTab(self, title)
|
self.parent.addTab(self, title)
|
||||||
|
|
||||||
def generate_position(self):
|
def generate_position(self):
|
||||||
@@ -352,40 +367,116 @@ class Tab(QtWidgets.QWidget):
|
|||||||
# self.exit_all.activated.connect(self.sneaky_exit)
|
# self.exit_all.activated.connect(self.sneaky_exit)
|
||||||
|
|
||||||
def exit_fullscreen(self):
|
def exit_fullscreen(self):
|
||||||
|
self.window().show()
|
||||||
self.contentView.setWindowFlags(QtCore.Qt.Widget)
|
self.contentView.setWindowFlags(QtCore.Qt.Widget)
|
||||||
self.contentView.setWindowState(QtCore.Qt.WindowNoState)
|
self.contentView.setWindowState(QtCore.Qt.WindowNoState)
|
||||||
self.contentView.show()
|
self.contentView.show()
|
||||||
self.window().show()
|
|
||||||
|
def chapter_change(self):
|
||||||
|
chapter_name = self.window().bookToolBar.tocBox.currentText()
|
||||||
|
required_content = self.metadata['content'][chapter_name]
|
||||||
|
|
||||||
|
if self.are_we_doing_images_only:
|
||||||
|
self.contentView.loadImage(required_content)
|
||||||
|
else:
|
||||||
|
self.contentView.clear()
|
||||||
|
self.contentView.setHtml(required_content)
|
||||||
|
|
||||||
|
def format_view(self, font, font_size, foreground, background, padding):
|
||||||
|
self.contentView.setViewportMargins(padding, 0, padding, 0)
|
||||||
|
|
||||||
|
if self.are_we_doing_images_only:
|
||||||
|
self.contentView.setBackgroundBrush(
|
||||||
|
QtGui.QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern))
|
||||||
|
else:
|
||||||
|
self.contentView.setStyleSheet(
|
||||||
|
"QTextEdit {{font-family: {0}; font-size: {1}px; color: {2}; background-color: {3}}}".format(
|
||||||
|
font, font_size, foreground, background))
|
||||||
|
|
||||||
def sneaky_change(self):
|
def sneaky_change(self):
|
||||||
direction = -1
|
direction = -1
|
||||||
if self.sender().objectName() == 'nextChapter':
|
if self.sender().objectName() == 'nextChapter':
|
||||||
direction = 1
|
direction = 1
|
||||||
|
|
||||||
self.contentView.change_chapter(direction, True)
|
self.contentView.common_functions.change_chapter(
|
||||||
|
direction, True)
|
||||||
|
|
||||||
def sneaky_exit(self):
|
def sneaky_exit(self):
|
||||||
self.contentView.hide()
|
self.contentView.hide()
|
||||||
self.window().closeEvent()
|
self.window().closeEvent()
|
||||||
|
|
||||||
|
|
||||||
|
class PliantQGraphicsView(QtWidgets.QGraphicsView):
|
||||||
|
def __init__(self, main_window, parent=None):
|
||||||
|
super(PliantQGraphicsView, self).__init__(parent)
|
||||||
|
self.main_window = main_window
|
||||||
|
self.image_pixmap = None
|
||||||
|
self.ignore_wheel_event = False
|
||||||
|
self.ignore_wheel_event_number = 0
|
||||||
|
self.common_functions = PliantWidgetsCommonFunctions(self, self.main_window)
|
||||||
|
|
||||||
|
def loadImage(self, image_path):
|
||||||
|
self.image_pixmap = QtGui.QPixmap()
|
||||||
|
self.image_pixmap.load(image_path)
|
||||||
|
self.resizeEvent()
|
||||||
|
|
||||||
|
def resizeEvent(self, event=None):
|
||||||
|
if not self.image_pixmap:
|
||||||
|
return
|
||||||
|
|
||||||
|
profile_index = self.main_window.bookToolBar.profileBox.currentIndex()
|
||||||
|
current_profile = self.main_window.bookToolBar.profileBox.itemData(
|
||||||
|
profile_index, QtCore.Qt.UserRole)
|
||||||
|
padding = current_profile['padding']
|
||||||
|
|
||||||
|
available_width = self.viewport().width() - 2 * padding
|
||||||
|
|
||||||
|
if self.image_pixmap.width() > available_width:
|
||||||
|
image_pixmap = self.image_pixmap.scaledToWidth(
|
||||||
|
available_width, QtCore.Qt.SmoothTransformation)
|
||||||
|
else:
|
||||||
|
image_pixmap = self.image_pixmap
|
||||||
|
|
||||||
|
graphics_scene = QtWidgets.QGraphicsScene()
|
||||||
|
graphics_scene.addPixmap(image_pixmap)
|
||||||
|
|
||||||
|
self.setScene(graphics_scene)
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def wheelEvent(self, event):
|
||||||
|
self.common_functions.wheelEvent(event, True)
|
||||||
|
|
||||||
|
|
||||||
class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
||||||
def __init__(self, main_window, parent=None):
|
def __init__(self, main_window, parent=None):
|
||||||
super(PliantQTextBrowser, self).__init__(parent)
|
super(PliantQTextBrowser, self).__init__(parent)
|
||||||
self.main_window = main_window
|
self.main_window = main_window
|
||||||
self.ignore_wheel_event = False
|
self.ignore_wheel_event = False
|
||||||
self.ignore_wheel_event_number = 0
|
self.ignore_wheel_event_number = 0
|
||||||
|
self.common_functions = PliantWidgetsCommonFunctions(self, self.main_window)
|
||||||
|
|
||||||
def wheelEvent(self, event):
|
def wheelEvent(self, event):
|
||||||
if self.ignore_wheel_event:
|
self.common_functions.wheelEvent(event, False)
|
||||||
|
|
||||||
|
|
||||||
|
class PliantWidgetsCommonFunctions():
|
||||||
|
def __init__(self, parent_widget, main_window):
|
||||||
|
self.pw = parent_widget
|
||||||
|
self.main_window = main_window
|
||||||
|
|
||||||
|
def wheelEvent(self, event, are_we_doing_images_only):
|
||||||
|
if self.pw.ignore_wheel_event:
|
||||||
# Ignore first n wheel events after a chapter change
|
# Ignore first n wheel events after a chapter change
|
||||||
self.ignore_wheel_event_number += 1
|
self.pw.ignore_wheel_event_number += 1
|
||||||
if self.ignore_wheel_event_number > 20:
|
if self.pw.ignore_wheel_event_number > 20:
|
||||||
self.ignore_wheel_event = False
|
self.pw.ignore_wheel_event = False
|
||||||
self.ignore_wheel_event_number = 0
|
self.pw.ignore_wheel_event_number = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
QtWidgets.QTextBrowser.wheelEvent(self, event)
|
if are_we_doing_images_only:
|
||||||
|
QtWidgets.QGraphicsView.wheelEvent(self.pw, event)
|
||||||
|
else:
|
||||||
|
QtWidgets.QTextBrowser.wheelEvent(self.pw, event)
|
||||||
|
|
||||||
# Since this is a delta on a mouse move event, it cannot ever be 0
|
# Since this is a delta on a mouse move event, it cannot ever be 0
|
||||||
vertical_pdelta = event.pixelDelta().y()
|
vertical_pdelta = event.pixelDelta().y()
|
||||||
@@ -396,19 +487,19 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
|
|
||||||
if abs(vertical_pdelta) > 100: # Adjust sensitivity here
|
if abs(vertical_pdelta) > 100: # Adjust sensitivity here
|
||||||
# Implies that no scrollbar movement is possible
|
# Implies that no scrollbar movement is possible
|
||||||
if self.verticalScrollBar().value() == self.verticalScrollBar().maximum() == 0:
|
if self.pw.verticalScrollBar().value() == self.pw.verticalScrollBar().maximum() == 0:
|
||||||
if moving_up:
|
if moving_up:
|
||||||
self.change_chapter(-1)
|
self.change_chapter(-1)
|
||||||
else:
|
else:
|
||||||
self.change_chapter(1)
|
self.change_chapter(1)
|
||||||
|
|
||||||
# Implies that the scrollbar is at the bottom
|
# Implies that the scrollbar is at the bottom
|
||||||
elif self.verticalScrollBar().value() == self.verticalScrollBar().maximum():
|
elif self.pw.verticalScrollBar().value() == self.pw.verticalScrollBar().maximum():
|
||||||
if not moving_up:
|
if not moving_up:
|
||||||
self.change_chapter(1)
|
self.change_chapter(1)
|
||||||
|
|
||||||
# Implies scrollbar is at the top
|
# Implies scrollbar is at the top
|
||||||
elif self.verticalScrollBar().value() == 0:
|
elif self.pw.verticalScrollBar().value() == 0:
|
||||||
if moving_up:
|
if moving_up:
|
||||||
self.change_chapter(-1)
|
self.change_chapter(-1)
|
||||||
|
|
||||||
@@ -422,12 +513,12 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
|
|||||||
|
|
||||||
# Set page position depending on if the chapter number is increasing or decreasing
|
# Set page position depending on if the chapter number is increasing or decreasing
|
||||||
if direction == 1 or was_button_pressed:
|
if direction == 1 or was_button_pressed:
|
||||||
self.verticalScrollBar().setValue(0)
|
self.pw.verticalScrollBar().setValue(0)
|
||||||
else:
|
else:
|
||||||
self.verticalScrollBar().setValue(
|
self.pw.verticalScrollBar().setValue(
|
||||||
self.verticalScrollBar().maximum())
|
self.pw.verticalScrollBar().maximum())
|
||||||
|
|
||||||
self.ignore_wheel_event = True
|
self.pw.ignore_wheel_event = True
|
||||||
|
|
||||||
|
|
||||||
class LibraryDelegate(QtWidgets.QStyledItemDelegate):
|
class LibraryDelegate(QtWidgets.QStyledItemDelegate):
|
||||||
|
Reference in New Issue
Block a user