Fix build formatting and font handling (#1891)
This commit is contained in:
@@ -59,6 +59,7 @@ fmt_strike-md = nw_tb-strike-md.svg
|
||||
fmt_subscript = nw_tb-subscript.svg
|
||||
fmt_superscript = nw_tb-superscript.svg
|
||||
fmt_underline = nw_tb-underline.svg
|
||||
font = nw_font.svg
|
||||
forward = typ_chevron-right.svg
|
||||
import = mixed_import.svg
|
||||
list = typ_th-list.svg
|
||||
@@ -78,6 +79,7 @@ proj_scene = mixed_document-scene.svg
|
||||
proj_section = mixed_document-section.svg
|
||||
proj_stats = typ_chart-bar-grey.svg
|
||||
proj_title = mixed_document-title.svg
|
||||
quote = nw_quote.svg
|
||||
refresh = typ_refresh.svg
|
||||
remove = typ_minus.svg
|
||||
revert = typ_refresh-flipped.svg
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.5744 5.8208v-4.2853h-1.4527v-1.0064h4.1067v1.0064h-1.4527v4.2853z" fill="#aeaeae" stroke-width="1.1503"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 267 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1.3715 3.0659q-0.32092-0.25674-0.44928-0.44928-0.12836-0.19255-0.12837-0.44928 0-0.42361 0.28241-0.69319 0.28241-0.28241 0.68035-0.28241 0.25674 0 0.44928 0.10269 0.19255 0.089858 0.3466 0.23106 0.24391 0.4878 0.24391 1.0141 0 0.42361-0.14121 0.82157-0.12837 0.38511-0.37227 0.71886-0.23106 0.33377-0.55199 0.61618-0.30808 0.26958-0.65467 0.46213l-0.25674-0.41078q0.29525-0.21822 0.57766-0.53914 0.28241-0.33375 0.46213-0.73171zm2.7598 0q-0.32092-0.25674-0.44928-0.44928-0.12837-0.19255-0.12837-0.44928 0-0.42361 0.28241-0.69319 0.28241-0.28241 0.68035-0.28241 0.25674 0 0.44928 0.10269 0.19255 0.089858 0.3466 0.23106 0.24391 0.4878 0.24391 1.0141 0 0.42361-0.14121 0.82157-0.12837 0.38511-0.37227 0.71886-0.23106 0.33377-0.55199 0.61618-0.30808 0.26958-0.65467 0.46213l-0.25674-0.41078q0.29525-0.21822 0.57766-0.53914 0.28241-0.33375 0.46213-0.73171z" fill="#aeaeae" fill-opacity=".78039" stroke-width="1.8194"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -59,6 +59,7 @@ fmt_strike-md = nw_tb-strike-md.svg
|
||||
fmt_subscript = nw_tb-subscript.svg
|
||||
fmt_superscript = nw_tb-superscript.svg
|
||||
fmt_underline = nw_tb-underline.svg
|
||||
font = nw_font.svg
|
||||
forward = typ_chevron-right.svg
|
||||
import = mixed_import.svg
|
||||
list = typ_th-list.svg
|
||||
@@ -78,6 +79,7 @@ proj_scene = mixed_document-scene.svg
|
||||
proj_section = mixed_document-section.svg
|
||||
proj_stats = typ_chart-bar-grey.svg
|
||||
proj_title = mixed_document-title.svg
|
||||
quote = nw_quote.svg
|
||||
refresh = typ_refresh.svg
|
||||
remove = typ_minus.svg
|
||||
revert = typ_refresh-flipped.svg
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.5744 5.8208v-4.2853h-1.4527v-1.0064h4.1067v1.0064h-1.4527v4.2853z" fill-opacity=".78039" stroke-width="1.1503"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 274 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m1.3715 3.0659q-0.32092-0.25674-0.44928-0.44928-0.12836-0.19255-0.12837-0.44928 0-0.42361 0.28241-0.69319 0.28241-0.28241 0.68035-0.28241 0.25674 0 0.44928 0.10269 0.19255 0.089858 0.3466 0.23106 0.24391 0.4878 0.24391 1.0141 0 0.42361-0.14121 0.82157-0.12837 0.38511-0.37227 0.71886-0.23106 0.33377-0.55199 0.61618-0.30808 0.26958-0.65467 0.46213l-0.25674-0.41078q0.29525-0.21822 0.57766-0.53914 0.28241-0.33375 0.46213-0.73171zm2.7598 0q-0.32092-0.25674-0.44928-0.44928-0.12837-0.19255-0.12837-0.44928 0-0.42361 0.28241-0.69319 0.28241-0.28241 0.68035-0.28241 0.25674 0 0.44928 0.10269 0.19255 0.089858 0.3466 0.23106 0.24391 0.4878 0.24391 1.0141 0 0.42361-0.14121 0.82157-0.12837 0.38511-0.37227 0.71886-0.23106 0.33377-0.55199 0.61618-0.30808 0.26958-0.65467 0.46213l-0.25674-0.41078q0.29525-0.21822 0.57766-0.53914 0.28241-0.33375 0.46213-0.73171z" fill-opacity=".78039" stroke-width="1.8194"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -405,7 +405,9 @@ def describeFont(font: QFont) -> str:
|
||||
"""Describe a font in a way that can be displayed on the GUI."""
|
||||
if isinstance(font, QFont):
|
||||
info = QFontInfo(font)
|
||||
return f"{font.family()} {info.styleName()} @ {font.pointSize()} pt"
|
||||
family = info.family()
|
||||
styles = [v for v in info.styleName().split() if v not in family]
|
||||
return " ".join([f"{info.pointSize()} pt", family] + styles)
|
||||
return "Error"
|
||||
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ class Config:
|
||||
self.hideVScroll = False # Hide vertical scroll bars on main widgets
|
||||
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
|
||||
self.lastNotes = "0x0" # The latest release notes that have been shown
|
||||
self.nativeFont = True # Use native font dialog
|
||||
|
||||
# Size Settings
|
||||
self._mainWinSize = [1200, 650] # Last size of the main GUI window
|
||||
@@ -598,6 +599,7 @@ class Config:
|
||||
self.hideVScroll = conf.rdBool(sec, "hidevscroll", self.hideVScroll)
|
||||
self.hideHScroll = conf.rdBool(sec, "hidehscroll", self.hideHScroll)
|
||||
self.lastNotes = conf.rdStr(sec, "lastnotes", self.lastNotes)
|
||||
self.nativeFont = conf.rdBool(sec, "nativefont", self.nativeFont)
|
||||
self._lastPath = conf.rdPath(sec, "lastpath", self._lastPath)
|
||||
|
||||
# Sizes
|
||||
@@ -707,6 +709,7 @@ class Config:
|
||||
"hidevscroll": str(self.hideVScroll),
|
||||
"hidehscroll": str(self.hideHScroll),
|
||||
"lastnotes": str(self.lastNotes),
|
||||
"nativefont": str(self.nativeFont),
|
||||
"lastpath": str(self._lastPath),
|
||||
}
|
||||
|
||||
|
||||
@@ -76,12 +76,12 @@ SETTINGS_TEMPLATE = {
|
||||
"text.includeBodyText": (bool, True),
|
||||
"text.ignoredKeywords": (str, ""),
|
||||
"text.addNoteHeadings": (bool, True),
|
||||
"format.textFont": (str, CONFIG.textFont.family()),
|
||||
"format.textSize": (int, 12),
|
||||
"format.textFont": (str, CONFIG.textFont.toString()),
|
||||
"format.lineHeight": (float, 1.15, 0.75, 3.0),
|
||||
"format.justifyText": (bool, False),
|
||||
"format.stripUnicode": (bool, False),
|
||||
"format.replaceTabs": (bool, False),
|
||||
"format.keepBreaks": (bool, True),
|
||||
"format.firstLineIndent": (bool, False),
|
||||
"format.firstIndentWidth": (float, 1.4),
|
||||
"format.indentFirstPar": (bool, False),
|
||||
@@ -96,7 +96,6 @@ SETTINGS_TEMPLATE = {
|
||||
"odt.addColours": (bool, True),
|
||||
"odt.pageHeader": (str, nwHeadFmt.ODT_AUTO),
|
||||
"odt.pageCountOffset": (int, 0),
|
||||
"md.preserveBreaks": (bool, True),
|
||||
"html.addStyles": (bool, True),
|
||||
"html.preserveTabs": (bool, False),
|
||||
}
|
||||
@@ -125,13 +124,13 @@ SETTINGS_LABELS = {
|
||||
"text.addNoteHeadings": QT_TRANSLATE_NOOP("Builds", "Add Titles for Notes"),
|
||||
|
||||
"format.grpFormat": QT_TRANSLATE_NOOP("Builds", "Text Format"),
|
||||
"format.textFont": QT_TRANSLATE_NOOP("Builds", "Font Family"),
|
||||
"format.textSize": QT_TRANSLATE_NOOP("Builds", "Font Size"),
|
||||
"format.textFont": QT_TRANSLATE_NOOP("Builds", "Text Font"),
|
||||
"format.lineHeight": QT_TRANSLATE_NOOP("Builds", "Line Height"),
|
||||
"format.grpOptions": QT_TRANSLATE_NOOP("Builds", "Text Options"),
|
||||
"format.justifyText": QT_TRANSLATE_NOOP("Builds", "Justify Text Margins"),
|
||||
"format.stripUnicode": QT_TRANSLATE_NOOP("Builds", "Replace Unicode Characters"),
|
||||
"format.replaceTabs": QT_TRANSLATE_NOOP("Builds", "Replace Tabs with Spaces"),
|
||||
"format.keepBreaks": QT_TRANSLATE_NOOP("Builds", "Preserve Hard Line Breaks"),
|
||||
|
||||
"format.grpParIndent": QT_TRANSLATE_NOOP("Builds", "First Line Indent"),
|
||||
"format.firstLineIndent": QT_TRANSLATE_NOOP("Builds", "Enable Indent"),
|
||||
@@ -153,9 +152,6 @@ SETTINGS_LABELS = {
|
||||
"odt.pageHeader": QT_TRANSLATE_NOOP("Builds", "Page Header"),
|
||||
"odt.pageCountOffset": QT_TRANSLATE_NOOP("Builds", "Page Counter Offset"),
|
||||
|
||||
"md": QT_TRANSLATE_NOOP("Builds", "Markdown (.md)"),
|
||||
"md.preserveBreaks": QT_TRANSLATE_NOOP("Builds", "Preserve Hard Line Breaks"),
|
||||
|
||||
"html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"),
|
||||
"html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
|
||||
"html.preserveTabs": QT_TRANSLATE_NOOP("Builds", "Preserve Tab Characters"),
|
||||
|
||||
@@ -28,7 +28,7 @@ import logging
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5.QtGui import QFont, QFontInfo
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.constants import nwLabels
|
||||
@@ -216,16 +216,10 @@ class NWBuildDocument:
|
||||
makeObj = ToMarkdown(self._project)
|
||||
filtered = self._setupBuild(makeObj)
|
||||
|
||||
if extendedMd:
|
||||
makeObj.setExtendedMarkdown()
|
||||
else:
|
||||
makeObj.setStandardMarkdown()
|
||||
|
||||
makeObj.setExtendedMarkdown(extendedMd)
|
||||
if self._build.getBool("format.replaceTabs"):
|
||||
makeObj.replaceTabs(nSpaces=4, spaceChar=" ")
|
||||
|
||||
makeObj.setPreserveBreaks(self._build.getBool("md.preserveBreaks"))
|
||||
|
||||
for i, tHandle in enumerate(self._queue):
|
||||
self._error = None
|
||||
if filtered.get(tHandle, (False, 0))[0]:
|
||||
@@ -285,13 +279,9 @@ class NWBuildDocument:
|
||||
def _setupBuild(self, bldObj: Tokenizer) -> dict:
|
||||
"""Configure the build object."""
|
||||
# Get Settings
|
||||
textFont = self._build.getStr("format.textFont")
|
||||
textSize = self._build.getInt("format.textSize")
|
||||
|
||||
fontFamily = textFont or CONFIG.textFont.family()
|
||||
bldFont = QFont(fontFamily, textSize)
|
||||
fontInfo = QFontInfo(bldFont)
|
||||
textFixed = fontInfo.fixedPitch()
|
||||
textFont = QFont(CONFIG.textFont)
|
||||
textFont.fromString(self._build.getStr("format.textFont"))
|
||||
bldObj.setFont(textFont)
|
||||
|
||||
bldObj.setTitleFormat(
|
||||
self._build.getStr("headings.fmtTitle"),
|
||||
@@ -330,9 +320,9 @@ class NWBuildDocument:
|
||||
self._build.getBool("headings.breakScene")
|
||||
)
|
||||
|
||||
bldObj.setFont(fontFamily, textSize, textFixed)
|
||||
bldObj.setJustify(self._build.getBool("format.justifyText"))
|
||||
bldObj.setLineHeight(self._build.getFloat("format.lineHeight"))
|
||||
bldObj.setKeepLineBreaks(self._build.getBool("format.keepBreaks"))
|
||||
bldObj.setFirstLineIndent(
|
||||
self._build.getBool("format.firstLineIndent"),
|
||||
self._build.getFloat("format.firstIndentWidth"),
|
||||
|
||||
@@ -34,6 +34,7 @@ from novelwriter.common import formatTimeStamp
|
||||
from novelwriter.constants import nwHeadFmt, nwHtmlUnicode, nwKeyWords, nwLabels
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.tokenizer import T_Formats, Tokenizer, stripEscape
|
||||
from novelwriter.types import FONT_STYLE, FONT_WEIGHTS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -373,8 +374,16 @@ class ToHtml(Tokenizer):
|
||||
mScale = self._lineHeight/1.15
|
||||
|
||||
styles = []
|
||||
styles.append("body {{font-family: '{0:s}'; font-size: {1:d}pt;}}".format(
|
||||
self._textFont, self._textSize
|
||||
font = self._textFont
|
||||
styles.append((
|
||||
"body {{"
|
||||
"font-family: '{0:s}'; font-size: {1:d}pt; "
|
||||
"font-weight: {2:d}; font-style: {3:s};"
|
||||
"}}"
|
||||
).format(
|
||||
font.family(), font.pointSize(),
|
||||
FONT_WEIGHTS.get(font.weight(), 400),
|
||||
FONT_STYLE.get(font.style(), "normal"),
|
||||
))
|
||||
styles.append((
|
||||
"p {{"
|
||||
|
||||
@@ -34,6 +34,7 @@ from pathlib import Path
|
||||
from time import time
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
from novelwriter.common import checkInt, formatTimeStamp, numberToRoman
|
||||
from novelwriter.constants import (
|
||||
@@ -139,9 +140,7 @@ class Tokenizer(ABC):
|
||||
self._markdown: list[str] = []
|
||||
|
||||
# User Settings
|
||||
self._textFont = "Serif" # Output text font
|
||||
self._textSize = 11 # Output text size
|
||||
self._textFixed = False # Fixed width text
|
||||
self._textFont = QFont("Serif", 11) # Output text font
|
||||
self._lineHeight = 1.15 # Line height in units of em
|
||||
self._blockIndent = 4.00 # Block indent in units of em
|
||||
self._firstIndent = False # Enable first line indent
|
||||
@@ -315,11 +314,9 @@ class Tokenizer(ABC):
|
||||
)
|
||||
return
|
||||
|
||||
def setFont(self, family: str, size: int, isFixed: bool = False) -> None:
|
||||
def setFont(self, font: QFont) -> None:
|
||||
"""Set the build font."""
|
||||
self._textFont = family
|
||||
self._textSize = round(int(size))
|
||||
self._textFixed = isFixed
|
||||
self._textFont = font
|
||||
return
|
||||
|
||||
def setLineHeight(self, height: float) -> None:
|
||||
|
||||
@@ -81,15 +81,11 @@ class ToMarkdown(Tokenizer):
|
||||
supports concatenating novelWriter markup files.
|
||||
"""
|
||||
|
||||
M_STD = 0 # Standard Markdown
|
||||
M_EXT = 1 # Extended Markdown
|
||||
|
||||
def __init__(self, project: NWProject) -> None:
|
||||
super().__init__(project)
|
||||
self._genMode = self.M_STD
|
||||
self._fullMD: list[str] = []
|
||||
self._preserveBreaks = True
|
||||
self._usedNotes: dict[str, int] = {}
|
||||
self._extended = True
|
||||
return
|
||||
|
||||
##
|
||||
@@ -105,19 +101,9 @@ class ToMarkdown(Tokenizer):
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setStandardMarkdown(self) -> None:
|
||||
"""Set the converter to use standard Markdown formatting."""
|
||||
self._genMode = self.M_STD
|
||||
return
|
||||
|
||||
def setExtendedMarkdown(self) -> None:
|
||||
def setExtendedMarkdown(self, state: bool) -> None:
|
||||
"""Set the converter to use Extended Markdown formatting."""
|
||||
self._genMode = self.M_EXT
|
||||
return
|
||||
|
||||
def setPreserveBreaks(self, state: bool) -> None:
|
||||
"""Preserve line breaks in paragraphs."""
|
||||
self._preserveBreaks = state
|
||||
self._extended = state
|
||||
return
|
||||
|
||||
##
|
||||
@@ -132,12 +118,12 @@ class ToMarkdown(Tokenizer):
|
||||
"""Convert the list of text tokens into a Markdown document."""
|
||||
self._result = ""
|
||||
|
||||
if self._genMode == self.M_STD:
|
||||
mTags = STD_MD
|
||||
cSkip = ""
|
||||
else:
|
||||
if self._extended:
|
||||
mTags = EXT_MD
|
||||
cSkip = nwUnicode.U_MMSP
|
||||
else:
|
||||
mTags = STD_MD
|
||||
cSkip = ""
|
||||
|
||||
lines = []
|
||||
for tType, _, tText, tFormat, tStyle in self._tokens:
|
||||
@@ -195,7 +181,7 @@ class ToMarkdown(Tokenizer):
|
||||
def appendFootnotes(self) -> None:
|
||||
"""Append the footnotes in the buffer."""
|
||||
if self._usedNotes:
|
||||
tags = STD_MD if self._genMode == self.M_STD else EXT_MD
|
||||
tags = EXT_MD if self._extended else STD_MD
|
||||
footnotes = self._localLookup("Footnotes")
|
||||
|
||||
lines = []
|
||||
|
||||
+62
-38
@@ -35,11 +35,14 @@ from hashlib import sha256
|
||||
from pathlib import Path
|
||||
from zipfile import ZipFile
|
||||
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
from novelwriter import __version__
|
||||
from novelwriter.common import xmlIndent
|
||||
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.tokenizer import T_Formats, Tokenizer, stripEscape
|
||||
from novelwriter.types import FONT_STYLE, FONT_WEIGHTS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -108,6 +111,10 @@ S_TEXT = "Text_20_body"
|
||||
S_META = "Text_20_Meta"
|
||||
S_HNF = "Header_20_and_20_Footer"
|
||||
|
||||
# Font Data
|
||||
FONT_WEIGHT_NUM = ["100", "200", "300", "400", "500", "600", "700", "800", "900"]
|
||||
FONT_WEIGHT_MAP = {"400": "normal", "700": "bold"}
|
||||
|
||||
|
||||
class ToOdt(Tokenizer):
|
||||
"""Core: Open Document Writer
|
||||
@@ -149,16 +156,18 @@ class ToOdt(Tokenizer):
|
||||
self._errData = [] # List of errors encountered
|
||||
|
||||
# Properties
|
||||
self._textFont = "Liberation Serif"
|
||||
self._textSize = 12
|
||||
self._textFixed = False
|
||||
self._textFont = QFont("Liberation Serif", 12)
|
||||
self._colourHead = False
|
||||
self._headerFormat = ""
|
||||
self._pageOffset = 0
|
||||
|
||||
# Internal
|
||||
self._fontFamily = "'Liberation Serif'"
|
||||
self._fontFamily = "Liberation Serif"
|
||||
self._fontSize = 12
|
||||
self._fontWeight = "normal"
|
||||
self._fontStyle = "normal"
|
||||
self._fontPitch = "variable"
|
||||
self._fontBold = "bold"
|
||||
self._fSizeTitle = "30pt"
|
||||
self._fSizeHead1 = "24pt"
|
||||
self._fSizeHead2 = "20pt"
|
||||
@@ -260,19 +269,25 @@ class ToOdt(Tokenizer):
|
||||
# Initialise Variables
|
||||
# ====================
|
||||
|
||||
self._fontFamily = self._textFont
|
||||
if len(self._textFont.split()) > 1:
|
||||
self._fontFamily = f"'{self._textFont}'"
|
||||
self._fontPitch = "fixed" if self._textFixed else "variable"
|
||||
intWeight = FONT_WEIGHTS.get(self._textFont.weight(), 400)
|
||||
fontWeight = str(intWeight)
|
||||
fontBold = str(min(intWeight + 300, 900))
|
||||
|
||||
self._fSizeTitle = f"{round(2.50 * self._textSize):d}pt"
|
||||
self._fSizeHead1 = f"{round(2.00 * self._textSize):d}pt"
|
||||
self._fSizeHead2 = f"{round(1.60 * self._textSize):d}pt"
|
||||
self._fSizeHead3 = f"{round(1.30 * self._textSize):d}pt"
|
||||
self._fSizeHead4 = f"{round(1.15 * self._textSize):d}pt"
|
||||
self._fSizeHead = f"{round(1.15 * self._textSize):d}pt"
|
||||
self._fSizeText = f"{self._textSize:d}pt"
|
||||
self._fSizeFoot = f"{round(0.8*self._textSize):d}pt"
|
||||
self._fontFamily = self._textFont.family()
|
||||
self._fontSize = self._textFont.pointSize()
|
||||
self._fontWeight = FONT_WEIGHT_MAP.get(fontWeight, fontWeight)
|
||||
self._fontStyle = FONT_STYLE.get(self._textFont.style(), "normal")
|
||||
self._fontPitch = "fixed" if self._textFont.fixedPitch() else "variable"
|
||||
self._fontBold = FONT_WEIGHT_MAP.get(fontBold, fontBold)
|
||||
|
||||
self._fSizeTitle = f"{round(2.50 * self._fontSize):d}pt"
|
||||
self._fSizeHead1 = f"{round(2.00 * self._fontSize):d}pt"
|
||||
self._fSizeHead2 = f"{round(1.60 * self._fontSize):d}pt"
|
||||
self._fSizeHead3 = f"{round(1.30 * self._fontSize):d}pt"
|
||||
self._fSizeHead4 = f"{round(1.15 * self._fontSize):d}pt"
|
||||
self._fSizeHead = f"{round(1.15 * self._fontSize):d}pt"
|
||||
self._fSizeText = f"{self._fontSize:d}pt"
|
||||
self._fSizeFoot = f"{round(0.8*self._fontSize):d}pt"
|
||||
|
||||
mScale = self._lineHeight/1.15
|
||||
|
||||
@@ -320,7 +335,7 @@ class ToOdt(Tokenizer):
|
||||
tAttr[_mkTag("office", "version")] = X_VERS
|
||||
|
||||
fAttr = {}
|
||||
fAttr[_mkTag("style", "name")] = self._textFont
|
||||
fAttr[_mkTag("style", "name")] = self._fontFamily
|
||||
fAttr[_mkTag("style", "font-pitch")] = self._fontPitch
|
||||
|
||||
if self._isFlat:
|
||||
@@ -726,7 +741,7 @@ class ToOdt(Tokenizer):
|
||||
|
||||
style = ODTTextStyle(f"T{len(self._autoText)+1:d}")
|
||||
if hFmt & X_BLD:
|
||||
style.setFontWeight("bold")
|
||||
style.setFontWeight(self._fontBold)
|
||||
if hFmt & X_ITA:
|
||||
style.setFontStyle("italic")
|
||||
if hFmt & X_DEL:
|
||||
@@ -764,7 +779,7 @@ class ToOdt(Tokenizer):
|
||||
|
||||
def _emToCm(self, value: float) -> str:
|
||||
"""Converts an em value to centimetres."""
|
||||
return f"{value*2.54/72*self._textSize:.3f}cm"
|
||||
return f"{value*2.54/72*self._fontSize:.3f}cm"
|
||||
|
||||
##
|
||||
# Style Elements
|
||||
@@ -808,8 +823,10 @@ class ToOdt(Tokenizer):
|
||||
_mkTag("style", "writing-mode"): "page",
|
||||
})
|
||||
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
||||
_mkTag("style", "font-name"): self._textFont,
|
||||
_mkTag("style", "font-name"): self._fontFamily,
|
||||
_mkTag("fo", "font-family"): self._fontFamily,
|
||||
_mkTag("fo", "font-weight"): self._fontWeight,
|
||||
_mkTag("fo", "font-style"): self._fontStyle,
|
||||
_mkTag("fo", "font-size"): self._fSizeText,
|
||||
_mkTag("fo", "language"): self._dLanguage,
|
||||
_mkTag("fo", "country"): self._dCountry,
|
||||
@@ -822,8 +839,10 @@ class ToOdt(Tokenizer):
|
||||
_mkTag("style", "class"): "text",
|
||||
})
|
||||
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
||||
_mkTag("style", "font-name"): self._textFont,
|
||||
_mkTag("style", "font-name"): self._fontFamily,
|
||||
_mkTag("fo", "font-family"): self._fontFamily,
|
||||
_mkTag("fo", "font-weight"): self._fontWeight,
|
||||
_mkTag("fo", "font-style"): self._fontStyle,
|
||||
_mkTag("fo", "font-size"): self._fSizeText,
|
||||
})
|
||||
|
||||
@@ -841,8 +860,10 @@ class ToOdt(Tokenizer):
|
||||
_mkTag("fo", "keep-with-next"): "always",
|
||||
})
|
||||
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
||||
_mkTag("style", "font-name"): self._textFont,
|
||||
_mkTag("style", "font-name"): self._fontFamily,
|
||||
_mkTag("fo", "font-family"): self._fontFamily,
|
||||
_mkTag("fo", "font-weight"): self._fontWeight,
|
||||
_mkTag("fo", "font-style"): self._fontStyle,
|
||||
_mkTag("fo", "font-size"): self._fSizeHead,
|
||||
})
|
||||
|
||||
@@ -868,9 +889,10 @@ class ToOdt(Tokenizer):
|
||||
style.setMarginBottom(self._mBotText)
|
||||
style.setLineHeight(self._fLineHeight)
|
||||
style.setTextAlign(self._textAlign)
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeText)
|
||||
style.setFontWeight(self._fontWeight)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -891,9 +913,10 @@ class ToOdt(Tokenizer):
|
||||
style.setMarginTop(self._mTopMeta)
|
||||
style.setMarginBottom(self._mBotMeta)
|
||||
style.setLineHeight(self._fLineHeight)
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeText)
|
||||
style.setFontWeight(self._fontWeight)
|
||||
style.setColour(self._colMetaTx)
|
||||
style.setOpacity(self._opaMetaTx)
|
||||
style.packXML(self._xStyl)
|
||||
@@ -908,10 +931,10 @@ class ToOdt(Tokenizer):
|
||||
style.setMarginTop(self._mTopTitle)
|
||||
style.setMarginBottom(self._mBotTitle)
|
||||
style.setTextAlign("center")
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeTitle)
|
||||
style.setFontWeight("bold")
|
||||
style.setFontWeight(self._fontBold)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -925,9 +948,10 @@ class ToOdt(Tokenizer):
|
||||
style.setMarginBottom(self._mBotText)
|
||||
style.setLineHeight(self._fLineHeight)
|
||||
style.setTextAlign("center")
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeText)
|
||||
style.setFontWeight(self._fontWeight)
|
||||
style.packXML(self._xStyl)
|
||||
self._mainPara[style.name] = style
|
||||
|
||||
@@ -940,10 +964,10 @@ class ToOdt(Tokenizer):
|
||||
style.setClass("text")
|
||||
style.setMarginTop(self._mTopHead1)
|
||||
style.setMarginBottom(self._mBotHead1)
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead1)
|
||||
style.setFontWeight("bold")
|
||||
style.setFontWeight(self._fontBold)
|
||||
style.setColour(self._colHead12)
|
||||
style.setOpacity(self._opaHead12)
|
||||
style.packXML(self._xStyl)
|
||||
@@ -958,10 +982,10 @@ class ToOdt(Tokenizer):
|
||||
style.setClass("text")
|
||||
style.setMarginTop(self._mTopHead2)
|
||||
style.setMarginBottom(self._mBotHead2)
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead2)
|
||||
style.setFontWeight("bold")
|
||||
style.setFontWeight(self._fontBold)
|
||||
style.setColour(self._colHead12)
|
||||
style.setOpacity(self._opaHead12)
|
||||
style.packXML(self._xStyl)
|
||||
@@ -976,10 +1000,10 @@ class ToOdt(Tokenizer):
|
||||
style.setClass("text")
|
||||
style.setMarginTop(self._mTopHead3)
|
||||
style.setMarginBottom(self._mBotHead3)
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead3)
|
||||
style.setFontWeight("bold")
|
||||
style.setFontWeight(self._fontBold)
|
||||
style.setColour(self._colHead34)
|
||||
style.setOpacity(self._opaHead34)
|
||||
style.packXML(self._xStyl)
|
||||
@@ -994,10 +1018,10 @@ class ToOdt(Tokenizer):
|
||||
style.setClass("text")
|
||||
style.setMarginTop(self._mTopHead4)
|
||||
style.setMarginBottom(self._mBotHead4)
|
||||
style.setFontName(self._textFont)
|
||||
style.setFontName(self._fontFamily)
|
||||
style.setFontFamily(self._fontFamily)
|
||||
style.setFontSize(self._fSizeHead4)
|
||||
style.setFontWeight("bold")
|
||||
style.setFontWeight(self._fontBold)
|
||||
style.setColour(self._colHead34)
|
||||
style.setOpacity(self._opaHead34)
|
||||
style.packXML(self._xStyl)
|
||||
@@ -1077,7 +1101,7 @@ class ODTParagraphStyle:
|
||||
VALID_BREAK = ["auto", "column", "page", "even-page", "odd-page", "inherit"]
|
||||
VALID_LEVEL = ["1", "2", "3", "4"]
|
||||
VALID_CLASS = ["text", "chapter", "extra"]
|
||||
VALID_WEIGHT = ["normal", "inherit", "bold"]
|
||||
VALID_WEIGHT = ["normal", "bold"] + FONT_WEIGHT_NUM
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
|
||||
@@ -1320,8 +1344,8 @@ class ODTTextStyle:
|
||||
Only the used settings are exposed here to keep the class minimal
|
||||
and fast.
|
||||
"""
|
||||
VALID_WEIGHT = ["normal", "inherit", "bold"]
|
||||
VALID_STYLE = ["normal", "inherit", "italic"]
|
||||
VALID_WEIGHT = ["normal", "bold"] + FONT_WEIGHT_NUM
|
||||
VALID_STYLE = ["normal", "italic", "oblique"]
|
||||
VALID_POS = ["super", "sub"]
|
||||
VALID_LSTYLE = ["none", "solid"]
|
||||
VALID_LTYPE = ["single", "double"]
|
||||
|
||||
@@ -30,8 +30,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QKeyEvent, QKeySequence
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractButton, QApplication, QCompleter, QDialog, QDialogButtonBox,
|
||||
QFileDialog, QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout,
|
||||
QWidget
|
||||
QFileDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -183,7 +182,7 @@ class GuiPreferences(QDialog):
|
||||
self.guiFont.setMinimumWidth(fontWidth)
|
||||
self.guiFont.setText(describeFont(self._guiFont))
|
||||
self.guiFont.setCursorPosition(0)
|
||||
self.guiFontButton = NIconToolButton(self, iSz, "more")
|
||||
self.guiFontButton = NIconToolButton(self, iSz, "font")
|
||||
self.guiFontButton.clicked.connect(self._selectGuiFont)
|
||||
self.mainForm.addRow(
|
||||
self.tr("Application font"), self.guiFont,
|
||||
@@ -207,6 +206,14 @@ class GuiPreferences(QDialog):
|
||||
self.tr("Scrolling available with mouse wheel and keys only.")
|
||||
)
|
||||
|
||||
# Native Font Dialog
|
||||
self.nativeFont = NSwitch(self)
|
||||
self.nativeFont.setChecked(CONFIG.nativeFont)
|
||||
self.mainForm.addRow(
|
||||
self.tr("Use the system's font selection dialog"), self.nativeFont,
|
||||
self.tr("Turn off to use the Qt font dialog, which may have more options.")
|
||||
)
|
||||
|
||||
# Document Style
|
||||
# ==============
|
||||
|
||||
@@ -233,7 +240,7 @@ class GuiPreferences(QDialog):
|
||||
self.textFont.setMinimumWidth(fontWidth)
|
||||
self.textFont.setText(describeFont(CONFIG.textFont))
|
||||
self.textFont.setCursorPosition(0)
|
||||
self.textFontButton = NIconToolButton(self, iSz, "more")
|
||||
self.textFontButton = NIconToolButton(self, iSz, "font")
|
||||
self.textFontButton.clicked.connect(self._selectTextFont)
|
||||
self.mainForm.addRow(
|
||||
self.tr("Document font"), self.textFont,
|
||||
@@ -695,7 +702,7 @@ class GuiPreferences(QDialog):
|
||||
self.quoteSym["SO"].setFixedWidth(boxFixed)
|
||||
self.quoteSym["SO"].setAlignment(QtAlignCenter)
|
||||
self.quoteSym["SO"].setText(CONFIG.fmtSQuoteOpen)
|
||||
self.btnSingleStyleO = NIconToolButton(self, iSz, "more")
|
||||
self.btnSingleStyleO = NIconToolButton(self, iSz, "quote")
|
||||
self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
|
||||
self.mainForm.addRow(
|
||||
self.tr("Single quote open style"), self.quoteSym["SO"],
|
||||
@@ -709,7 +716,7 @@ class GuiPreferences(QDialog):
|
||||
self.quoteSym["SC"].setFixedWidth(boxFixed)
|
||||
self.quoteSym["SC"].setAlignment(QtAlignCenter)
|
||||
self.quoteSym["SC"].setText(CONFIG.fmtSQuoteClose)
|
||||
self.btnSingleStyleC = NIconToolButton(self, iSz, "more")
|
||||
self.btnSingleStyleC = NIconToolButton(self, iSz, "quote")
|
||||
self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
|
||||
self.mainForm.addRow(
|
||||
self.tr("Single quote close style"), self.quoteSym["SC"],
|
||||
@@ -724,7 +731,7 @@ class GuiPreferences(QDialog):
|
||||
self.quoteSym["DO"].setFixedWidth(boxFixed)
|
||||
self.quoteSym["DO"].setAlignment(QtAlignCenter)
|
||||
self.quoteSym["DO"].setText(CONFIG.fmtDQuoteOpen)
|
||||
self.btnDoubleStyleO = NIconToolButton(self, iSz, "more")
|
||||
self.btnDoubleStyleO = NIconToolButton(self, iSz, "quote")
|
||||
self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
|
||||
self.mainForm.addRow(
|
||||
self.tr("Double quote open style"), self.quoteSym["DO"],
|
||||
@@ -738,7 +745,7 @@ class GuiPreferences(QDialog):
|
||||
self.quoteSym["DC"].setFixedWidth(boxFixed)
|
||||
self.quoteSym["DC"].setAlignment(QtAlignCenter)
|
||||
self.quoteSym["DC"].setText(CONFIG.fmtDQuoteClose)
|
||||
self.btnDoubleStyleC = NIconToolButton(self, iSz, "more")
|
||||
self.btnDoubleStyleC = NIconToolButton(self, iSz, "quote")
|
||||
self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
|
||||
self.mainForm.addRow(
|
||||
self.tr("Double quote close style"), self.quoteSym["DC"],
|
||||
@@ -804,7 +811,7 @@ class GuiPreferences(QDialog):
|
||||
@pyqtSlot()
|
||||
def _selectGuiFont(self) -> None:
|
||||
"""Open the QFontDialog and set a font for the font style."""
|
||||
font, status = QFontDialog.getFont(self._guiFont, self)
|
||||
font, status = SHARED.getFont(self._guiFont, self.nativeFont.isChecked())
|
||||
if status:
|
||||
self.guiFont.setText(describeFont(font))
|
||||
self.guiFont.setCursorPosition(0)
|
||||
@@ -814,7 +821,7 @@ class GuiPreferences(QDialog):
|
||||
@pyqtSlot()
|
||||
def _selectTextFont(self) -> None:
|
||||
"""Open the QFontDialog and set a font for the font style."""
|
||||
font, status = QFontDialog.getFont(CONFIG.textFont, self)
|
||||
font, status = SHARED.getFont(self._textFont, self.nativeFont.isChecked())
|
||||
if status:
|
||||
self.textFont.setText(describeFont(font))
|
||||
self.textFont.setCursorPosition(0)
|
||||
@@ -883,6 +890,7 @@ class GuiPreferences(QDialog):
|
||||
CONFIG.guiTheme = guiTheme
|
||||
CONFIG.hideVScroll = self.hideVScroll.isChecked()
|
||||
CONFIG.hideHScroll = self.hideHScroll.isChecked()
|
||||
CONFIG.nativeFont = self.nativeFont.isChecked()
|
||||
CONFIG.setGuiFont(self._guiFont)
|
||||
|
||||
# Document Style
|
||||
|
||||
@@ -50,6 +50,7 @@ class GuiQuoteSelect(QDialog):
|
||||
|
||||
logger.debug("Create: GuiQuoteSelect")
|
||||
self.setObjectName("GuiQuoteSelect")
|
||||
self.setWindowTitle(self.tr("Select Quote Style"))
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.innerBox = QHBoxLayout()
|
||||
|
||||
@@ -501,9 +501,9 @@ class GuiIcons:
|
||||
|
||||
# General Button Icons
|
||||
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "cross",
|
||||
"document", "down", "edit", "export", "forward", "import", "list", "maximise", "menu",
|
||||
"minimise", "more", "noncheckable", "open", "panel", "refresh", "remove", "revert",
|
||||
"search_replace", "search", "settings", "star", "unchecked", "up", "view",
|
||||
"document", "down", "edit", "export", "font", "forward", "import", "list", "maximise",
|
||||
"menu", "minimise", "more", "noncheckable", "open", "panel", "quote", "refresh", "remove",
|
||||
"revert", "search_replace", "search", "settings", "star", "unchecked", "up", "view",
|
||||
|
||||
# Switches
|
||||
"sticky-on", "sticky-off",
|
||||
|
||||
+14
-3
@@ -31,7 +31,8 @@ from time import time
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal
|
||||
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QWidget
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtWidgets import QFileDialog, QFontDialog, QMessageBox, QWidget
|
||||
|
||||
from novelwriter.common import formatFileFilter
|
||||
from novelwriter.constants import nwFiles
|
||||
@@ -255,8 +256,11 @@ class SharedData(QObject):
|
||||
QThreadPool.globalInstance().start(runnable, priority=priority)
|
||||
return
|
||||
|
||||
def getProjectPath(self, parent: QWidget, path: str | Path | None = None,
|
||||
allowZip: bool = False) -> Path | None:
|
||||
def getProjectPath(
|
||||
self, parent: QWidget,
|
||||
path: str | Path | None = None,
|
||||
allowZip: bool = False
|
||||
) -> Path | None:
|
||||
"""Open the file dialog and select a novelWriter project file."""
|
||||
label = (self.tr("novelWriter Project File or Zip File")
|
||||
if allowZip else self.tr("novelWriter Project File"))
|
||||
@@ -267,6 +271,13 @@ class SharedData(QObject):
|
||||
)
|
||||
return Path(selected) if selected else None
|
||||
|
||||
def getFont(self, current: QFont, native: bool) -> tuple[QFont, bool]:
|
||||
"""Open the font dialog and select a font."""
|
||||
kwargs = {}
|
||||
if not native:
|
||||
kwargs["options"] = QFontDialog.FontDialogOption.DontUseNativeDialog
|
||||
return QFontDialog.getFont(current, self.mainGui, self.tr("Select Font"), **kwargs)
|
||||
|
||||
def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None:
|
||||
"""Find a top level widget."""
|
||||
for widget in self.mainGui.children():
|
||||
|
||||
@@ -31,7 +31,7 @@ from time import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QPalette, QResizeEvent
|
||||
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
|
||||
from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
|
||||
@@ -402,12 +402,12 @@ class GuiManuscript(NToolDialog):
|
||||
|
||||
def _updatePreview(self, data: dict, build: BuildSettings) -> None:
|
||||
"""Update the preview widget and set relevant values."""
|
||||
textFont = QFont()
|
||||
textFont.fromString(build.getStr("format.textFont"))
|
||||
|
||||
self.docPreview.setContent(data)
|
||||
self.docPreview.setBuildName(build.name)
|
||||
self.docPreview.setTextFont(
|
||||
build.getStr("format.textFont"),
|
||||
build.getInt("format.textSize")
|
||||
)
|
||||
self.docPreview.setTextFont(textFont)
|
||||
self.docPreview.setJustify(
|
||||
build.getBool("format.justifyText")
|
||||
)
|
||||
@@ -787,7 +787,7 @@ class _PreviewWidget(QTextBrowser):
|
||||
self._updateDocMargins()
|
||||
self._updateBuildAge()
|
||||
|
||||
self.setTextFont(CONFIG.textFont.family(), CONFIG.textFont.pointSize())
|
||||
self.setTextFont(CONFIG.textFont)
|
||||
|
||||
# Age Timer
|
||||
self.ageTimer = QTimer(self)
|
||||
@@ -817,18 +817,14 @@ class _PreviewWidget(QTextBrowser):
|
||||
self.document().setDefaultTextOption(pOptions)
|
||||
return
|
||||
|
||||
def setTextFont(self, family: str, size: int) -> None:
|
||||
def setTextFont(self, font: QFont) -> None:
|
||||
"""Set the text font properties and then reset for sub-widgets.
|
||||
This needs special attention since there appears to be a bug in
|
||||
Qt 5.15.3. See issues #1862 and #1875.
|
||||
"""
|
||||
if family and size > 4:
|
||||
font = self.font()
|
||||
font.setFamily(family)
|
||||
font.setPointSize(size)
|
||||
self.setFont(font)
|
||||
self.buildProgress.setFont(SHARED.theme.guiFont)
|
||||
self.ageLabel.setFont(SHARED.theme.guiFontSmall)
|
||||
self.setFont(font)
|
||||
self.buildProgress.setFont(SHARED.theme.guiFont)
|
||||
self.ageLabel.setFont(SHARED.theme.guiFontSmall)
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
@@ -30,13 +30,14 @@ from typing import TYPE_CHECKING
|
||||
from PyQt5.QtCore import QEvent, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractButton, QAbstractItemView, QDialogButtonBox, QFontDialog, QFrame,
|
||||
QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu,
|
||||
QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, QTreeWidget,
|
||||
QTreeWidgetItem, QVBoxLayout, QWidget
|
||||
QAbstractButton, QAbstractItemView, QDialogButtonBox, QFrame, QGridLayout,
|
||||
QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QPlainTextEdit,
|
||||
QPushButton, QSplitter, QStackedWidget, QTreeWidget, QTreeWidgetItem,
|
||||
QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import describeFont
|
||||
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, trConst
|
||||
from novelwriter.core.buildsettings import BuildSettings, FilterMode
|
||||
from novelwriter.extensions.configlayout import (
|
||||
@@ -1052,6 +1053,7 @@ class _FormatTab(NScrollableForm):
|
||||
|
||||
self._build = build
|
||||
self._unitScale = 1.0
|
||||
self._textFont = QFont(CONFIG.textFont)
|
||||
|
||||
iPx = SHARED.theme.baseIconHeight
|
||||
iSz = SHARED.theme.baseIconSize
|
||||
@@ -1063,24 +1065,16 @@ class _FormatTab(NScrollableForm):
|
||||
|
||||
self.addGroupLabel(self._build.getLabel("format.grpFormat"))
|
||||
|
||||
# Font Family
|
||||
# Text Font
|
||||
self.textFont = QLineEdit(self)
|
||||
self.textFont.setReadOnly(True)
|
||||
self.btnTextFont = NIconToolButton(self, iSz, "more")
|
||||
self.btnTextFont = NIconToolButton(self, iSz, "font")
|
||||
self.btnTextFont.clicked.connect(self._selectFont)
|
||||
self.addRow(
|
||||
self._build.getLabel("format.textFont"), self.textFont,
|
||||
button=self.btnTextFont, stretch=(3, 2)
|
||||
button=self.btnTextFont, stretch=(1, 1)
|
||||
)
|
||||
|
||||
# Font Size
|
||||
self.textSize = NSpinBox(self)
|
||||
self.textSize.setMinimum(8)
|
||||
self.textSize.setMaximum(60)
|
||||
self.textSize.setSingleStep(1)
|
||||
self.textSize.setMinimumWidth(spW)
|
||||
self.addRow(self._build.getLabel("format.textSize"), self.textSize, unit="pt")
|
||||
|
||||
# Line Height
|
||||
self.lineHeight = NDoubleSpinBox(self)
|
||||
self.lineHeight.setFixedWidth(spW)
|
||||
@@ -1098,10 +1092,12 @@ class _FormatTab(NScrollableForm):
|
||||
self.justifyText = NSwitch(self, height=iPx)
|
||||
self.stripUnicode = NSwitch(self, height=iPx)
|
||||
self.replaceTabs = NSwitch(self, height=iPx)
|
||||
self.keepBreaks = NSwitch(self, height=iPx)
|
||||
|
||||
self.addRow(self._build.getLabel("format.justifyText"), self.justifyText)
|
||||
self.addRow(self._build.getLabel("format.stripUnicode"), self.stripUnicode)
|
||||
self.addRow(self._build.getLabel("format.replaceTabs"), self.replaceTabs)
|
||||
self.addRow(self._build.getLabel("format.keepBreaks"), self.keepBreaks)
|
||||
|
||||
# First Line Indent
|
||||
# =================
|
||||
@@ -1173,17 +1169,17 @@ class _FormatTab(NScrollableForm):
|
||||
|
||||
def loadContent(self) -> None:
|
||||
"""Populate the widgets."""
|
||||
textFont = self._build.getStr("format.textFont")
|
||||
if not textFont:
|
||||
textFont = str(CONFIG.textFont.family())
|
||||
self._textFont = QFont()
|
||||
self._textFont.fromString(self._build.getStr("format.textFont"))
|
||||
|
||||
self.textFont.setText(describeFont(self._textFont))
|
||||
self.textFont.setCursorPosition(0)
|
||||
|
||||
self.textFont.setText(textFont)
|
||||
self.textSize.setValue(self._build.getInt("format.textSize"))
|
||||
self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
|
||||
|
||||
self.justifyText.setChecked(self._build.getBool("format.justifyText"))
|
||||
self.stripUnicode.setChecked(self._build.getBool("format.stripUnicode"))
|
||||
self.replaceTabs.setChecked(self._build.getBool("format.replaceTabs"))
|
||||
self.keepBreaks.setChecked(self._build.getBool("format.keepBreaks"))
|
||||
|
||||
self.firstIndent.setChecked(self._build.getBool("format.firstLineIndent"))
|
||||
self.indentWidth.setValue(self._build.getFloat("format.firstIndentWidth"))
|
||||
@@ -1216,13 +1212,13 @@ class _FormatTab(NScrollableForm):
|
||||
|
||||
def saveContent(self) -> None:
|
||||
"""Save choices back into build object."""
|
||||
self._build.setValue("format.textFont", self.textFont.text())
|
||||
self._build.setValue("format.textSize", self.textSize.value())
|
||||
self._build.setValue("format.textFont", self._textFont.toString())
|
||||
self._build.setValue("format.lineHeight", self.lineHeight.value())
|
||||
|
||||
self._build.setValue("format.justifyText", self.justifyText.isChecked())
|
||||
self._build.setValue("format.stripUnicode", self.stripUnicode.isChecked())
|
||||
self._build.setValue("format.replaceTabs", self.replaceTabs.isChecked())
|
||||
self._build.setValue("format.keepBreaks", self.keepBreaks.isChecked())
|
||||
|
||||
self._build.setValue("format.firstLineIndent", self.firstIndent.isChecked())
|
||||
self._build.setValue("format.firstIndentWidth", self.indentWidth.value())
|
||||
@@ -1245,13 +1241,11 @@ class _FormatTab(NScrollableForm):
|
||||
@pyqtSlot()
|
||||
def _selectFont(self) -> None:
|
||||
"""Open the QFontDialog and set a font for the font style."""
|
||||
currFont = QFont()
|
||||
currFont.setFamily(self.textFont.text())
|
||||
currFont.setPointSize(self.textSize.value())
|
||||
newFont, status = QFontDialog.getFont(currFont, self)
|
||||
font, status = SHARED.getFont(self._textFont, CONFIG.nativeFont)
|
||||
if status:
|
||||
self.textFont.setText(newFont.family())
|
||||
self.textSize.setValue(newFont.pointSize())
|
||||
self.textFont.setText(describeFont(font))
|
||||
self.textFont.setCursorPosition(0)
|
||||
self._textFont = font
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
@@ -1379,12 +1373,6 @@ class _OutputTab(NScrollableForm):
|
||||
self.htmlPreserveTabs = NSwitch(self, height=iPx)
|
||||
self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
|
||||
|
||||
# Markdown Document
|
||||
self.addGroupLabel(self._build.getLabel("md"))
|
||||
|
||||
self.mdPreserveBreaks = NSwitch(self, height=iPx)
|
||||
self.addRow(self._build.getLabel("md.preserveBreaks"), self.mdPreserveBreaks)
|
||||
|
||||
# Finalise
|
||||
self.finalise()
|
||||
|
||||
@@ -1397,7 +1385,6 @@ class _OutputTab(NScrollableForm):
|
||||
self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
|
||||
self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
|
||||
self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
|
||||
self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
|
||||
self.odtPageHeader.setCursorPosition(0)
|
||||
return
|
||||
|
||||
@@ -1408,7 +1395,6 @@ class _OutputTab(NScrollableForm):
|
||||
self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
|
||||
self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
|
||||
self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
|
||||
self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
+21
-1
@@ -24,7 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from __future__ import annotations
|
||||
|
||||
from PyQt5.QtCore import QRegularExpression, Qt
|
||||
from PyQt5.QtGui import QColor, QPainter, QTextCursor, QTextFormat
|
||||
from PyQt5.QtGui import QColor, QFont, QPainter, QTextCursor, QTextFormat
|
||||
from PyQt5.QtWidgets import QDialogButtonBox, QSizePolicy, QStyle
|
||||
|
||||
# Qt Alignment Flags
|
||||
@@ -105,3 +105,23 @@ QtSizeMinimumExpanding = QSizePolicy.Policy.MinimumExpanding
|
||||
# Other
|
||||
|
||||
QRegExUnicode = QRegularExpression.PatternOption.UseUnicodePropertiesOption
|
||||
|
||||
# Maps
|
||||
|
||||
FONT_WEIGHTS: dict[int, int] = {
|
||||
QFont.Weight.Thin: 100,
|
||||
QFont.Weight.ExtraLight: 200,
|
||||
QFont.Weight.Light: 300,
|
||||
QFont.Weight.Normal: 400,
|
||||
QFont.Weight.Medium: 500,
|
||||
QFont.Weight.DemiBold: 600,
|
||||
QFont.Weight.Bold: 700,
|
||||
QFont.Weight.ExtraBold: 800,
|
||||
QFont.Weight.Black: 900,
|
||||
}
|
||||
|
||||
FONT_STYLE: dict[int, str] = {
|
||||
QFont.Style.StyleNormal: "normal",
|
||||
QFont.Style.StyleItalic: "italic",
|
||||
QFont.Style.StyleOblique: "oblique",
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ localisation = en_GB
|
||||
hidevscroll = False
|
||||
hidehscroll = False
|
||||
lastnotes = 0x0
|
||||
nativefont = True
|
||||
lastpath =
|
||||
|
||||
[Sizes]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<office:document xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta>
|
||||
<meta:creation-date>2024-04-24T18:30:38</meta:creation-date>
|
||||
<meta:generator>novelWriter/2.5a2</meta:generator>
|
||||
<meta:creation-date>2024-05-22T23:05:27</meta:creation-date>
|
||||
<meta:generator>novelWriter/2.5a4</meta:generator>
|
||||
<meta:initial-creator>Jane Smith</meta:initial-creator>
|
||||
<meta:editing-cycles>1234</meta:editing-cycles>
|
||||
<meta:editing-duration>P42DT12H34M56S</meta:editing-duration>
|
||||
<dc:title>Test Project</dc:title>
|
||||
<dc:date>2024-04-24T18:30:38</dc:date>
|
||||
<dc:date>2024-05-22T23:05:27</dc:date>
|
||||
<dc:creator>Jane Smith</dc:creator>
|
||||
</office:meta>
|
||||
<office:font-face-decls>
|
||||
@@ -16,50 +16,50 @@
|
||||
<office:styles>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" fo:language="nb" fo:country="NO" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-weight="normal" fo:font-style="normal" fo:font-size="12pt" fo:language="nb" fo:country="NO" />
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-weight="normal" fo:font-style="normal" fo:font-size="12pt" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" fo:keep-with-next="always" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="14pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-weight="normal" fo:font-style="normal" fo:font-size="14pt" />
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" />
|
||||
<style:style style:name="Text_20_body" style:family="paragraph" style:display-name="Text body" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" fo:text-align="left" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="First_20_line_20_indent" style:family="paragraph" style:display-name="First line indent" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:text-indent="0.593cm" />
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_Meta" style:family="paragraph" style:display-name="Text Meta" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" fo:color="#813709" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="12pt" fo:font-weight="normal" fo:color="#813709" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:display-name="Title" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" fo:text-align="center" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="30pt" fo:font-weight="bold" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="30pt" fo:font-weight="bold" />
|
||||
</style:style>
|
||||
<style:style style:name="Separator" style:family="paragraph" style:display-name="Separator" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" fo:text-align="center" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="24pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="24pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:family="paragraph" style:display-name="Heading 2" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.353cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="19pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="19pt" fo:font-weight="bold" fo:color="#2a6099" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:family="paragraph" style:display-name="Heading 3" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="16pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="16pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4" style:family="paragraph" style:display-name="Heading 4" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="14pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="14pt" fo:font-weight="bold" fo:color="#444444" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:display-name="Header" style:parent-style-name="Header_20_and_20_Footer">
|
||||
<style:paragraph-properties fo:text-align="right" />
|
||||
|
||||
@@ -6,50 +6,50 @@
|
||||
<office:styles>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" fo:language="en" fo:country="GB" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-weight="normal" fo:font-style="normal" fo:font-size="12pt" fo:language="en" fo:country="GB" />
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-weight="normal" fo:font-style="normal" fo:font-size="12pt" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" fo:keep-with-next="always" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="14pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-weight="normal" fo:font-style="normal" fo:font-size="14pt" />
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" />
|
||||
<style:style style:name="Text_20_body" style:family="paragraph" style:display-name="Text body" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" fo:text-align="left" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="First_20_line_20_indent" style:family="paragraph" style:display-name="First line indent" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:text-indent="0.593cm" />
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_Meta" style:family="paragraph" style:display-name="Text Meta" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:display-name="Title" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" fo:text-align="center" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="30pt" fo:font-weight="bold" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="30pt" fo:font-weight="bold" />
|
||||
</style:style>
|
||||
<style:style style:name="Separator" style:family="paragraph" style:display-name="Separator" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" fo:text-align="center" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="24pt" fo:font-weight="bold" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="24pt" fo:font-weight="bold" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:family="paragraph" style:display-name="Heading 2" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.353cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="19pt" fo:font-weight="bold" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="19pt" fo:font-weight="bold" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:family="paragraph" style:display-name="Heading 3" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="16pt" fo:font-weight="bold" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="16pt" fo:font-weight="bold" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4" style:family="paragraph" style:display-name="Heading 4" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="14pt" fo:font-weight="bold" />
|
||||
<style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" fo:font-size="14pt" fo:font-weight="bold" />
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:display-name="Header" style:parent-style-name="Header_20_and_20_Footer">
|
||||
<style:paragraph-properties fo:text-align="right" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<title>Lorem Ipsum</title>
|
||||
</head>
|
||||
<style>
|
||||
body {font-family: 'Arial'; font-size: 12pt;}
|
||||
body {font-family: 'Arial'; font-size: 12pt; font-weight: 400; font-style: normal;}
|
||||
p {text-align: justify; line-height: 150%; margin-top: 0.00em; margin-bottom: 0.76em;}
|
||||
h1 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 1.30em; margin-bottom: 0.65em;}
|
||||
h2 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 1.09em; margin-bottom: 0.65em;}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
"meta": {
|
||||
"projectName": "Lorem Ipsum",
|
||||
"novelAuthor": "lipsum.com",
|
||||
"buildTime": 1714336438,
|
||||
"buildTimeStr": "2024-04-28 22:33:58"
|
||||
"buildTime": 1716412100,
|
||||
"buildTimeStr": "2024-05-22 23:08:20"
|
||||
},
|
||||
"text": {
|
||||
"css": [
|
||||
"body {font-family: 'Arial'; font-size: 12pt;}",
|
||||
"body {font-family: 'Arial'; font-size: 12pt; font-weight: 400; font-style: normal;}",
|
||||
"p {text-align: justify; line-height: 150%; margin-top: 0.00em; margin-bottom: 0.76em;}",
|
||||
"h1 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 1.30em; margin-bottom: 0.65em;}",
|
||||
"h2 {color: rgb(66, 113, 174); page-break-after: avoid; margin-top: 1.09em; margin-bottom: 0.65em;}",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<office:document xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta>
|
||||
<meta:creation-date>2024-05-10T15:23:56</meta:creation-date>
|
||||
<meta:generator>novelWriter/2.5a3</meta:generator>
|
||||
<meta:creation-date>2024-05-22T23:05:26</meta:creation-date>
|
||||
<meta:generator>novelWriter/2.5a4</meta:generator>
|
||||
<meta:initial-creator>lipsum.com</meta:initial-creator>
|
||||
<meta:editing-cycles>45</meta:editing-cycles>
|
||||
<meta:editing-duration>P0DT0H36M8S</meta:editing-duration>
|
||||
<dc:title>Lorem Ipsum</dc:title>
|
||||
<dc:date>2024-05-10T15:23:56</dc:date>
|
||||
<dc:date>2024-05-22T23:05:26</dc:date>
|
||||
<dc:creator>lipsum.com</dc:creator>
|
||||
</office:meta>
|
||||
<office:font-face-decls>
|
||||
@@ -16,26 +16,26 @@
|
||||
<office:styles>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" fo:language="en" fo:country="GB" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-weight="normal" fo:font-style="normal" fo:font-size="12pt" fo:language="en" fo:country="GB" />
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-weight="normal" fo:font-style="normal" fo:font-size="12pt" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.322cm" fo:margin-bottom="0.276cm" fo:keep-with-next="always" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="14pt" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-weight="normal" fo:font-style="normal" fo:font-size="14pt" />
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" />
|
||||
<style:style style:name="Text_20_body" style:family="paragraph" style:display-name="Text body" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.322cm" fo:line-height="150%" fo:text-align="justify" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="First_20_line_20_indent" style:family="paragraph" style:display-name="First line indent" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:text-indent="0.593cm" />
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_Meta" style:family="paragraph" style:display-name="Text Meta" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.322cm" fo:line-height="150%" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" fo:color="#813709" loext:opacity="100%" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" fo:font-weight="normal" fo:color="#813709" loext:opacity="100%" />
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:display-name="Title" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.552cm" fo:margin-bottom="0.276cm" fo:text-align="center" />
|
||||
@@ -43,7 +43,7 @@
|
||||
</style:style>
|
||||
<style:style style:name="Separator" style:family="paragraph" style:display-name="Separator" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.322cm" fo:line-height="150%" fo:text-align="center" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" />
|
||||
<style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="12pt" fo:font-weight="normal" />
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.552cm" fo:margin-bottom="0.276cm" />
|
||||
|
||||
@@ -492,7 +492,8 @@ def testBaseCommon_describeFont():
|
||||
"""Test the describeFont function."""
|
||||
fontDB = QFontDatabase()
|
||||
font = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont)
|
||||
assert font.family() in describeFont(font)
|
||||
font.setPointSize(12)
|
||||
assert describeFont(font).startswith("12 pt")
|
||||
assert describeFont(None) == "Error" # type: ignore
|
||||
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ def testCoreBuildSettings_BuildValues():
|
||||
build = BuildSettings()
|
||||
|
||||
strSetting = "headings.fmtTitle"
|
||||
intSetting = "format.textSize"
|
||||
intSetting = "odt.pageCountOffset"
|
||||
boolSetting = "filter.includeNovel"
|
||||
floatSetting = "format.lineHeight"
|
||||
|
||||
|
||||
@@ -58,8 +58,7 @@ BUILD_CONF = {
|
||||
"text.includeBodyText": True,
|
||||
"text.addNoteHeadings": True,
|
||||
"format.buildLang": "en_GB",
|
||||
"format.textFont": "Arial",
|
||||
"format.textSize": 12,
|
||||
"format.textFont": "Arial,12",
|
||||
"format.lineHeight": 1.5,
|
||||
"format.justifyText": True,
|
||||
"format.stripUnicode": False,
|
||||
|
||||
@@ -316,7 +316,6 @@ def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
# Title
|
||||
html._tokens = [
|
||||
(html.T_TITLE, 1, "A Title", [], html.A_PBB | html.A_CENTRE),
|
||||
(html.T_EMPTY, 1, "", [], html.A_NONE),
|
||||
]
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
@@ -327,7 +326,6 @@ def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
# Unnumbered
|
||||
html._tokens = [
|
||||
(html.T_HEAD2, 1, "Prologue", [], html.A_PBB),
|
||||
(html.T_EMPTY, 1, "", [], html.A_NONE),
|
||||
]
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
@@ -341,7 +339,6 @@ def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
# Separator
|
||||
html._tokens = [
|
||||
(html.T_SEP, 1, "* * *", [], html.A_CENTRE),
|
||||
(html.T_EMPTY, 1, "", [], html.A_NONE),
|
||||
]
|
||||
html.doConvert()
|
||||
assert html.result == "<p class='sep' style='text-align: center;'>* * *</p>\n"
|
||||
@@ -349,7 +346,6 @@ def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
# Skip
|
||||
html._tokens = [
|
||||
(html.T_SKIP, 1, "", [], html.A_NONE),
|
||||
(html.T_EMPTY, 1, "", [], html.A_NONE),
|
||||
]
|
||||
html.doConvert()
|
||||
assert html.result == "<p class='skip'> </p>\n"
|
||||
@@ -425,8 +421,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
|
||||
# Indent Left
|
||||
html._tokens = [
|
||||
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_L),
|
||||
(html.T_EMPTY, 2, "", [], html.A_NONE),
|
||||
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_L),
|
||||
]
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
@@ -435,8 +430,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
|
||||
# Indent Right
|
||||
html._tokens = [
|
||||
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_R),
|
||||
(html.T_EMPTY, 2, "", [], html.A_NONE),
|
||||
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_R),
|
||||
]
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
|
||||
@@ -24,6 +24,8 @@ import json
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
from novelwriter.constants import nwHeadFmt
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.tokenizer import HeadingFormatter, Tokenizer, stripEscape
|
||||
@@ -50,9 +52,7 @@ def testCoreToken_Setters(mockGUI):
|
||||
assert tokens._fmtScene == nwHeadFmt.TITLE
|
||||
assert tokens._fmtHScene == nwHeadFmt.TITLE
|
||||
assert tokens._fmtSection == nwHeadFmt.TITLE
|
||||
assert tokens._textFont == "Serif"
|
||||
assert tokens._textSize == 11
|
||||
assert tokens._textFixed is False
|
||||
assert tokens._textFont == QFont("Serif", 11)
|
||||
assert tokens._lineHeight == 1.15
|
||||
assert tokens._blockIndent == 4.0
|
||||
assert tokens._doJustify is False
|
||||
@@ -82,7 +82,7 @@ def testCoreToken_Setters(mockGUI):
|
||||
tokens.setSceneFormat(f"S: {nwHeadFmt.TITLE}", True)
|
||||
tokens.setHardSceneFormat(f"H: {nwHeadFmt.TITLE}", True)
|
||||
tokens.setSectionFormat(f"X: {nwHeadFmt.TITLE}", True)
|
||||
tokens.setFont("Monospace", 10, True)
|
||||
tokens.setFont(QFont("Monospace", 10))
|
||||
tokens.setLineHeight(2.0)
|
||||
tokens.setBlockIndent(6.0)
|
||||
tokens.setJustify(True)
|
||||
@@ -106,9 +106,7 @@ def testCoreToken_Setters(mockGUI):
|
||||
assert tokens._fmtScene == f"S: {nwHeadFmt.TITLE}"
|
||||
assert tokens._fmtHScene == f"H: {nwHeadFmt.TITLE}"
|
||||
assert tokens._fmtSection == f"X: {nwHeadFmt.TITLE}"
|
||||
assert tokens._textFont == "Monospace"
|
||||
assert tokens._textSize == 10
|
||||
assert tokens._textFixed is True
|
||||
assert tokens._textFont == QFont("Monospace", 10)
|
||||
assert tokens._lineHeight == 2.0
|
||||
assert tokens._blockIndent == 6.0
|
||||
assert tokens._doJustify is True
|
||||
@@ -1835,7 +1833,7 @@ def testCoreToken_SceneSeparators(mockGUI):
|
||||
# ===========================
|
||||
# Requires a fresh builder class
|
||||
md = ToMarkdown(project)
|
||||
md.setExtendedMarkdown()
|
||||
md.setExtendedMarkdown(True)
|
||||
md._isNovel = True
|
||||
|
||||
md._text = (
|
||||
|
||||
@@ -82,7 +82,7 @@ def testCoreToMarkdown_ConvertParagraphs(mockGUI):
|
||||
toMD._isFirst = True
|
||||
|
||||
# Text for Extended Markdown
|
||||
toMD.setExtendedMarkdown()
|
||||
toMD.setExtendedMarkdown(True)
|
||||
toMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
toMD.tokenizeText()
|
||||
toMD.doConvert()
|
||||
@@ -91,7 +91,7 @@ def testCoreToMarkdown_ConvertParagraphs(mockGUI):
|
||||
)
|
||||
|
||||
# Text for Standard Markdown
|
||||
toMD.setStandardMarkdown()
|
||||
toMD.setExtendedMarkdown(False)
|
||||
toMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
toMD.tokenizeText()
|
||||
toMD.doConvert()
|
||||
@@ -100,7 +100,7 @@ def testCoreToMarkdown_ConvertParagraphs(mockGUI):
|
||||
)
|
||||
|
||||
# Shortcodes for Extended Markdown
|
||||
toMD.setExtendedMarkdown()
|
||||
toMD.setExtendedMarkdown(True)
|
||||
toMD._text = (
|
||||
"Some [b]bold[/b], [i]italic[/i], [s]strike[/s], [u]underline[/u], [m]mark[/m], "
|
||||
"super[sup]script[/sup], sub[sub]script[/sub] here\n"
|
||||
@@ -113,7 +113,7 @@ def testCoreToMarkdown_ConvertParagraphs(mockGUI):
|
||||
)
|
||||
|
||||
# Shortcodes for Standard Markdown
|
||||
toMD.setStandardMarkdown()
|
||||
toMD.setExtendedMarkdown(False)
|
||||
toMD._text = (
|
||||
"Some [b]bold[/b], [i]italic[/i], [s]strike[/s], [u]underline[/u], [m]mark[/m], "
|
||||
"super[sup]script[/sup], sub[sub]script[/sub] here\n"
|
||||
@@ -215,6 +215,7 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
|
||||
toMD = ToMarkdown(project)
|
||||
|
||||
toMD._isNovel = True
|
||||
toMD.setExtendedMarkdown(False)
|
||||
|
||||
# Special Titles
|
||||
# ==============
|
||||
@@ -222,7 +223,6 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
|
||||
# Title
|
||||
toMD._tokens = [
|
||||
(toMD.T_TITLE, 1, "A Title", [], toMD.A_PBB | toMD.A_CENTRE),
|
||||
(toMD.T_EMPTY, 1, "", [], toMD.A_NONE),
|
||||
]
|
||||
toMD.doConvert()
|
||||
assert toMD.result == "# A Title\n\n"
|
||||
@@ -233,7 +233,6 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
|
||||
# Separator
|
||||
toMD._tokens = [
|
||||
(toMD.T_SEP, 1, "* * *", [], toMD.A_CENTRE),
|
||||
(toMD.T_EMPTY, 1, "", [], toMD.A_NONE),
|
||||
]
|
||||
toMD.doConvert()
|
||||
assert toMD.result == "* * *\n\n"
|
||||
@@ -241,7 +240,6 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
|
||||
# Skip
|
||||
toMD._tokens = [
|
||||
(toMD.T_SKIP, 1, "", [], toMD.A_NONE),
|
||||
(toMD.T_EMPTY, 1, "", [], toMD.A_NONE),
|
||||
]
|
||||
toMD.doConvert()
|
||||
assert toMD.result == "\n\n"
|
||||
|
||||
@@ -683,7 +683,6 @@ def testCoreToOdt_ConvertDirect(mockGUI):
|
||||
doc = ToOdt(project, isFlat=True)
|
||||
doc._tokens = [
|
||||
(doc.T_TEXT, 1, "This is a paragraph", [], doc.A_JUSTIFY),
|
||||
(doc.T_EMPTY, 1, "", [], doc.A_NONE),
|
||||
]
|
||||
doc.initDocument()
|
||||
doc.doConvert()
|
||||
@@ -704,7 +703,6 @@ def testCoreToOdt_ConvertDirect(mockGUI):
|
||||
doc = ToOdt(project, isFlat=True)
|
||||
doc._tokens = [
|
||||
(doc.T_TEXT, 1, "This is a paragraph", [], doc.A_PBA),
|
||||
(doc.T_EMPTY, 1, "", [], doc.A_NONE),
|
||||
]
|
||||
doc.initDocument()
|
||||
doc.doConvert()
|
||||
@@ -1045,10 +1043,26 @@ def testCoreToOdt_ODTParagraphStyle():
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", None]
|
||||
parStyle.setFontWeight("normal")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "normal"]
|
||||
parStyle.setFontWeight("inherit")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "inherit"]
|
||||
parStyle.setFontWeight("bold")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "bold"]
|
||||
parStyle.setFontWeight("100")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "100"]
|
||||
parStyle.setFontWeight("200")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "200"]
|
||||
parStyle.setFontWeight("300")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "300"]
|
||||
parStyle.setFontWeight("400")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "400"]
|
||||
parStyle.setFontWeight("500")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "500"]
|
||||
parStyle.setFontWeight("600")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "600"]
|
||||
parStyle.setFontWeight("700")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "700"]
|
||||
parStyle.setFontWeight("800")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "800"]
|
||||
parStyle.setFontWeight("900")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", "900"]
|
||||
parStyle.setFontWeight("stuff")
|
||||
assert parStyle._tAttr["font-weight"] == ["fo", None]
|
||||
|
||||
@@ -1118,10 +1132,26 @@ def testCoreToOdt_ODTTextStyle():
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", None]
|
||||
txtStyle.setFontWeight("normal")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "normal"]
|
||||
txtStyle.setFontWeight("inherit")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "inherit"]
|
||||
txtStyle.setFontWeight("bold")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "bold"]
|
||||
txtStyle.setFontWeight("100")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "100"]
|
||||
txtStyle.setFontWeight("200")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "200"]
|
||||
txtStyle.setFontWeight("300")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "300"]
|
||||
txtStyle.setFontWeight("400")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "400"]
|
||||
txtStyle.setFontWeight("500")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "500"]
|
||||
txtStyle.setFontWeight("600")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "600"]
|
||||
txtStyle.setFontWeight("700")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "700"]
|
||||
txtStyle.setFontWeight("800")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "800"]
|
||||
txtStyle.setFontWeight("900")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", "900"]
|
||||
txtStyle.setFontWeight("stuff")
|
||||
assert txtStyle._tAttr["font-weight"] == ["fo", None]
|
||||
|
||||
@@ -1131,10 +1161,10 @@ def testCoreToOdt_ODTTextStyle():
|
||||
assert txtStyle._tAttr["font-style"] == ["fo", None]
|
||||
txtStyle.setFontStyle("normal")
|
||||
assert txtStyle._tAttr["font-style"] == ["fo", "normal"]
|
||||
txtStyle.setFontStyle("inherit")
|
||||
assert txtStyle._tAttr["font-style"] == ["fo", "inherit"]
|
||||
txtStyle.setFontStyle("italic")
|
||||
assert txtStyle._tAttr["font-style"] == ["fo", "italic"]
|
||||
txtStyle.setFontStyle("oblique")
|
||||
assert txtStyle._tAttr["font-style"] == ["fo", "oblique"]
|
||||
txtStyle.setFontStyle("stuff")
|
||||
assert txtStyle._tAttr["font-style"] == ["fo", None]
|
||||
|
||||
|
||||
@@ -160,20 +160,12 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, tstPaths):
|
||||
prefs = GuiPreferences(nwGUI)
|
||||
prefs.show()
|
||||
|
||||
# Mock Font
|
||||
class MockFont:
|
||||
|
||||
def family(self):
|
||||
return "TestFont"
|
||||
|
||||
def pointSize(self):
|
||||
return 42
|
||||
|
||||
# Appearance
|
||||
prefs.guiLocale.setCurrentIndex(prefs.guiLocale.findData("en_US"))
|
||||
prefs.guiTheme.setCurrentIndex(prefs.guiTheme.findData("default_dark"))
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr(QFontDialog, "getFont", lambda *a: (QFont(), True))
|
||||
mp.setattr(QFontDialog, "getFont", lambda *a, **k: (QFont(), True))
|
||||
prefs.nativeFont.setChecked(True) # Use OS font dialog
|
||||
prefs.guiFontButton.click()
|
||||
prefs.hideVScroll.setChecked(True)
|
||||
prefs.hideHScroll.setChecked(True)
|
||||
@@ -187,7 +179,8 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, tstPaths):
|
||||
# Document Style
|
||||
prefs.guiSyntax.setCurrentIndex(prefs.guiSyntax.findData("default_dark"))
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr(QFontDialog, "getFont", lambda *a: (QFont(), True))
|
||||
mp.setattr(QFontDialog, "getFont", lambda *a, **k: (QFont(), True))
|
||||
prefs.nativeFont.setChecked(False) # Use Qt font dialog
|
||||
prefs.textFontButton.click()
|
||||
prefs.emphLabels.setChecked(False)
|
||||
prefs.showFullPath.setChecked(False)
|
||||
|
||||
@@ -26,7 +26,8 @@ from PyQt5.QtCore import pyqtSlot
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtWidgets import QFontDialog
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter import SHARED
|
||||
from novelwriter.common import describeFont
|
||||
from novelwriter.constants import nwHeadFmt
|
||||
from novelwriter.core.buildsettings import BuildSettings, FilterMode
|
||||
from novelwriter.tools.manussettings import (
|
||||
@@ -547,11 +548,8 @@ def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
|
||||
"""Test the Format Tab of the GuiBuildSettings dialog."""
|
||||
build = BuildSettings()
|
||||
|
||||
textFont = str(CONFIG.textFont.family())
|
||||
|
||||
build.setValue("format.buildLang", "en_US")
|
||||
build.setValue("format.textFont", "") # Will fall back to config value
|
||||
build.setValue("format.textSize", 12)
|
||||
build.setValue("format.lineHeight", 1.2)
|
||||
|
||||
build.setValue("format.justifyText", False)
|
||||
@@ -577,8 +575,6 @@ def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
|
||||
assert bSettings.toolStack.currentWidget() is fmtTab
|
||||
|
||||
# Check initial values
|
||||
assert fmtTab.textFont.text() == textFont
|
||||
assert fmtTab.textSize.value() == 12
|
||||
assert fmtTab.lineHeight.value() == 1.2
|
||||
|
||||
assert fmtTab.justifyText.isChecked() is False
|
||||
@@ -599,8 +595,9 @@ def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
|
||||
assert fmtTab.rightMargin.value() == 15.0
|
||||
|
||||
# Change values
|
||||
fmtTab.textFont.setText("Arial")
|
||||
fmtTab.textSize.setValue(11)
|
||||
testFont = QFont("Arial", 11)
|
||||
fmtTab._textFont = testFont
|
||||
fmtTab.textFont.setText(describeFont(testFont))
|
||||
fmtTab.lineHeight.setValue(1.15)
|
||||
|
||||
fmtTab.justifyText.setChecked(True)
|
||||
@@ -617,8 +614,7 @@ def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
|
||||
# Save values
|
||||
fmtTab.saveContent()
|
||||
|
||||
assert build.getStr("format.textFont") == "Arial"
|
||||
assert build.getInt("format.textSize") == 11
|
||||
assert build.getStr("format.textFont") == testFont.toString()
|
||||
assert build.getFloat("format.lineHeight") == 1.15
|
||||
|
||||
assert build.getBool("format.justifyText") is True
|
||||
@@ -643,11 +639,10 @@ def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
|
||||
font = QFont()
|
||||
font.setFamily("Times")
|
||||
font.setPointSize(10)
|
||||
mp.setattr(QFontDialog, "getFont", lambda *a: (font, True))
|
||||
mp.setattr(QFontDialog, "getFont", lambda *a, **k: (font, True))
|
||||
|
||||
fmtTab.btnTextFont.click()
|
||||
assert fmtTab.textFont.text() == "Times"
|
||||
assert fmtTab.textSize.value() == 10
|
||||
assert fmtTab._textFont == font
|
||||
|
||||
# Finish
|
||||
bSettings._dialogButtonClicked(bSettings.buttonBox.button(QtDialogClose))
|
||||
@@ -677,13 +672,11 @@ def testBuildSettings_Output(qtbot, nwGUI):
|
||||
assert outTab.odtPageCountOffset.value() == 0
|
||||
assert outTab.htmlAddStyles.isChecked() is False
|
||||
assert outTab.htmlPreserveTabs.isChecked() is False
|
||||
assert outTab.mdPreserveBreaks.isChecked() is True
|
||||
|
||||
# Toggle all
|
||||
outTab.odtAddColours.setChecked(True)
|
||||
outTab.htmlAddStyles.setChecked(True)
|
||||
outTab.htmlPreserveTabs.setChecked(True)
|
||||
outTab.mdPreserveBreaks.setChecked(False)
|
||||
|
||||
# Change Values
|
||||
outTab.odtPageCountOffset.setValue(1)
|
||||
@@ -697,7 +690,6 @@ def testBuildSettings_Output(qtbot, nwGUI):
|
||||
assert build.getInt("odt.pageCountOffset") == 1
|
||||
assert build.getBool("html.addStyles") is True
|
||||
assert build.getBool("html.preserveTabs") is True
|
||||
assert build.getBool("md.preserveBreaks") is False
|
||||
|
||||
# Reset header format
|
||||
outTab.btnPageHeader.click()
|
||||
|
||||
Reference in New Issue
Block a user