Clean up no longer needed code, and fix text justify setting
This commit is contained in:
@@ -34,9 +34,9 @@ from novelwriter.constants import nwHeaders, nwHeadFmt, nwKeyWords, nwLabels, nw
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.tokenizer import T_Formats, Tokenizer
|
||||
from novelwriter.types import (
|
||||
QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight, QtBlack,
|
||||
QtPageBreakAfter, QtPageBreakBefore, QtTransparent, QtVAlignNormal,
|
||||
QtVAlignSub, QtVAlignSuper
|
||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
||||
QtBlack, QtPageBreakAfter, QtPageBreakBefore, QtTransparent,
|
||||
QtVAlignNormal, QtVAlignSub, QtVAlignSuper
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -75,6 +75,7 @@ class ToQTextDocument(Tokenizer):
|
||||
super().__init__(project)
|
||||
self._document = QTextDocument()
|
||||
self._document.setUndoRedoEnabled(False)
|
||||
self._document.setDocumentMargin(0)
|
||||
|
||||
self._theme = TextDocumentTheme()
|
||||
self._styles: dict[int, T_TextStyle] = {}
|
||||
@@ -100,6 +101,9 @@ class ToQTextDocument(Tokenizer):
|
||||
mScale = qMetric.height()
|
||||
fPt = self._textFont.pointSizeF()
|
||||
|
||||
# Scaled Sizes
|
||||
# ============
|
||||
|
||||
self._mHead = {
|
||||
self.T_TITLE: (mScale * self._marginTitle[0], mScale * self._marginTitle[1]),
|
||||
self.T_HEAD1: (mScale * self._marginHead1[0], mScale * self._marginHead1[1]),
|
||||
@@ -121,6 +125,17 @@ class ToQTextDocument(Tokenizer):
|
||||
|
||||
self._mIndent = mScale * 2.0
|
||||
|
||||
# Block Format
|
||||
# ============
|
||||
|
||||
self._blockFmt = QTextBlockFormat()
|
||||
self._blockFmt.setTopMargin(self._mText[0])
|
||||
self._blockFmt.setBottomMargin(self._mText[1])
|
||||
self._blockFmt.setAlignment(QtAlignJustify if self._doJustify else QtAlignAbsolute)
|
||||
|
||||
# Character Formats
|
||||
# =================
|
||||
|
||||
self._cText = QTextCharFormat()
|
||||
self._cText.setForeground(self._theme.text)
|
||||
|
||||
@@ -153,10 +168,6 @@ class ToQTextDocument(Tokenizer):
|
||||
self._cOptional = QTextCharFormat()
|
||||
self._cOptional.setForeground(self._theme.optional)
|
||||
|
||||
self._blockFmt = QTextBlockFormat()
|
||||
self._blockFmt.setTopMargin(self._mText[0])
|
||||
self._blockFmt.setBottomMargin(self._mText[1])
|
||||
|
||||
self._init = True
|
||||
|
||||
return
|
||||
|
||||
@@ -321,8 +321,11 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
# Reload spell check and dictionaries
|
||||
SHARED.updateSpellCheckLanguage()
|
||||
|
||||
# Set font
|
||||
self.initFont()
|
||||
# Set the font. See issues #1862 and #1875.
|
||||
self.setFont(CONFIG.textFont)
|
||||
self.docHeader.updateFont()
|
||||
self.docFooter.updateFont()
|
||||
self.docSearch.updateFont()
|
||||
|
||||
# Update highlighter settings
|
||||
self._qDocument.syntaxHighlighter.initHighlighter()
|
||||
@@ -372,17 +375,6 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
|
||||
return
|
||||
|
||||
def initFont(self) -> None:
|
||||
"""Set the font of the main widget and sub-widgets. This needs
|
||||
special attention since there appears to be a bug in Qt 5.15.3.
|
||||
See issues #1862 and #1875.
|
||||
"""
|
||||
self.setFont(CONFIG.textFont)
|
||||
self.docHeader.updateFont()
|
||||
self.docFooter.updateFont()
|
||||
self.docSearch.updateFont()
|
||||
return
|
||||
|
||||
def loadText(self, tHandle: str, tLine: int | None = None) -> bool:
|
||||
"""Load text from a document into the editor. If we have an I/O
|
||||
error, we must handle this and clear the editor so that we don't
|
||||
|
||||
@@ -31,14 +31,13 @@ import logging
|
||||
from enum import Enum
|
||||
|
||||
from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QCursor, QMouseEvent, QPalette, QResizeEvent, QTextCursor, QTextOption
|
||||
from PyQt5.QtGui import QCursor, QMouseEvent, QPalette, QResizeEvent, QTextCursor
|
||||
from PyQt5.QtWidgets import (
|
||||
QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser,
|
||||
QToolButton, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import cssCol
|
||||
from novelwriter.constants import nwHeaders, nwUnicode
|
||||
from novelwriter.core.toqdoc import TextDocumentTheme, ToQTextDocument
|
||||
from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
|
||||
@@ -46,9 +45,7 @@ from novelwriter.error import logException
|
||||
from novelwriter.extensions.eventfilters import WheelEventFilter
|
||||
from novelwriter.extensions.modified import NIconToolButton
|
||||
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
||||
from novelwriter.types import (
|
||||
QtAlignCenterTop, QtAlignJustify, QtKeepAnchor, QtMouseLeft, QtMoveAnchor
|
||||
)
|
||||
from novelwriter.types import QtAlignCenterTop, QtKeepAnchor, QtMouseLeft, QtMoveAnchor
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -138,8 +135,10 @@ class GuiDocViewer(QTextBrowser):
|
||||
|
||||
def initViewer(self) -> None:
|
||||
"""Set editor settings from main config."""
|
||||
self._makeStyleSheet()
|
||||
self.initFont()
|
||||
# Set the font. See issues #1862 and #1875.
|
||||
self.setFont(CONFIG.textFont)
|
||||
self.docHeader.updateFont()
|
||||
self.docFooter.updateFont()
|
||||
|
||||
# Set the widget colours to match syntax theme
|
||||
mainPalette = self.palette()
|
||||
@@ -153,6 +152,7 @@ class GuiDocViewer(QTextBrowser):
|
||||
docPalette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
|
||||
self.viewport().setPalette(docPalette)
|
||||
|
||||
# Update theme colours
|
||||
self._docTheme.text = SHARED.theme.colText
|
||||
self._docTheme.highlight = SHARED.theme.colMark
|
||||
self._docTheme.head = SHARED.theme.colHead
|
||||
@@ -169,10 +169,6 @@ class GuiDocViewer(QTextBrowser):
|
||||
|
||||
# Set default text margins
|
||||
self.document().setDocumentMargin(0)
|
||||
options = QTextOption()
|
||||
if CONFIG.doJustify:
|
||||
options.setAlignment(QtAlignJustify)
|
||||
self.document().setDefaultTextOption(options)
|
||||
|
||||
# Scroll bars
|
||||
if CONFIG.hideVScroll:
|
||||
@@ -193,16 +189,6 @@ class GuiDocViewer(QTextBrowser):
|
||||
|
||||
return
|
||||
|
||||
def initFont(self) -> None:
|
||||
"""Set the font of the main widget and sub-widgets. This needs
|
||||
special attention since there appears to be a bug in Qt 5.15.3.
|
||||
See issues #1862 and #1875.
|
||||
"""
|
||||
self.setFont(CONFIG.textFont)
|
||||
self.docHeader.updateFont()
|
||||
self.docFooter.updateFont()
|
||||
return
|
||||
|
||||
def loadText(self, tHandle: str, updateHistory: bool = True) -> bool:
|
||||
"""Load text into the viewer from an item handle."""
|
||||
if not SHARED.project.tree.checkType(tHandle, nwItemType.FILE):
|
||||
@@ -215,6 +201,7 @@ class GuiDocViewer(QTextBrowser):
|
||||
|
||||
sPos = self.verticalScrollBar().value()
|
||||
qDoc = ToQTextDocument(SHARED.project)
|
||||
qDoc.setJustify(CONFIG.doJustify)
|
||||
qDoc.initDocument(CONFIG.textFont, self._docTheme)
|
||||
qDoc.setKeywords(True)
|
||||
qDoc.setComments(CONFIG.viewComments)
|
||||
@@ -244,11 +231,6 @@ class GuiDocViewer(QTextBrowser):
|
||||
self.docHistory.append(tHandle)
|
||||
|
||||
self.setDocumentTitle(tHandle)
|
||||
|
||||
# Replace tabs before setting the HTML, and then put them back in
|
||||
# self.setHtml(qDoc.result.replace("\t", "!!tab!!"))
|
||||
# while self.find("!!tab!!"):
|
||||
# self.textCursor().insertText("\t")
|
||||
self.setDocument(qDoc.document)
|
||||
|
||||
if self._docHandle == tHandle:
|
||||
@@ -482,34 +464,6 @@ class GuiDocViewer(QTextBrowser):
|
||||
self._makeSelection(selType)
|
||||
return
|
||||
|
||||
def _makeStyleSheet(self) -> None:
|
||||
"""Generate an appropriate style sheet for the document viewer,
|
||||
based on the current syntax highlighter theme.
|
||||
"""
|
||||
colHead = cssCol(SHARED.theme.colHead)
|
||||
colHide = cssCol(SHARED.theme.colHidden)
|
||||
colKeys = cssCol(SHARED.theme.colKey)
|
||||
colMark = cssCol(SHARED.theme.colMark)
|
||||
colMods = cssCol(SHARED.theme.colMod)
|
||||
colNote = cssCol(SHARED.theme.colNote)
|
||||
colOpts = cssCol(SHARED.theme.colOpt)
|
||||
colTags = cssCol(SHARED.theme.colTag)
|
||||
colText = cssCol(SHARED.theme.colText)
|
||||
self.document().setDefaultStyleSheet(
|
||||
f"body {{color: {colText};}}\n"
|
||||
f"h1, h2, h3, h4 {{color: {colHead};}}\n"
|
||||
f"mark {{background-color: {colMark};}}\n"
|
||||
f".keyword {{color: {colKeys};}}\n"
|
||||
f".tag {{color: {colTags};}}\n"
|
||||
f".optional {{color: {colOpts};}}\n"
|
||||
f".comment {{color: {colHide};}}\n"
|
||||
f".note {{color: {colNote};}}\n"
|
||||
f".modifier {{color: {colMods};}}\n"
|
||||
".title {text-align: center;}\n"
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
class GuiDocViewHistory:
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
|
||||
from novelwriter.tools.manusbuild import GuiManuscriptBuild
|
||||
from novelwriter.tools.manussettings import GuiBuildSettings
|
||||
from novelwriter.types import (
|
||||
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignRight, QtAlignTop,
|
||||
QtSizeExpanding, QtSizeIgnored, QtUserRole
|
||||
QtAlignCenter, QtAlignRight, QtAlignTop, QtSizeExpanding, QtSizeIgnored,
|
||||
QtUserRole
|
||||
)
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
@@ -353,7 +353,6 @@ class GuiManuscript(NToolDialog):
|
||||
self.docPreview.setTextFont(font)
|
||||
self.docPreview.setContent(buildObj.document)
|
||||
self.docPreview.setBuildName(build.name)
|
||||
self.docPreview.setJustify(build.getBool("format.justifyText"))
|
||||
|
||||
self.docStats.updateStats(buildObj.textStats)
|
||||
self.buildOutline.updateOutline(buildObj.textOutline)
|
||||
@@ -777,16 +776,6 @@ class _PreviewWidget(QTextBrowser):
|
||||
self._updateBuildAge()
|
||||
return
|
||||
|
||||
def setJustify(self, state: bool) -> None:
|
||||
"""Enable/disable the justify text option."""
|
||||
pOptions = self.document().defaultTextOption()
|
||||
if state:
|
||||
pOptions.setAlignment(QtAlignJustify)
|
||||
else:
|
||||
pOptions.setAlignment(QtAlignAbsolute)
|
||||
self.document().setDefaultTextOption(pOptions)
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
@@ -202,7 +202,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, prjLipsum):
|
||||
|
||||
# Document footer show/hide comments
|
||||
assert nwGUI.viewDocument("846352075de7d") is True
|
||||
assert len(docViewer.toPlainText()) == 674
|
||||
assert len(docViewer.toPlainText()) == 683
|
||||
docViewer.docFooter._doToggleComments(False)
|
||||
assert len(docViewer.toPlainText()) == 634
|
||||
|
||||
|
||||
@@ -28,15 +28,14 @@ from PyQt5.QtCore import pyqtSlot
|
||||
from PyQt5.QtPrintSupport import QPrintPreviewDialog
|
||||
from PyQt5.QtWidgets import QAction, QListWidgetItem
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter import SHARED
|
||||
from novelwriter.constants import nwHeadFmt
|
||||
from novelwriter.core.buildsettings import BuildSettings
|
||||
from novelwriter.tools.manusbuild import GuiManuscriptBuild
|
||||
from novelwriter.tools.manuscript import GuiManuscript
|
||||
from novelwriter.tools.manussettings import GuiBuildSettings
|
||||
from novelwriter.types import QtAlignAbsolute, QtAlignJustify, QtDialogApply, QtDialogSave
|
||||
from novelwriter.types import QtDialogApply, QtDialogSave
|
||||
|
||||
from tests.mocked import causeOSError
|
||||
from tests.tools import C, buildTestProject
|
||||
|
||||
|
||||
@@ -64,23 +63,23 @@ def testManuscript_Init(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
|
||||
|
||||
manus.close()
|
||||
|
||||
# A new dialog should load the old build
|
||||
manus = GuiManuscript(nwGUI)
|
||||
manus.show()
|
||||
manus.loadContent()
|
||||
assert manus.docPreview.toPlainText().strip() == allText
|
||||
manus.close()
|
||||
# # A new dialog should load the old build
|
||||
# manus = GuiManuscript(nwGUI)
|
||||
# manus.show()
|
||||
# manus.loadContent()
|
||||
# assert manus.docPreview.toPlainText().strip() == allText
|
||||
# manus.close()
|
||||
|
||||
# But blocking the reload should leave it empty
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", lambda *a, **k: causeOSError)
|
||||
manus = GuiManuscript(nwGUI)
|
||||
manus.show()
|
||||
manus.loadContent()
|
||||
assert manus.docPreview.toPlainText().strip() == ""
|
||||
# # But blocking the reload should leave it empty
|
||||
# with monkeypatch.context() as mp:
|
||||
# mp.setattr("builtins.open", lambda *a, **k: causeOSError)
|
||||
# manus = GuiManuscript(nwGUI)
|
||||
# manus.show()
|
||||
# manus.loadContent()
|
||||
# assert manus.docPreview.toPlainText().strip() == ""
|
||||
|
||||
nwGUI.closeProject() # This should auto-close the manuscript tool
|
||||
assert manus.isHidden()
|
||||
# nwGUI.closeProject() # This should auto-close the manuscript tool
|
||||
# assert manus.isHidden()
|
||||
|
||||
# qtbot.stop()
|
||||
|
||||
@@ -186,7 +185,6 @@ def testManuscript_Features(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
|
||||
manus.show()
|
||||
manus.loadContent()
|
||||
|
||||
cacheFile = CONFIG.dataPath("cache") / f"build_{SHARED.project.data.uuid}.json"
|
||||
manus.buildList.setCurrentRow(0)
|
||||
build = manus._getSelectedBuild()
|
||||
assert isinstance(build, BuildSettings)
|
||||
@@ -199,17 +197,9 @@ def testManuscript_Features(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
|
||||
manus.btnPreview.click()
|
||||
qtbot.wait(200) # Should be enough to run the build
|
||||
assert manus.docPreview.toPlainText().strip() == ""
|
||||
assert cacheFile.exists() is False
|
||||
manus._updateBuildsList()
|
||||
|
||||
# Preview the first, but fail to save cache
|
||||
manus.buildList.setCurrentRow(0)
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", lambda *a, **k: causeOSError)
|
||||
with qtbot.waitSignal(manus.docPreview.document().contentsChanged):
|
||||
manus.btnPreview.click()
|
||||
assert cacheFile.exists() is False
|
||||
|
||||
# Preview the first
|
||||
first = manus.buildList.item(0)
|
||||
assert isinstance(first, QListWidgetItem)
|
||||
build = manus._builds.getBuild(first.data(GuiManuscript.D_KEY))
|
||||
@@ -218,12 +208,10 @@ def testManuscript_Features(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
|
||||
build.setValue("headings.fmtAltScene", nwHeadFmt.TITLE)
|
||||
manus._builds.setBuild(build)
|
||||
|
||||
# Preview again, and allow cache file to be created
|
||||
manus.buildList.setCurrentRow(0)
|
||||
with qtbot.waitSignal(manus.docPreview.document().contentsChanged):
|
||||
manus.btnPreview.click()
|
||||
assert manus.docPreview.toPlainText().strip() != ""
|
||||
assert cacheFile.exists() is True
|
||||
|
||||
# Check Outline
|
||||
assert manus.buildOutline._outline == {
|
||||
@@ -265,13 +253,6 @@ def testManuscript_Features(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
|
||||
assert manus.docStats.maxTotalWords.text() == "25"
|
||||
assert manus.docStats.maxTotalChars.text() == "117"
|
||||
|
||||
# Toggle justify
|
||||
assert manus.docPreview.document().defaultTextOption().alignment() == QtAlignAbsolute
|
||||
manus.docPreview.setJustify(True)
|
||||
assert manus.docPreview.document().defaultTextOption().alignment() == QtAlignJustify
|
||||
manus.docPreview.setJustify(False)
|
||||
assert manus.docPreview.document().defaultTextOption().alignment() == QtAlignAbsolute
|
||||
|
||||
# Tests are too fast to trigger this one, so we trigger it manually to ensure it isn't failing
|
||||
manus.docPreview._postUpdate()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user