Let the shared class handle alert dialogs

This commit is contained in:
Veronica Berglyd Olsen
2023-08-14 17:08:53 +02:00
parent 3441ff38de
commit a17e73b5a2
17 changed files with 107 additions and 236 deletions
+7 -12
View File
@@ -28,21 +28,17 @@ from __future__ import annotations
import shutil import shutil
import logging import logging
from typing import TYPE_CHECKING, Iterable from typing import Iterable
from functools import partial from functools import partial
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from novelwriter import CONFIG from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwAlert
from novelwriter.common import minmax, simplified from novelwriter.common import minmax, simplified
from novelwriter.constants import nwItemClass from novelwriter.constants import nwItemClass
from novelwriter.core.item import NWItem from novelwriter.core.item import NWItem
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -312,8 +308,7 @@ class ProjectBuilder:
parameter provided by the New Project Wizard. parameter provided by the New Project Wizard.
""" """
def __init__(self, mainGui: GuiMain) -> None: def __init__(self) -> None:
self.mainGui = mainGui
self.tr = partial(QCoreApplication.translate, "NWProject") self.tr = partial(QCoreApplication.translate, "NWProject")
return return
@@ -478,17 +473,17 @@ class ProjectBuilder:
try: try:
shutil.unpack_archive(pkgSample, projPath) shutil.unpack_archive(pkgSample, projPath)
except Exception as exc: except Exception as exc:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"Failed to create a new example project." "Failed to create a new example project."
), level=nwAlert.ERROR, exc=exc) ), exc=exc)
return False return False
else: else:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"Failed to create a new example project. " "Failed to create a new example project. "
"Could not find the necessary files. " "Could not find the necessary files. "
"They seem to be missing from this installation." "They seem to be missing from this installation."
), level=nwAlert.ERROR) ))
return False return False
return True return True
+4 -1
View File
@@ -216,7 +216,7 @@ class NWProject(QObject):
# Project Methods # Project Methods
## ##
def openProject(self, projPath: str | Path) -> bool: def openProject(self, projPath: str | Path, clearLock: bool = False) -> bool:
"""Open the project file provided. If it doesn't exist, assume """Open the project file provided. If it doesn't exist, assume
it is a folder and look for the file within it. If successful, it is a folder and look for the file within it. If successful,
parse the XML of the file and populate the project variables and parse the XML of the file and populate the project variables and
@@ -230,6 +230,9 @@ class NWProject(QObject):
# Project Lock # Project Lock
# ============ # ============
if clearLock:
self._storage.clearLockFile()
lockStatus = self._storage.readLockFile() lockStatus = self._storage.readLockFile()
if len(lockStatus) > 0: if len(lockStatus) > 0:
if lockStatus[0] == "ERROR": if lockStatus[0] == "ERROR":
+6 -3
View File
@@ -25,6 +25,7 @@ from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
@@ -40,6 +41,9 @@ from novelwriter import CONFIG, SHARED
from novelwriter.common import formatInt from novelwriter.common import formatInt
from novelwriter.constants import nwFiles from novelwriter.constants import nwFiles
if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -55,13 +59,12 @@ class GuiProjectLoad(QDialog):
D_PATH = Qt.ItemDataRole.UserRole D_PATH = Qt.ItemDataRole.UserRole
def __init__(self, mainGui): def __init__(self, mainGui: GuiMain) -> None:
super().__init__(parent=mainGui) super().__init__(parent=mainGui)
logger.debug("Create: GuiProjectLoad") logger.debug("Create: GuiProjectLoad")
self.setObjectName("GuiProjectLoad") self.setObjectName("GuiProjectLoad")
self.mainGui = mainGui
self.openState = self.NONE_STATE self.openState = self.NONE_STATE
self.openPath = None self.openPath = None
@@ -225,7 +228,7 @@ class GuiProjectLoad(QDialog):
selList = self.listBox.selectedItems() selList = self.listBox.selectedItems()
if selList: if selList:
projName = selList[0].text(self.C_NAME) projName = selList[0].text(self.C_NAME)
msgYes = self.mainGui.askQuestion(self.tr( msgYes = SHARED.question(self.tr(
"Remove '{0}' from the recent projects list? " "Remove '{0}' from the recent projects list? "
"The project files will not be deleted." "The project files will not be deleted."
).format(projName)) ).format(projName))
+1 -7
View File
@@ -35,7 +35,6 @@ from PyQt5.QtWidgets import (
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwAlert
from novelwriter.common import simplified from novelwriter.common import simplified
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
from novelwriter.extensions.pageddialog import NPagedDialog from novelwriter.extensions.pageddialog import NPagedDialog
@@ -288,8 +287,6 @@ class GuiProjectEditStatus(QWidget):
def __init__(self, projGui, isStatus): def __init__(self, projGui, isStatus):
super().__init__(parent=projGui) super().__init__(parent=projGui)
self.mainGui = projGui.mainGui
if isStatus: if isStatus:
self.theStatus = SHARED.project.data.itemStatus self.theStatus = SHARED.project.data.itemStatus
pageLabel = self.tr("Novel File Status Levels") pageLabel = self.tr("Novel File Status Levels")
@@ -441,9 +438,7 @@ class GuiProjectEditStatus(QWidget):
if isinstance(selItem, QTreeWidgetItem): if isinstance(selItem, QTreeWidgetItem):
iRow = self.listBox.indexOfTopLevelItem(selItem) iRow = self.listBox.indexOfTopLevelItem(selItem)
if selItem.data(self.COL_LABEL, self.NUM_ROLE) > 0: if selItem.data(self.COL_LABEL, self.NUM_ROLE) > 0:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr("Cannot delete a status item that is in use."))
"Cannot delete a status item that is in use."
), level=nwAlert.ERROR)
else: else:
self.listBox.takeTopLevelItem(iRow) self.listBox.takeTopLevelItem(iRow)
self.colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE)) self.colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
@@ -574,7 +569,6 @@ class GuiProjectEditReplace(QWidget):
def __init__(self, projGui): def __init__(self, projGui):
super().__init__(parent=projGui) super().__init__(parent=projGui)
self.mainGui = projGui.mainGui
self.arChanged = False self.arChanged = False
wCol0 = CONFIG.pxInt( wCol0 = CONFIG.pxInt(
+3 -8
View File
@@ -34,7 +34,6 @@ from PyQt5.QtWidgets import (
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwAlert
from novelwriter.core.spellcheck import UserDictionary from novelwriter.core.spellcheck import UserDictionary
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING: # pragma: no cover
@@ -52,8 +51,6 @@ class GuiWordList(QDialog):
self.setObjectName("GuiWordList") self.setObjectName("GuiWordList")
self.setWindowTitle(self.tr("Project Word List")) self.setWindowTitle(self.tr("Project Word List"))
self.mainGui = mainGui
mS = CONFIG.pxInt(250) mS = CONFIG.pxInt(250)
wW = CONFIG.pxInt(320) wW = CONFIG.pxInt(320)
wH = CONFIG.pxInt(340) wH = CONFIG.pxInt(340)
@@ -123,15 +120,13 @@ class GuiWordList(QDialog):
"""Add a new word to the word list.""" """Add a new word to the word list."""
word = self.newEntry.text().strip() word = self.newEntry.text().strip()
if word == "": if word == "":
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr("Cannot add a blank word."))
"Cannot add a blank word."
), level=nwAlert.ERROR)
return return
if self.listBox.findItems(word, Qt.MatchExactly): if self.listBox.findItems(word, Qt.MatchExactly):
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"The word '{0}' is already in the word list." "The word '{0}' is already in the word list."
).format(word), level=nwAlert.ERROR) ).format(word))
return return
self.listBox.addItem(word) self.listBox.addItem(word)
+13 -16
View File
@@ -50,7 +50,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwAlert, nwDocAction, nwDocInsert, nwDocMode, nwItemClass from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass
from novelwriter.common import minmax, transferCase from novelwriter.common import minmax, transferCase
from novelwriter.constants import nwConst, nwKeyWords, nwUnicode from novelwriter.constants import nwConst, nwKeyWords, nwUnicode
from novelwriter.core.index import countWords from novelwriter.core.index import countWords
@@ -380,14 +380,14 @@ class GuiDocEditor(QTextEdit):
docSize = len(theDoc) docSize = len(theDoc)
if docSize > nwConst.MAX_DOCSIZE: if docSize > nwConst.MAX_DOCSIZE:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"The document you are trying to open is too big. " "The document you are trying to open is too big. "
"The document size is {0} MB. " "The document size is {0} MB. "
"The maximum size allowed is {1} MB." "The maximum size allowed is {1} MB."
).format( ).format(
f"{docSize/1.0e6:.2f}", f"{docSize/1.0e6:.2f}",
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}" f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
), level=nwAlert.ERROR) ))
self.clearEditor() self.clearEditor()
return False return False
@@ -478,14 +478,14 @@ class GuiDocEditor(QTextEdit):
""" """
docSize = len(theText) docSize = len(theText)
if docSize > nwConst.MAX_DOCSIZE: if docSize > nwConst.MAX_DOCSIZE:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"The text you are trying to add is too big. " "The text you are trying to add is too big. "
"The text size is {0} MB. " "The text size is {0} MB. "
"The maximum size allowed is {1} MB." "The maximum size allowed is {1} MB."
).format( ).format(
f"{docSize/1.0e6:.2f}", f"{docSize/1.0e6:.2f}",
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}" f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
), level=nwAlert.ERROR) ))
return False return False
qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
@@ -524,7 +524,7 @@ class GuiDocEditor(QTextEdit):
if not self._nwDocument.writeDocument(docText): if not self._nwDocument.writeDocument(docText):
saveOk = False saveOk = False
if self._nwDocument._currHash != self._nwDocument._prevHash: if self._nwDocument._currHash != self._nwDocument._prevHash:
msgYes = self.mainGui.askQuestion(self.tr( msgYes = SHARED.question(self.tr(
"This document has been changed outside of novelWriter " "This document has been changed outside of novelWriter "
"while it was open. Overwrite the file on disk?" "while it was open. Overwrite the file on disk?"
)) ))
@@ -532,10 +532,9 @@ class GuiDocEditor(QTextEdit):
saveOk = self._nwDocument.writeDocument(docText, forceWrite=True) saveOk = self._nwDocument.writeDocument(docText, forceWrite=True)
if not saveOk: if not saveOk:
self.mainGui.makeAlert( SHARED.error(
self.tr("Could not save document."), self.tr("Could not save document."),
info=self._nwDocument.getError(), info=self._nwDocument.getError()
level=nwAlert.ERROR
) )
return False return False
@@ -723,7 +722,7 @@ class GuiDocEditor(QTextEdit):
if not CONFIG.hasEnchant: if not CONFIG.hasEnchant:
if theMode: if theMode:
self.mainGui.makeAlert(self.tr( SHARED.info(self.tr(
"Spell checking requires the package PyEnchant. " "Spell checking requires the package PyEnchant. "
"It does not appear to be installed." "It does not appear to be installed."
)) ))
@@ -867,7 +866,7 @@ class GuiDocEditor(QTextEdit):
if self._nwDocument is None: if self._nwDocument is None:
logger.error("No document open") logger.error("No document open")
return False return False
self.mainGui.makeAlert( SHARED.info(
self.tr("The currently open file is saved in:"), self.tr("The currently open file is saved in:"),
info=self._nwDocument.getFileLocation() info=self._nwDocument.getFileLocation()
) )
@@ -1103,12 +1102,12 @@ class GuiDocEditor(QTextEdit):
self._lastFind = None self._lastFind = None
if self.document().characterCount() > nwConst.MAX_DOCSIZE: if self.document().characterCount() > nwConst.MAX_DOCSIZE:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"The document has grown too big and you cannot add more text to it. " "The document has grown too big and you cannot add more text to it. "
"The maximum size of a single novelWriter document is {0} MB." "The maximum size of a single novelWriter document is {0} MB."
).format( ).format(
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}" f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
), level=nwAlert.ERROR) ))
self.undo() self.undo()
return return
@@ -1665,9 +1664,7 @@ class GuiDocEditor(QTextEdit):
""" """
theCursor = self.textCursor() theCursor = self.textCursor()
if not theCursor.hasSelection(): if not theCursor.hasSelection():
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr("Please select some text before calling replace quotes."))
"Please select some text before calling replace quotes."
), level=nwAlert.ERROR)
return False return False
posS = theCursor.selectionStart() posS = theCursor.selectionStart()
+20 -30
View File
@@ -49,7 +49,7 @@ from novelwriter.dialogs.docsplit import GuiDocSplit
from novelwriter.dialogs.editlabel import GuiEditLabel from novelwriter.dialogs.editlabel import GuiEditLabel
from novelwriter.dialogs.projsettings import GuiProjectSettings from novelwriter.dialogs.projsettings import GuiProjectSettings
from novelwriter.enum import ( from novelwriter.enum import (
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwWidget nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
) )
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING: # pragma: no cover
@@ -582,9 +582,7 @@ class GuiProjectTree(QTreeWidget):
sHandle = self.getSelectedHandle() sHandle = self.getSelectedHandle()
pItem = SHARED.project.tree[sHandle] if sHandle else None pItem = SHARED.project.tree[sHandle] if sHandle else None
if sHandle is None or pItem is None: if sHandle is None or pItem is None:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr("Did not find anywhere to add the file or folder!"))
"Did not find anywhere to add the file or folder!"
), level=nwAlert.ERROR)
return False return False
# Collect some information about the selected item # Collect some information about the selected item
@@ -593,9 +591,7 @@ class GuiProjectTree(QTreeWidget):
sIsParent = False if qItem is None else qItem.childCount() > 0 sIsParent = False if qItem is None else qItem.childCount() > 0
if SHARED.project.tree.isTrash(sHandle): if SHARED.project.tree.isTrash(sHandle):
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr("Cannot add new files or folders to the Trash folder."))
"Cannot add new files or folders to the Trash folder."
), level=nwAlert.ERROR)
return False return False
# Set default label and determine if new item is to be added # Set default label and determine if new item is to be added
@@ -831,9 +827,7 @@ class GuiProjectTree(QTreeWidget):
logger.debug("Emptying Trash folder") logger.debug("Emptying Trash folder")
if trashHandle is None: if trashHandle is None:
self.mainGui.makeAlert(self.tr( SHARED.info(self.tr("There is currently no Trash folder in this project."))
"There is currently no Trash folder in this project."
))
return False return False
theTrash = self.getTreeFromHandle(trashHandle) theTrash = self.getTreeFromHandle(trashHandle)
@@ -842,12 +836,10 @@ class GuiProjectTree(QTreeWidget):
nTrash = len(theTrash) nTrash = len(theTrash)
if nTrash == 0: if nTrash == 0:
self.mainGui.makeAlert(self.tr( SHARED.info(self.tr("The Trash folder is already empty."))
"The Trash folder is already empty."
))
return False return False
msgYes = self.mainGui.askQuestion( msgYes = SHARED.question(
self.tr("Permanently delete {0} file(s) from Trash?").format(nTrash) self.tr("Permanently delete {0} file(s) from Trash?").format(nTrash)
) )
if not msgYes: if not msgYes:
@@ -893,8 +885,8 @@ class GuiProjectTree(QTreeWidget):
return False return False
if askFirst: if askFirst:
msgYes = self.mainGui.askQuestion( msgYes = SHARED.question(
self.tr("Move '{0}' to Trash?").format(nwItemS.itemName), self.tr("Move '{0}' to Trash?").format(nwItemS.itemName)
) )
if not msgYes: if not msgYes:
logger.info("Action cancelled by user") logger.info("Action cancelled by user")
@@ -928,9 +920,7 @@ class GuiProjectTree(QTreeWidget):
if nwItemS.isRootType(): if nwItemS.isRootType():
# Only an empty ROOT folder can be deleted # Only an empty ROOT folder can be deleted
if trItemS.childCount() > 0: if trItemS.childCount() > 0:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr("Root folders can only be deleted when they are empty."))
"Root folders can only be deleted when they are empty."
), level=nwAlert.ERROR)
return False return False
logger.debug("Permanently deleting root folder '%s'", tHandle) logger.debug("Permanently deleting root folder '%s'", tHandle)
@@ -948,7 +938,7 @@ class GuiProjectTree(QTreeWidget):
else: else:
if askFirst: if askFirst:
msgYes = self.mainGui.askQuestion( msgYes = SHARED.question(
self.tr("Permanently delete '{0}'?").format(nwItemS.itemName) self.tr("Permanently delete '{0}'?").format(nwItemS.itemName)
) )
if not msgYes: if not msgYes:
@@ -1517,7 +1507,7 @@ class GuiProjectTree(QTreeWidget):
"""Convert a folder to a note or document.""" """Convert a folder to a note or document."""
tItem = SHARED.project.tree[tHandle] tItem = SHARED.project.tree[tHandle]
if tItem is not None and tItem.isFolderType(): if tItem is not None and tItem.isFolderType():
msgYes = self.mainGui.askQuestion(self.tr( msgYes = SHARED.question(self.tr(
"Do you want to convert the folder to a {0}? " "Do you want to convert the folder to a {0}? "
"This action cannot be reversed." "This action cannot be reversed."
).format(trConst(nwLabels.LAYOUT_NAME[itemLayout]))) ).format(trConst(nwLabels.LAYOUT_NAME[itemLayout])))
@@ -1559,7 +1549,7 @@ class GuiProjectTree(QTreeWidget):
mrgData = dlgMerge.getData() mrgData = dlgMerge.getData()
mrgList = mrgData.get("finalItems", []) mrgList = mrgData.get("finalItems", [])
if not mrgList: if not mrgList:
self.mainGui.makeAlert(self.tr("No documents selected for merging.")) SHARED.info(self.tr("No documents selected for merging."))
return False return False
# Save the open document first, in case it's part of merge # Save the open document first, in case it's part of merge
@@ -1582,9 +1572,9 @@ class GuiProjectTree(QTreeWidget):
docMerger.appendText(sHandle, True, mLabel) docMerger.appendText(sHandle, True, mLabel)
if not docMerger.writeTargetDoc(): if not docMerger.writeTargetDoc():
self.mainGui.makeAlert( SHARED.error(
self.tr("Could not write document content."), self.tr("Could not write document content."),
info=docMerger.getError(), level=nwAlert.ERROR info=docMerger.getError()
) )
return False return False
@@ -1646,9 +1636,9 @@ class GuiProjectTree(QTreeWidget):
self.revealNewTreeItem(dHandle, nHandle=nHandle, wordCount=True) self.revealNewTreeItem(dHandle, nHandle=nHandle, wordCount=True)
self._alertTreeChange(dHandle, flush=False) self._alertTreeChange(dHandle, flush=False)
if not writeOk: if not writeOk:
self.mainGui.makeAlert( SHARED.error(
self.tr("Could not write document content."), self.tr("Could not write document content."),
info=docSplit.getError(), level=nwAlert.ERROR info=docSplit.getError()
) )
if splitData.get("moveToTrash", False): if splitData.get("moveToTrash", False):
@@ -1673,7 +1663,7 @@ class GuiProjectTree(QTreeWidget):
else: else:
question = self.tr("Do you want to duplicate this item and all child items?") question = self.tr("Do you want to duplicate this item and all child items?")
if not self.mainGui.askQuestion(question): if not SHARED.question(question):
return False return False
docDup = DocDuplicator(SHARED.project) docDup = DocDuplicator(SHARED.project)
@@ -1685,7 +1675,7 @@ class GuiProjectTree(QTreeWidget):
dupCount += 1 dupCount += 1
if dupCount != nItems: if dupCount != nItems:
self.mainGui.makeAlert(self.tr("Could not duplicate all items."), level=nwAlert.WARN) SHARED.warn(self.tr("Could not duplicate all items."))
self.saveTreeOrder() self.saveTreeOrder()
@@ -1742,9 +1732,9 @@ class GuiProjectTree(QTreeWidget):
elif pHandle and pHandle in self._treeMap: elif pHandle and pHandle in self._treeMap:
pItem = self._treeMap[pHandle] pItem = self._treeMap[pHandle]
else: else:
self.mainGui.makeAlert(self.tr( SHARED.error(self.tr(
"There is nowhere to add item with name '{0}'." "There is nowhere to add item with name '{0}'."
).format(nwItem.itemName), level=nwAlert.ERROR) ).format(nwItem.itemName))
return None return None
byIndex = -1 byIndex = -1
+26 -78
View File
@@ -31,7 +31,7 @@ from pathlib import Path
from datetime import datetime from datetime import datetime
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence, QPixmap from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
qApp, QDialog, QFileDialog, QMainWindow, QMessageBox, QShortcut, QSplitter, qApp, QDialog, QFileDialog, QMainWindow, QMessageBox, QShortcut, QSplitter,
QStackedWidget, QVBoxLayout, QWidget QStackedWidget, QVBoxLayout, QWidget
@@ -63,10 +63,10 @@ from novelwriter.core.project import NWProject
from novelwriter.core.coretools import ProjectBuilder from novelwriter.core.coretools import ProjectBuilder
from novelwriter.enum import ( from novelwriter.enum import (
nwDocAction, nwDocMode, nwItemType, nwItemClass, nwAlert, nwWidget, nwView nwDocAction, nwDocMode, nwItemType, nwItemClass, nwWidget, nwView
) )
from novelwriter.common import getGuiItem, hexToInt from novelwriter.common import getGuiItem, hexToInt
from novelwriter.constants import nwFiles, nwLabels, trConst from novelwriter.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -133,7 +133,6 @@ class GuiMain(QMainWindow):
# ============= # =============
# Sizes # Sizes
iPx = SHARED.theme.fontPixelSize
mPx = CONFIG.pxInt(4) mPx = CONFIG.pxInt(4)
hWd = CONFIG.pxInt(4) hWd = CONFIG.pxInt(4)
@@ -301,15 +300,6 @@ class GuiMain(QMainWindow):
keyEscape.setKey(QKeySequence(Qt.Key_Escape)) keyEscape.setKey(QKeySequence(Qt.Key_Escape))
keyEscape.activated.connect(self._keyPressEscape) keyEscape.activated.connect(self._keyPressEscape)
# Cache Alert Pixmaps
pxSize = (2*iPx, 2*iPx)
self.alertPix: dict[nwAlert, QPixmap] = {
nwAlert.INFO: SHARED.theme.getPixmap("alert_info", pxSize),
nwAlert.WARN: SHARED.theme.getPixmap("alert_warn", pxSize),
nwAlert.ERROR: SHARED.theme.getPixmap("alert_error", pxSize),
nwAlert.ASK: SHARED.theme.getPixmap("alert_question", pxSize),
}
# Check that config loaded fine # Check that config loaded fine
self.reportConfErr() self.reportConfErr()
@@ -325,11 +315,11 @@ class GuiMain(QMainWindow):
logger.debug("Ready: GUI") logger.debug("Ready: GUI")
if __hexversion__[-2] == "a" and logger.getEffectiveLevel() > logging.DEBUG: if __hexversion__[-2] == "a" and logger.getEffectiveLevel() > logging.DEBUG:
self.makeAlert(self.tr( SHARED.warn(self.tr(
"You are running an untested development version of novelWriter. " "You are running an untested development version of novelWriter. "
"Please be careful when working on a live project " "Please be careful when working on a live project "
"and make sure you take regular backups." "and make sure you take regular backups."
), level=nwAlert.WARN) ))
logger.info("novelWriter is ready ...") logger.info("novelWriter is ready ...")
self.mainStatus.setStatusMessage(self.tr("novelWriter is ready ...")) self.mainStatus.setStatusMessage(self.tr("novelWriter is ready ..."))
@@ -377,9 +367,9 @@ class GuiMain(QMainWindow):
"""Create a new project via the new project wizard.""" """Create a new project via the new project wizard."""
if SHARED.hasProject: if SHARED.hasProject:
if not self.closeProject(): if not self.closeProject():
self.makeAlert(self.tr( SHARED.error(self.tr(
"Cannot create a new project when another project is open." "Cannot create a new project when another project is open."
), level=nwAlert.ERROR) ))
return False return False
if projData is None: if projData is None:
@@ -394,14 +384,14 @@ class GuiMain(QMainWindow):
return False return False
if (Path(projPath) / nwFiles.PROJ_FILE).is_file(): if (Path(projPath) / nwFiles.PROJ_FILE).is_file():
self.makeAlert(self.tr( SHARED.error(self.tr(
"A project already exists in that location. " "A project already exists in that location. "
"Please choose another folder." "Please choose another folder."
), level=nwAlert.ERROR) ))
return False return False
logger.info("Creating new project") logger.info("Creating new project")
nwProject = ProjectBuilder(self) nwProject = ProjectBuilder()
if nwProject.buildProject(projData): if nwProject.buildProject(projData):
self.openProject(projPath) self.openProject(projPath)
else: else:
@@ -419,7 +409,7 @@ class GuiMain(QMainWindow):
return True return True
if not isYes: if not isYes:
msgYes = self.askQuestion("%s<br>%s" % ( msgYes = SHARED.question("%s<br>%s" % (
self.tr("Close the current project?"), self.tr("Close the current project?"),
self.tr("Changes are saved automatically.") self.tr("Changes are saved automatically.")
)) ))
@@ -434,7 +424,7 @@ class GuiMain(QMainWindow):
if SHARED.project.data.doBackup and CONFIG.backupOnClose: if SHARED.project.data.doBackup and CONFIG.backupOnClose:
doBackup = True doBackup = True
if CONFIG.askBeforeBackup: if CONFIG.askBeforeBackup:
doBackup = self.askQuestion(self.tr("Backup the current project?")) doBackup = SHARED.question(self.tr("Backup the current project?"))
if doBackup: if doBackup:
SHARED.project.backupProject(False) SHARED.project.backupProject(False)
@@ -505,9 +495,8 @@ class GuiMain(QMainWindow):
except Exception: except Exception:
lockDetails = "" lockDetails = ""
if self.askQuestion(lockText, info=lockInfo, details=lockDetails, level=nwAlert.WARN): if SHARED.question(lockText, info=lockInfo, details=lockDetails, warn=True):
SHARED.unlockProject() if not SHARED.openProject(projFile, clearLock=True):
if not SHARED.openProject(projFile):
return False return False
else: else:
return False return False
@@ -545,7 +534,7 @@ class GuiMain(QMainWindow):
# Check if we need to rebuild the index # Check if we need to rebuild the index
if SHARED.project.index.indexBroken: if SHARED.project.index.indexBroken:
self.makeAlert(self.tr("The project index is outdated or broken. Rebuilding index.")) SHARED.info(self.tr("The project index is outdated or broken. Rebuilding index."))
self.rebuildIndex() self.rebuildIndex()
# Make sure the changed status is set to false on things opened # Make sure the changed status is set to false on things opened
@@ -731,19 +720,19 @@ class GuiMain(QMainWindow):
theText = inFile.read() theText = inFile.read()
CONFIG.setLastPath(loadFile) CONFIG.setLastPath(loadFile)
except Exception as exc: except Exception as exc:
self.makeAlert(self.tr( SHARED.error(self.tr(
"Could not read file. The file must be an existing text file." "Could not read file. The file must be an existing text file."
), level=nwAlert.ERROR, exc=exc) ), exc=exc)
return False return False
if self.docEditor.docHandle is None: if self.docEditor.docHandle is None:
self.makeAlert(self.tr( SHARED.error(self.tr(
"Please open a document to import the text file into." "Please open a document to import the text file into."
), level=nwAlert.ERROR) ))
return False return False
if not self.docEditor.isEmpty: if not self.docEditor.isEmpty:
msgYes = self.askQuestion(self.tr( msgYes = SHARED.question(self.tr(
"Importing the file will overwrite the current content of " "Importing the file will overwrite the current content of "
"the document. Do you want to proceed?" "the document. Do you want to proceed?"
)) ))
@@ -845,7 +834,7 @@ class GuiMain(QMainWindow):
qApp.restoreOverrideCursor() qApp.restoreOverrideCursor()
if not beQuiet: if not beQuiet:
self.makeAlert(self.tr("The project index has been successfully rebuilt.")) SHARED.info(self.tr("The project index has been successfully rebuilt."))
return True return True
@@ -891,7 +880,7 @@ class GuiMain(QMainWindow):
self.saveDocument() self.saveDocument()
if dlgConf.needsRestart: if dlgConf.needsRestart:
self.makeAlert(self.tr( SHARED.info(self.tr(
"Some changes will not be applied until novelWriter has been restarted." "Some changes will not be applied until novelWriter has been restarted."
)) ))
@@ -1074,54 +1063,13 @@ class GuiMain(QMainWindow):
return return
def makeAlert(self, text: str, info: str = "", details: str = "",
level: nwAlert = nwAlert.INFO, exc: Exception | None = None) -> None:
"""Alert both the user and the logger at the same time."""
logText = " ".join(filter(None, [text, info, details]))
if level == nwAlert.INFO:
logger.info(logText, stacklevel=2)
elif level == nwAlert.WARN:
logger.warning(logText, stacklevel=2)
elif level == nwAlert.ERROR:
logger.error(logText, stacklevel=2, exc_info=exc)
if exc is not None:
tExc = f"{type(exc).__name__}: {str(exc)}"
info = f"{info}<br>{tExc}" if info else tExc
msgBox = QMessageBox(self)
msgBox.setWindowTitle(trConst(nwLabels.ALERT_NAME[level]))
msgBox.setText(text)
msgBox.setInformativeText(info)
msgBox.setDetailedText(details)
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.setIconPixmap(self.alertPix[level])
msgBox.adjustSize()
msgBox.exec_()
return
def askQuestion(self, text: str, info: str = "", details: str = "",
level: nwAlert = nwAlert.ASK) -> bool:
"""Ask the user a Yes/No question, and return the answer."""
msgBox = QMessageBox(self)
msgBox.setWindowTitle(trConst(nwLabels.ALERT_NAME[level]))
msgBox.setText(text)
msgBox.setInformativeText(info)
msgBox.setDetailedText(details)
msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
msgBox.setIconPixmap(self.alertPix[level])
msgBox.adjustSize()
msgBox.exec_()
return msgBox.result() == QMessageBox.Yes
def reportConfErr(self) -> bool: def reportConfErr(self) -> bool:
"""Checks if the Config module has any errors to report, and let """Checks if the Config module has any errors to report, and let
the user know if this is the case. The Config module caches the user know if this is the case. The Config module caches
errors since it is initialised before the GUI itself. errors since it is initialised before the GUI itself.
""" """
if CONFIG.hasError: if CONFIG.hasError:
self.makeAlert(CONFIG.errorText(), level=nwAlert.ERROR) SHARED.error(CONFIG.errorText())
return True return True
return False return False
@@ -1132,7 +1080,7 @@ class GuiMain(QMainWindow):
def closeMain(self) -> bool: def closeMain(self) -> bool:
"""Save everything, and close novelWriter.""" """Save everything, and close novelWriter."""
if SHARED.hasProject: if SHARED.hasProject:
msgYes = self.askQuestion("%s<br>%s" % ( msgYes = SHARED.question("%s<br>%s" % (
self.tr("Do you want to exit novelWriter?"), self.tr("Do you want to exit novelWriter?"),
self.tr("Changes are saved automatically.") self.tr("Changes are saved automatically.")
)) ))
@@ -1380,13 +1328,13 @@ class GuiMain(QMainWindow):
""" """
tHandle, sTitle = SHARED.project.index.getTagSource(tag) tHandle, sTitle = SHARED.project.index.getTagSource(tag)
if tHandle is None: if tHandle is None:
self.makeAlert(self.tr( SHARED.error(self.tr(
"Could not find the reference for tag '{0}'. It either doesn't " "Could not find the reference for tag '{0}'. It either doesn't "
"exist, or the index is out of date. The index can be updated " "exist, or the index is out of date. The index can be updated "
"from the Tools menu, or by pressing {1}." "from the Tools menu, or by pressing {1}."
).format( ).format(
tag, "F9" tag, "F9"
), level=nwAlert.ERROR) ))
return None, None return None, None
return tHandle, sTitle return tHandle, sTitle
+4 -8
View File
@@ -104,14 +104,14 @@ class SharedData(QObject):
logger.debug("SharedData instance initialised") logger.debug("SharedData instance initialised")
return return
def openProject(self, path: str | Path) -> bool: def openProject(self, path: str | Path, clearLock: bool = False) -> bool:
"""Open a project.""" """Open a project."""
if self.project.isValid: if self.project.isValid:
logger.error("A project is already open") logger.error("A project is already open")
return False return False
self._lockedBy = None self._lockedBy = None
status = self.project.openProject(path) status = self.project.openProject(path, clearLock=clearLock)
if status is False: if status is False:
# We must cache the lock status before resetting the project # We must cache the lock status before resetting the project
self._lockedBy = self.project.lockStatus self._lockedBy = self.project.lockStatus
@@ -132,10 +132,6 @@ class SharedData(QObject):
self._resetProject() self._resetProject()
return return
def unlockProject(self) -> bool:
"""Remove the project lock."""
return self.project.storage.clearLockFile()
## ##
# Alert Boxes # Alert Boxes
## ##
@@ -171,10 +167,10 @@ class SharedData(QObject):
return return
def question(self, text: str, info: str = "", details: str = "", warn: bool = False) -> bool: def question(self, text: str, info: str = "", details: str = "", warn: bool = False) -> bool:
"""Open an error alert box.""" """Open a question box."""
self._alert = _GuiAlert(self.mainGui, self.theme) self._alert = _GuiAlert(self.mainGui, self.theme)
self._alert.setMessage(text, info, details) self._alert.setMessage(text, info, details)
self._alert.setAlertType(_GuiAlert.ERROR, True) self._alert.setAlertType(_GuiAlert.WARN if warn else _GuiAlert.ASK, True)
self._alert.exec_() self._alert.exec_()
return self._alert.result() == QMessageBox.Yes return self._alert.result() == QMessageBox.Yes
+4 -10
View File
@@ -25,7 +25,6 @@ from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING
from pathlib import Path from pathlib import Path
from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
@@ -36,7 +35,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwAlert, nwBuildFmt from novelwriter.enum import nwBuildFmt
from novelwriter.common import makeFileNameSafe from novelwriter.common import makeFileNameSafe
from novelwriter.constants import nwLabels from novelwriter.constants import nwLabels
from novelwriter.core.item import NWItem from novelwriter.core.item import NWItem
@@ -44,9 +43,6 @@ from novelwriter.core.docbuild import NWBuildDocument
from novelwriter.core.buildsettings import BuildSettings from novelwriter.core.buildsettings import BuildSettings
from novelwriter.extensions.simpleprogress import NProgressSimple from novelwriter.extensions.simpleprogress import NProgressSimple
if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -59,14 +55,12 @@ class GuiManuscriptBuild(QDialog):
D_KEY = Qt.ItemDataRole.UserRole D_KEY = Qt.ItemDataRole.UserRole
def __init__(self, parent: QWidget, mainGui: GuiMain, build: BuildSettings): def __init__(self, parent: QWidget, build: BuildSettings):
super().__init__(parent=parent) super().__init__(parent=parent)
logger.debug("Create: GuiManuscriptBuild") logger.debug("Create: GuiManuscriptBuild")
self.setObjectName("GuiManuscriptBuild") self.setObjectName("GuiManuscriptBuild")
self.mainGui = mainGui
self._parent = parent self._parent = parent
self._build = build self._build = build
@@ -308,14 +302,14 @@ class GuiManuscriptBuild(QDialog):
self.buildProgress.setValue(0) self.buildProgress.setValue(0)
bPath = Path(self.buildPath.text()) bPath = Path(self.buildPath.text())
if not bPath.is_dir(): if not bPath.is_dir():
self.mainGui.makeAlert(self.tr("Output folder does not exist."), level=nwAlert.ERROR) SHARED.error(self.tr("Output folder does not exist."))
return False return False
bExt = nwLabels.BUILD_EXT[bFormat] bExt = nwLabels.BUILD_EXT[bFormat]
buildPath = (bPath / makeFileNameSafe(bName)).with_suffix(bExt) buildPath = (bPath / makeFileNameSafe(bName)).with_suffix(bExt)
if buildPath.exists(): if buildPath.exists():
if not self.mainGui.askQuestion( if not SHARED.question(
self.tr("The file already exists. Do you want to overwrite it?") self.tr("The file already exists. Do you want to overwrite it?")
): ):
return False return False
+2 -2
View File
@@ -268,7 +268,7 @@ class GuiManuscript(QDialog):
"""Delete the currently selected build settings entry.""" """Delete the currently selected build settings entry."""
build = self._getSelectedBuild() build = self._getSelectedBuild()
if build is not None: if build is not None:
if self.mainGui.askQuestion(self.tr("Delete build '{0}'?".format(build.name))): if SHARED.question(self.tr("Delete build '{0}'?".format(build.name))):
self._builds.removeBuild(build.buildID) self._builds.removeBuild(build.buildID)
self._updateBuildsList() self._updateBuildsList()
return return
@@ -325,7 +325,7 @@ class GuiManuscript(QDialog):
"""Open the build dialog and build the manuscript.""" """Open the build dialog and build the manuscript."""
build = self._getSelectedBuild() build = self._getSelectedBuild()
if isinstance(build, BuildSettings): if isinstance(build, BuildSettings):
dlgBuild = GuiManuscriptBuild(self, self.mainGui, build) dlgBuild = GuiManuscriptBuild(self, build)
dlgBuild.exec_() dlgBuild.exec_()
# After the build is done, save build settings changes # After the build is done, save build settings changes
+1 -3
View File
@@ -76,8 +76,6 @@ class GuiBuildSettings(QDialog):
if CONFIG.osDarwin: if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool) self.setWindowFlag(Qt.WindowType.Tool)
self.mainGui = mainGui
self._build = build self._build = build
self.setWindowTitle(self.tr("Manuscript Build Settings")) self.setWindowTitle(self.tr("Manuscript Build Settings"))
@@ -245,7 +243,7 @@ class GuiBuildSettings(QDialog):
whether the user wants to save them. whether the user wants to save them.
""" """
if self._build.changed: if self._build.changed:
response = self.mainGui.askQuestion(self.tr( response = SHARED.question(self.tr(
"Do you want to save your changes to '{0}'?".format(self._build.name) "Do you want to save your changes to '{0}'?".format(self._build.name)
)) ))
if response: if response:
+3 -6
View File
@@ -37,7 +37,6 @@ from PyQt5.QtWidgets import (
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwAlert
from novelwriter.error import formatException from novelwriter.error import formatException
from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax
from novelwriter.constants import nwConst from novelwriter.constants import nwConst
@@ -72,8 +71,6 @@ class GuiWritingStats(QDialog):
if CONFIG.osDarwin: if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool) self.setWindowFlag(Qt.WindowType.Tool)
self.mainGui = mainGui
self.logData = [] self.logData = []
self.filterData = [] self.filterData = []
self.timeFilter = 0.0 self.timeFilter = 0.0
@@ -413,14 +410,14 @@ class GuiWritingStats(QDialog):
# Report to user # Report to user
if wSuccess: if wSuccess:
self.mainGui.makeAlert( SHARED.info(
self.tr("{0} file successfully written to:").format(textFmt), self.tr("{0} file successfully written to:").format(textFmt),
info=savePath info=savePath
) )
else: else:
self.mainGui.makeAlert( SHARED.error(
self.tr("Failed to write {0} file.").format(textFmt), self.tr("Failed to write {0} file.").format(textFmt),
info=errMsg, level=nwAlert.ERROR info=errMsg
) )
return wSuccess return wSuccess
-28
View File
@@ -31,31 +31,13 @@ class MockGuiMain(QWidget):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.mainStatus = MockStatusBar() self.mainStatus = MockStatusBar()
self.projPath = "" self.projPath = ""
# Test Variables
self.askResponse = True
self.lastAlert = ""
self.lastQuestion = ""
return return
def postLaunchTasks(self, cmdOpen): def postLaunchTasks(self, cmdOpen):
return return
def makeAlert(self, text, info="", detals="", level=0, exc=None):
assert isinstance(text, str)
print("%s: %s" % (str(level), text))
self.lastAlert = str(text)
return
def askQuestion(self, text, info="", details="", level=3):
print("Question: %s" % text)
self.lastQuestion = text
return self.askResponse
def setStatus(self, theMessage): def setStatus(self, theMessage):
return return
@@ -72,16 +54,6 @@ class MockGuiMain(QWidget):
def close(self): def close(self):
return "close" return "close"
# Test Functions
def undo(self):
self.askResponse = True
return
def clear(self):
self.lastAlert = ""
return
# END Class MockGuiMain # END Class MockGuiMain
+7 -7
View File
@@ -410,7 +410,7 @@ def testCoreTools_NewMinimal(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
testFile = tstPaths.outDir / "coreTools_NewMinimal_nwProject.nwx" testFile = tstPaths.outDir / "coreTools_NewMinimal_nwProject.nwx"
compFile = tstPaths.refDir / "coreTools_NewMinimal_nwProject.nwx" compFile = tstPaths.refDir / "coreTools_NewMinimal_nwProject.nwx"
projBuild = ProjectBuilder(mockGUI) projBuild = ProjectBuilder()
# Setting no data should fail # Setting no data should fail
assert projBuild.buildProject({}) is False assert projBuild.buildProject({}) is False
@@ -432,7 +432,7 @@ def testCoreTools_NewMinimal(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
@pytest.mark.core @pytest.mark.core
def testCoreTools_NewCustomA(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd): def testCoreTools_NewCustomA(monkeypatch, fncPath, tstPaths, mockRnd):
"""Create a new project from a project wizard dictionary. """Create a new project from a project wizard dictionary.
Custom type with chapters and scenes. Custom type with chapters and scenes.
""" """
@@ -460,7 +460,7 @@ def testCoreTools_NewCustomA(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"numScenes": 3, "numScenes": 3,
} }
projBuild = ProjectBuilder(mockGUI) projBuild = ProjectBuilder()
assert projBuild.buildProject(projData) is True assert projBuild.buildProject(projData) is True
copyfile(projFile, testFile) copyfile(projFile, testFile)
@@ -470,7 +470,7 @@ def testCoreTools_NewCustomA(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
@pytest.mark.core @pytest.mark.core
def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd): def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockRnd):
"""Create a new project from a project wizard dictionary. """Create a new project from a project wizard dictionary.
Custom type without chapters, but with scenes. Custom type without chapters, but with scenes.
""" """
@@ -498,7 +498,7 @@ def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"numScenes": 6, "numScenes": 6,
} }
projBuild = ProjectBuilder(mockGUI) projBuild = ProjectBuilder()
assert projBuild.buildProject(projData) is True assert projBuild.buildProject(projData) is True
copyfile(projFile, testFile) copyfile(projFile, testFile)
@@ -508,7 +508,7 @@ def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
@pytest.mark.core @pytest.mark.core
def testCoreTools_NewSample(monkeypatch, fncPath, tstPaths, mockGUI): def testCoreTools_NewSample(monkeypatch, fncPath, tstPaths):
"""Check that we can create a new project can be created from the """Check that we can create a new project can be created from the
provided sample project via a zip file. provided sample project via a zip file.
""" """
@@ -522,7 +522,7 @@ def testCoreTools_NewSample(monkeypatch, fncPath, tstPaths, mockGUI):
"popCustom": False, "popCustom": False,
} }
projBuild = ProjectBuilder(mockGUI) projBuild = ProjectBuilder()
# No path set # No path set
assert projBuild.buildProject({"popSample": True}) is False assert projBuild.buildProject({"popSample": True}) is False
+4 -15
View File
@@ -27,7 +27,7 @@ from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox
from tools import C, writeFile, buildTestProject from tools import C, writeFile, buildTestProject
from novelwriter import CONFIG from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwDocAction, nwDocInsert from novelwriter.enum import nwDocAction, nwDocInsert
from novelwriter.constants import nwKeyWords, nwUnicode from novelwriter.constants import nwKeyWords, nwUnicode
from novelwriter.gui.doceditor import GuiDocEditor from novelwriter.gui.doceditor import GuiDocEditor
@@ -653,21 +653,10 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
# Reveal File Location # Reveal File Location
# ==================== # ====================
theMessage = ""
def recordMsg(*args, **kwargs):
nonlocal theMessage
theMessage = "%s|%s" % (args[0], kwargs["info"])
return None
assert not theMessage
monkeypatch.setattr(nwGUI, "makeAlert", recordMsg)
nwGUI.mainMenu.aFileDetails.activate(QAction.Trigger) nwGUI.mainMenu.aFileDetails.activate(QAction.Trigger)
path = str(projPath / "content" / "000000000000f.nwd")
theBits = theMessage.split("|") logMsg = SHARED.alert.logMessage if SHARED.alert else ""
assert len(theBits) == 2 assert logMsg == f"The currently open file is saved in: {path}"
assert theBits[0] == "The currently open file is saved in:"
assert theBits[1] == str(projPath / "content" / "000000000000f.nwd")
# qtbot.stop() # qtbot.stop()
+2 -2
View File
@@ -45,7 +45,7 @@ def testManuscriptBuild_Main(
build = BuildSettings() build = BuildSettings()
build.setLastPath(fncPath) build.setLastPath(fncPath)
manus = GuiManuscriptBuild(nwGUI, nwGUI, build) manus = GuiManuscriptBuild(nwGUI, build)
manus.show() manus.show()
# Check initial values # Check initial values
@@ -101,7 +101,7 @@ def testManuscriptBuild_Main(
# Error Handling # Error Handling
# ============== # ==============
manus = GuiManuscriptBuild(nwGUI, nwGUI, build) manus = GuiManuscriptBuild(nwGUI, build)
manus.show() manus.show()
# Name, path and format should be remembered # Name, path and format should be remembered