Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make some improvements to the viewer and test coverage #1902

Merged
merged 3 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions novelwriter/gui/docviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,6 @@ def loadText(self, tHandle: str, updateHistory: bool = True) -> bool:
})
self.updateDocMargins()

# Since we change the content while it may still be rendering, we mark
# the document dirty again to make sure it's re-rendered properly.
self.redrawText()
QApplication.restoreOverrideCursor()
self.documentLoaded.emit(tHandle)

Expand All @@ -259,12 +256,6 @@ def reloadText(self) -> None:
self.loadText(self._docHandle, updateHistory=False)
return

def redrawText(self) -> None:
"""Redraw the text by marking the content as "dirty"."""
self.document().markContentsDirty(0, self.document().characterCount())
self.updateDocMargins()
return

def docAction(self, action: nwDocAction) -> bool:
"""Process document actions on the current document."""
logger.debug("Requesting action: '%s'", action.name)
Expand Down
2 changes: 1 addition & 1 deletion novelwriter/gui/mainmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def _buildProjectMenu(self) -> None:
# Project > Edit
self.aEditItem = self.projMenu.addAction(self.tr("Rename Item"))
self.aEditItem.setShortcut("F2")
self.aEditItem.triggered.connect(lambda: self.mainGui.editItemLabel(None))
self.aEditItem.triggered.connect(lambda: self.mainGui.projView.renameTreeItem(None))

# Project > Delete
self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item"))
Expand Down
30 changes: 8 additions & 22 deletions novelwriter/guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,6 @@ def __init__(self) -> None:
self.keyEscape.setKey(Qt.Key.Key_Escape)
self.keyEscape.activated.connect(self._keyPressEscape)

# Check that config loaded fine
self.reportConfErr()

# Initialise Main GUI
self.initMain()
self.asProjTimer.start()
Expand All @@ -328,6 +325,10 @@ def initMain(self) -> None:

def postLaunchTasks(self, cmdOpen: str | None) -> None:
"""Process tasks after the main window has been created."""
# Check that config loaded fine
if CONFIG.hasError:
SHARED.error(CONFIG.errorText())

if cmdOpen:
QApplication.processEvents()
logger.info("Command line path: %s", cmdOpen)
Expand Down Expand Up @@ -616,6 +617,10 @@ def viewDocument(self, tHandle: str | None = None, sTitle: str | None = None) ->
# Make sure main tab is in Editor view
self._changeView(nwView.EDITOR)

# If we're loading the document in the editor, it may need to be saved
if tHandle == self.docEditor.docHandle and self.docEditor.docChanged:
self.saveDocument()

logger.debug("Viewing document with handle '%s'", tHandle)
updateHistory = tHandle != self.docViewer.docHandle
if self.docViewer.loadText(tHandle, updateHistory=updateHistory):
Expand Down Expand Up @@ -719,14 +724,6 @@ def openSelectedItem(self) -> None:

return

def editItemLabel(self, tHandle: str | None = None) -> None:
"""Open the edit item dialog."""
if SHARED.hasProject:
if tHandle is None and (self.docEditor.anyFocus() or SHARED.focusMode):
tHandle = self.docEditor.docHandle
self.projView.renameTreeItem(tHandle)
return

def rebuildTrees(self) -> None:
"""Rebuild the project tree."""
self.projView.populateTree()
Expand Down Expand Up @@ -847,15 +844,6 @@ def showDictionariesDialog(self) -> None:
SHARED.error(self.tr("Could not initialise the dialog."))
return

def reportConfErr(self) -> None:
"""Checks if the Config module has any errors to report, and let
the user know if this is the case. The Config module caches
errors since it is initialised before the GUI itself.
"""
if CONFIG.hasError:
SHARED.error(CONFIG.errorText())
return

##
# Main Window Actions
##
Expand Down Expand Up @@ -886,9 +874,7 @@ def closeMain(self) -> bool:

if SHARED.hasProject:
self.closeProject(True)

CONFIG.saveConfig()
self.reportConfErr()

QApplication.quit()

Expand Down
69 changes: 69 additions & 0 deletions tests/test_gui/test_gui_guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,21 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, projPath):
# Check that latest release info updated
assert CONFIG.lastNotes != "0x0"

# Set some config error
CONFIG._hasError = True
CONFIG._errData.append("Foo")

# Check that project open dialog launches
nwGUI.postLaunchTasks(None)
qtbot.waitUntil(lambda: SHARED.findTopLevelWidget(GuiWelcome) is not None, timeout=1000)
assert isinstance(welcome := SHARED.findTopLevelWidget(GuiWelcome), GuiWelcome)
welcome.show()
welcome.close()

# Config errors should be cleared
assert SHARED.lastAlert == "Foo"
assert CONFIG._hasError is False

# qtbot.stop()


Expand Down Expand Up @@ -567,6 +575,67 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
# qtbot.stop()


@pytest.mark.gui
def testGuiMain_Viewing(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test the document viewer."""
buildTestProject(nwGUI, projPath)
nwGUI.closeProject()

# View before a project is open does nothing
assert nwGUI.splitView.isVisible() is False
assert nwGUI.viewDocument(None) is False
assert nwGUI.splitView.isVisible() is False

# Open project requires a path
assert nwGUI.openProject(None) is False
assert SHARED.hasProject is False

# Open the test project, properly
nwGUI.openProject(projPath)
assert nwGUI.docEditor.docHandle == C.hTitlePage

# If editor has focus, open that document
with monkeypatch.context() as mp:
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: True)
nwGUI.viewDocument(None)
assert nwGUI.docViewer.docHandle == C.hTitlePage
nwGUI.closeDocViewer()

# If editor does not have focus, open selected handle
with monkeypatch.context() as mp:
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: False)
nwGUI.projView.projTree.setSelectedHandle(C.hSceneDoc)
nwGUI.viewDocument(None)
assert nwGUI.docViewer.docHandle == C.hSceneDoc

# If there is no selection, get last selected
SHARED.project.data.setLastHandle(C.hChapterDoc, "viewer")
assert SHARED.project.data.getLastHandle("viewer") == C.hChapterDoc
with monkeypatch.context() as mp:
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: False)
nwGUI.projView.projTree.clearSelection()
nwGUI.viewDocument(None)
assert nwGUI.docViewer.docHandle == C.hChapterDoc

# If all fails, don't open anything
SHARED.project.data.setLastHandle(None, "viewer")
assert SHARED.project.data.getLastHandle("viewer") is None
with monkeypatch.context() as mp:
mp.setattr(nwGUI.docEditor, "hasFocus", lambda *a: False)
nwGUI.projView.projTree.clearSelection()
assert nwGUI.viewDocument(None) is False

# If editor doc was edited and requested for the viewer, save it first
nwGUI.openDocument(C.hSceneDoc)
nwGUI.docEditor.setPlainText("### New Scene\n\nWith some stuff in it!\n\n")
assert nwGUI.docEditor.docChanged is True

nwGUI.viewDocument(C.hSceneDoc)
assert nwGUI.docViewer.toPlainText() == "New Scene\nWith some stuff in it!"

# qtbot.stop()


@pytest.mark.gui
def testGuiMain_Features(qtbot, nwGUI, projPath, mockRnd):
"""Test various features of the main window."""
Expand Down