Skip to content

Commit

Permalink
Clean up no longer needed code, and fix text justify setting
Browse files Browse the repository at this point in the history
  • Loading branch information
vkbo committed May 24, 2024
1 parent e74c105 commit a4e3bf8
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 125 deletions.
25 changes: 18 additions & 7 deletions novelwriter/core/toqdoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
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__)
Expand Down Expand Up @@ -75,6 +75,7 @@ def __init__(self, project: NWProject) -> None:
super().__init__(project)
self._document = QTextDocument()
self._document.setUndoRedoEnabled(False)
self._document.setDocumentMargin(0)

self._theme = TextDocumentTheme()
self._styles: dict[int, T_TextStyle] = {}
Expand All @@ -100,6 +101,9 @@ def initDocument(self, font: QFont, theme: TextDocumentTheme) -> None:
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]),
Expand All @@ -121,6 +125,17 @@ def initDocument(self, font: QFont, theme: TextDocumentTheme) -> None:

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)

Expand Down Expand Up @@ -153,10 +168,6 @@ def initDocument(self, font: QFont, theme: TextDocumentTheme) -> None:
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
Expand Down
18 changes: 5 additions & 13 deletions novelwriter/gui/doceditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,11 @@ def initEditor(self) -> None:
# 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()
Expand Down Expand Up @@ -372,17 +375,6 @@ def initEditor(self) -> None:

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
Expand Down
62 changes: 8 additions & 54 deletions novelwriter/gui/docviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,21 @@
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
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__)

Expand Down Expand Up @@ -138,8 +135,10 @@ def updateTheme(self) -> None:

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()
Expand All @@ -153,6 +152,7 @@ def initViewer(self) -> None:
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
Expand All @@ -169,10 +169,6 @@ def initViewer(self) -> None:

# 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:
Expand All @@ -193,16 +189,6 @@ def initViewer(self) -> None:

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):
Expand All @@ -215,6 +201,7 @@ def loadText(self, tHandle: str, updateHistory: bool = True) -> bool:

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)
Expand Down Expand Up @@ -244,11 +231,6 @@ def loadText(self, tHandle: str, updateHistory: bool = True) -> bool:
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:
Expand Down Expand Up @@ -482,34 +464,6 @@ def _makePosSelection(self, selType: QTextCursor.SelectionType, pos: QPoint) ->
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:

Expand Down
15 changes: 2 additions & 13 deletions novelwriter/tools/manuscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
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
Expand Down Expand Up @@ -353,7 +353,6 @@ def _generatePreview(self) -> None:
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)
Expand Down Expand Up @@ -777,16 +776,6 @@ def setBuildName(self, name: str) -> None:
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
Expand Down
2 changes: 1 addition & 1 deletion tests/test_gui/test_gui_docviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def mockExec(*a):

# 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

Expand Down
55 changes: 18 additions & 37 deletions tests/test_tools/test_tools_manuscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
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


Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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)
Expand All @@ -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))
Expand All @@ -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 == {
Expand Down Expand Up @@ -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()

Expand Down

0 comments on commit a4e3bf8

Please sign in to comment.