Move the spell check instance to the shared class
This commit is contained in:
@@ -47,11 +47,15 @@ class NWSpellEnchant:
|
||||
|
||||
def __init__(self, project: NWProject) -> None:
|
||||
self._project = project
|
||||
self._dictObj = FakeEnchant()
|
||||
self._enchant = FakeEnchant()
|
||||
self._userDict = UserDictionary(project)
|
||||
self._language = None
|
||||
self._broker = None
|
||||
logger.debug("Enchant spell checking activated")
|
||||
logger.debug("Ready: NWSpellEnchant")
|
||||
return
|
||||
|
||||
def __del__(self): # pragma: no cover
|
||||
logger.debug("Delete: NWSpellEnchant")
|
||||
return
|
||||
|
||||
##
|
||||
@@ -72,7 +76,7 @@ class NWSpellEnchant:
|
||||
crash. Note that enchant will allow loading an empty string as
|
||||
a tag, but this will fail later on. See issue #1096.
|
||||
"""
|
||||
self._dictObj = FakeEnchant()
|
||||
self._enchant = FakeEnchant()
|
||||
self._broker = None
|
||||
self._language = None
|
||||
|
||||
@@ -81,7 +85,7 @@ class NWSpellEnchant:
|
||||
|
||||
if language and enchant.dict_exists(language):
|
||||
self._broker = enchant.Broker()
|
||||
self._dictObj = self._broker.request_dict(language)
|
||||
self._enchant = self._broker.request_dict(language)
|
||||
self._language = language
|
||||
logger.debug("Enchant spell checking for language '%s' loaded", language)
|
||||
else:
|
||||
@@ -90,12 +94,11 @@ class NWSpellEnchant:
|
||||
except Exception:
|
||||
logger.error("Failed to load enchant spell checking for language '%s'", language)
|
||||
|
||||
if self._dictObj is None:
|
||||
self._dictObj = FakeEnchant()
|
||||
if self._enchant is None:
|
||||
self._enchant = FakeEnchant()
|
||||
else:
|
||||
self._userDict.load()
|
||||
for pWord in self._userDict:
|
||||
self._dictObj.add_to_session(pWord)
|
||||
for word in self._userDict:
|
||||
self._enchant.add_to_session(word)
|
||||
|
||||
return
|
||||
|
||||
@@ -106,14 +109,14 @@ class NWSpellEnchant:
|
||||
def checkWord(self, word: str) -> bool:
|
||||
"""Wrapper function for pyenchant."""
|
||||
try:
|
||||
return bool(self._dictObj.check(word))
|
||||
return bool(self._enchant.check(word))
|
||||
except Exception:
|
||||
return True
|
||||
|
||||
def suggestWords(self, word: str) -> list[str]:
|
||||
"""Wrapper function for pyenchant."""
|
||||
try:
|
||||
return self._dictObj.suggest(word)
|
||||
return self._enchant.suggest(word)
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
@@ -123,7 +126,7 @@ class NWSpellEnchant:
|
||||
if not word:
|
||||
return False
|
||||
try:
|
||||
self._dictObj.add_to_session(word)
|
||||
self._enchant.add_to_session(word)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -133,6 +136,11 @@ class NWSpellEnchant:
|
||||
|
||||
return added
|
||||
|
||||
def loadUserWordList(self) -> None:
|
||||
"""Load the user word list from the project."""
|
||||
self._userDict.load()
|
||||
return
|
||||
|
||||
def listDictionaries(self) -> list[tuple[str, str]]:
|
||||
"""Wrapper function for pyenchant."""
|
||||
retList = []
|
||||
@@ -142,22 +150,18 @@ class NWSpellEnchant:
|
||||
retList.append((spTag, spProvider.name))
|
||||
except Exception:
|
||||
logger.error("Failed to list languages for enchant spell checking")
|
||||
|
||||
return retList
|
||||
|
||||
def describeDict(self) -> tuple[str, str]:
|
||||
"""Return the tag and provider of the currently loaded
|
||||
dictionary.
|
||||
"""
|
||||
"""Describe the currently loaded dictionary."""
|
||||
try:
|
||||
tag = self._dictObj.tag
|
||||
name = self._dictObj.provider.name # type: ignore
|
||||
tag = self._enchant.tag
|
||||
name = self._enchant.provider.name # type: ignore
|
||||
except Exception:
|
||||
logger.error("Failed to extract information about the dictionary")
|
||||
logException()
|
||||
tag = ""
|
||||
name = ""
|
||||
|
||||
return tag, name
|
||||
|
||||
# END Class NWSpellEnchant
|
||||
@@ -192,7 +196,6 @@ class UserDictionary:
|
||||
def __init__(self, project: NWProject) -> None:
|
||||
self._project = project
|
||||
self._words = set()
|
||||
self._path = None
|
||||
return
|
||||
|
||||
def __contains__(self, word: str) -> bool:
|
||||
@@ -212,13 +215,14 @@ class UserDictionary:
|
||||
|
||||
def load(self) -> None:
|
||||
"""Load the user's dictionary."""
|
||||
self._path = self._project.storage.getMetaFile(nwFiles.DICT_FILE)
|
||||
self._words = set()
|
||||
if isinstance(self._path, Path) and self._path.is_file():
|
||||
wordList = self._project.storage.getMetaFile(nwFiles.DICT_FILE)
|
||||
if isinstance(wordList, Path) and wordList.is_file():
|
||||
try:
|
||||
with open(self._path, mode="r", encoding="utf-8") as fObj:
|
||||
with open(wordList, mode="r", encoding="utf-8") as fObj:
|
||||
data = json.load(fObj)
|
||||
self._words = set(data.get("novelWriter.userDict", []))
|
||||
logger.info("Loaded: %s", nwFiles.DICT_FILE)
|
||||
except Exception:
|
||||
logger.error("Failed to load user dictionary")
|
||||
logException()
|
||||
@@ -226,17 +230,15 @@ class UserDictionary:
|
||||
|
||||
def save(self) -> None:
|
||||
"""Save the user's dictionary."""
|
||||
if self._path is None:
|
||||
self._path = self._project.storage.getMetaFile(nwFiles.DICT_FILE)
|
||||
if not isinstance(self._path, Path):
|
||||
return
|
||||
try:
|
||||
with open(self._path, mode="w", encoding="utf-8") as fObj:
|
||||
data = {"novelWriter.userDict": list(self._words)}
|
||||
json.dump(data, fObj, indent=2)
|
||||
except Exception:
|
||||
logger.error("Failed to save user dictionary")
|
||||
logException()
|
||||
wordList = self._project.storage.getMetaFile(nwFiles.DICT_FILE)
|
||||
if isinstance(wordList, Path):
|
||||
try:
|
||||
with open(wordList, mode="w", encoding="utf-8") as fObj:
|
||||
data = {"novelWriter.userDict": list(self._words)}
|
||||
json.dump(data, fObj, indent=2)
|
||||
except Exception:
|
||||
logger.error("Failed to save user dictionary")
|
||||
logException()
|
||||
return
|
||||
|
||||
# END Class UserDictionary
|
||||
|
||||
@@ -49,8 +49,6 @@ class GuiPreferences(NPagedDialog):
|
||||
logger.debug("Create: GuiPreferences")
|
||||
self.setObjectName("GuiPreferences")
|
||||
|
||||
self.mainGui = mainGui
|
||||
|
||||
self.setWindowTitle(self.tr("Preferences"))
|
||||
|
||||
self.tabGeneral = GuiPreferencesGeneral(self)
|
||||
@@ -645,8 +643,6 @@ class GuiPreferencesEditor(QWidget):
|
||||
def __init__(self, prefsGui):
|
||||
super().__init__(parent=prefsGui)
|
||||
|
||||
self.mainGui = prefsGui.mainGui
|
||||
|
||||
# The Form
|
||||
self.mainForm = NConfigLayout()
|
||||
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
||||
@@ -662,7 +658,7 @@ class GuiPreferencesEditor(QWidget):
|
||||
self.spellLanguage = QComboBox(self)
|
||||
self.spellLanguage.setMaximumWidth(mW)
|
||||
|
||||
langAvail = self.mainGui.docEditor.spEnchant.listDictionaries()
|
||||
langAvail = SHARED.spelling.listDictionaries()
|
||||
if CONFIG.hasEnchant and langAvail:
|
||||
for spTag, spProv in langAvail:
|
||||
qLocal = QLocale(spTag)
|
||||
|
||||
@@ -199,8 +199,6 @@ class GuiProjectEditMain(QWidget):
|
||||
def __init__(self, projGui):
|
||||
super().__init__(parent=projGui)
|
||||
|
||||
self.mainGui = projGui.mainGui
|
||||
|
||||
# The Form
|
||||
self.mainForm = NConfigLayout()
|
||||
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
||||
@@ -244,7 +242,7 @@ class GuiProjectEditMain(QWidget):
|
||||
self.spellLang = QComboBox(self)
|
||||
self.spellLang.setMaximumWidth(xW)
|
||||
self.spellLang.addItem(self.tr("Default"), "None")
|
||||
langAvail = self.mainGui.docEditor.spEnchant.listDictionaries()
|
||||
langAvail = SHARED.spelling.listDictionaries()
|
||||
for spTag, spProv in langAvail:
|
||||
qLocal = QLocale(spTag)
|
||||
spLang = qLocal.nativeLanguageName().title()
|
||||
|
||||
@@ -54,7 +54,6 @@ from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass
|
||||
from novelwriter.common import minmax, transferCase
|
||||
from novelwriter.constants import nwConst, nwKeyWords, nwUnicode
|
||||
from novelwriter.core.index import countWords
|
||||
from novelwriter.core.spellcheck import NWSpellEnchant
|
||||
from novelwriter.gui.dochighlight import GuiDocHighlighter
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
@@ -133,8 +132,7 @@ class GuiDocEditor(QTextEdit):
|
||||
self.docSearch = GuiDocEditSearch(self)
|
||||
|
||||
# Syntax
|
||||
self.spEnchant = NWSpellEnchant(SHARED.project)
|
||||
self.highLight = GuiDocHighlighter(qDoc, self.spEnchant)
|
||||
self.highLight = GuiDocHighlighter(qDoc)
|
||||
|
||||
# Context Menu
|
||||
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
@@ -702,8 +700,8 @@ class GuiDocEditor(QTextEdit):
|
||||
else:
|
||||
theLang = SHARED.project.data.spellLang
|
||||
|
||||
self.spEnchant.setLanguage(theLang)
|
||||
_, theProvider = self.spEnchant.describeDict()
|
||||
SHARED.spelling.setLanguage(theLang)
|
||||
_, theProvider = SHARED.spelling.describeDict()
|
||||
|
||||
self.spellDictionaryChanged.emit(str(theLang), str(theProvider))
|
||||
if not self._bigDoc:
|
||||
@@ -711,37 +709,37 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
return True
|
||||
|
||||
def toggleSpellCheck(self, theMode):
|
||||
def toggleSpellCheck(self, state: bool) -> None:
|
||||
"""This is the main spell check setting function, and this one
|
||||
should call all other setSpellCheck functions in other classes.
|
||||
If the spell check mode (theMode) is not defined (None), then
|
||||
toggle the current status saved in this class.
|
||||
"""
|
||||
if theMode is None:
|
||||
theMode = not self._spellCheck
|
||||
if state is None:
|
||||
state = not self._spellCheck
|
||||
|
||||
if not CONFIG.hasEnchant:
|
||||
if theMode:
|
||||
if state:
|
||||
SHARED.info(self.tr(
|
||||
"Spell checking requires the package PyEnchant. "
|
||||
"It does not appear to be installed."
|
||||
))
|
||||
theMode = False
|
||||
state = False
|
||||
|
||||
if self.spEnchant.spellLanguage is None:
|
||||
theMode = False
|
||||
if SHARED.spelling.spellLanguage is None:
|
||||
state = False
|
||||
|
||||
self._spellCheck = theMode
|
||||
self.mainGui.mainMenu.setSpellCheck(theMode)
|
||||
SHARED.project.data.setSpellCheck(theMode)
|
||||
self.highLight.setSpellCheck(theMode)
|
||||
if not self._bigDoc or theMode is False:
|
||||
self._spellCheck = state
|
||||
self.mainGui.mainMenu.setSpellCheck(state)
|
||||
SHARED.project.data.setSpellCheck(state)
|
||||
self.highLight.setSpellCheck(state)
|
||||
if not self._bigDoc or state is False:
|
||||
# We don't run the spell checker automatically on big docs
|
||||
self.spellCheckDocument()
|
||||
|
||||
logger.debug("Spell check is set to '%s'", str(theMode))
|
||||
logger.debug("Spell check is set to '%s'", str(state))
|
||||
|
||||
return True
|
||||
return
|
||||
|
||||
def spellCheckDocument(self) -> None:
|
||||
"""Rerun the highlighter to update spell checking status of the
|
||||
@@ -1193,14 +1191,14 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
if spellCheck:
|
||||
logger.debug("Looking up '%s' in the dictionary", theWord)
|
||||
spellCheck &= not self.spEnchant.checkWord(theWord)
|
||||
spellCheck &= not SHARED.spelling.checkWord(theWord)
|
||||
|
||||
if spellCheck:
|
||||
mnuContext.addSeparator()
|
||||
mnuHead = QAction(self.tr("Spelling Suggestion(s)"), mnuContext)
|
||||
mnuContext.addAction(mnuHead)
|
||||
|
||||
theSuggest = self.spEnchant.suggestWords(theWord)[:15]
|
||||
theSuggest = SHARED.spelling.suggestWords(theWord)[:15]
|
||||
if len(theSuggest) > 0:
|
||||
for aWord in theSuggest:
|
||||
mnuWord = QAction("%s %s" % (nwUnicode.U_ENDASH, aWord), mnuContext)
|
||||
@@ -1245,7 +1243,7 @@ class GuiDocEditor(QTextEdit):
|
||||
"""
|
||||
theWord = theCursor.selectedText().strip().strip(self._nonWord)
|
||||
logger.debug("Added '%s' to project dictionary", theWord)
|
||||
self.spEnchant.addWord(theWord)
|
||||
SHARED.spelling.addWord(theWord)
|
||||
self.highLight.rehighlightBlock(theCursor.block())
|
||||
return
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ from time import time
|
||||
|
||||
from PyQt5.QtCore import Qt, QRegularExpression
|
||||
from PyQt5.QtGui import (
|
||||
QColor, QTextCharFormat, QFont, QSyntaxHighlighter, QBrush
|
||||
QColor, QTextCharFormat, QFont, QSyntaxHighlighter, QBrush, QTextDocument
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -46,13 +46,11 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
BLOCK_META = 2
|
||||
BLOCK_TITLE = 4
|
||||
|
||||
def __init__(self, theDoc, spEnchant):
|
||||
super().__init__(theDoc)
|
||||
def __init__(self, document: QTextDocument) -> None:
|
||||
super().__init__(document)
|
||||
|
||||
logger.debug("Create: GuiDocHighlighter")
|
||||
|
||||
self.theDoc = theDoc
|
||||
self.spEnchant = spEnchant
|
||||
self.theHandle = None
|
||||
self.spellCheck = False
|
||||
self.spellRx = None
|
||||
@@ -387,7 +385,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
rxSpell = self.spellRx.globalMatch(theText.replace("_", " "), 0)
|
||||
while rxSpell.hasNext():
|
||||
rxMatch = rxSpell.next()
|
||||
if not self.spEnchant.checkWord(rxMatch.captured(0)):
|
||||
if not SHARED.spelling.checkWord(rxMatch.captured(0)):
|
||||
if rxMatch.captured(0).isupper() or rxMatch.captured(0).isnumeric():
|
||||
continue
|
||||
xPos = rxMatch.capturedStart(0)
|
||||
|
||||
+16
-2
@@ -32,6 +32,8 @@ from pathlib import Path
|
||||
from PyQt5.QtCore import QObject, pyqtSignal
|
||||
from PyQt5.QtWidgets import QMessageBox, QWidget
|
||||
|
||||
from novelwriter.core.spellcheck import NWSpellEnchant
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
from novelwriter.gui.theme import GuiTheme
|
||||
@@ -43,18 +45,20 @@ logger = logging.getLogger(__name__)
|
||||
class SharedData(QObject):
|
||||
|
||||
__slots__ = (
|
||||
"_gui", "_theme", "_project", "_lockedBy", "_alert",
|
||||
"_gui", "_theme", "_project", "_spelling", "_lockedBy", "_alert",
|
||||
"_idleTime", "_idleRefTime",
|
||||
)
|
||||
|
||||
projectStatusChanged = pyqtSignal(bool)
|
||||
projectStatusMessage = pyqtSignal(str)
|
||||
spellLanguageChanged = pyqtSignal(str, str)
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._gui = None
|
||||
self._theme = None
|
||||
self._project = None
|
||||
self._spelling = None
|
||||
self._lockedBy = None
|
||||
self._alert = None
|
||||
self._idleTime = 0.0
|
||||
@@ -82,6 +86,13 @@ class SharedData(QObject):
|
||||
raise Exception("SharedData class not fully initialised")
|
||||
return self._project
|
||||
|
||||
@property
|
||||
def spelling(self) -> NWSpellEnchant:
|
||||
"""Return the active NWProject instance."""
|
||||
if self._spelling is None:
|
||||
raise Exception("SharedData class not fully initialised")
|
||||
return self._spelling
|
||||
|
||||
@property
|
||||
def hasProject(self) -> bool:
|
||||
"""Return True if the project instance is populated."""
|
||||
@@ -130,6 +141,7 @@ class SharedData(QObject):
|
||||
self._lockedBy = self.project.lockStatus
|
||||
self._resetProject()
|
||||
|
||||
self.spelling.loadUserWordList()
|
||||
self._resetIdleTimer()
|
||||
|
||||
return status
|
||||
@@ -220,11 +232,13 @@ class SharedData(QObject):
|
||||
##
|
||||
|
||||
def _resetProject(self) -> None:
|
||||
"""Create a new project instance."""
|
||||
"""Create a new project and spell checking instance."""
|
||||
from novelwriter.core.project import NWProject
|
||||
if isinstance(self._project, NWProject):
|
||||
del self._project
|
||||
del self._spelling
|
||||
self._project = NWProject()
|
||||
self._spelling = NWSpellEnchant(self._project)
|
||||
return
|
||||
|
||||
def _resetIdleTimer(self) -> None:
|
||||
|
||||
@@ -58,17 +58,14 @@ def testCoreSpell_UserDictionary(monkeypatch, mockGUI, fncPath):
|
||||
assert sorted(userDict) == ["bar", "foo"]
|
||||
|
||||
# Save the file, but fail
|
||||
assert userDict._path is None
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
userDict.save()
|
||||
|
||||
# There should be no file, but the file path should now be cached
|
||||
assert userDict._path == dictFile
|
||||
# There should be no file
|
||||
assert not dictFile.exists()
|
||||
|
||||
# Break the path check
|
||||
userDict._path = None
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("novelwriter.core.storage.NWStorage.getMetaFile", lambda *a: None)
|
||||
userDict.save()
|
||||
@@ -85,23 +82,19 @@ def testCoreSpell_UserDictionary(monkeypatch, mockGUI, fncPath):
|
||||
assert sorted(userDict) == []
|
||||
|
||||
# Load the file, but fail
|
||||
userDict._path = None
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
userDict.load()
|
||||
|
||||
# Path is now set, but no words
|
||||
assert userDict._path == dictFile
|
||||
# No words loaded
|
||||
assert sorted(userDict) == []
|
||||
|
||||
# Break the path check
|
||||
userDict._path = None
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("novelwriter.core.storage.NWStorage.getMetaFile", lambda *a: None)
|
||||
userDict.load()
|
||||
|
||||
# Path is now None, and no words
|
||||
assert userDict._path is None
|
||||
# No words loaded
|
||||
assert sorted(userDict) == []
|
||||
|
||||
# Load the words again, properly
|
||||
@@ -122,18 +115,18 @@ def testCoreSpell_FakeEnchant(monkeypatch, mockGUI, fncPath):
|
||||
mp.setitem(sys.modules, "enchant", None)
|
||||
spChk = NWSpellEnchant(project)
|
||||
spChk.setLanguage("en_US")
|
||||
assert isinstance(spChk._dictObj, FakeEnchant)
|
||||
assert isinstance(spChk._enchant, FakeEnchant)
|
||||
|
||||
# Request a non-existent dictionary
|
||||
spChk = NWSpellEnchant(project)
|
||||
spChk.setLanguage("whatchamajig")
|
||||
assert isinstance(spChk._dictObj, FakeEnchant)
|
||||
assert isinstance(spChk._enchant, FakeEnchant)
|
||||
|
||||
# Request an empty language string
|
||||
# See issue https://github.com/vkbo/novelWriter/issues/1096
|
||||
spChk = NWSpellEnchant(project)
|
||||
spChk.setLanguage("")
|
||||
assert isinstance(spChk._dictObj, FakeEnchant)
|
||||
assert isinstance(spChk._enchant, FakeEnchant)
|
||||
|
||||
# FakeEnchant should handle requests
|
||||
fkChk = FakeEnchant()
|
||||
@@ -164,14 +157,14 @@ def testCoreSpell_Enchant(monkeypatch, mockGUI, fncPath):
|
||||
assert spChk.spellLanguage is None
|
||||
|
||||
# Check that the FakeEnchant class is actually handling this
|
||||
assert isinstance(spChk._dictObj, FakeEnchant)
|
||||
assert isinstance(spChk._enchant, FakeEnchant)
|
||||
assert spChk.checkWord("word") is True
|
||||
assert spChk.suggestWords("word") == []
|
||||
assert spChk.addWord("word") is True
|
||||
|
||||
# Set the dict to None, and check enchant error handling
|
||||
spChk = NWSpellEnchant(project)
|
||||
spChk._dictObj = None # type: ignore
|
||||
spChk._enchant = None # type: ignore
|
||||
assert spChk.checkWord("word") is True
|
||||
assert spChk.suggestWords("word") == []
|
||||
assert spChk.addWord("word") is False
|
||||
@@ -182,7 +175,7 @@ def testCoreSpell_Enchant(monkeypatch, mockGUI, fncPath):
|
||||
spChk = NWSpellEnchant(project)
|
||||
spChk.setLanguage("en_US")
|
||||
spChk.setLanguage("en_US")
|
||||
assert isinstance(spChk._dictObj, enchant.Dict)
|
||||
assert isinstance(spChk._enchant, enchant.Dict)
|
||||
assert spChk.spellLanguage == "en_US"
|
||||
assert spChk.listDictionaries() != []
|
||||
assert spChk.describeDict() != ("", "")
|
||||
@@ -194,6 +187,6 @@ def testCoreSpell_Enchant(monkeypatch, mockGUI, fncPath):
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("enchant.Broker.request_dict", lambda *a: None)
|
||||
spChk.setLanguage("en_US")
|
||||
assert isinstance(spChk._dictObj, FakeEnchant)
|
||||
assert isinstance(spChk._enchant, FakeEnchant)
|
||||
|
||||
# END Test testCoreSpell_Enchant
|
||||
|
||||
@@ -30,7 +30,7 @@ from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
||||
from novelwriter.dialogs.preferences import GuiPreferences
|
||||
|
||||
@@ -42,7 +42,7 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
|
||||
"""Test the preferences dialog."""
|
||||
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
|
||||
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
|
||||
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
|
||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "none")])
|
||||
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr(GuiPreferences, "updateTheme", lambda *a: True)
|
||||
|
||||
@@ -84,10 +84,9 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
|
||||
|
||||
@pytest.mark.gui
|
||||
def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
||||
"""Test the main tab of the project settings dialog.
|
||||
"""
|
||||
"""Test the main tab of the project settings dialog."""
|
||||
# Mock components
|
||||
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
|
||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "none")])
|
||||
|
||||
# Create new project
|
||||
buildTestProject(nwGUI, projPath)
|
||||
@@ -152,7 +151,7 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
||||
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||
|
||||
# Mock components
|
||||
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
|
||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "none")])
|
||||
|
||||
# Create new project
|
||||
mockRnd.reset()
|
||||
@@ -348,12 +347,11 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
||||
|
||||
@pytest.mark.gui
|
||||
def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
||||
"""Test the auto-replace tab of the project settings dialog.
|
||||
"""
|
||||
"""Test the auto-replace tab of the project settings dialog."""
|
||||
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||
|
||||
# Mock components
|
||||
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
|
||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "none")])
|
||||
|
||||
# Create new project
|
||||
mockRnd.reset()
|
||||
|
||||
Reference in New Issue
Block a user