diff --git a/novelwriter/dialogs/wordlist.py b/novelwriter/dialogs/wordlist.py
index 54ec2f2f..721ab91e 100644
--- a/novelwriter/dialogs/wordlist.py
+++ b/novelwriter/dialogs/wordlist.py
@@ -25,14 +25,13 @@ from __future__ import annotations
import logging
-from typing import TYPE_CHECKING
from pathlib import Path
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import (
QAbstractItemView, QApplication, QDialog, QDialogButtonBox, QFileDialog,
- QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout
+ QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout, QWidget
)
from novelwriter import CONFIG, SHARED
@@ -42,9 +41,6 @@ from novelwriter.extensions.configlayout import NColourLabel
from novelwriter.extensions.modified import NIconToolButton
from novelwriter.types import QtDialogClose, QtDialogSave
-if TYPE_CHECKING: # pragma: no cover
- from novelwriter.guimain import GuiMain
-
logger = logging.getLogger(__name__)
@@ -52,8 +48,8 @@ class GuiWordList(QDialog):
newWordListReady = pyqtSignal()
- def __init__(self, mainGui: GuiMain) -> None:
- super().__init__(parent=mainGui)
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
logger.debug("Create: GuiWordList")
self.setObjectName("GuiWordList")
diff --git a/novelwriter/extensions/modified.py b/novelwriter/extensions/modified.py
index 8f185b24..450647ac 100644
--- a/novelwriter/extensions/modified.py
+++ b/novelwriter/extensions/modified.py
@@ -28,6 +28,7 @@ along with this program. If not, see .
from __future__ import annotations
from enum import Enum
+from typing import TYPE_CHECKING
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QWheelEvent
@@ -38,10 +39,13 @@ from PyQt5.QtWidgets import (
from novelwriter import CONFIG, SHARED
+if TYPE_CHECKING: # pragma: no cover
+ from novelwriter.guimain import GuiMain
+
class NToolDialog(QDialog):
- def __init__(self, parent: QWidget | None = None) -> None:
+ def __init__(self, parent: GuiMain) -> None:
super().__init__(parent=parent)
self.setModal(False)
if CONFIG.osDarwin:
diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py
index 7ed3fab7..662b1c35 100644
--- a/novelwriter/gui/doceditor.py
+++ b/novelwriter/gui/doceditor.py
@@ -36,7 +36,6 @@ import logging
from enum import Enum
from time import time
-from typing import TYPE_CHECKING
from PyQt5.QtCore import (
QObject, QPoint, QRegularExpression, QRunnable, Qt, QTimer, pyqtSignal,
@@ -69,9 +68,6 @@ from novelwriter.types import (
QtMoveAnchor, QtMoveLeft, QtMoveRight
)
-if TYPE_CHECKING: # pragma: no cover
- from novelwriter.guimain import GuiMain
-
logger = logging.getLogger(__name__)
@@ -107,15 +103,14 @@ class GuiDocEditor(QPlainTextEdit):
requestProjectItemSelected = pyqtSignal(str, bool)
requestProjectItemRenamed = pyqtSignal(str, str)
requestNewNoteCreation = pyqtSignal(str, nwItemClass)
+ requestNextDocument = pyqtSignal(str, bool)
- def __init__(self, mainGui: GuiMain) -> None:
- super().__init__(parent=mainGui)
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
logger.debug("Create: GuiDocEditor")
# Class Variables
- self.mainGui = mainGui
-
self._nwDocument = None
self._nwItem = None
@@ -477,7 +472,6 @@ class GuiDocEditor(QPlainTextEdit):
cC, wC, pC = standardCounter(docText)
self._updateDocCounts(cC, wC, pC)
- self.saveCursorPosition()
if not self._nwDocument.writeDocument(docText):
saveOk = False
if self._nwDocument.hashError:
@@ -1320,9 +1314,8 @@ class GuiDocEditor(QPlainTextEdit):
self.docSearch.setResultCount(0, 0)
self._lastFind = None
if CONFIG.searchNextFile and not goBack:
- self.mainGui.openNextDocument(
- self._docHandle, wrapAround=CONFIG.searchLoop
- )
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
+ QApplication.processEvents()
self.beginSearch()
self.setFocus()
return
@@ -1341,9 +1334,8 @@ class GuiDocEditor(QPlainTextEdit):
if resIdx > maxIdx and self._docHandle:
if CONFIG.searchNextFile and not goBack:
- self.mainGui.openNextDocument(
- self._docHandle, wrapAround=CONFIG.searchLoop
- )
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
+ QApplication.processEvents()
self.beginSearch()
self.setFocus()
return
diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py
index 7d6b05cf..6ac50c19 100644
--- a/novelwriter/gui/mainmenu.py
+++ b/novelwriter/gui/mainmenu.py
@@ -25,16 +25,16 @@ from __future__ import annotations
import logging
-from typing import TYPE_CHECKING
from pathlib import Path
+from typing import TYPE_CHECKING
-from PyQt5.QtGui import QDesktopServices
from PyQt5.QtCore import QUrl, pyqtSignal, pyqtSlot
-from PyQt5.QtWidgets import QMenuBar, QAction
+from PyQt5.QtGui import QDesktopServices
+from PyQt5.QtWidgets import QAction, QMenuBar
from novelwriter import CONFIG, SHARED
from novelwriter.common import openExternalPath
-from novelwriter.constants import nwConst, trConst, nwKeyWords, nwLabels, nwUnicode
+from novelwriter.constants import nwConst, nwKeyWords, nwLabels, nwUnicode, trConst
from novelwriter.enum import nwDocAction, nwDocInsert, nwView, nwWidget
from novelwriter.extensions.eventfilters import StatusTipFilter
@@ -202,7 +202,7 @@ class GuiMainMenu(QMenuBar):
# Document > Save
self.aSaveDoc = self.docuMenu.addAction(self.tr("Save Document"))
self.aSaveDoc.setShortcut("Ctrl+S")
- self.aSaveDoc.triggered.connect(self.mainGui.saveDocument)
+ self.aSaveDoc.triggered.connect(self.mainGui.forceSaveDocument)
# Document > Close
self.aCloseDoc = self.docuMenu.addAction(self.tr("Close Document"))
diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py
index 6643df47..68aa8c46 100644
--- a/novelwriter/gui/noveltree.py
+++ b/novelwriter/gui/noveltree.py
@@ -29,9 +29,8 @@ import logging
from enum import Enum
from time import time
-from typing import TYPE_CHECKING
-from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSlot, pyqtSignal
+from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
from PyQt5.QtWidgets import (
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
@@ -52,9 +51,6 @@ from novelwriter.types import (
QtUserRole
)
-if TYPE_CHECKING: # pragma: no cover
- from novelwriter.guimain import GuiMain
-
logger = logging.getLogger(__name__)
@@ -74,10 +70,8 @@ class GuiNovelView(QWidget):
selectedItemChanged = pyqtSignal(str)
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
- def __init__(self, mainGui: GuiMain) -> None:
- super().__init__(parent=mainGui)
-
- self.mainGui = mainGui
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
# Build GUI
self.novelTree = GuiNovelTree(self)
@@ -202,7 +196,6 @@ class GuiNovelToolBar(QWidget):
logger.debug("Create: GuiNovelToolBar")
self.novelView = novelView
- self.mainGui = novelView.mainGui
iSz = SHARED.theme.baseIconSize
mPx = CONFIG.pxInt(2)
@@ -378,7 +371,6 @@ class GuiNovelTree(QTreeWidget):
logger.debug("Create: GuiNovelTree")
self.novelView = novelView
- self.mainGui = novelView.mainGui
# Internal Variables
self._treeMap = {}
@@ -493,7 +485,7 @@ class GuiNovelTree(QTreeWidget):
if rootHandle is None:
rootHandle = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
- treeChanged = self.mainGui.projView.changedSince(self._lastBuild)
+ treeChanged = SHARED.mainGui.projView.changedSince(self._lastBuild)
indexChanged = SHARED.project.index.rootChangedSince(rootHandle, self._lastBuild)
if not (treeChanged or indexChanged or overRide):
logger.debug("No changes have been made to the novel index")
diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py
index 8074325b..34a324da 100644
--- a/novelwriter/gui/projtree.py
+++ b/novelwriter/gui/projtree.py
@@ -30,12 +30,9 @@ import logging
from enum import Enum
from time import time
-from typing import TYPE_CHECKING
-from PyQt5.QtCore import QPoint, QTimer, Qt, pyqtSignal, pyqtSlot
-from PyQt5.QtGui import (
- QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
-)
+from PyQt5.QtCore import QPoint, Qt, QTimer, pyqtSignal, pyqtSlot
+from PyQt5.QtGui import QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
from PyQt5.QtWidgets import (
QAbstractItemView, QAction, QDialog, QFrame, QHBoxLayout, QHeaderView,
QLabel, QMenu, QShortcut, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
@@ -44,24 +41,21 @@ from PyQt5.QtWidgets import (
from novelwriter import CONFIG, SHARED
from novelwriter.common import minmax
-from novelwriter.constants import nwHeaders, nwUnicode, trConst, nwLabels
+from novelwriter.constants import nwHeaders, nwLabels, nwUnicode, trConst
from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter
from novelwriter.core.item import NWItem
from novelwriter.dialogs.docmerge import GuiDocMerge
from novelwriter.dialogs.docsplit import GuiDocSplit
from novelwriter.dialogs.editlabel import GuiEditLabel
from novelwriter.dialogs.projectsettings import GuiProjectSettings
-from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout
+from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType
from novelwriter.extensions.modified import NIconToolButton
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
from novelwriter.types import (
QtAlignLeft, QtAlignRight, QtMouseLeft, QtMouseMiddle, QtSizeExpanding,
- QtUserRole,
+ QtUserRole
)
-if TYPE_CHECKING: # pragma: no cover
- from novelwriter.guimain import GuiMain
-
logger = logging.getLogger(__name__)
@@ -83,10 +77,8 @@ class GuiProjectView(QWidget):
# Requests for the main GUI
projectSettingsRequest = pyqtSignal(int)
- def __init__(self, mainGui: GuiMain) -> None:
- super().__init__(parent=mainGui)
-
- self.mainGui = mainGui
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
# Build GUI
self.projTree = GuiProjectTree(self)
@@ -265,7 +257,6 @@ class GuiProjectToolBar(QWidget):
self.projView = projView
self.projTree = projView.projTree
- self.mainGui = projView.mainGui
iSz = SHARED.theme.baseIconSize
mPx = CONFIG.pxInt(2)
@@ -501,7 +492,6 @@ class GuiProjectTree(QTreeWidget):
logger.debug("Create: GuiProjectTree")
self.projView = projView
- self.mainGui = projView.mainGui
# Internal Variables
self._treeMap: dict[str, QTreeWidgetItem] = {}
@@ -1012,8 +1002,7 @@ class GuiProjectTree(QTreeWidget):
trItemP.takeChild(tIndex)
for dHandle in reversed(self.getTreeFromHandle(tHandle)):
- if self.mainGui.docEditor.docHandle == dHandle:
- self.mainGui.closeDocument()
+ SHARED.closeDocument(dHandle)
SHARED.project.removeItem(dHandle)
self._treeMap.pop(dHandle, None)
@@ -1412,7 +1401,7 @@ class GuiProjectTree(QTreeWidget):
if not newFile:
itemList.remove(tHandle)
- dlgMerge = GuiDocMerge(self.mainGui, tHandle, itemList)
+ dlgMerge = GuiDocMerge(SHARED.mainGui, tHandle, itemList)
dlgMerge.exec()
if dlgMerge.result() == QDialog.DialogCode.Accepted:
@@ -1424,7 +1413,7 @@ class GuiProjectTree(QTreeWidget):
return False
# Save the open document first, in case it's part of merge
- self.mainGui.saveDocument()
+ SHARED.saveDocument()
# Create merge object, and append docs
docMerger = DocMerger(SHARED.project)
@@ -1453,7 +1442,8 @@ class GuiProjectTree(QTreeWidget):
if newFile:
self.revealNewTreeItem(mHandle, nHandle=tHandle, wordCount=True)
- self.mainGui.openDocument(mHandle, doScroll=True)
+ self.projView.openDocumentRequest.emit(mHandle, nwDocMode.EDIT, "", False)
+ self.projView.setSelectedHandle(mHandle, doScroll=True)
if mrgData.get("moveToTrash", False):
for sHandle in reversed(mrgData.get("finalItems", [])):
@@ -1482,7 +1472,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("Only valid document items can be split")
return False
- dlgSplit = GuiDocSplit(self.mainGui, tHandle)
+ dlgSplit = GuiDocSplit(SHARED.mainGui, tHandle)
dlgSplit.exec()
if dlgSplit.result() == QDialog.DialogCode.Accepted:
diff --git a/novelwriter/gui/search.py b/novelwriter/gui/search.py
index 93ee759b..17d18f53 100644
--- a/novelwriter/gui/search.py
+++ b/novelwriter/gui/search.py
@@ -259,7 +259,7 @@ class GuiProjectSearch(QWidget):
if not self._blocked:
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
start = time()
- SHARED.mainGui.saveDocument()
+ SHARED.saveDocument()
self._blocked = True
self._map = {}
self.searchResult.clear()
diff --git a/novelwriter/gui/sidebar.py b/novelwriter/gui/sidebar.py
index d5dce50d..0620ad2d 100644
--- a/novelwriter/gui/sidebar.py
+++ b/novelwriter/gui/sidebar.py
@@ -27,8 +27,8 @@ import logging
from typing import TYPE_CHECKING
-from PyQt5.QtGui import QPalette
from PyQt5.QtCore import QEvent, QPoint, QSize, pyqtSignal
+from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QMenu, QVBoxLayout, QWidget
from novelwriter import CONFIG, SHARED
@@ -58,7 +58,7 @@ class GuiSideBar(QWidget):
iSz = QSize(iPx, iPx)
self.setContentsMargins(0, 0, 0, 0)
- self.installEventFilter(StatusTipFilter(mainGui))
+ self.installEventFilter(StatusTipFilter(self.mainGui))
# Buttons
self.tbProject = NIconToolButton(self, iSz)
diff --git a/novelwriter/gui/statusbar.py b/novelwriter/gui/statusbar.py
index 1992d609..6b51731a 100644
--- a/novelwriter/gui/statusbar.py
+++ b/novelwriter/gui/statusbar.py
@@ -27,26 +27,23 @@ import logging
from datetime import datetime
from time import time
-from typing import TYPE_CHECKING, Literal
+from typing import Literal
-from PyQt5.QtCore import pyqtSlot, QLocale
-from PyQt5.QtWidgets import QApplication, QStatusBar, QLabel
+from PyQt5.QtCore import QLocale, pyqtSlot
+from PyQt5.QtWidgets import QApplication, QLabel, QStatusBar, QWidget
from novelwriter import CONFIG, SHARED
from novelwriter.common import formatTime
from novelwriter.constants import nwConst
from novelwriter.extensions.statusled import StatusLED
-if TYPE_CHECKING: # pragma: no cover
- from novelwriter.guimain import GuiMain
-
logger = logging.getLogger(__name__)
class GuiMainStatus(QStatusBar):
- def __init__(self, mainGui: GuiMain) -> None:
- super().__init__(parent=mainGui)
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
logger.debug("Create: GuiMainStatus")
@@ -238,6 +235,7 @@ class GuiMainStatus(QStatusBar):
before starting novelWriter.
"""
import tracemalloc
+
from collections import Counter
widgets = QApplication.allWidgets()
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index afe7966d..e35699e8 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -263,6 +263,7 @@ class GuiMain(QMainWindow):
self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem)
self.docEditor.requestNewNoteCreation.connect(self.projView.createNewNote)
self.docEditor.docTextChanged.connect(self.projSearch.textChanged)
+ self.docEditor.requestNextDocument.connect(self.openNextDocument)
self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle)
self.docViewer.loadDocumentTagRequest.connect(self._followTag)
@@ -369,9 +370,7 @@ class GuiMain(QMainWindow):
if not msgYes:
return False
- if self.docEditor.docChanged:
- self.saveDocument()
-
+ self.saveDocument()
saveOK = self.saveProject()
doBackup = False
if SHARED.project.data.doBackup and CONFIG.backupOnClose:
@@ -514,9 +513,7 @@ class GuiMain(QMainWindow):
# Disable focus mode if it is active
if SHARED.focusMode:
SHARED.setFocusMode(False)
- self.docEditor.saveCursorPosition()
- if self.docEditor.docChanged:
- self.saveDocument()
+ self.saveDocument()
self.docEditor.clearEditor()
if not beforeOpen:
self.novelView.setActiveHandle(None)
@@ -553,42 +550,43 @@ class GuiMain(QMainWindow):
return True
- def openNextDocument(self, tHandle: str, wrapAround: bool = False) -> bool:
+ @pyqtSlot(str, bool)
+ def openNextDocument(self, tHandle: str, wrapAround: bool) -> None:
"""Open the next document in the project tree, following the
document with the given handle. Stop when reaching the end.
"""
- if not SHARED.hasProject:
- logger.error("No project open")
- return False
+ if SHARED.hasProject:
+ nHandle = None # The next handle after tHandle
+ fHandle = None # The first file handle we encounter
+ foundIt = False # We've found tHandle, pick the next we see
+ for tItem in SHARED.project.tree:
+ if not tItem.isFileType():
+ continue
+ if fHandle is None:
+ fHandle = tItem.itemHandle
+ if tItem.itemHandle == tHandle:
+ foundIt = True
+ elif foundIt:
+ nHandle = tItem.itemHandle
+ break
+ if nHandle is not None:
+ self.openDocument(nHandle, tLine=1, doScroll=True)
+ elif wrapAround:
+ self.openDocument(fHandle, tLine=1, doScroll=True)
+ return
- nHandle = None # The next handle after tHandle
- fHandle = None # The first file handle we encounter
- foundIt = False # We've found tHandle, pick the next we see
- for tItem in SHARED.project.tree:
- if not tItem.isFileType():
- continue
- if fHandle is None:
- fHandle = tItem.itemHandle
- if tItem.itemHandle == tHandle:
- foundIt = True
- elif foundIt:
- nHandle = tItem.itemHandle
- break
-
- if nHandle is not None:
- self.openDocument(nHandle, tLine=1, doScroll=True)
- return True
- elif wrapAround:
- self.openDocument(fHandle, tLine=1, doScroll=True)
- return False
-
- return False
-
- @pyqtSlot()
- def saveDocument(self) -> None:
+ def saveDocument(self, force: bool = False) -> None:
"""Save the current documents."""
if SHARED.hasProject:
- self.docEditor.saveText()
+ self.docEditor.saveCursorPosition()
+ if force or self.docEditor.docChanged:
+ self.docEditor.saveText()
+ return
+
+ @pyqtSlot()
+ def forceSaveDocument(self) -> None:
+ """Save document even of it has not changed."""
+ self.saveDocument(force=True)
return
def viewDocument(self, tHandle: str | None = None, sTitle: str | None = None) -> bool:
@@ -1133,7 +1131,7 @@ class GuiMain(QMainWindow):
@pyqtSlot()
def _reloadViewer(self) -> None:
"""Reload the document in the viewer."""
- if self.docEditor.docChanged and self.docEditor.docHandle == self.docViewer.docHandle:
+ if self.docEditor.docHandle == self.docViewer.docHandle:
# If the two panels have the same document, save any changes in the editor
self.saveDocument()
self.docViewer.reloadText()
@@ -1213,7 +1211,7 @@ class GuiMain(QMainWindow):
doSave &= SHARED.project.projChanged
doSave &= SHARED.project.storage.isOpen()
if doSave:
- logger.debug("Autosaving project")
+ logger.debug("Auto-saving project")
self.saveProject(autoSave=True)
return
@@ -1221,7 +1219,7 @@ class GuiMain(QMainWindow):
def _autoSaveDocument(self) -> None:
"""Autosave of the document. This is a timer-activated slot."""
if SHARED.hasProject and self.docEditor.docChanged:
- logger.debug("Autosaving document")
+ logger.debug("Auto-saving document")
self.saveDocument()
return
diff --git a/novelwriter/shared.py b/novelwriter/shared.py
index be323386..6586f676 100644
--- a/novelwriter/shared.py
+++ b/novelwriter/shared.py
@@ -171,6 +171,17 @@ class SharedData(QObject):
logger.debug("Thread Pool Max Count: %d", QThreadPool.globalInstance().maxThreadCount())
return
+ def closeDocument(self, tHandle: str | None = None) -> None:
+ """Close the document editor, optionally a specific document."""
+ if tHandle is None or tHandle == self.mainGui.docEditor.docHandle:
+ self.mainGui.closeDocument()
+ return
+
+ def saveDocument(self) -> None:
+ """Forward save document call to main GUI."""
+ self.mainGui.saveDocument()
+ return
+
def openProject(self, path: str | Path, clearLock: bool = False) -> bool:
"""Open a project."""
if self.project.isValid:
@@ -198,7 +209,7 @@ class SharedData(QObject):
def closeProject(self) -> None:
"""Close the current project."""
- self._closeDialogs()
+ self._closeToolDialogs()
self.project.closeProject(self._idleTime)
self._resetProject()
self._resetIdleTimer()
@@ -357,15 +368,12 @@ class SharedData(QObject):
self._idleTime = 0.0
return
- def _closeDialogs(self) -> None:
- """Close non-modal dialogs."""
- from novelwriter.tools.manuscript import GuiManuscript
- from novelwriter.tools.writingstats import GuiWritingStats
-
+ def _closeToolDialogs(self) -> None:
+ """Close all open tool dialogs."""
+ from novelwriter.extensions.modified import NToolDialog
for widget in self.mainGui.children():
- if isinstance(widget, (GuiManuscript, GuiWritingStats)):
+ if isinstance(widget, NToolDialog):
widget.close()
-
return
# END Class SharedData
diff --git a/novelwriter/tools/manusbuild.py b/novelwriter/tools/manusbuild.py
index e27e8b6a..8b6cdb0e 100644
--- a/novelwriter/tools/manusbuild.py
+++ b/novelwriter/tools/manusbuild.py
@@ -327,7 +327,7 @@ class GuiManuscriptBuild(QDialog):
return False
# Make sure editor content is saved before we start
- SHARED.mainGui.saveDocument()
+ SHARED.saveDocument()
docBuild = NWBuildDocument(SHARED.project, self._build)
docBuild.queueAll()
diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py
index 58c4ec53..47bbdc10 100644
--- a/novelwriter/tools/manuscript.py
+++ b/novelwriter/tools/manuscript.py
@@ -28,6 +28,7 @@ import logging
from datetime import datetime
from time import time
+from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
@@ -56,6 +57,9 @@ from novelwriter.types import (
QtSizeExpanding, QtSizeIgnored, QtUserRole
)
+if TYPE_CHECKING: # pragma: no cover
+ from novelwriter.guimain import GuiMain
+
logger = logging.getLogger(__name__)
@@ -69,7 +73,7 @@ class GuiManuscript(NToolDialog):
D_KEY = QtUserRole
- def __init__(self, parent: QWidget) -> None:
+ def __init__(self, parent: GuiMain) -> None:
super().__init__(parent=parent)
logger.debug("Create: GuiManuscript")
@@ -335,7 +339,7 @@ class GuiManuscript(NToolDialog):
return
# Make sure editor content is saved before we start
- SHARED.mainGui.saveDocument()
+ SHARED.saveDocument()
docBuild = NWBuildDocument(SHARED.project, build)
docBuild.setPreviewMode(True)
diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py
index e138b592..77b8035a 100644
--- a/novelwriter/tools/manussettings.py
+++ b/novelwriter/tools/manussettings.py
@@ -25,6 +25,8 @@ from __future__ import annotations
import logging
+from typing import TYPE_CHECKING
+
from PyQt5.QtCore import QEvent, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
from PyQt5.QtWidgets import (
@@ -51,6 +53,9 @@ from novelwriter.types import (
QtRoleApply, QtRoleReject, QtUserRole
)
+if TYPE_CHECKING: # pragma: no cover
+ from novelwriter.guimain import GuiMain
+
logger = logging.getLogger(__name__)
@@ -69,7 +74,7 @@ class GuiBuildSettings(NToolDialog):
newSettingsReady = pyqtSignal(BuildSettings)
- def __init__(self, parent: QWidget, build: BuildSettings) -> None:
+ def __init__(self, parent: GuiMain, build: BuildSettings) -> None:
super().__init__(parent=parent)
logger.debug("Create: GuiBuildSettings")
diff --git a/novelwriter/tools/writingstats.py b/novelwriter/tools/writingstats.py
index ad0a5508..cc59f9f0 100644
--- a/novelwriter/tools/writingstats.py
+++ b/novelwriter/tools/writingstats.py
@@ -69,8 +69,8 @@ class GuiWritingStats(NToolDialog):
FMT_JSON = 0
FMT_CSV = 1
- def __init__(self, mainGui: GuiMain) -> None:
- super().__init__(parent=mainGui)
+ def __init__(self, parent: GuiMain) -> None:
+ super().__init__(parent=parent)
logger.debug("Create: GuiWritingStats")
self.setObjectName("GuiWritingStats")
diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx
index 40d46cee..5aa8cdba 100644
--- a/sample/nwProject.nwx
+++ b/sample/nwProject.nwx
@@ -1,6 +1,6 @@
-
-
+
+
Sample Project
Jane Smith
@@ -58,7 +58,7 @@
Chapter One
-
-
+
Making a Scene
-
diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py
index dc6ffcfc..2a2205e8 100644
--- a/tests/test_gui/test_gui_guimain.py
+++ b/tests/test_gui/test_gui_guimain.py
@@ -21,24 +21,25 @@ along with this program. If not, see .
from __future__ import annotations
import sys
-import pytest
from shutil import copyfile
-from tools import C, NWD_IGNORE, cmpFiles, buildTestProject, XML_IGNORE
+import pytest
-from PyQt5.QtGui import QPalette
from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QMenu, QInputDialog
+from PyQt5.QtGui import QPalette
+from PyQt5.QtWidgets import QInputDialog, QMenu
from novelwriter import CONFIG, SHARED
+from novelwriter.dialogs.editlabel import GuiEditLabel
from novelwriter.enum import nwItemType, nwView, nwWidget
-from novelwriter.gui.outline import GuiOutlineView
-from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.gui.doceditor import GuiDocEditor
from novelwriter.gui.noveltree import GuiNovelView
+from novelwriter.gui.outline import GuiOutlineView
+from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.tools.welcome import GuiWelcome
-from novelwriter.dialogs.editlabel import GuiEditLabel
+
+from tests.tools import NWD_IGNORE, XML_IGNORE, C, buildTestProject, cmpFiles
KEY_DELAY = 1
@@ -50,7 +51,6 @@ def testGuiMain_ProjectBlocker(nwGUI):
assert nwGUI.closeProject() is True
assert nwGUI.saveProject() is False
assert nwGUI.openDocument(None) is False
- assert nwGUI.openNextDocument(None) is False
assert nwGUI.viewDocument(None) is False
assert nwGUI.importDocument() is False
@@ -84,7 +84,7 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, projPath):
nwGUI.closeProject()
# Check that latest release info updated
- CONFIG.lastNotes != "0x0"
+ assert CONFIG.lastNotes != "0x0"
# Check that project open dialog launches
nwGUI.postLaunchTasks(None)
@@ -522,6 +522,8 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
assert docEditor.docChanged
nwGUI.saveDocument()
assert docEditor.docChanged is False
+ nwGUI.forceSaveDocument()
+ assert docEditor.docChanged is False
nwGUI.rebuildIndex()
# Open and view the edited document