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

6
TODO
View File

@@ -97,19 +97,19 @@ TODO
✓ Define every widget in code
Bugs:
Deselecting all directories in the settings dialog also filters out manually added books
Last line in QTextBrowser should never be cut off
Bookmark name for a page that's not on the TOC and has nothing before
Screen position still keeps jumping when inside a paragraph
Better recursion needed for fb2 toc
Search results should ignore punctuation
Keep text size for annotations
Sort by new is not working
Drag and drop is acting out
Search and annotation buttons become visible when font settings are hidden in comics
Secondary:
Auto switch between flow and single page mode
Text to speech
Definitions dialog needs to respond to escape
Zoom slider for comics
Zoom slider for comics / library
Tab tooltip
Additional Settings:
Find definitions on Google

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