Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
  • Loading branch information
vkbo committed Jul 21, 2024
2 parents b7da56a + 5936e1a commit f532857
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 28 deletions.
10 changes: 10 additions & 0 deletions novelwriter/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,16 @@ def simplified(text: str) -> str:
return " ".join(str(text).strip().split())


def compact(text: str) -> str:
"""Compact a string by removing spaces."""
return "".join(str(text).split())


def uniqueCompact(text: str) -> str:
"""Return a unique, compact and sorted string."""
return "".join(sorted(set(compact(text))))


def elide(text: str, length: int) -> str:
"""Elide a piece of text to a maximum length."""
if len(text) > (cut := max(4, length)):
Expand Down
10 changes: 5 additions & 5 deletions novelwriter/dialogs/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
)

from novelwriter import CONFIG, SHARED
from novelwriter.common import describeFont
from novelwriter.common import describeFont, uniqueCompact
from novelwriter.constants import nwUnicode
from novelwriter.dialogs.quotes import GuiQuoteSelect
from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
Expand Down Expand Up @@ -952,8 +952,8 @@ def _doSave(self) -> None:
# Text Highlighting
dialogueStyle = self.dialogStyle.currentData()
allowOpenDial = self.allowOpenDial.isChecked()
narratorBreak = self.narratorBreak.text()
dialogueLine = self.dialogLine.text()
narratorBreak = self.narratorBreak.text().strip()
dialogueLine = self.dialogLine.text().strip()
altDialogOpen = self.altDialogOpen.text()
altDialogClose = self.altDialogClose.text()
highlightEmph = self.highlightEmph.isChecked()
Expand Down Expand Up @@ -983,8 +983,8 @@ def _doSave(self) -> None:
CONFIG.doReplaceDQuote = self.doReplaceDQuote.isChecked()
CONFIG.doReplaceDash = self.doReplaceDash.isChecked()
CONFIG.doReplaceDots = self.doReplaceDots.isChecked()
CONFIG.fmtPadBefore = self.fmtPadBefore.text().strip()
CONFIG.fmtPadAfter = self.fmtPadAfter.text().strip()
CONFIG.fmtPadBefore = uniqueCompact(self.fmtPadBefore.text())
CONFIG.fmtPadAfter = uniqueCompact(self.fmtPadAfter.text())
CONFIG.fmtPadThin = self.fmtPadThin.isChecked()

# Quotation Style
Expand Down
31 changes: 16 additions & 15 deletions novelwriter/guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,14 @@ def closeDocument(self, beforeOpen: bool = False) -> None:
self.novelView.setActiveHandle(None)
return

