Significant improvements to dialog tests
This commit is contained in:
+1
-1
@@ -195,7 +195,7 @@ def main(sysArgs=None):
|
|||||||
testMode = True
|
testMode = True
|
||||||
|
|
||||||
# Set Config Options
|
# Set Config Options
|
||||||
CONFIG.blockGUI = not testMode
|
CONFIG.showGUI = not testMode
|
||||||
CONFIG.debugInfo = debugLevel < logging.INFO
|
CONFIG.debugInfo = debugLevel < logging.INFO
|
||||||
CONFIG.cmdOpen = cmdOpen
|
CONFIG.cmdOpen = cmdOpen
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ class Config:
|
|||||||
self.appHandle = self.appName.lower()
|
self.appHandle = self.appName.lower()
|
||||||
|
|
||||||
# Debug Settings
|
# Debug Settings
|
||||||
self.blockGUI = True # Allow blocking the GUI (disabled for testing)
|
self.showGUI = True # Allow blocking the GUI (disabled for testing)
|
||||||
self.debugInfo = False # True if log level is DEBUG or VERBOSE
|
self.debugInfo = False # True if log level is DEBUG or VERBOSE
|
||||||
|
|
||||||
# Config Error Handling
|
# Config Error Handling
|
||||||
|
|||||||
+9
-4
@@ -382,6 +382,7 @@ class NWProject():
|
|||||||
# ==========================
|
# ==========================
|
||||||
|
|
||||||
if not self.ensureFolderStructure():
|
if not self.ensureFolderStructure():
|
||||||
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
|
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
|
||||||
@@ -475,6 +476,7 @@ class NWProject():
|
|||||||
"Project file does not appear to be a novelWriterXML file.",
|
"Project file does not appear to be a novelWriterXML file.",
|
||||||
nwAlert.ERROR
|
nwAlert.ERROR
|
||||||
)
|
)
|
||||||
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check Project Storage Version
|
# Check Project Storage Version
|
||||||
@@ -489,7 +491,7 @@ class NWProject():
|
|||||||
# parser will lose the autoReplace settings if allowed to
|
# parser will lose the autoReplace settings if allowed to
|
||||||
# read the file. Introduced in version 0.10.
|
# read the file. Introduced in version 0.10.
|
||||||
|
|
||||||
if fileVersion == "1.0" and self.mainConf.blockGUI:
|
if fileVersion == "1.0" and self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(self.theParent, "Old Project Version", (
|
msgRes = msgBox.question(self.theParent, "Old Project Version", (
|
||||||
"The project file and data is created by a novelWriter version "
|
"The project file and data is created by a novelWriter version "
|
||||||
@@ -499,9 +501,10 @@ class NWProject():
|
|||||||
"any more, so make sure you have a recent backup."
|
"any more, so make sure you have a recent backup."
|
||||||
))
|
))
|
||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
elif fileVersion != "1.1" and fileVersion != "1.2" and self.mainConf.blockGUI:
|
elif fileVersion != "1.1" and fileVersion != "1.2" and self.mainConf.showGUI:
|
||||||
self.makeAlert((
|
self.makeAlert((
|
||||||
"Unknown or unsupported novelWriter project file format. "
|
"Unknown or unsupported novelWriter project file format. "
|
||||||
"The project cannot be opened by this version of novelWriter. "
|
"The project cannot be opened by this version of novelWriter. "
|
||||||
@@ -509,12 +512,13 @@ class NWProject():
|
|||||||
).format(
|
).format(
|
||||||
vers = appVersion,
|
vers = appVersion,
|
||||||
), nwAlert.ERROR)
|
), nwAlert.ERROR)
|
||||||
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check novelWriter Version
|
# Check novelWriter Version
|
||||||
# =========================
|
# =========================
|
||||||
|
|
||||||
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.blockGUI:
|
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
||||||
"This project was saved by a newer version of novelWriter, version %s. "
|
"This project was saved by a newer version of novelWriter, version %s. "
|
||||||
@@ -525,6 +529,7 @@ class NWProject():
|
|||||||
appVersion, nw.__version__
|
appVersion, nw.__version__
|
||||||
))
|
))
|
||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Start Parsing the XML
|
# Start Parsing the XML
|
||||||
@@ -927,7 +932,7 @@ class NWProject():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if path.isdir(projPath):
|
if path.isdir(projPath):
|
||||||
if self.mainConf.blockGUI and listdir(self.projPath):
|
if self.mainConf.showGUI and listdir(self.projPath):
|
||||||
self.theParent.makeAlert((
|
self.theParent.makeAlert((
|
||||||
"New project folder is not empty. "
|
"New project folder is not empty. "
|
||||||
"Each project requires a dedicated project folder."
|
"Each project requires a dedicated project folder."
|
||||||
|
|||||||
+1
-1
@@ -160,7 +160,7 @@ def exceptionHandler(exType, exValue, exTrace, testMode=False):
|
|||||||
|
|
||||||
errMsg = NWErrorMessage(nwGUI)
|
errMsg = NWErrorMessage(nwGUI)
|
||||||
errMsg.setMessage(exType, exValue, exTrace)
|
errMsg.setMessage(exType, exValue, exTrace)
|
||||||
if nw.CONFIG.blockGUI:
|
if nw.CONFIG.showGUI:
|
||||||
errMsg.exec_()
|
errMsg.exec_()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
+2
-2
@@ -634,7 +634,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
if not path.isdir(saveDir):
|
if not path.isdir(saveDir):
|
||||||
saveDir = self.mainConf.homePath
|
saveDir = self.mainConf.homePath
|
||||||
|
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
dlgOpt = QFileDialog.Options()
|
dlgOpt = QFileDialog.Options()
|
||||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
saveTo = QFileDialog.getSaveFileName(
|
saveTo = QFileDialog.getSaveFileName(
|
||||||
@@ -746,7 +746,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
errMsg = "Unknown format"
|
errMsg = "Unknown format"
|
||||||
|
|
||||||
# Report to user
|
# Report to user
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
if wSuccess:
|
if wSuccess:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
"%s file successfully written to:<br> %s" % (
|
"%s file successfully written to:<br> %s" % (
|
||||||
|
|||||||
+1
-1
@@ -163,7 +163,7 @@ class GuiDocSplit(QDialog):
|
|||||||
), nwAlert.ERROR)
|
), nwAlert.ERROR)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Split Document", (
|
self, "Split Document", (
|
||||||
|
|||||||
+4
-4
@@ -192,7 +192,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aOpenProject = QAction("Open Project", self)
|
self.aOpenProject = QAction("Open Project", self)
|
||||||
self.aOpenProject.setStatusTip("Open project")
|
self.aOpenProject.setStatusTip("Open project")
|
||||||
self.aOpenProject.setShortcut("Ctrl+Shift+O")
|
self.aOpenProject.setShortcut("Ctrl+Shift+O")
|
||||||
self.aOpenProject.triggered.connect(lambda: self.theParent.manageProjects())
|
self.aOpenProject.triggered.connect(lambda: self.theParent.showProjectLoadDialog())
|
||||||
self.projMenu.addAction(self.aOpenProject)
|
self.projMenu.addAction(self.aOpenProject)
|
||||||
|
|
||||||
# Project > Save Project
|
# Project > Save Project
|
||||||
@@ -213,7 +213,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aProjectSettings = QAction("Project Settings", self)
|
self.aProjectSettings = QAction("Project Settings", self)
|
||||||
self.aProjectSettings.setStatusTip("Project settings")
|
self.aProjectSettings.setStatusTip("Project settings")
|
||||||
self.aProjectSettings.setShortcut("Ctrl+Shift+,")
|
self.aProjectSettings.setShortcut("Ctrl+Shift+,")
|
||||||
self.aProjectSettings.triggered.connect(lambda: self.theParent.editProjectDialog())
|
self.aProjectSettings.triggered.connect(lambda: self.theParent.showProjectSettingsDialog())
|
||||||
self.projMenu.addAction(self.aProjectSettings)
|
self.projMenu.addAction(self.aProjectSettings)
|
||||||
|
|
||||||
# Project > Separator
|
# Project > Separator
|
||||||
@@ -829,7 +829,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aBuildProject = QAction("Build Novel Project", self)
|
self.aBuildProject = QAction("Build Novel Project", self)
|
||||||
self.aBuildProject.setStatusTip("Launch the Build novel project tool")
|
self.aBuildProject.setStatusTip("Launch the Build novel project tool")
|
||||||
self.aBuildProject.setShortcut("F5")
|
self.aBuildProject.setShortcut("F5")
|
||||||
self.aBuildProject.triggered.connect(lambda: self.theParent.buildProjectDialog())
|
self.aBuildProject.triggered.connect(lambda: self.theParent.showBuildProjectDialog())
|
||||||
self.toolsMenu.addAction(self.aBuildProject)
|
self.toolsMenu.addAction(self.aBuildProject)
|
||||||
|
|
||||||
# Tools > Writing Stats
|
# Tools > Writing Stats
|
||||||
@@ -843,7 +843,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aPreferences = QAction("Preferences", self)
|
self.aPreferences = QAction("Preferences", self)
|
||||||
self.aPreferences.setStatusTip("Preferences")
|
self.aPreferences.setStatusTip("Preferences")
|
||||||
self.aPreferences.setShortcut("Ctrl+,")
|
self.aPreferences.setShortcut("Ctrl+,")
|
||||||
self.aPreferences.triggered.connect(lambda: self.theParent.editConfigDialog())
|
self.aPreferences.triggered.connect(lambda: self.theParent.showPreferencesDialog())
|
||||||
self.toolsMenu.addAction(self.aPreferences)
|
self.toolsMenu.addAction(self.aPreferences)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class GuiPreferences(PagedDialog):
|
|||||||
validEntries &= retA
|
validEntries &= retA
|
||||||
needsRestart |= retB
|
needsRestart |= retB
|
||||||
|
|
||||||
if needsRestart and self.mainConf.blockGUI:
|
if needsRestart:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgBox.information(
|
msgBox.information(
|
||||||
self, "Preferences",
|
self, "Preferences",
|
||||||
@@ -120,7 +120,7 @@ class GuiPreferences(PagedDialog):
|
|||||||
"""Close the preferences without saving the changes.
|
"""Close the preferences without saving the changes.
|
||||||
"""
|
"""
|
||||||
logger.verbose("ConfigEditor close button clicked")
|
logger.verbose("ConfigEditor close button clicked")
|
||||||
self.close()
|
self.reject()
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiPreferences
|
# END Class GuiPreferences
|
||||||
|
|||||||
+2
-2
@@ -178,7 +178,7 @@ class GuiProjectLoad(QDialog):
|
|||||||
"""Browse for a folder path.
|
"""Browse for a folder path.
|
||||||
"""
|
"""
|
||||||
logger.verbose("GuiProjectLoad browse button clicked")
|
logger.verbose("GuiProjectLoad browse button clicked")
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
dlgOpt = QFileDialog.Options()
|
dlgOpt = QFileDialog.Options()
|
||||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
projFile, _ = QFileDialog.getOpenFileName(
|
projFile, _ = QFileDialog.getOpenFileName(
|
||||||
@@ -219,7 +219,7 @@ class GuiProjectLoad(QDialog):
|
|||||||
selList = self.listBox.selectedItems()
|
selList = self.listBox.selectedItems()
|
||||||
if selList:
|
if selList:
|
||||||
doRemove = False
|
doRemove = False
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Remove Entry",
|
self, "Remove Entry",
|
||||||
|
|||||||
+13
-3
@@ -124,13 +124,25 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
newList = self.tabReplace.getNewList()
|
newList = self.tabReplace.getNewList()
|
||||||
self.theProject.setAutoReplace(newList)
|
self.theProject.setAutoReplace(newList)
|
||||||
|
|
||||||
self._doClose()
|
self._saveGuiSettings()
|
||||||
|
self.accept()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _doClose(self):
|
def _doClose(self):
|
||||||
"""Save settings and close the dialog.
|
"""Save settings and close the dialog.
|
||||||
"""
|
"""
|
||||||
|
self._saveGuiSettings()
|
||||||
|
self.reject()
|
||||||
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
def _saveGuiSettings(self):
|
||||||
|
"""Save GUI settings.
|
||||||
|
"""
|
||||||
winWidth = self.mainConf.rpxInt(self.width())
|
winWidth = self.mainConf.rpxInt(self.width())
|
||||||
winHeight = self.mainConf.rpxInt(self.height())
|
winHeight = self.mainConf.rpxInt(self.height())
|
||||||
replaceColW = self.mainConf.rpxInt(self.tabReplace.listBox.columnWidth(0))
|
replaceColW = self.mainConf.rpxInt(self.tabReplace.listBox.columnWidth(0))
|
||||||
@@ -139,8 +151,6 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
self.optState.setValue("GuiProjectSettings", "winHeight", winHeight)
|
self.optState.setValue("GuiProjectSettings", "winHeight", winHeight)
|
||||||
self.optState.setValue("GuiProjectSettings", "replaceColW", replaceColW)
|
self.optState.setValue("GuiProjectSettings", "replaceColW", replaceColW)
|
||||||
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiProjectSettings
|
# END Class GuiProjectSettings
|
||||||
|
|||||||
+4
-4
@@ -261,7 +261,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
"""Move an item up or down in the tree, but only if the treeView
|
"""Move an item up or down in the tree, but only if the treeView
|
||||||
has focus. This also applies when the menu is used.
|
has focus. This also applies when the menu is used.
|
||||||
"""
|
"""
|
||||||
hasFocus = qApp.focusWidget() == self or not self.mainConf.blockGUI
|
hasFocus = qApp.focusWidget() == self or not self.mainConf.showGUI
|
||||||
if hasFocus and self.theParent.hasProject:
|
if hasFocus and self.theParent.hasProject:
|
||||||
|
|
||||||
tHandle = self.getSelectedHandle()
|
tHandle = self.getSelectedHandle()
|
||||||
@@ -362,7 +362,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.makeAlert("The Trash folder is already empty.", nwAlert.INFO)
|
self.makeAlert("The Trash folder is already empty.", nwAlert.INFO)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Empty Trash", "Permanently delete %d file%s from Trash?" % (
|
self, "Empty Trash", "Permanently delete %d file%s from Trash?" % (
|
||||||
@@ -416,7 +416,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
# If the file is in the trash folder already, as the
|
# If the file is in the trash folder already, as the
|
||||||
# user if they want to permanently delete the file.
|
# user if they want to permanently delete the file.
|
||||||
doPermanent = False
|
doPermanent = False
|
||||||
if self.mainConf.blockGUI and not alreadyAsked:
|
if self.mainConf.showGUI and not alreadyAsked:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Delete File", "Permanently delete file '%s'?" % nwItemS.itemName
|
self, "Delete File", "Permanently delete file '%s'?" % nwItemS.itemName
|
||||||
@@ -445,7 +445,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
# The file is not already in the trash folder, so we
|
# The file is not already in the trash folder, so we
|
||||||
# move it there.
|
# move it there.
|
||||||
doTrash = False
|
doTrash = False
|
||||||
if self.mainConf.blockGUI and askForTrash:
|
if self.mainConf.showGUI and askForTrash:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Delete File", "Move file '%s' to Trash?" % nwItemS.itemName
|
self, "Delete File", "Move file '%s' to Trash?" % nwItemS.itemName
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ class GuiWritingStats(QDialog):
|
|||||||
if not path.isdir(saveDir):
|
if not path.isdir(saveDir):
|
||||||
saveDir = self.mainConf.homePath
|
saveDir = self.mainConf.homePath
|
||||||
|
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
dlgOpt = QFileDialog.Options()
|
dlgOpt = QFileDialog.Options()
|
||||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
saveTo = QFileDialog.getSaveFileName(
|
saveTo = QFileDialog.getSaveFileName(
|
||||||
@@ -380,7 +380,7 @@ class GuiWritingStats(QDialog):
|
|||||||
errMsg = str(e)
|
errMsg = str(e)
|
||||||
|
|
||||||
# Report to user
|
# Report to user
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
if wSuccess:
|
if wSuccess:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
"%s file successfully written to:<br> %s" % (
|
"%s file successfully written to:<br> %s" % (
|
||||||
|
|||||||
+75
-63
@@ -195,8 +195,8 @@ class GuiMain(QMainWindow):
|
|||||||
self.setStatus = self.statusBar.setStatus
|
self.setStatus = self.statusBar.setStatus
|
||||||
self.setProjectStatus = self.statusBar.setProjectStatus
|
self.setProjectStatus = self.statusBar.setProjectStatus
|
||||||
|
|
||||||
if self.mainConf.blockGUI:
|
# Force a show of the GUI
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
# Check that config loaded fine
|
# Check that config loaded fine
|
||||||
self.reportConfErr()
|
self.reportConfErr()
|
||||||
@@ -218,7 +218,8 @@ class GuiMain(QMainWindow):
|
|||||||
logger.debug("Opening project from additional command line option")
|
logger.debug("Opening project from additional command line option")
|
||||||
self.openProject(self.mainConf.cmdOpen)
|
self.openProject(self.mainConf.cmdOpen)
|
||||||
else:
|
else:
|
||||||
self.manageProjects()
|
if self.mainConf.showGUI:
|
||||||
|
self.showProjectLoadDialog()
|
||||||
|
|
||||||
logger.debug("novelWriter is ready ...")
|
logger.debug("novelWriter is ready ...")
|
||||||
self.statusBar.setStatus("novelWriter is ready ...")
|
self.statusBar.setStatus("novelWriter is ready ...")
|
||||||
@@ -245,24 +246,6 @@ class GuiMain(QMainWindow):
|
|||||||
# Project Actions
|
# Project Actions
|
||||||
##
|
##
|
||||||
|
|
||||||
def manageProjects(self):
|
|
||||||
"""Opens the projects dialog for selecting either existing
|
|
||||||
projects from a cache of recently opened projects, or provide a
|
|
||||||
browse button for projects not yet cached.
|
|
||||||
"""
|
|
||||||
if not self.mainConf.blockGUI:
|
|
||||||
return False
|
|
||||||
|
|
||||||
dlgProj = GuiProjectLoad(self)
|
|
||||||
dlgProj.exec_()
|
|
||||||
if dlgProj.result() == QDialog.Accepted:
|
|
||||||
if dlgProj.openState == GuiProjectLoad.OPEN_STATE:
|
|
||||||
self.openProject(dlgProj.openPath)
|
|
||||||
elif dlgProj.openState == GuiProjectLoad.NEW_STATE:
|
|
||||||
self.newProject()
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def newProject(self, projData=None, forceNew=False):
|
def newProject(self, projData=None, forceNew=False):
|
||||||
"""Create new project with a few default files and folders.
|
"""Create new project with a few default files and folders.
|
||||||
The variable forceNew is used for testing.
|
The variable forceNew is used for testing.
|
||||||
@@ -275,8 +258,8 @@ class GuiMain(QMainWindow):
|
|||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if projData is None and self.mainConf.blockGUI:
|
if projData is None and self.mainConf.showGUI:
|
||||||
projData = self.newProjectDialog()
|
projData = self.showNewProjectDialog()
|
||||||
|
|
||||||
if projData is None:
|
if projData is None:
|
||||||
return False
|
return False
|
||||||
@@ -316,7 +299,7 @@ class GuiMain(QMainWindow):
|
|||||||
# There is no project loaded, everything OK
|
# There is no project loaded, everything OK
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.mainConf.blockGUI and not isYes:
|
if self.mainConf.showGUI and not isYes:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Close Project", "Save changes and close current project?"
|
self, "Close Project", "Save changes and close current project?"
|
||||||
@@ -332,7 +315,7 @@ class GuiMain(QMainWindow):
|
|||||||
doBackup = False
|
doBackup = False
|
||||||
if self.theProject.doBackup and self.mainConf.backupOnClose:
|
if self.theProject.doBackup and self.mainConf.backupOnClose:
|
||||||
doBackup = True
|
doBackup = True
|
||||||
if self.mainConf.blockGUI and self.mainConf.askBeforeBackup:
|
if self.mainConf.showGUI and self.mainConf.askBeforeBackup:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Backup Project", "Backup current project?"
|
self, "Backup Project", "Backup current project?"
|
||||||
@@ -379,7 +362,7 @@ class GuiMain(QMainWindow):
|
|||||||
# reason handled by the project class.
|
# reason handled by the project class.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
try:
|
try:
|
||||||
lockDetails = (
|
lockDetails = (
|
||||||
"<br><br>The project was locked by the computer "
|
"<br><br>The project was locked by the computer "
|
||||||
@@ -449,7 +432,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
# If the project is new, it may not have a path, so we need one
|
# If the project is new, it may not have a path, so we need one
|
||||||
if self.theProject.projPath is None:
|
if self.theProject.projPath is None:
|
||||||
projPath = self.saveProjectDialog()
|
projPath = self.selectProjectPath()
|
||||||
self.theProject.setProjectPath(projPath)
|
self.theProject.setProjectPath(projPath)
|
||||||
if self.theProject.projPath is None:
|
if self.theProject.projPath is None:
|
||||||
return False
|
return False
|
||||||
@@ -611,7 +594,7 @@ class GuiMain(QMainWindow):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if not self.docEditor.isEmpty():
|
if not self.docEditor.isEmpty():
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(self, "Import Document", (
|
msgRes = msgBox.question(self, "Import Document", (
|
||||||
"Importing the file will overwrite the current content of the document. "
|
"Importing the file will overwrite the current content of the document. "
|
||||||
@@ -629,7 +612,7 @@ class GuiMain(QMainWindow):
|
|||||||
def mergeDocuments(self):
|
def mergeDocuments(self):
|
||||||
"""Merge multiple documents to one single new document.
|
"""Merge multiple documents to one single new document.
|
||||||
"""
|
"""
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
dlgMerge = GuiDocMerge(self, self.theProject)
|
dlgMerge = GuiDocMerge(self, self.theProject)
|
||||||
dlgMerge.exec_()
|
dlgMerge.exec_()
|
||||||
return True
|
return True
|
||||||
@@ -637,7 +620,7 @@ class GuiMain(QMainWindow):
|
|||||||
def splitDocument(self):
|
def splitDocument(self):
|
||||||
"""Split a single document into multiple documents.
|
"""Split a single document into multiple documents.
|
||||||
"""
|
"""
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
dlgSplit = GuiDocSplit(self, self.theProject)
|
dlgSplit = GuiDocSplit(self, self.theProject)
|
||||||
dlgSplit.exec_()
|
dlgSplit.exec_()
|
||||||
return True
|
return True
|
||||||
@@ -684,7 +667,7 @@ class GuiMain(QMainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
logger.verbose("Requesting change to item %s" % tHandle)
|
logger.verbose("Requesting change to item %s" % tHandle)
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
dlgProj = GuiItemEditor(self, self.theProject, tHandle)
|
dlgProj = GuiItemEditor(self, self.theProject, tHandle)
|
||||||
dlgProj.exec_()
|
dlgProj.exec_()
|
||||||
if dlgProj.result() == QDialog.Accepted:
|
if dlgProj.result() == QDialog.Accepted:
|
||||||
@@ -746,7 +729,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
qApp.restoreOverrideCursor()
|
qApp.restoreOverrideCursor()
|
||||||
|
|
||||||
if self.mainConf.blockGUI and not beQuiet:
|
if self.mainConf.showGUI and not beQuiet:
|
||||||
self.makeAlert("The project index has been successfully rebuilt.", nwAlert.INFO)
|
self.makeAlert("The project index has been successfully rebuilt.", nwAlert.INFO)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -763,7 +746,7 @@ class GuiMain(QMainWindow):
|
|||||||
# Main Dialogs
|
# Main Dialogs
|
||||||
##
|
##
|
||||||
|
|
||||||
def saveProjectDialog(self):
|
def selectProjectPath(self):
|
||||||
"""Select where to save project.
|
"""Select where to save project.
|
||||||
"""
|
"""
|
||||||
dlgOpt = QFileDialog.Options()
|
dlgOpt = QFileDialog.Options()
|
||||||
@@ -776,7 +759,22 @@ class GuiMain(QMainWindow):
|
|||||||
return projPath
|
return projPath
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def newProjectDialog(self):
|
def showProjectLoadDialog(self):
|
||||||
|
"""Opens the projects dialog for selecting either existing
|
||||||
|
projects from a cache of recently opened projects, or provide a
|
||||||
|
browse button for projects not yet cached.
|
||||||
|
"""
|
||||||
|
dlgProj = GuiProjectLoad(self)
|
||||||
|
dlgProj.exec_()
|
||||||
|
if dlgProj.result() == QDialog.Accepted:
|
||||||
|
if dlgProj.openState == GuiProjectLoad.OPEN_STATE:
|
||||||
|
self.openProject(dlgProj.openPath)
|
||||||
|
elif dlgProj.openState == GuiProjectLoad.NEW_STATE:
|
||||||
|
self.newProject()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def showNewProjectDialog(self):
|
||||||
"""Open the wizard and assemble the project options dict.
|
"""Open the wizard and assemble the project options dict.
|
||||||
"""
|
"""
|
||||||
newProj = GuiProjectWizard(self)
|
newProj = GuiProjectWizard(self)
|
||||||
@@ -787,62 +785,76 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def editConfigDialog(self):
|
def showPreferencesDialog(self):
|
||||||
"""Open the preferences dialog.
|
"""Open the preferences dialog.
|
||||||
"""
|
"""
|
||||||
dlgConf = GuiPreferences(self, self.theProject)
|
dlgConf = GuiPreferences(self, self.theProject)
|
||||||
if dlgConf.exec_() == QDialog.Accepted:
|
dlgConf.exec_()
|
||||||
|
|
||||||
|
if dlgConf.result() == QDialog.Accepted:
|
||||||
logger.debug("Applying new preferences")
|
logger.debug("Applying new preferences")
|
||||||
self.initMain()
|
self.initMain()
|
||||||
self.theTheme.updateTheme()
|
self.theTheme.updateTheme()
|
||||||
self.saveDocument()
|
self.saveDocument()
|
||||||
self.docEditor.initEditor()
|
self.docEditor.initEditor()
|
||||||
self.docViewer.initViewer()
|
self.docViewer.initViewer()
|
||||||
return True
|
|
||||||
|
|
||||||
def editProjectDialog(self):
|
return
|
||||||
|
|
||||||
|
def showProjectSettingsDialog(self):
|
||||||
"""Open the project settings dialog.
|
"""Open the project settings dialog.
|
||||||
"""
|
"""
|
||||||
if self.hasProject:
|
if not self.hasProject:
|
||||||
dlgProj = GuiProjectSettings(self, self.theProject)
|
logger.error("No project open")
|
||||||
dlgProj.exec_()
|
return
|
||||||
|
|
||||||
|
dlgProj = GuiProjectSettings(self, self.theProject)
|
||||||
|
dlgProj.exec_()
|
||||||
|
|
||||||
|
if dlgProj.result() == QDialog.Accepted:
|
||||||
|
logger.debug("Applying new project settings")
|
||||||
self.docEditor.setDictionaries()
|
self.docEditor.setDictionaries()
|
||||||
self._setWindowTitle(self.theProject.projName)
|
self._setWindowTitle(self.theProject.projName)
|
||||||
return True
|
|
||||||
|
|
||||||
def buildProjectDialog(self):
|
return
|
||||||
|
|
||||||
|
def showBuildProjectDialog(self):
|
||||||
"""Open the build project dialog.
|
"""Open the build project dialog.
|
||||||
"""
|
"""
|
||||||
if self.hasProject:
|
if not self.hasProject:
|
||||||
dlgBuild = GuiBuildNovel(self, self.theProject)
|
logger.error("No project open")
|
||||||
dlgBuild.setModal(False)
|
return
|
||||||
dlgBuild.show()
|
|
||||||
return True
|
dlgBuild = GuiBuildNovel(self, self.theProject)
|
||||||
|
dlgBuild.setModal(False)
|
||||||
|
dlgBuild.show()
|
||||||
|
return
|
||||||
|
|
||||||
def showWritingStatsDialog(self):
|
def showWritingStatsDialog(self):
|
||||||
"""Open the session log dialog.
|
"""Open the session log dialog.
|
||||||
"""
|
"""
|
||||||
if self.hasProject:
|
if not self.hasProject:
|
||||||
dlgStats = GuiWritingStats(self, self.theProject)
|
logger.error("No project open")
|
||||||
dlgStats.setModal(False)
|
return
|
||||||
dlgStats.show()
|
|
||||||
return True
|
dlgStats = GuiWritingStats(self, self.theProject)
|
||||||
|
dlgStats.setModal(False)
|
||||||
|
dlgStats.show()
|
||||||
|
return
|
||||||
|
|
||||||
def showAboutNWDialog(self):
|
def showAboutNWDialog(self):
|
||||||
"""Show the about dialog for novelWriter.
|
"""Show the about dialog for novelWriter.
|
||||||
"""
|
"""
|
||||||
if self.mainConf.blockGUI:
|
dlgAbout = GuiAbout(self)
|
||||||
dlgAbout = GuiAbout(self)
|
dlgAbout.exec_()
|
||||||
dlgAbout.exec_()
|
return
|
||||||
return True
|
|
||||||
|
|
||||||
def showAboutQtDialog(self):
|
def showAboutQtDialog(self):
|
||||||
"""Show the about dialog for Qt.
|
"""Show the about dialog for Qt.
|
||||||
"""
|
"""
|
||||||
if self.mainConf.blockGUI:
|
msgBox = QMessageBox()
|
||||||
msgBox = QMessageBox()
|
msgBox.aboutQt(self, "About Qt")
|
||||||
msgBox.aboutQt(self, "About Qt")
|
return
|
||||||
return True
|
|
||||||
|
|
||||||
def makeAlert(self, theMessage, theLevel=nwAlert.INFO):
|
def makeAlert(self, theMessage, theLevel=nwAlert.INFO):
|
||||||
"""Alert both the user and the logger at the same time. Message
|
"""Alert both the user and the logger at the same time. Message
|
||||||
@@ -871,7 +883,7 @@ class GuiMain(QMainWindow):
|
|||||||
logger.error(msgLine)
|
logger.error(msgLine)
|
||||||
|
|
||||||
# Popup
|
# Popup
|
||||||
if self.mainConf.blockGUI:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
if theLevel == nwAlert.INFO:
|
if theLevel == nwAlert.INFO:
|
||||||
msgBox.information(self, "Information", popMsg)
|
msgBox.information(self, "Information", popMsg)
|
||||||
@@ -902,7 +914,7 @@ class GuiMain(QMainWindow):
|
|||||||
def closeMain(self):
|
def closeMain(self):
|
||||||
"""Save everything, and close novelWriter.
|
"""Save everything, and close novelWriter.
|
||||||
"""
|
"""
|
||||||
if self.mainConf.blockGUI and self.hasProject:
|
if self.mainConf.showGUI and self.hasProject:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Exit", "Do you want to save changes and exit?"
|
self, "Exit", "Do you want to save changes and exit?"
|
||||||
|
|||||||
+79
-5
@@ -9,12 +9,22 @@ import shutil
|
|||||||
from os import path, mkdir
|
from os import path, mkdir
|
||||||
from nwdummy import DummyMain
|
from nwdummy import DummyMain
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import QFileDialog, QMessageBox
|
||||||
|
|
||||||
sys.path.insert(1, path.abspath(path.join(path.dirname(__file__), path.pardir)))
|
sys.path.insert(1, path.abspath(path.join(path.dirname(__file__), path.pardir)))
|
||||||
|
|
||||||
from nw.config import Config # noqa: E402
|
from nw.config import Config # noqa: E402
|
||||||
|
|
||||||
|
##
|
||||||
|
# Core Test Folders
|
||||||
|
##
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def nwTemp():
|
def nwTemp():
|
||||||
|
"""A temporary folder for the test session. This folder is
|
||||||
|
presistent after the test so that the status of generated files can
|
||||||
|
be checked. The folder is instead cleared before a new test session.
|
||||||
|
"""
|
||||||
testDir = path.dirname(__file__)
|
testDir = path.dirname(__file__)
|
||||||
tempDir = path.join(testDir, "temp")
|
tempDir = path.join(testDir, "temp")
|
||||||
if path.isdir(tempDir):
|
if path.isdir(tempDir):
|
||||||
@@ -25,31 +35,51 @@ def nwTemp():
|
|||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def nwRef():
|
def nwRef():
|
||||||
|
"""The folder where all the reference files are stored for verifying
|
||||||
|
the results of tests.
|
||||||
|
"""
|
||||||
testDir = path.dirname(__file__)
|
testDir = path.dirname(__file__)
|
||||||
refDir = path.join(testDir, "reference")
|
refDir = path.join(testDir, "reference")
|
||||||
return refDir
|
return refDir
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
##
|
||||||
def nwConf(nwRef, nwTemp):
|
# novelWriter Objects
|
||||||
theConf = Config()
|
##
|
||||||
theConf.initConfig(nwRef, nwTemp)
|
|
||||||
return theConf
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def tmpConf(nwTemp):
|
def tmpConf(nwTemp):
|
||||||
|
"""Create a temporary novelWriter configuration object.
|
||||||
|
"""
|
||||||
theConf = Config()
|
theConf = Config()
|
||||||
theConf.initConfig(nwTemp, nwTemp)
|
theConf.initConfig(nwTemp, nwTemp)
|
||||||
theConf.setLastPath("")
|
theConf.setLastPath("")
|
||||||
return theConf
|
return theConf
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def nwConf(nwRef, nwTemp):
|
||||||
|
"""Temporary novelWriter configuration used for the dummy instance
|
||||||
|
of novelWriter's main GUI.
|
||||||
|
"""
|
||||||
|
theConf = Config()
|
||||||
|
theConf.initConfig(nwRef, nwTemp)
|
||||||
|
return theConf
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def nwDummy(nwRef, nwTemp, nwConf):
|
def nwDummy(nwRef, nwTemp, nwConf):
|
||||||
|
"""Create a dummy instance of novelWriter's main GUI class.
|
||||||
|
"""
|
||||||
theDummy = DummyMain()
|
theDummy = DummyMain()
|
||||||
theDummy.mainConf = nwConf
|
theDummy.mainConf = nwConf
|
||||||
return theDummy
|
return theDummy
|
||||||
|
|
||||||
|
##
|
||||||
|
# Temporary Test Folders
|
||||||
|
##
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def nwTempProj(nwTemp):
|
def nwTempProj(nwTemp):
|
||||||
|
"""A temporary folder for project tests.
|
||||||
|
"""
|
||||||
projDir = path.join(nwTemp, "proj")
|
projDir = path.join(nwTemp, "proj")
|
||||||
if not path.isdir(projDir):
|
if not path.isdir(projDir):
|
||||||
mkdir(projDir)
|
mkdir(projDir)
|
||||||
@@ -57,6 +87,8 @@ def nwTempProj(nwTemp):
|
|||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def nwTempGUI(nwTemp):
|
def nwTempGUI(nwTemp):
|
||||||
|
"""A temporary folder for GUI tests.
|
||||||
|
"""
|
||||||
guiDir = path.join(nwTemp, "gui")
|
guiDir = path.join(nwTemp, "gui")
|
||||||
if not path.isdir(guiDir):
|
if not path.isdir(guiDir):
|
||||||
mkdir(guiDir)
|
mkdir(guiDir)
|
||||||
@@ -64,6 +96,8 @@ def nwTempGUI(nwTemp):
|
|||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def nwTempBuild(nwTemp):
|
def nwTempBuild(nwTemp):
|
||||||
|
"""A temporary folder for build tests.
|
||||||
|
"""
|
||||||
buildDir = path.join(nwTemp, "build")
|
buildDir = path.join(nwTemp, "build")
|
||||||
if not path.isdir(buildDir):
|
if not path.isdir(buildDir):
|
||||||
mkdir(buildDir)
|
mkdir(buildDir)
|
||||||
@@ -71,6 +105,8 @@ def nwTempBuild(nwTemp):
|
|||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def nwFuncTemp(nwTemp):
|
def nwFuncTemp(nwTemp):
|
||||||
|
"""A temporary folder for a single test function.
|
||||||
|
"""
|
||||||
funcDir = path.join(nwTemp, "ftemp")
|
funcDir = path.join(nwTemp, "ftemp")
|
||||||
if path.isdir(funcDir):
|
if path.isdir(funcDir):
|
||||||
shutil.rmtree(funcDir)
|
shutil.rmtree(funcDir)
|
||||||
@@ -81,8 +117,14 @@ def nwFuncTemp(nwTemp):
|
|||||||
shutil.rmtree(funcDir)
|
shutil.rmtree(funcDir)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Temp Folders for Projects
|
||||||
|
##
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def nwMinimal(nwTemp):
|
def nwMinimal(nwTemp):
|
||||||
|
"""A minimal novelWriter example project.
|
||||||
|
"""
|
||||||
testDir = path.dirname(__file__)
|
testDir = path.dirname(__file__)
|
||||||
minimalStore = path.join(testDir, "minimal")
|
minimalStore = path.join(testDir, "minimal")
|
||||||
minimalDir = path.join(nwTemp, "minimal")
|
minimalDir = path.join(nwTemp, "minimal")
|
||||||
@@ -102,6 +144,9 @@ def nwMinimal(nwTemp):
|
|||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def nwLipsum(nwTemp):
|
def nwLipsum(nwTemp):
|
||||||
|
"""A medium sized novelWriter example project with a lot of Lorem
|
||||||
|
Ipsum dummy text.
|
||||||
|
"""
|
||||||
testDir = path.dirname(__file__)
|
testDir = path.dirname(__file__)
|
||||||
lipsumStore = path.join(testDir, "lipsum")
|
lipsumStore = path.join(testDir, "lipsum")
|
||||||
lipsumDir = path.join(nwTemp, "lipsum")
|
lipsumDir = path.join(nwTemp, "lipsum")
|
||||||
@@ -121,6 +166,8 @@ def nwLipsum(nwTemp):
|
|||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def nwOldProj(nwTemp):
|
def nwOldProj(nwTemp):
|
||||||
|
"""A minimal movelWriter project using the old folder structure.
|
||||||
|
"""
|
||||||
testDir = path.dirname(__file__)
|
testDir = path.dirname(__file__)
|
||||||
oldProjStore = path.join(testDir, "oldproj")
|
oldProjStore = path.join(testDir, "oldproj")
|
||||||
oldProjDir = path.join(nwTemp, "oldproj")
|
oldProjDir = path.join(nwTemp, "oldproj")
|
||||||
@@ -131,3 +178,30 @@ def nwOldProj(nwTemp):
|
|||||||
if path.isdir(oldProjDir):
|
if path.isdir(oldProjDir):
|
||||||
shutil.rmtree(oldProjDir)
|
shutil.rmtree(oldProjDir)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Monkey Patch Dialogs
|
||||||
|
##
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def mnkQtDialogs(monkeypatch, nwTemp):
|
||||||
|
"""Mock Qt dialog functions to prevent GUI blocking while testing.
|
||||||
|
"""
|
||||||
|
monkeypatch.setattr(
|
||||||
|
QFileDialog, "getExistingDirectory", lambda *args, **kwargs: nwTemp
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
QMessageBox, "question", lambda *args, **kwargs: QMessageBox.Yes
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
QMessageBox, "information", lambda *args, **kwargs: None
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
QMessageBox, "warning", lambda *args, **kwargs: None
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
QMessageBox, "critical", lambda *args, **kwargs: None
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
|||||||
+84
-16
@@ -7,13 +7,14 @@ import pytest
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from nwtools import cmpFiles
|
from nwtools import cmpFiles, getGuiItem
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QItemSelectionModel
|
from PyQt5.QtCore import Qt, QItemSelectionModel
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialogButtonBox, QTreeWidgetItem, QListWidgetItem, QDialog
|
QDialogButtonBox, QTreeWidgetItem, QListWidgetItem, QDialog, QAction,
|
||||||
|
QMessageBox
|
||||||
)
|
)
|
||||||
|
|
||||||
from nw.gui import (
|
from nw.gui import (
|
||||||
@@ -28,22 +29,34 @@ keyDelay = 2
|
|||||||
stepDelay = 20
|
stepDelay = 20
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testProjectEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
def testProjectSettings(qtbot, monkeypatch, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||||
qtbot.addWidget(nwGUI)
|
qtbot.addWidget(nwGUI)
|
||||||
nwGUI.show()
|
nwGUI.show()
|
||||||
qtbot.waitForWindowShown(nwGUI)
|
qtbot.waitForWindowShown(nwGUI)
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
# Create new, save, open project
|
# Check that we cannot open when there is no project
|
||||||
|
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
|
||||||
|
assert getGuiItem("GuiProjectSettings") is None
|
||||||
|
|
||||||
|
# Create new project
|
||||||
nwGUI.theProject.projTree.setSeed(42)
|
nwGUI.theProject.projTree.setSeed(42)
|
||||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||||
nwGUI.mainConf.backupPath = nwFuncTemp
|
nwGUI.mainConf.backupPath = nwFuncTemp
|
||||||
|
|
||||||
projEdit = GuiProjectSettings(nwGUI, nwGUI.theProject)
|
# Get the dialog object
|
||||||
|
monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *args: None)
|
||||||
|
monkeypatch.setattr(GuiProjectSettings, "result", lambda *args: QDialog.Accepted)
|
||||||
|
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
|
||||||
|
qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000)
|
||||||
|
|
||||||
|
projEdit = getGuiItem("GuiProjectSettings")
|
||||||
|
assert isinstance(projEdit, GuiProjectSettings)
|
||||||
projEdit.show()
|
projEdit.show()
|
||||||
qtbot.addWidget(projEdit)
|
qtbot.addWidget(projEdit)
|
||||||
|
|
||||||
|
# Main settings
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
projEdit.tabMain.editName.setText("")
|
projEdit.tabMain.editName.setText("")
|
||||||
for c in "Project Name":
|
for c in "Project Name":
|
||||||
@@ -199,6 +212,10 @@ def testWritingStatsExport(qtbot, nwFuncTemp, nwTemp):
|
|||||||
assert nwGUI.closeProject()
|
assert nwGUI.closeProject()
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
|
# Check that we cannot open when there is no project
|
||||||
|
nwGUI.mainMenu.aWritingStats.activate(QAction.Trigger)
|
||||||
|
assert getGuiItem("GuiWritingStats") is None
|
||||||
|
|
||||||
assert nwGUI.openProject(nwFuncTemp)
|
assert nwGUI.openProject(nwFuncTemp)
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
@@ -239,8 +256,11 @@ def testWritingStatsExport(qtbot, nwFuncTemp, nwTemp):
|
|||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
nwGUI.mainConf.lastPath = nwFuncTemp
|
nwGUI.mainConf.lastPath = nwFuncTemp
|
||||||
sessLog = GuiWritingStats(nwGUI, nwGUI.theProject)
|
nwGUI.mainMenu.aWritingStats.activate(QAction.Trigger)
|
||||||
sessLog.show()
|
qtbot.waitUntil(lambda: getGuiItem("GuiWritingStats") is not None, timeout=1000)
|
||||||
|
|
||||||
|
sessLog = getGuiItem("GuiWritingStats")
|
||||||
|
assert isinstance(sessLog, GuiWritingStats)
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
assert sessLog._saveData(sessLog.FMT_CSV)
|
assert sessLog._saveData(sessLog.FMT_CSV)
|
||||||
@@ -337,17 +357,29 @@ def testWritingStatsExport(qtbot, nwFuncTemp, nwTemp):
|
|||||||
nwGUI.closeMain()
|
nwGUI.closeMain()
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testAboutBox(qtbot, nwFuncTemp, nwTemp):
|
def testAboutBox(qtbot, monkeypatch, nwFuncTemp, nwTemp):
|
||||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||||
qtbot.addWidget(nwGUI)
|
qtbot.addWidget(nwGUI)
|
||||||
nwGUI.show()
|
nwGUI.show()
|
||||||
qtbot.waitForWindowShown(nwGUI)
|
qtbot.waitForWindowShown(nwGUI)
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
msgAbout = GuiAbout(nwGUI)
|
# NW About
|
||||||
|
monkeypatch.setattr(GuiAbout, "exec_", lambda *args: None)
|
||||||
|
nwGUI.mainMenu.aAboutNW.activate(QAction.Trigger)
|
||||||
|
qtbot.waitUntil(lambda: getGuiItem("GuiAbout") is not None, timeout=1000)
|
||||||
|
|
||||||
|
msgAbout = getGuiItem("GuiAbout")
|
||||||
|
assert isinstance(msgAbout, GuiAbout)
|
||||||
|
msgAbout.show()
|
||||||
|
|
||||||
assert msgAbout.pageAbout.document().characterCount() > 100
|
assert msgAbout.pageAbout.document().characterCount() > 100
|
||||||
assert msgAbout.pageLicense.document().characterCount() > 100
|
assert msgAbout.pageLicense.document().characterCount() > 100
|
||||||
|
|
||||||
|
# Qt About
|
||||||
|
monkeypatch.setattr(QMessageBox, "aboutQt", lambda *args, **kwargs: None)
|
||||||
|
nwGUI.mainMenu.aAboutQt.activate(QAction.Trigger)
|
||||||
|
|
||||||
# qtbot.stopForInteraction()
|
# qtbot.stopForInteraction()
|
||||||
msgAbout._doClose()
|
msgAbout._doClose()
|
||||||
nwGUI.closeMain()
|
nwGUI.closeMain()
|
||||||
@@ -361,11 +393,20 @@ def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
|||||||
qtbot.waitForWindowShown(nwGUI)
|
qtbot.waitForWindowShown(nwGUI)
|
||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
assert nwGUI.openProject(nwLipsum)
|
# Check that we cannot open when there is no project
|
||||||
|
nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger)
|
||||||
|
assert getGuiItem("GuiBuildNovel") is None
|
||||||
|
|
||||||
|
# Open a project
|
||||||
|
assert nwGUI.openProject(nwLipsum)
|
||||||
nwGUI.mainConf.lastPath = nwLipsum
|
nwGUI.mainConf.lastPath = nwLipsum
|
||||||
|
|
||||||
nwBuild = GuiBuildNovel(nwGUI, nwGUI.theProject)
|
# Open the tool
|
||||||
|
nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger)
|
||||||
|
qtbot.waitUntil(lambda: getGuiItem("GuiBuildNovel") is not None, timeout=1000)
|
||||||
|
|
||||||
|
nwBuild = getGuiItem("GuiBuildNovel")
|
||||||
|
assert isinstance(nwBuild, GuiBuildNovel)
|
||||||
|
|
||||||
# Default Settings
|
# Default Settings
|
||||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||||
@@ -764,7 +805,7 @@ def testNewProjectWizard(qtbot, nwLipsum, nwTemp):
|
|||||||
nwGUI.closeMain()
|
nwGUI.closeMain()
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testLoadProject(qtbot, nwMinimal, nwTemp):
|
def testLoadProject(qtbot, monkeypatch, nwMinimal, nwTemp):
|
||||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
||||||
qtbot.addWidget(nwGUI)
|
qtbot.addWidget(nwGUI)
|
||||||
nwGUI.show()
|
nwGUI.show()
|
||||||
@@ -774,7 +815,13 @@ def testLoadProject(qtbot, nwMinimal, nwTemp):
|
|||||||
assert nwGUI.openProject(nwMinimal)
|
assert nwGUI.openProject(nwMinimal)
|
||||||
assert nwGUI.closeProject()
|
assert nwGUI.closeProject()
|
||||||
|
|
||||||
nwLoad = GuiProjectLoad(nwGUI)
|
monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *args: None)
|
||||||
|
monkeypatch.setattr(GuiProjectLoad, "result", lambda *args: QDialog.Accepted)
|
||||||
|
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
|
||||||
|
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000)
|
||||||
|
|
||||||
|
nwLoad = getGuiItem("GuiProjectLoad")
|
||||||
|
assert isinstance(nwLoad, GuiProjectLoad)
|
||||||
nwLoad.show()
|
nwLoad.show()
|
||||||
|
|
||||||
recentCount = nwLoad.listBox.topLevelItemCount()
|
recentCount = nwLoad.listBox.topLevelItemCount()
|
||||||
@@ -793,6 +840,7 @@ def testLoadProject(qtbot, nwMinimal, nwTemp):
|
|||||||
assert nwLoad.openPath == selPath
|
assert nwLoad.openPath == selPath
|
||||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||||
|
|
||||||
|
# Just create a new project load from scratch for the rest of the test
|
||||||
del nwLoad
|
del nwLoad
|
||||||
nwLoad = GuiProjectLoad(nwGUI)
|
nwLoad = GuiProjectLoad(nwGUI)
|
||||||
nwLoad.show()
|
nwLoad.show()
|
||||||
@@ -815,7 +863,7 @@ def testLoadProject(qtbot, nwMinimal, nwTemp):
|
|||||||
nwGUI.closeMain()
|
nwGUI.closeMain()
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testPreferences(qtbot, nwMinimal, nwTemp, nwRef, tmpConf):
|
def testPreferences(qtbot, monkeypatch, mnkQtDialogs, nwMinimal, nwTemp, nwRef, tmpConf):
|
||||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
||||||
qtbot.addWidget(nwGUI)
|
qtbot.addWidget(nwGUI)
|
||||||
nwGUI.show()
|
nwGUI.show()
|
||||||
@@ -823,11 +871,17 @@ def testPreferences(qtbot, nwMinimal, nwTemp, nwRef, tmpConf):
|
|||||||
qtbot.wait(stepDelay)
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
assert nwGUI.openProject(nwMinimal)
|
assert nwGUI.openProject(nwMinimal)
|
||||||
nwPrefs = GuiPreferences(nwGUI, nwGUI.theProject)
|
|
||||||
|
monkeypatch.setattr(GuiPreferences, "exec_", lambda *args: None)
|
||||||
|
monkeypatch.setattr(GuiPreferences, "result", lambda *args: QDialog.Accepted)
|
||||||
|
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger)
|
||||||
|
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000)
|
||||||
|
|
||||||
|
nwPrefs = getGuiItem("GuiPreferences")
|
||||||
|
assert isinstance(nwPrefs, GuiPreferences)
|
||||||
nwPrefs.show()
|
nwPrefs.show()
|
||||||
|
|
||||||
# Override Config
|
# Override Config
|
||||||
tmpConf.blockGUI = False
|
|
||||||
tmpConf.confPath = nwMinimal
|
tmpConf.confPath = nwMinimal
|
||||||
nwGUI.mainConf = tmpConf
|
nwGUI.mainConf = tmpConf
|
||||||
nwPrefs.mainConf = tmpConf
|
nwPrefs.mainConf = tmpConf
|
||||||
@@ -991,3 +1045,17 @@ def testQuotesDialog(qtbot, nwMinimal, nwTemp):
|
|||||||
nwQuot.close()
|
nwQuot.close()
|
||||||
nwGUI.closeMain()
|
nwGUI.closeMain()
|
||||||
nwGUI.close()
|
nwGUI.close()
|
||||||
|
|
||||||
|
@pytest.mark.gui
|
||||||
|
def testDialogsOpenClose(qtbot, mnkQtDialogs, nwMinimal, nwTemp):
|
||||||
|
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp, nwMinimal])
|
||||||
|
qtbot.addWidget(nwGUI)
|
||||||
|
nwGUI.show()
|
||||||
|
qtbot.waitForWindowShown(nwGUI)
|
||||||
|
qtbot.wait(stepDelay)
|
||||||
|
|
||||||
|
assert nwGUI.selectProjectPath() == nwTemp
|
||||||
|
|
||||||
|
# qtbot.stopForInteraction()
|
||||||
|
nwGUI.closeMain()
|
||||||
|
nwGUI.close()
|
||||||
|
|||||||
@@ -223,6 +223,10 @@ def testDocEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
|||||||
qtbot.keyClick(nwGUI.docEditor, c, delay=keyDelay)
|
qtbot.keyClick(nwGUI.docEditor, c, delay=keyDelay)
|
||||||
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=keyDelay)
|
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=keyDelay)
|
||||||
|
|
||||||
|
# Trigger autosaves before making more changes
|
||||||
|
nwGUI._autoSaveDocument()
|
||||||
|
nwGUI._autoSaveProject()
|
||||||
|
|
||||||
# Select the 'New Scene' file
|
# Select the 'New Scene' file
|
||||||
nwGUI.setFocus(1)
|
nwGUI.setFocus(1)
|
||||||
nwGUI.treeView.clearSelection()
|
nwGUI.treeView.clearSelection()
|
||||||
|
|||||||
@@ -580,9 +580,9 @@ def testOrphanedFiles(nwDummy, nwLipsum):
|
|||||||
assert theProject.closeProject()
|
assert theProject.closeProject()
|
||||||
|
|
||||||
@pytest.mark.project
|
@pytest.mark.project
|
||||||
def testOldProject(nwDummy, nwOldProj):
|
def testOldProject(nwDummy, nwOldProj, mnkQtDialogs):
|
||||||
theProject = NWProject(nwDummy)
|
theProject = NWProject(nwDummy)
|
||||||
theProject.mainConf.blockGUI = False
|
theProject.mainConf.showGUI = False
|
||||||
|
|
||||||
# Create dummy files for known legacy files
|
# Create dummy files for known legacy files
|
||||||
deleteFiles = [
|
deleteFiles = [
|
||||||
|
|||||||
Reference in New Issue
Block a user