Update docs and test coverage
This commit is contained in:
@@ -132,6 +132,7 @@ A GUI theme ``.conf`` file consists of the following settings:
|
|||||||
|
|
||||||
[GUI]
|
[GUI]
|
||||||
helptext = 0, 0, 0
|
helptext = 0, 0, 0
|
||||||
|
fadedtext = 128, 128, 128
|
||||||
errortext = 255, 0, 0
|
errortext = 255, 0, 0
|
||||||
statusnone = 120, 120, 120
|
statusnone = 120, 120, 120
|
||||||
statussaved = 2, 133, 37
|
statussaved = 2, 133, 37
|
||||||
@@ -149,7 +150,7 @@ colour values are RGB numbers on the format ``r, g, b`` where each is an integer
|
|||||||
not defined, it is computed as a colour between the ``window`` and ``windowtext`` colour.
|
not defined, it is computed as a colour between the ``window`` and ``windowtext`` colour.
|
||||||
|
|
||||||
.. versionadded:: 2.5
|
.. versionadded:: 2.5
|
||||||
The ``errortext`` theme colour entry was added.
|
The ``fadedtext`` and ``errortext`` theme colour entries were added.
|
||||||
|
|
||||||
|
|
||||||
Custom Syntax Theme
|
Custom Syntax Theme
|
||||||
|
|||||||
@@ -1172,16 +1172,13 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
@pyqtSlot(nwDocAction)
|
@pyqtSlot(nwDocAction)
|
||||||
def _passDocumentAction(self, action: nwDocAction) -> None:
|
def _passDocumentAction(self, action: nwDocAction) -> None:
|
||||||
"""Pass on a document action to the document viewer if it has
|
"""Pass on a document action to the editor or viewer based on
|
||||||
focus, or pass it to the document editor if it or any of its
|
which one has focus, or if neither has focus, ignore it.
|
||||||
child widgets have focus. If neither has focus, ignore it.
|
|
||||||
"""
|
"""
|
||||||
if self.docViewer.hasFocus():
|
if self.docEditor.hasFocus():
|
||||||
self.docViewer.docAction(action)
|
|
||||||
elif self.docEditor.hasFocus():
|
|
||||||
self.docEditor.docAction(action)
|
self.docEditor.docAction(action)
|
||||||
else:
|
elif self.docViewer.hasFocus():
|
||||||
logger.debug("Action cancelled as neither editor nor viewer has focus")
|
self.docViewer.docAction(action)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ from PyQt5.QtWidgets import QInputDialog, QMenu
|
|||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
from novelwriter.enum import nwFocus, nwItemType, nwView
|
from novelwriter.enum import nwDocAction, nwFocus, nwItemType, nwView
|
||||||
from novelwriter.gui.doceditor import GuiDocEditor
|
from novelwriter.gui.doceditor import GuiDocEditor
|
||||||
from novelwriter.gui.noveltree import GuiNovelView
|
from novelwriter.gui.noveltree import GuiNovelView
|
||||||
from novelwriter.gui.outline import GuiOutlineView
|
from novelwriter.gui.outline import GuiOutlineView
|
||||||
@@ -64,7 +64,21 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, projPath):
|
|||||||
|
|
||||||
# Open Lipsum project
|
# Open Lipsum project
|
||||||
nwGUI.postLaunchTasks(projPath)
|
nwGUI.postLaunchTasks(projPath)
|
||||||
|
assert SHARED.hasProject is True
|
||||||
nwGUI.closeProject()
|
nwGUI.closeProject()
|
||||||
|
assert SHARED.hasProject is False
|
||||||
|
|
||||||
|
# Open as if called from Welcome
|
||||||
|
nwGUI._openProjectFromWelcome(projPath)
|
||||||
|
assert SHARED.hasProject is True
|
||||||
|
nwGUI.closeProject()
|
||||||
|
assert SHARED.hasProject is False
|
||||||
|
|
||||||
|
# Open as if called from Welcome, invalid path
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(nwGUI, "showWelcomeDialog", lambda *a: None)
|
||||||
|
nwGUI._openProjectFromWelcome(None)
|
||||||
|
assert SHARED.hasProject is False
|
||||||
|
|
||||||
# Project open fails
|
# Project open fails
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
@@ -689,3 +703,118 @@ def testGuiMain_Features(qtbot, nwGUI, projPath, mockRnd):
|
|||||||
nwGUI.sideBar.mSettings.hide()
|
nwGUI.sideBar.mSettings.hide()
|
||||||
|
|
||||||
# qtbot.stop()
|
# qtbot.stop()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.gui
|
||||||
|
def testGuiMain_FocusView(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||||
|
"""Test switching focus and view of the main window."""
|
||||||
|
buildTestProject(nwGUI, projPath)
|
||||||
|
|
||||||
|
nwGUI.openDocument(C.hSceneDoc)
|
||||||
|
nwGUI.viewDocument(C.hSceneDoc)
|
||||||
|
|
||||||
|
# Toggle Focus
|
||||||
|
# ============
|
||||||
|
nwGUI.docEditor.setFocus()
|
||||||
|
assert nwGUI.docEditor.anyFocus()
|
||||||
|
|
||||||
|
# Simulate focus change to viewer
|
||||||
|
nwGUI._appFocusChanged(None, nwGUI.docViewer)
|
||||||
|
assert nwGUI.docEditor.docHeader.itemTitle._state is False
|
||||||
|
assert nwGUI.docViewer.docHeader.itemTitle._state is True
|
||||||
|
|
||||||
|
# Simulate focus change to editor
|
||||||
|
nwGUI._appFocusChanged(None, nwGUI.docEditor)
|
||||||
|
assert nwGUI.docEditor.docHeader.itemTitle._state is True
|
||||||
|
assert nwGUI.docViewer.docHeader.itemTitle._state is False
|
||||||
|
|
||||||
|
# Focus Tree
|
||||||
|
# ==========
|
||||||
|
assert nwGUI.projStack.currentWidget() == nwGUI.projView
|
||||||
|
|
||||||
|
# Switch from editor to project tree
|
||||||
|
nwGUI.docEditor.setFocus()
|
||||||
|
nwGUI._switchFocus(nwFocus.TREE)
|
||||||
|
assert nwGUI.projStack.currentWidget() == nwGUI.projView
|
||||||
|
|
||||||
|
# Triggering again should switch to novel view
|
||||||
|
nwGUI._switchFocus(nwFocus.TREE)
|
||||||
|
assert nwGUI.projStack.currentWidget() == nwGUI.novelView
|
||||||
|
|
||||||
|
# Switch from editor to novel view
|
||||||
|
nwGUI.docEditor.setFocus()
|
||||||
|
nwGUI._switchFocus(nwFocus.TREE)
|
||||||
|
assert nwGUI.projStack.currentWidget() == nwGUI.novelView
|
||||||
|
|
||||||
|
# Triggering again should switch back to project tree
|
||||||
|
nwGUI._switchFocus(nwFocus.TREE)
|
||||||
|
assert nwGUI.projStack.currentWidget() == nwGUI.projView
|
||||||
|
|
||||||
|
# If in search mode, should default to project tree
|
||||||
|
nwGUI._changeView(nwView.SEARCH)
|
||||||
|
nwGUI._switchFocus(nwFocus.TREE)
|
||||||
|
assert nwGUI.projStack.currentWidget() == nwGUI.projView
|
||||||
|
|
||||||
|
# Focus Document
|
||||||
|
# ==============
|
||||||
|
nwGUI._switchFocus(nwFocus.TREE)
|
||||||
|
|
||||||
|
def mockEmitEditorFocus(*a):
|
||||||
|
nwGUI._appFocusChanged(None, nwGUI.docEditor)
|
||||||
|
|
||||||
|
def mockEmitViewerFocus(*a):
|
||||||
|
nwGUI._appFocusChanged(None, nwGUI.docViewer)
|
||||||
|
|
||||||
|
# Switch to viewer
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: True)
|
||||||
|
mp.setattr(nwGUI.docViewer, "hasFocus", lambda *a: False)
|
||||||
|
mp.setattr(nwGUI.docEditor, "setFocus", mockEmitEditorFocus)
|
||||||
|
mp.setattr(nwGUI.docViewer, "setFocus", mockEmitViewerFocus)
|
||||||
|
nwGUI._switchFocus(nwFocus.DOCUMENT)
|
||||||
|
assert nwGUI.docEditor.docHeader.itemTitle._state is False
|
||||||
|
assert nwGUI.docViewer.docHeader.itemTitle._state is True
|
||||||
|
|
||||||
|
# Call again to switch to editor
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: False)
|
||||||
|
mp.setattr(nwGUI.docViewer, "hasFocus", lambda *a: True)
|
||||||
|
mp.setattr(nwGUI.docEditor, "setFocus", mockEmitEditorFocus)
|
||||||
|
mp.setattr(nwGUI.docViewer, "setFocus", mockEmitViewerFocus)
|
||||||
|
nwGUI._switchFocus(nwFocus.DOCUMENT)
|
||||||
|
assert nwGUI.docEditor.docHeader.itemTitle._state is True
|
||||||
|
assert nwGUI.docViewer.docHeader.itemTitle._state is False
|
||||||
|
|
||||||
|
# Default to editor
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: False)
|
||||||
|
mp.setattr(nwGUI.docViewer, "hasFocus", lambda *a: False)
|
||||||
|
mp.setattr(nwGUI.docEditor, "setFocus", mockEmitEditorFocus)
|
||||||
|
mp.setattr(nwGUI.docViewer, "setFocus", mockEmitViewerFocus)
|
||||||
|
nwGUI._switchFocus(nwFocus.DOCUMENT)
|
||||||
|
assert nwGUI.docEditor.docHeader.itemTitle._state is True
|
||||||
|
assert nwGUI.docViewer.docHeader.itemTitle._state is False
|
||||||
|
|
||||||
|
# Focus Outline
|
||||||
|
# =============
|
||||||
|
nwGUI._switchFocus(nwFocus.OUTLINE)
|
||||||
|
assert nwGUI.mainStack.currentWidget() == nwGUI.outlineView
|
||||||
|
|
||||||
|
# Pass Actions
|
||||||
|
# ============
|
||||||
|
|
||||||
|
# Pass to editor
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: True)
|
||||||
|
mp.setattr(nwGUI.docViewer, "hasFocus", lambda *a: False)
|
||||||
|
nwGUI._passDocumentAction(nwDocAction.SEL_ALL)
|
||||||
|
assert nwGUI.docEditor.textCursor().hasSelection() is True
|
||||||
|
|
||||||
|
# Pass to viewer
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: False)
|
||||||
|
mp.setattr(nwGUI.docViewer, "hasFocus", lambda *a: True)
|
||||||
|
nwGUI._passDocumentAction(nwDocAction.SEL_ALL)
|
||||||
|
assert nwGUI.docViewer.textCursor().hasSelection() is True
|
||||||
|
|
||||||
|
# qtbot.stop()
|
||||||
|
|||||||
Reference in New Issue
Block a user