def openDocument(self, tHandle: str | None, tLine: int | None = None,
changeFocus: bool = True, doScroll: bool = False) -> bool:
def openDocument(
self,
tHandle: str | None,
tLine: int | None = None,
sTitle: str | None = None,
changeFocus: bool = True,
doScroll: bool = False
) -> bool:
"""Open a specific document, optionally at a given line."""
if not SHARED.hasProject:
logger.error("No project open")
Expand All @@ -537,9 +543,12 @@ def openDocument(self, tHandle: str | None, tLine: int | None = None,
logger.debug("Requested item '%s' is not a document", tHandle)
return False

if sTitle and tLine is None:
if hItem := SHARED.project.index.getItemHeading(tHandle, sTitle):
tLine = hItem.line

self._changeView(nwView.EDITOR)
cHandle = self.docEditor.docHandle
if cHandle == tHandle:
if tHandle == self.docEditor.docHandle:
self.docEditor.setCursorLine(tLine)
if changeFocus:
self.docEditor.setFocus()
Expand Down Expand Up @@ -711,7 +720,6 @@ def openSelectedItem(self) -> None:
if SHARED.hasProject:
tHandle = None
sTitle = None
tLine = None
if self.projView.treeHasFocus():
tHandle = self.projView.getSelectedHandle()
elif self.novelView.treeHasFocus():
Expand All @@ -722,11 +730,8 @@ def openSelectedItem(self) -> None:
logger.warning("No item selected")
return

if tHandle and sTitle:
if hItem := SHARED.project.index.getItemHeading(tHandle, sTitle):
tLine = hItem.line
if tHandle:
self.openDocument(tHandle, tLine=tLine, changeFocus=False, doScroll=False)
self.openDocument(tHandle, sTitle=sTitle, changeFocus=False, doScroll=False)

return

Expand Down Expand Up @@ -1118,7 +1123,7 @@ def _followTag(self, tag: str, mode: nwDocMode) -> None:
tHandle, sTitle = self._getTagSource(tag)
if tHandle is not None:
if mode == nwDocMode.EDIT:
self.openDocument(tHandle)
self.openDocument(tHandle, sTitle=sTitle)
elif mode == nwDocMode.VIEW:
self.viewDocument(tHandle=tHandle, sTitle=sTitle)
return
Expand All @@ -1137,11 +1142,7 @@ def _openDocument(self, tHandle: str, mode: nwDocMode, sTitle: str, setFocus: bo
"""Handle an open document request."""
if tHandle is not None:
if mode == nwDocMode.EDIT:
tLine = None
hItem = SHARED.project.index.getItemHeading(tHandle, sTitle)
if hItem is not None:
tLine = hItem.line
self.openDocument(tHandle, tLine=tLine, changeFocus=setFocus)
self.openDocument(tHandle, sTitle=sTitle, changeFocus=setFocus)
elif mode == nwDocMode.VIEW:
self.viewDocument(tHandle=tHandle, sTitle=sTitle)
return
Expand Down
33 changes: 27 additions & 6 deletions tests/test_base/test_base_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@

from novelwriter.common import (
NWConfigParser, checkBool, checkFloat, checkInt, checkIntTuple, checkPath,
checkString, checkStringNone, checkUuid, cssCol, describeFont, elide,
formatFileFilter, formatInt, formatTime, formatTimeStamp, formatVersion,
fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout,
isItemType, isListInstance, isTitleTag, jsonEncode, makeFileNameSafe,
minmax, numberToRoman, openExternalPath, readTextFile, simplified,
transferCase, xmlIndent, yesNo
checkString, checkStringNone, checkUuid, compact, cssCol, describeFont,
elide, formatFileFilter, formatInt, formatTime, formatTimeStamp,
formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass,
isItemLayout, isItemType, isListInstance, isTitleTag, jsonEncode,
makeFileNameSafe, minmax, numberToRoman, openExternalPath, readTextFile,
simplified, transferCase, uniqueCompact, xmlIndent, yesNo
)

from tests.mocked import causeOSError
Expand Down Expand Up @@ -346,6 +346,27 @@ def testBaseCommon_simplified():
assert simplified("\tHello\n\r\tWorld") == "Hello World"


@pytest.mark.base
def testBaseCommon_compact():
"""Test the compact function."""
assert compact("! ! !") == "!!!"
assert compact("1\t2\t3") == "123"
assert compact("1\n2\n3") == "123"
assert compact("1\r2\r3") == "123"
assert compact("1\u00a02\u00a03") == "123"


@pytest.mark.base
def testBaseCommon_uniqueCompact():
"""Test the uniqueCompact function."""
assert uniqueCompact("! ! !") == "!"
assert uniqueCompact("1\t2\t3") == "123"
assert uniqueCompact("1\n2\n3") == "123"
assert uniqueCompact("1\r2\r3") == "123"
assert uniqueCompact("1\u00a02\u00a03") == "123"
assert uniqueCompact("3 2 1") == "123"


@pytest.mark.base
def testBaseCommon_elide():
"""Test the elide function."""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dialogs/test_dlg_preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, tstPaths):
assert CONFIG.doReplaceDQuote is False
assert CONFIG.doReplaceDash is False
assert CONFIG.doReplaceDots is False
assert CONFIG.fmtPadBefore == "!?:"
assert CONFIG.fmtPadBefore == "!:?"
assert CONFIG.fmtPadAfter == "¡¿"
assert CONFIG.fmtPadThin is True

Expand Down
22 changes: 21 additions & 1 deletion tests/test_gui/test_gui_guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.tools.welcome import GuiWelcome

from tests.mocked import causeOSError
from tests.tools import NWD_IGNORE, XML_IGNORE, C, buildTestProject, cmpFiles

KEY_DELAY = 1
Expand Down Expand Up @@ -651,7 +652,7 @@ def testGuiMain_Viewing(qtbot, monkeypatch, nwGUI, projPath, mockRnd):


@pytest.mark.gui
def testGuiMain_Features(qtbot, nwGUI, projPath, mockRnd):
def testGuiMain_Features(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test various features of the main window."""
buildTestProject(nwGUI, projPath)
assert SHARED.focusMode is False
Expand All @@ -672,6 +673,7 @@ def testGuiMain_Features(qtbot, nwGUI, projPath, mockRnd):

# Enable focus mode
nwGUI.toggleFocusMode()
assert SHARED.focusMode is True
assert nwGUI.treePane.isVisible() is False
assert nwGUI.mainStatus.isVisible() is False
assert nwGUI.mainMenu.isVisible() is False
Expand All @@ -680,12 +682,19 @@ def testGuiMain_Features(qtbot, nwGUI, projPath, mockRnd):

# Disable focus mode
nwGUI.toggleFocusMode()
assert SHARED.focusMode is False
assert nwGUI.treePane.isVisible() is True
assert nwGUI.mainStatus.isVisible() is True
assert nwGUI.mainMenu.isVisible() is True
assert nwGUI.sideBar.isVisible() is True
assert nwGUI.splitView.isVisible() is True

# Closing editor disables focus mode
nwGUI.toggleFocusMode()
assert SHARED.focusMode is True
nwGUI.closeDocument()
assert SHARED.focusMode is False

# Full Screen Mode
# ================

Expand All @@ -702,6 +711,17 @@ def testGuiMain_Features(qtbot, nwGUI, projPath, mockRnd):
nwGUI.sideBar.mSettings.show()
nwGUI.sideBar.mSettings.hide()

# Document Open Errors
# ====================

# Cannot edit a folder
assert nwGUI.openDocument(C.hChapterDir) is False

# Handle I/O error
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert nwGUI.openDocument(C.hChapterDoc) is False

# qtbot.stop()


Expand Down

0 comments on commit f532857

Please sign in to comment.