Keeping a heading with next paragraph in QTextDocument

275 Views Asked by At

I'm learning how to use QTextDocument in PySide6, and it seems to have most features for displaying rich text, but I can't see how to keep a heading with the next paragraph.

In this example, "Heading 13" is at the bottom of page 2 and its following paragraph is at the top of page 3. How can I move "Heading 13" to page 3 so they stay together? A page break in the middle of a paragraph doesn't bother me, I just don't like a heading all by itself.

from PySide6.QtGui import QPdfWriter, QPageSize, QTextDocument, QTextCursor
from PySide6.QtWidgets import QApplication


app = QApplication()
pdf = QPdfWriter('example.pdf')
pdf.setPageSize(QPageSize.Letter)

document = QTextDocument()
cursor = QTextCursor(document)
cursor.insertHtml('<h1>Title</h1>')
for i in range(1, 21):
    cursor.insertText('\n')
    cursor.insertHtml(f'<h3>Heading {i}</h3>')
    cursor.insertText('\n')
    cursor.insertHtml('<p>Lorem ipsum dolor sit amet, consectetur '
                      'adipiscing elit. Aliquam sed congue mauris. '
                      'Curabitur a lobortis odio. Maecenas non metus id '
                      'sapien congue sagittis quis ac ipsum. Sed ut '
                      'tincidunt ex. Proin sed neque at nunc sollicitudin '
                      'sagittis eget molestie mauris. Integer condimentum '
                      'lacus quis enim scelerisque, at cursus orci porta. '
                      'Aenean non tellus arcu. Sed quis odio turpis. '
                      'Vivamus facilisis.</p>')
document.print_(pdf)
1

There are 1 best solutions below

3
Haru On

For example, do you want to do like this?

import PySide6
from PySide6.QtGui import QPdfWriter, QPageSize, QTextDocument, QTextCursor
from PySide6.QtWidgets import QApplication
import sys, os, re
dirname  =  os.path.dirname(PySide6.__file__)
plugin_path  =  os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH']  =  plugin_path
app = QApplication()
pdf = QPdfWriter('example.pdf')
pdf.setPageSize(QPageSize.Letter)
  
document = QTextDocument()
cursor = QTextCursor(document)
cursor.insertHtml('<h1>Title</h1>')
    
document.setPageSize(QPageSize.size(QPageSize.A4, QPageSize.Point))
pagesize = document.pageSize()
pagecount = 0
bottom = 0
average_height = 0
pagebreak = False
for i in range(1, 21):
    firstinsert_rect = document.documentLayout().blockBoundingRect(document.findBlockByNumber(cursor.block().blockNumber()))
    pagecount = int(document.documentLayout().blockBoundingRect(document.findBlockByNumber(cursor.block().blockNumber())).y()/pagesize.height()) + 1
    if pagecount != int((bottom + average_height)/pagesize.height()) + 1:
        bf = cursor.blockFormat()
        bf.setPageBreakPolicy(bf.PageBreak_AlwaysAfter)
        cursor.setBlockFormat(bf)
        pagebreak = True
    cursor.insertText('\n')
    if pagebreak:
        pagebreak = False
        bf = cursor.blockFormat()
        bf.setPageBreakPolicy(bf.PageBreak_Auto)
        cursor.setBlockFormat(bf)
    cursor.insertHtml(f'<h3>Heading {i}</h3>')
    cursor.insertText('\n')
    cursor.insertHtml('<p>Lorem ipsum dolor sit amet, consectetur '
                          'adipiscing elit. Aliquam sed congue mauris. '
                          'Curabitur a lobortis odio. Maecenas non metus id '
                          'sapien congue sagittis quis ac ipsum. Sed ut '
                          'tincidunt ex. Proin sed neque at nunc sollicitudin '
                          'sagittis eget molestie mauris. Integer condimentum '
                          'lacus quis enim scelerisque, at cursus orci porta. '
                          'Aenean non tellus arcu. Sed quis odio turpis. '
                          'Vivamus facilisis.</p>')
    lastinsert_rect = document.documentLayout().blockBoundingRect(document.findBlockByNumber(cursor.block().blockNumber()))
    average_height = lastinsert_rect.bottom() - firstinsert_rect.y()
    bottom = lastinsert_rect.bottom()
        
document.print_(pdf)