Only add page break before first line of a heading in PDF and preview (#2415)
This commit is contained in:
@@ -40,8 +40,9 @@ from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, s
|
|||||||
from novelwriter.formats.tokenizer import HEADINGS, Tokenizer
|
from novelwriter.formats.tokenizer import HEADINGS, Tokenizer
|
||||||
from novelwriter.types import (
|
from novelwriter.types import (
|
||||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
||||||
QtKeepAnchor, QtMoveAnchor, QtPageBreakAfter, QtPageBreakBefore,
|
QtKeepAnchor, QtMoveAnchor, QtPageBreakAfter, QtPageBreakAuto,
|
||||||
QtPropLineHeight, QtTransparent, QtVAlignNormal, QtVAlignSub, QtVAlignSuper
|
QtPageBreakBefore, QtPropLineHeight, QtTransparent, QtVAlignNormal,
|
||||||
|
QtVAlignSub, QtVAlignSuper
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -253,8 +254,10 @@ class ToQTextDocument(Tokenizer):
|
|||||||
|
|
||||||
elif tType in HEADINGS:
|
elif tType in HEADINGS:
|
||||||
bFmt, cFmt = self._genHeadStyle(tType, tMeta, bFmt)
|
bFmt, cFmt = self._genHeadStyle(tType, tMeta, bFmt)
|
||||||
newBlock(cursor, bFmt)
|
for tPart in tText.split("\n"):
|
||||||
cursor.insertText(tText, cFmt)
|
newBlock(cursor, bFmt)
|
||||||
|
cursor.insertText(tPart, cFmt)
|
||||||
|
bFmt.setPageBreakPolicy(QtPageBreakAuto)
|
||||||
|
|
||||||
elif tType == BlockTyp.SEP:
|
elif tType == BlockTyp.SEP:
|
||||||
newBlock(cursor, bFmt)
|
newBlock(cursor, bFmt)
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ QtVAlignSuper = QTextCharFormat.VerticalAlignment.AlignSuperScript
|
|||||||
|
|
||||||
QtPageBreakBefore = QTextFormat.PageBreakFlag.PageBreak_AlwaysBefore
|
QtPageBreakBefore = QTextFormat.PageBreakFlag.PageBreak_AlwaysBefore
|
||||||
QtPageBreakAfter = QTextFormat.PageBreakFlag.PageBreak_AlwaysAfter
|
QtPageBreakAfter = QTextFormat.PageBreakFlag.PageBreak_AlwaysAfter
|
||||||
|
QtPageBreakAuto = QTextFormat.PageBreakFlag.PageBreak_Auto
|
||||||
|
|
||||||
QtPropLineHeight = 1 # QTextBlockFormat.LineHeightTypes.ProportionalHeight
|
QtPropLineHeight = 1 # QTextBlockFormat.LineHeightTypes.ProportionalHeight
|
||||||
|
|
||||||
|
|||||||
@@ -25,14 +25,15 @@ import pytest
|
|||||||
from PyQt6.QtGui import QFont, QTextBlock, QTextCharFormat, QTextCursor
|
from PyQt6.QtGui import QFont, QTextBlock, QTextCharFormat, QTextCursor
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.constants import nwUnicode
|
from novelwriter.constants import nwHeadFmt, nwUnicode
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.enum import nwComment
|
from novelwriter.enum import nwComment
|
||||||
from novelwriter.formats.shared import BlockFmt, BlockTyp, TextDocumentTheme
|
from novelwriter.formats.shared import BlockFmt, BlockTyp, TextDocumentTheme
|
||||||
from novelwriter.formats.toqdoc import ToQTextDocument
|
from novelwriter.formats.toqdoc import ToQTextDocument
|
||||||
from novelwriter.types import (
|
from novelwriter.types import (
|
||||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
||||||
QtPageBreakAfter, QtTransparent, QtVAlignNormal, QtVAlignSub, QtVAlignSuper
|
QtPageBreakAfter, QtPageBreakAuto, QtPageBreakBefore, QtTransparent,
|
||||||
|
QtVAlignNormal, QtVAlignSub, QtVAlignSuper
|
||||||
)
|
)
|
||||||
|
|
||||||
THEME = TextDocumentTheme()
|
THEME = TextDocumentTheme()
|
||||||
@@ -54,6 +55,11 @@ def testFmtToQTextDocument_ConvertHeaders(mockGUI):
|
|||||||
|
|
||||||
doc._isNovel = True
|
doc._isNovel = True
|
||||||
doc._isFirst = True
|
doc._isFirst = True
|
||||||
|
|
||||||
|
# Add a line break in chapter header format, see #2415
|
||||||
|
doc.setChapterFormat(f"{nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
|
||||||
|
|
||||||
|
# Populate
|
||||||
doc._text = (
|
doc._text = (
|
||||||
"#! Title\n"
|
"#! Title\n"
|
||||||
"# Partition\n"
|
"# Partition\n"
|
||||||
@@ -63,12 +69,13 @@ def testFmtToQTextDocument_ConvertHeaders(mockGUI):
|
|||||||
)
|
)
|
||||||
doc.tokenizeText()
|
doc.tokenizeText()
|
||||||
doc.doConvert()
|
doc.doConvert()
|
||||||
assert doc.document.blockCount() == 5
|
assert doc.document.blockCount() == 6
|
||||||
|
|
||||||
# Title
|
# Title
|
||||||
block = doc.document.findBlockByNumber(0)
|
block = doc.document.findBlockByNumber(0)
|
||||||
assert block.text() == "Title"
|
assert block.text() == "Title"
|
||||||
bFmt = block.blockFormat()
|
bFmt = block.blockFormat()
|
||||||
|
assert bFmt.pageBreakPolicy() == QtPageBreakAuto # Expected on first title
|
||||||
assert bFmt.topMargin() == doc._mHead[BlockTyp.TITLE][0]
|
assert bFmt.topMargin() == doc._mHead[BlockTyp.TITLE][0]
|
||||||
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.TITLE][1]
|
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.TITLE][1]
|
||||||
cFmt = charFmtInBlock(block, 1)
|
cFmt = charFmtInBlock(block, 1)
|
||||||
@@ -87,10 +94,23 @@ def testFmtToQTextDocument_ConvertHeaders(mockGUI):
|
|||||||
assert cFmt.fontPointSize() == doc._sHead[BlockTyp.PART]
|
assert cFmt.fontPointSize() == doc._sHead[BlockTyp.PART]
|
||||||
assert cFmt.foreground().color() == THEME.head
|
assert cFmt.foreground().color() == THEME.head
|
||||||
|
|
||||||
# Chapter
|
# Chapter, Line 1
|
||||||
block = doc.document.findBlockByNumber(2)
|
block = doc.document.findBlockByNumber(2)
|
||||||
|
assert block.text() == "1"
|
||||||
|
bFmt = block.blockFormat()
|
||||||
|
assert bFmt.pageBreakPolicy() == QtPageBreakBefore
|
||||||
|
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD1][0]
|
||||||
|
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD1][1]
|
||||||
|
cFmt = charFmtInBlock(block, 1)
|
||||||
|
assert cFmt.fontWeight() == QFont.Weight.Bold
|
||||||
|
assert cFmt.fontPointSize() == doc._sHead[BlockTyp.HEAD1]
|
||||||
|
assert cFmt.foreground().color() == THEME.head
|
||||||
|
|
||||||
|
# Chapter, Line 2
|
||||||
|
block = doc.document.findBlockByNumber(3)
|
||||||
assert block.text() == "Chapter"
|
assert block.text() == "Chapter"
|
||||||
bFmt = block.blockFormat()
|
bFmt = block.blockFormat()
|
||||||
|
assert bFmt.pageBreakPolicy() == QtPageBreakAuto # Important! See #2415
|
||||||
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD1][0]
|
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD1][0]
|
||||||
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD1][1]
|
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD1][1]
|
||||||
cFmt = charFmtInBlock(block, 1)
|
cFmt = charFmtInBlock(block, 1)
|
||||||
@@ -99,9 +119,10 @@ def testFmtToQTextDocument_ConvertHeaders(mockGUI):
|
|||||||
assert cFmt.foreground().color() == THEME.head
|
assert cFmt.foreground().color() == THEME.head
|
||||||
|
|
||||||
# Scene
|
# Scene
|
||||||
block = doc.document.findBlockByNumber(3)
|
block = doc.document.findBlockByNumber(4)
|
||||||
assert block.text() == "Scene"
|
assert block.text() == "Scene"
|
||||||
bFmt = block.blockFormat()
|
bFmt = block.blockFormat()
|
||||||
|
assert bFmt.pageBreakPolicy() == QtPageBreakAuto
|
||||||
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD2][0]
|
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD2][0]
|
||||||
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD2][1]
|
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD2][1]
|
||||||
cFmt = charFmtInBlock(block, 1)
|
cFmt = charFmtInBlock(block, 1)
|
||||||
@@ -110,9 +131,10 @@ def testFmtToQTextDocument_ConvertHeaders(mockGUI):
|
|||||||
assert cFmt.foreground().color() == THEME.head
|
assert cFmt.foreground().color() == THEME.head
|
||||||
|
|
||||||
# Section
|
# Section
|
||||||
block = doc.document.findBlockByNumber(4)
|
block = doc.document.findBlockByNumber(5)
|
||||||
assert block.text() == "Section"
|
assert block.text() == "Section"
|
||||||
bFmt = block.blockFormat()
|
bFmt = block.blockFormat()
|
||||||
|
assert bFmt.pageBreakPolicy() == QtPageBreakAuto
|
||||||
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD3][0]
|
assert bFmt.topMargin() == doc._mHead[BlockTyp.HEAD3][0]
|
||||||
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD3][1]
|
assert bFmt.bottomMargin() == doc._mHead[BlockTyp.HEAD3][1]
|
||||||
cFmt = charFmtInBlock(block, 1)
|
cFmt = charFmtInBlock(block, 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user