Add text paragraph formatting
This commit is contained in:
@@ -26,8 +26,8 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QFont, QFontMetrics, QTextBlockFormat, QTextCharFormat, QTextCursor,
|
QColor, QFont, QFontMetrics, QTextBlockFormat, QTextCharFormat,
|
||||||
QTextDocument
|
QTextCursor, QTextDocument
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter import SHARED
|
from novelwriter import SHARED
|
||||||
@@ -36,13 +36,13 @@ from novelwriter.core.project import NWProject
|
|||||||
from novelwriter.core.tokenizer import T_Formats, Tokenizer
|
from novelwriter.core.tokenizer import T_Formats, Tokenizer
|
||||||
from novelwriter.types import (
|
from novelwriter.types import (
|
||||||
QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight, QtPageBreakAfter,
|
QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight, QtPageBreakAfter,
|
||||||
QtPageBreakBefore
|
QtPageBreakBefore, QtTransparent, QtVAlignNormal, QtVAlignSub,
|
||||||
|
QtVAlignSuper
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
T_TextStyle = tuple[QTextBlockFormat, QTextCharFormat]
|
T_TextStyle = tuple[QTextBlockFormat, QTextCharFormat]
|
||||||
T_TextParFormat = tuple[str, QTextCharFormat]
|
|
||||||
|
|
||||||
|
|
||||||
class ToQTextDocument(Tokenizer):
|
class ToQTextDocument(Tokenizer):
|
||||||
@@ -58,7 +58,11 @@ class ToQTextDocument(Tokenizer):
|
|||||||
self._document.setUndoRedoEnabled(False)
|
self._document.setUndoRedoEnabled(False)
|
||||||
|
|
||||||
self._styles: dict[int, T_TextStyle] = {}
|
self._styles: dict[int, T_TextStyle] = {}
|
||||||
|
self._usedNotes: dict[str, int] = {}
|
||||||
|
|
||||||
self._init = False
|
self._init = False
|
||||||
|
self._bold = QFont.Weight.Bold
|
||||||
|
self._normal = QFont.Weight.Normal
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -166,8 +170,7 @@ class ToQTextDocument(Tokenizer):
|
|||||||
|
|
||||||
if tType == self.T_TEXT:
|
if tType == self.T_TEXT:
|
||||||
newBlock(bFmt)
|
newBlock(bFmt)
|
||||||
tTemp, cFmt = self._formatText(tText, tFormat, self._defaultChar)
|
self._insertFragments(tText, tFormat, cursor, self._defaultChar)
|
||||||
cursor.insertText(tTemp, cFmt)
|
|
||||||
|
|
||||||
elif tType in self.L_HEADINGS:
|
elif tType in self.L_HEADINGS:
|
||||||
bFmt, cFmt = self._genHeadStyle(tType, bFmt)
|
bFmt, cFmt = self._genHeadStyle(tType, bFmt)
|
||||||
@@ -222,23 +225,64 @@ class ToQTextDocument(Tokenizer):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _formatText(self, text: str, tFmt: T_Formats, dFmt: QTextCharFormat) -> T_TextParFormat:
|
def _insertFragments(
|
||||||
|
self, text: str, tFmt: T_Formats, cursor: QTextCursor,
|
||||||
|
dFmt: QTextCharFormat, bgCol: QColor = QtTransparent
|
||||||
|
) -> None:
|
||||||
"""Apply formatting tags to text."""
|
"""Apply formatting tags to text."""
|
||||||
temp = text
|
cFmt = QTextCharFormat(dFmt)
|
||||||
fmt = QTextCharFormat(dFmt)
|
start = 0
|
||||||
# for pos, fmt, data in reversed(tFmt):
|
for pos, fmt, data in tFmt:
|
||||||
# md = ""
|
|
||||||
# if fmt == self.FMT_FNOTE:
|
# Insert buffer with previous format
|
||||||
# if data in self._footnotes:
|
cursor.insertText(text[start:pos], cFmt)
|
||||||
# index = len(self._usedNotes) + 1
|
|
||||||
# self._usedNotes[data] = index
|
# Construct next format
|
||||||
# md = f"[{index}]"
|
if fmt == self.FMT_B_B:
|
||||||
# else:
|
cFmt.setFontWeight(self._bold)
|
||||||
# md = "[ERR]"
|
elif fmt == self.FMT_B_E:
|
||||||
# else:
|
cFmt.setFontWeight(self._normal)
|
||||||
# md = tags.get(fmt, "")
|
elif fmt == self.FMT_I_B:
|
||||||
# temp = f"{temp[:pos]}{md}{temp[pos:]}"
|
cFmt.setFontItalic(True)
|
||||||
return temp, fmt
|
elif fmt == self.FMT_I_E:
|
||||||
|
cFmt.setFontItalic(False)
|
||||||
|
elif fmt == self.FMT_D_B:
|
||||||
|
cFmt.setFontStrikeOut(True)
|
||||||
|
elif fmt == self.FMT_D_E:
|
||||||
|
cFmt.setFontStrikeOut(False)
|
||||||
|
elif fmt == self.FMT_U_B:
|
||||||
|
cFmt.setFontUnderline(True)
|
||||||
|
elif fmt == self.FMT_U_E:
|
||||||
|
cFmt.setFontUnderline(False)
|
||||||
|
elif fmt == self.FMT_M_B:
|
||||||
|
cFmt.setBackground(SHARED.theme.colMark)
|
||||||
|
elif fmt == self.FMT_M_E:
|
||||||
|
cFmt.setBackground(bgCol)
|
||||||
|
elif fmt == self.FMT_SUP_B:
|
||||||
|
cFmt.setVerticalAlignment(QtVAlignSuper)
|
||||||
|
elif fmt == self.FMT_SUP_E:
|
||||||
|
cFmt.setVerticalAlignment(QtVAlignNormal)
|
||||||
|
elif fmt == self.FMT_SUB_B:
|
||||||
|
cFmt.setVerticalAlignment(QtVAlignSub)
|
||||||
|
elif fmt == self.FMT_SUB_E:
|
||||||
|
cFmt.setVerticalAlignment(QtVAlignNormal)
|
||||||
|
elif fmt == self.FMT_FNOTE:
|
||||||
|
cFmt.setVerticalAlignment(QtVAlignSuper)
|
||||||
|
if data in self._footnotes:
|
||||||
|
index = len(self._usedNotes) + 1
|
||||||
|
self._usedNotes[data] = index
|
||||||
|
cursor.insertText(f"[{index}]", cFmt)
|
||||||
|
else:
|
||||||
|
cursor.insertText("[ERR]", cFmt)
|
||||||
|
cFmt.setVerticalAlignment(QtVAlignNormal)
|
||||||
|
|
||||||
|
# Move pos for next pass
|
||||||
|
start = pos
|
||||||
|
|
||||||
|
# Insert whatever is left in the buffer
|
||||||
|
cursor.insertText(text[start:], cFmt)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def _formatKeywords(self, text: str, style: int) -> str:
|
def _formatKeywords(self, text: str, style: int) -> str:
|
||||||
"""Apply Markdown formatting to keywords."""
|
"""Apply Markdown formatting to keywords."""
|
||||||
@@ -40,7 +40,7 @@ from PyQt5.QtWidgets import (
|
|||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.common import cssCol
|
from novelwriter.common import cssCol
|
||||||
from novelwriter.constants import nwHeaders, nwUnicode
|
from novelwriter.constants import nwHeaders, nwUnicode
|
||||||
from novelwriter.core.toqdocument import ToQTextDocument
|
from novelwriter.core.toqdoc import ToQTextDocument
|
||||||
from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
|
from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.extensions.eventfilters import WheelEventFilter
|
from novelwriter.extensions.eventfilters import WheelEventFilter
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from PyQt5.QtCore import QRegularExpression, Qt
|
from PyQt5.QtCore import QRegularExpression, Qt
|
||||||
from PyQt5.QtGui import QColor, QFont, QPainter, QTextCursor, QTextFormat
|
from PyQt5.QtGui import QColor, QFont, QPainter, QTextCharFormat, QTextCursor, QTextFormat
|
||||||
from PyQt5.QtWidgets import QDialogButtonBox, QSizePolicy, QStyle
|
from PyQt5.QtWidgets import QDialogButtonBox, QSizePolicy, QStyle
|
||||||
|
|
||||||
# Qt Alignment Flags
|
# Qt Alignment Flags
|
||||||
@@ -44,6 +44,10 @@ QtAlignRightMiddle = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
|
|||||||
QtAlignRightTop = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
|
QtAlignRightTop = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
|
||||||
QtAlignTop = Qt.AlignmentFlag.AlignTop
|
QtAlignTop = Qt.AlignmentFlag.AlignTop
|
||||||
|
|
||||||
|
QtVAlignNormal = QTextCharFormat.VerticalAlignment.AlignNormal
|
||||||
|
QtVAlignSub = QTextCharFormat.VerticalAlignment.AlignSubScript
|
||||||
|
QtVAlignSuper = QTextCharFormat.VerticalAlignment.AlignSuperScript
|
||||||
|
|
||||||
# Qt Page Break
|
# Qt Page Break
|
||||||
|
|
||||||
QtPageBreakBefore = QTextFormat.PageBreakFlag.PageBreak_AlwaysBefore
|
QtPageBreakBefore = QTextFormat.PageBreakFlag.PageBreak_AlwaysBefore
|
||||||
|
|||||||
Reference in New Issue
Block a user