Implement text pagination

Start double page mode
This commit is contained in:
BasioMeusPuga
2019-04-01 22:25:09 -04:00
parent af1b988d93
commit 0aea9ec33b
9 changed files with 8993 additions and 8157 deletions

View File

@@ -465,6 +465,18 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
self.parent = parent
self.main_window = main_window
# Available modes:
# flow - default
# singlePage
# doublePage
self.text_mode = 'flow'
# New pages will be generated following a resize
# This is timed so as not to drive the processor nuts
self.resizeTimer = QtCore.QTimer()
self.resizeTimer.setSingleShot(True)
self.resizeTimer.timeout.connect(self.create_pages)
self.annotation_mode = False
self.annotator = AnnotationPlacement()
self.current_annotation = None
@@ -485,14 +497,25 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
self.ignore_wheel_event_number = 0
self.at_end = False
self.page_cursors = []
self.page_number = 0
def wheelEvent(self, event):
if self.text_mode in ('singlePage', 'doublePage'):
vertical_pdelta = event.pixelDelta().y()
direction = -1
if vertical_pdelta < 0:
direction = 1
self.turn_page(direction)
return
self.record_position()
self.common_functions.wheelEvent(event)
def keyPressEvent(self, event):
QtWidgets.QTextEdit.keyPressEvent(self, event)
if event.key() == QtCore.Qt.Key_Space:
QtWidgets.QTextEdit.keyPressEvent(self, event)
if self.verticalScrollBar().value() == self.verticalScrollBar().maximum():
if self.at_end: # This makes sure the last lines of the chapter don't get skipped
self.common_functions.change_chapter(1, True)
@@ -500,15 +523,132 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
else:
self.at_end = False
self.set_top_line_cleanly()
self.record_position()
return
if self.text_mode == 'singlePage':
if event.key() == QtCore.Qt.Key_Down:
self.turn_page(1)
if event.key() == QtCore.Qt.Key_Up:
self.turn_page(-1)
self.record_position()
return
QtWidgets.QTextEdit.keyPressEvent(self, event)
def move_to_cursor(self, cursor):
self.setTextCursor(cursor)
self.verticalScrollBar().setValue(
self.verticalScrollBar().maximum())
self.ensureCursorVisible()
def set_top_line_cleanly(self):
# Find the cursor position of the top line and move to it
find_cursor = self.cursorForPosition(QtCore.QPoint(0, 0))
find_cursor.movePosition(
find_cursor.position(), QtGui.QTextCursor.KeepAnchor)
self.setTextCursor(find_cursor)
self.ensureCursorVisible()
cursorTop = self.cursorForPosition(QtCore.QPoint(0, 0))
self.move_to_cursor(cursorTop)
def resizeEvent(self, event=None):
QtWidgets.QTextBrowser.resizeEvent(self, event)
self.resizeTimer.start(100)
def create_pages(self, text_mode=None):
# Return to this value after page calcuation is done
cursorTop = self.cursorForPosition(QtCore.QPoint(0, 0))
# No changes in mode
# if text_mode == self.text_mode:
# return
# Account for resizeEvent
if not text_mode:
if self.text_mode == 'flow':
return
text_mode = self.text_mode
# Single Page mode
page_width = self.viewport().size().width()
page_height = self.viewport().size().height()
# Flow mode
if text_mode == 'flow':
page_height = -1
# TODO
# See what's an appropriate value to pad the text with
# profile_index = self.bookToolBar.profileBox.currentIndex()
# current_profile = self.bookToolBar.profileBox.itemData(
# profile_index, QtCore.Qt.UserRole)
# padding = 20
# Double page mode
if text_mode == 'doublePage':
page_width = page_width // 2 - 10
self.text_mode = text_mode
self.document().setPageSize(
QtCore.QSizeF(page_width, page_height))
self.generate_page_positions()
self.set_page(cursorTop)
def generate_page_positions(self):
self.verticalScrollBar().setValue(0)
cursorEnd = QtGui.QTextCursor(self.document())
cursorEnd.movePosition(QtGui.QTextCursor.End)
self.page_cursors = []
while True:
cursorTopLeft = self.cursorForPosition(
self.viewport().rect().topLeft())
cursorBottomLeft = self.cursorForPosition(
self.viewport().rect().bottomLeft())
cursorBottomRight = self.cursorForPosition(
self.viewport().rect().bottomRight())
self.page_cursors.append(
(cursorTopLeft.position(), cursorBottomRight.position()))
self.move_to_cursor(cursorBottomRight)
# TODO
# See if this requires a failsafe per number of iterations
if cursorEnd.position() == cursorBottomRight.position():
break
def set_page(self, originalCursor):
required_position = originalCursor.position()
if self.text_mode == 'flow':
page_start = required_position
if self.text_mode == 'singlePage':
for count, i in enumerate(self.page_cursors):
if i[0] <= required_position < i[1]:
page_start = i[0]
self.page_number = count
break
cursorGoTo = QtGui.QTextCursor(self.document())
cursorGoTo.setPosition(page_start)
self.move_to_cursor(cursorGoTo)
def turn_page(self, direction):
self.page_number += direction
if self.page_number in (-1, self.document().pageCount()):
self.page_number = 0
self.common_functions.change_chapter(direction)
self.create_pages()
else:
try:
page_start = self.page_cursors[self.page_number][0]
cursorGoTo = QtGui.QTextCursor(self.document())
cursorGoTo.setPosition(page_start)
self.move_to_cursor(cursorGoTo)
self.set_top_line_cleanly()
except IndexError:
pass
def record_position(self, return_as_bookmark=False):
self.parent.metadata['position']['is_read'] = False
@@ -617,8 +757,26 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
searchWikipediaAction = searchYoutubeAction = 'Does anyone know something funny in Latin?'
searchAction = searchGoogleAction = bookmarksToggleAction = 'TODO Insert Latin Joke'
deleteAnnotationAction = editAnnotationNoteAction = 'Latin quote 2. Electric Boogaloo.'
flowModeAction = singlePageAction = doublePageAction = 'We know the rules, you and I'
annotationActions = []
view_submenu_string = self._translate('PliantQTextBrowser', 'View')
viewSubMenu = contextMenu.addMenu(view_submenu_string)
viewSubMenu.setIcon(
self.main_window.QImageFactory.get_image('mail-thread-watch'))
flowModeAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('page-flow'),
self._translate('PliantQTextBrowser', 'Flow text'))
singlePageAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('page-single'),
self._translate('PliantQTextBrowser', 'Single page'))
doublePageAction = viewSubMenu.addAction(
self.main_window.QImageFactory.get_image('page-double'),
self._translate('PliantQTextBrowser', 'Double page'))
if self.parent.is_fullscreen:
fsToggleAction = contextMenu.addAction(
self.main_window.QImageFactory.get_image('view-fullscreen'),
@@ -709,6 +867,15 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
action = contextMenu.exec_(self.sender().mapToGlobal(position))
if action == flowModeAction:
self.create_pages('flow')
if action == singlePageAction:
self.create_pages('singlePage')
if action == doublePageAction:
self.create_pages('doublePages')
if action == addBookMarkAction:
self.parent.sideDock.bookmarks.add_bookmark(cursor_at_mouse.position())
@@ -793,6 +960,8 @@ class PliantWidgetsCommonFunctions:
self.pw.ignore_wheel_event_number = 0
return
# TODO
# This can probably be cleaned up
if self.are_we_doing_images_only:
QtWidgets.QGraphicsView.wheelEvent(self.pw, event)
else:

View File

@@ -1,8 +1,62 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
viewBox="0 0 22 22"
version="1.1"
id="svg7"
sodipodi:docname="page-double.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata11">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1043"
id="namedview9"
showgrid="false"
inkscape:zoom="10.727273"
inkscape:cx="11"
inkscape:cy="11"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<defs
id="defs3">
<style
id="current-color-scheme"
type="text/css">
.ColorScheme-Text { color:#444444; } .ColorScheme-Highlight { color:#4285f4; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 2 1 L 2 15 L 14 15 L 14 1 L 2 1 z M 4 3 L 12 3 L 12 13 L 4 13 L 4 3 z" transform="translate(4 4)"/>
</defs>
<path
style="fill:#5c616c;fill-opacity:1"
class="ColorScheme-Text"
d="M 1 1 L 1 15 L 15 15 L 15 1 L 1 1 z M 3 3 L 7 3 L 7 13 L 3 13 L 3 3 z M 9 3 L 13 3 L 13 13 L 9 13 L 9 3 z"
transform="translate(3 3)"
id="path5" />
</svg>

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
viewBox="0 0 22 22"
version="1.1"
id="svg7"
sodipodi:docname="page-flow.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata11">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1043"
id="namedview9"
showgrid="false"
inkscape:zoom="15.170655"
inkscape:cx="-1.2825494"
inkscape:cy="5.330307"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<defs
id="defs3">
<style
id="current-color-scheme"
type="text/css">
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; }
</style>
</defs>
<path
style="fill:#5c616c;fill-opacity:1"
class="ColorScheme-Text"
d="M 2 1 L 2 15 L 14 15 L 14 1 L 2 1 z M 4 3 L 12 3 L 12 13 L 4 13 L 4 3 z"
transform="translate(3 3)"
id="path5" />
<g
transform="matrix(0.64844409,0,0,0.64844409,5.8379769,5.8670545)"
id="g7"
style="fill:#5c616c;fill-opacity:1">
<path
inkscape:connector-curvature="0"
class="ColorScheme-Text"
d="m 7,2 v 8 L 3.5,6.5 2,8 8,14 14,8 12.5,6.5 9,10 V 2 Z"
style="color:#dfdfdf;fill:#5c616c;fill-opacity:1"
id="path5-3" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 2 1 L 2 15 L 14 15 L 14 1 L 2 1 z M 4 3 L 12 3 L 12 13 L 4 13 L 4 3 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 416 B

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
viewBox="0 0 22 22"
version="1.1"
id="svg7"
sodipodi:docname="page-flow.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata11">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1043"
id="namedview9"
showgrid="false"
inkscape:zoom="15.170655"
inkscape:cx="-1.2825494"
inkscape:cy="5.330307"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<defs
id="defs3">
<style
id="current-color-scheme"
type="text/css">
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; }
</style>
</defs>
<path
style="fill:currentColor"
class="ColorScheme-Text"
d="M 2 1 L 2 15 L 14 15 L 14 1 L 2 1 z M 4 3 L 12 3 L 12 13 L 4 13 L 4 3 z"
transform="translate(3 3)"
id="path5" />
<g
transform="matrix(0.64844409,0,0,0.64844409,5.8379769,5.8670545)"
id="g7">
<path
inkscape:connector-curvature="0"
class="ColorScheme-Text"
d="m 7,2 v 8 L 3.5,6.5 2,8 8,14 14,8 12.5,6.5 9,10 V 2 Z"
style="color:#dfdfdf;fill:currentColor"
id="path5-3" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#dfdfdf; } .ColorScheme-Highlight { color:#4285f4; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 2 1 L 2 15 L 14 15 L 14 1 L 2 1 z M 4 3 L 12 3 L 12 13 L 4 13 L 4 3 z" transform="translate(3 3)"/>
</svg>

After

Width:  |  Height:  |  Size: 416 B

View File

@@ -14,7 +14,11 @@
<file>LightIcons/search-word.svg</file>
<file>LightIcons/search-case.svg</file>
<file>DarkIcons/page-double.svg</file>
<file>DarkIcons/page-single.svg</file>
<file>DarkIcons/page-flow.svg</file>
<file>LightIcons/page-double.svg</file>
<file>LightIcons/page-single.svg</file>
<file>LightIcons/page-flow.svg</file>
<file>DarkIcons/about.svg</file>
<file>DarkIcons/switches.svg</file>
<file>LightIcons/about.svg</file>

File diff suppressed because it is too large Load Diff