diff --git a/nw/config.py b/nw/config.py
index 50941257..fa993523 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -89,6 +89,11 @@ class Config:
self.spellLanguage = "en_GB"
+ # Backup
+ self.backupPath = ""
+ self.backupOnClose = False
+ self.askBeforeBackup = True
+
# Path
self.recentList = [""]*10
@@ -167,22 +172,28 @@ class Config:
## Editor
cnfSec = "Editor"
- self.textFont = self._parseLine(cnfParse, cnfSec, "textfont", self.CNF_STR, self.textFont)
- self.textSize = self._parseLine(cnfParse, cnfSec, "textsize", self.CNF_INT, self.textSize)
- self.textFixedW = self._parseLine(cnfParse, cnfSec, "fixedwidth", self.CNF_BOOL, self.textFixedW)
- self.textWidth = self._parseLine(cnfParse, cnfSec, "width", self.CNF_INT, self.textWidth)
- self.textMargin = self._parseLine(cnfParse, cnfSec, "margin", self.CNF_INT, self.textMargin)
- self.tabWidth = self._parseLine(cnfParse, cnfSec, "tabwidth", self.CNF_INT, self.tabWidth)
- self.doJustify = self._parseLine(cnfParse, cnfSec, "justify", self.CNF_BOOL, self.doJustify)
- self.autoSelect = self._parseLine(cnfParse, cnfSec, "autoselect", self.CNF_BOOL, self.autoSelect)
- self.doReplace = self._parseLine(cnfParse, cnfSec, "autoreplace", self.CNF_BOOL, self.doReplace)
- self.doReplaceSQuote = self._parseLine(cnfParse, cnfSec, "repsquotes", self.CNF_BOOL, self.doReplaceSQuote)
- self.doReplaceDQuote = self._parseLine(cnfParse, cnfSec, "repdquotes", self.CNF_BOOL, self.doReplaceDQuote)
- self.doReplaceDash = self._parseLine(cnfParse, cnfSec, "repdash", self.CNF_BOOL, self.doReplaceDash)
- self.doReplaceDots = self._parseLine(cnfParse, cnfSec, "repdots", self.CNF_BOOL, self.doReplaceDots)
- self.fmtSingleQuotes = self._parseLine(cnfParse, cnfSec, "fmtsinglequote", self.CNF_LIST, self.fmtSingleQuotes)
- self.fmtDoubleQuotes = self._parseLine(cnfParse, cnfSec, "fmtdoublequote", self.CNF_LIST, self.fmtDoubleQuotes)
- self.spellLanguage = self._parseLine(cnfParse, cnfSec, "spellcheck", self.CNF_STR, self.spellLanguage)
+ self.textFont = self._parseLine(cnfParse, cnfSec, "textfont", self.CNF_STR, self.textFont)
+ self.textSize = self._parseLine(cnfParse, cnfSec, "textsize", self.CNF_INT, self.textSize)
+ self.textFixedW = self._parseLine(cnfParse, cnfSec, "fixedwidth", self.CNF_BOOL, self.textFixedW)
+ self.textWidth = self._parseLine(cnfParse, cnfSec, "width", self.CNF_INT, self.textWidth)
+ self.textMargin = self._parseLine(cnfParse, cnfSec, "margin", self.CNF_INT, self.textMargin)
+ self.tabWidth = self._parseLine(cnfParse, cnfSec, "tabwidth", self.CNF_INT, self.tabWidth)
+ self.doJustify = self._parseLine(cnfParse, cnfSec, "justify", self.CNF_BOOL, self.doJustify)
+ self.autoSelect = self._parseLine(cnfParse, cnfSec, "autoselect", self.CNF_BOOL, self.autoSelect)
+ self.doReplace = self._parseLine(cnfParse, cnfSec, "autoreplace", self.CNF_BOOL, self.doReplace)
+ self.doReplaceSQuote = self._parseLine(cnfParse, cnfSec, "repsquotes", self.CNF_BOOL, self.doReplaceSQuote)
+ self.doReplaceDQuote = self._parseLine(cnfParse, cnfSec, "repdquotes", self.CNF_BOOL, self.doReplaceDQuote)
+ self.doReplaceDash = self._parseLine(cnfParse, cnfSec, "repdash", self.CNF_BOOL, self.doReplaceDash)
+ self.doReplaceDots = self._parseLine(cnfParse, cnfSec, "repdots", self.CNF_BOOL, self.doReplaceDots)
+ self.fmtSingleQuotes = self._parseLine(cnfParse, cnfSec, "fmtsinglequote", self.CNF_LIST, self.fmtSingleQuotes)
+ self.fmtDoubleQuotes = self._parseLine(cnfParse, cnfSec, "fmtdoublequote", self.CNF_LIST, self.fmtDoubleQuotes)
+ self.spellLanguage = self._parseLine(cnfParse, cnfSec, "spellcheck", self.CNF_STR, self.spellLanguage)
+
+ ## Backup
+ cnfSec = "Backup"
+ self.backupPath = self._parseLine(cnfParse, cnfSec, "backuppath", self.CNF_STR, self.backupPath)
+ self.backupOnClose = self._parseLine(cnfParse, cnfSec, "backuponclose", self.CNF_BOOL, self.backupOnClose)
+ self.askBeforeBackup = self._parseLine(cnfParse, cnfSec, "askbeforebackup", self.CNF_BOOL, self.askBeforeBackup)
## Path
cnfSec = "Path"
@@ -240,6 +251,13 @@ class Config:
cnfParse.set(cnfSec,"fmtdoublequote",self._packList(self.fmtDoubleQuotes))
cnfParse.set(cnfSec,"spellcheck", str(self.spellLanguage))
+ ## Backup
+ cnfSec = "Backup"
+ cnfParse.add_section(cnfSec)
+ cnfParse.set(cnfSec,"backuppath", str(self.backupPath))
+ cnfParse.set(cnfSec,"backuponclose", str(self.backupOnClose))
+ cnfParse.set(cnfSec,"askbeforebackup",str(self.askBeforeBackup))
+
## Path
cnfSec = "Path"
cnfParse.add_section(cnfSec)
diff --git a/nw/gui/configeditor.py b/nw/gui/configeditor.py
index d90424f8..e6851b22 100644
--- a/nw/gui/configeditor.py
+++ b/nw/gui/configeditor.py
@@ -21,7 +21,7 @@ from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel,
QWidget, QTabWidget, QDialogButtonBox, QSpinBox, QGroupBox, QComboBox, QMessageBox,
- QCheckBox, QGridLayout, QFontComboBox
+ QCheckBox, QGridLayout, QFontComboBox, QPushButton, QFileDialog
)
from nw.enum import nwAlert
from nw.constants import nwQuotes
@@ -183,12 +183,47 @@ class GuiConfigEditGeneral(QWidget):
self.autoSaveForm.addWidget(self.autoSaveProj, 1, 1)
self.autoSaveForm.addWidget(QLabel("seconds"), 1, 2)
+ # Backup
+ self.projBackup = QGroupBox("Backup", self)
+ self.projBackupForm = QGridLayout(self)
+ self.projBackup.setLayout(self.projBackupForm)
+
+ self.projBackupPath = QLineEdit()
+ if path.isdir(self.mainConf.backupPath):
+ self.projBackupPath.setText(self.mainConf.backupPath)
+
+ self.projBackupGetPath = QPushButton(QIcon.fromTheme("folder"),"")
+ self.projBackupGetPath.clicked.connect(self._backupFolder)
+
+ self.projBackupClose = QCheckBox(self)
+ self.projBackupClose.setToolTip("Backup automatically on project close.")
+ if self.mainConf.backupOnClose:
+ self.projBackupClose.setCheckState(Qt.Checked)
+ else:
+ self.projBackupClose.setCheckState(Qt.Unchecked)
+
+ self.projBackupAsk = QCheckBox(self)
+ self.projBackupAsk.setToolTip("Ask before backup.")
+ if self.mainConf.askBeforeBackup:
+ self.projBackupAsk.setCheckState(Qt.Checked)
+ else:
+ self.projBackupAsk.setCheckState(Qt.Unchecked)
+
+ self.projBackupForm.addWidget(QLabel("Backup Folder"), 0, 0)
+ self.projBackupForm.addWidget(self.projBackupPath, 0, 1, 1, 3)
+ self.projBackupForm.addWidget(self.projBackupGetPath, 0, 4)
+ self.projBackupForm.addWidget(QLabel("Run on Close"), 1, 0)
+ self.projBackupForm.addWidget(self.projBackupClose, 1, 1)
+ self.projBackupForm.addWidget(QLabel("Ask Before Backuo"), 1, 2)
+ self.projBackupForm.addWidget(self.projBackupAsk, 1, 3)
+
# Assemble
- self.outerBox.addWidget(self.guiLook, 0, 0)
- self.outerBox.addWidget(self.spellLang, 1, 0)
- self.outerBox.addWidget(self.autoSave, 2, 0)
+ self.outerBox.addWidget(self.guiLook, 0, 0)
+ self.outerBox.addWidget(self.spellLang, 1, 0)
+ self.outerBox.addWidget(self.autoSave, 2, 0)
+ self.outerBox.addWidget(self.projBackup, 3, 0)
self.outerBox.setColumnStretch(2, 1)
- self.outerBox.setRowStretch(3, 1)
+ self.outerBox.setRowStretch(4, 1)
self.setLayout(self.outerBox)
return
@@ -198,25 +233,52 @@ class GuiConfigEditGeneral(QWidget):
validEntries = True
needsRestart = False
- guiTheme = self.guiLookTheme.currentData()
- guiSyntax = self.guiLookSyntax.currentData()
- spellLanguage = self.spellLangList.currentData()
- autoSaveDoc = self.autoSaveDoc.value()
- autoSaveProj = self.autoSaveProj.value()
+ guiTheme = self.guiLookTheme.currentData()
+ guiSyntax = self.guiLookSyntax.currentData()
+ spellLanguage = self.spellLangList.currentData()
+ autoSaveDoc = self.autoSaveDoc.value()
+ autoSaveProj = self.autoSaveProj.value()
+ backupPath = self.projBackupPath.text()
+ backupOnClose = self.projBackupClose.isChecked()
+ askBeforeBackup = self.projBackupAsk.isChecked()
# Check if restart is needed
needsRestart |= self.mainConf.guiTheme != guiTheme
- self.mainConf.guiTheme = guiTheme
- self.mainConf.guiSyntax = guiSyntax
- self.mainConf.spellLanguage = spellLanguage
- self.mainConf.autoSaveDoc = autoSaveDoc
- self.mainConf.autoSaveProj = autoSaveProj
+ self.mainConf.guiTheme = guiTheme
+ self.mainConf.guiSyntax = guiSyntax
+ self.mainConf.spellLanguage = spellLanguage
+ self.mainConf.autoSaveDoc = autoSaveDoc
+ self.mainConf.autoSaveProj = autoSaveProj
+ self.mainConf.backupPath = backupPath
+ self.mainConf.backupOnClose = backupOnClose
+ self.mainConf.askBeforeBackup = askBeforeBackup
self.mainConf.confChanged = True
return validEntries, needsRestart
+ ##
+ # Internal Functions
+ ##
+
+ def _backupFolder(self):
+
+ currDir = self.projBackupPath.text()
+ if not path.isdir(currDir):
+ currDir = ""
+
+ dlgOpt = QFileDialog.Options()
+ dlgOpt |= QFileDialog.ShowDirsOnly
+ dlgOpt |= QFileDialog.DontUseNativeDialog
+ newDir = QFileDialog.getExistingDirectory(
+ self,"Backup Directory",currDir,options=dlgOpt
+ )
+ if newDir:
+ self.projBackupPath.setText(newDir)
+ return True
+ return False
+
# END Class GuiConfigEditGeneral
class GuiConfigEditEditor(QWidget):
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 917af5f8..6fba5cfd 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -507,6 +507,12 @@ class GuiMainMenu(QMenuBar):
menuItem.triggered.connect(self.theParent.rebuildIndex)
self.toolsMenu.addAction(menuItem)
+ # Tools > Backup
+ menuItem = QAction(QIcon.fromTheme("drive-harddisk"), "Backup Project", self)
+ menuItem.setStatusTip("Backup Project")
+ menuItem.triggered.connect(self.theParent.backupProject)
+ self.toolsMenu.addAction(menuItem)
+
# Tools > Settings
menuItem = QAction(QIcon.fromTheme("preferences-system"), "Preferences", self)
menuItem.setStatusTip("Preferences")
diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py
index ab15c148..88da6ca6 100644
--- a/nw/gui/projecteditor.py
+++ b/nw/gui/projecteditor.py
@@ -21,7 +21,7 @@ from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel,
QWidget, QTabWidget, QDialogButtonBox, QListWidget, QListWidgetItem, QPushButton,
- QColorDialog, QAbstractItemView, QTreeWidget, QTreeWidgetItem
+ QColorDialog, QAbstractItemView, QTreeWidget, QTreeWidgetItem, QCheckBox
)
from nw.enum import nwAlert
@@ -81,9 +81,11 @@ class GuiProjectEditor(QDialog):
projName = self.tabMain.editName.text()
bookTitle = self.tabMain.editTitle.text()
bookAuthors = self.tabMain.editAuthors.toPlainText()
+ doBackup = self.tabMain.doBackup.isChecked()
self.theProject.setProjectName(projName)
self.theProject.setBookTitle(bookTitle)
self.theProject.setBookAuthors(bookAuthors)
+ self.theProject.setProjBackup(doBackup)
if self.tabStatus.colChanged:
statusCol = self.tabStatus.getNewList()
@@ -116,13 +118,19 @@ class GuiProjectEditMain(QWidget):
self.theParent = theParent
self.theProject = theProject
self.mainForm = QFormLayout()
+ self.backupBox = QHBoxLayout()
self.editName = QLineEdit()
self.editTitle = QLineEdit()
self.editAuthors = QPlainTextEdit()
+ self.doBackup = QCheckBox(self)
- self.mainForm.addRow("Working Title", self.editName)
- self.mainForm.addRow("Book Title", self.editTitle)
- self.mainForm.addRow("Book Authors", self.editAuthors)
+ self.mainForm.addRow("Working Title", self.editName)
+ self.mainForm.addRow("Book Title", self.editTitle)
+ self.mainForm.addRow("Book Authors", self.editAuthors)
+ self.mainForm.addRow(self.backupBox)
+ self.backupBox.addStretch(1)
+ self.backupBox.addWidget(QLabel("Backup on Close"))
+ self.backupBox.addWidget(self.doBackup)
self.editName.setText(self.theProject.projName)
self.editTitle.setText(self.theProject.bookTitle)
@@ -130,8 +138,13 @@ class GuiProjectEditMain(QWidget):
for bookAuthor in self.theProject.bookAuthors:
bookAuthors += bookAuthor+"\n"
self.editAuthors.setPlainText(bookAuthors)
+ if self.theProject.doBackup:
+ self.doBackup.setCheckState(Qt.Checked)
+ else:
+ self.doBackup.setCheckState(Qt.Unchecked)
self.setLayout(self.mainForm)
+ self.editAuthors.setMaximumHeight(120)
return
diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py
index 374668a6..7b9bb03e 100644
--- a/nw/gui/winmain.py
+++ b/nw/gui/winmain.py
@@ -36,6 +36,7 @@ from nw.project.project import NWProject
from nw.project.document import NWDoc
from nw.project.item import NWItem
from nw.project.index import NWIndex
+from nw.project.backup import NWBackup
from nw.tools.wordcount import countWords
from nw.theme import Theme
from nw.enum import nwItemType, nwAlert
@@ -112,7 +113,7 @@ class GuiMain(QMainWindow):
# Set Main Window Elements
self.setMenuBar(self.mainMenu)
self.setStatusBar(self.statusBar)
- self.statusBar.showMessage("Ready")
+ self.statusBar.setStatus("Ready")
# Set Up Autosaving Project Timer
self.asProjTimer = QTimer()
@@ -206,18 +207,33 @@ class GuiMain(QMainWindow):
if msgRes != QMessageBox.Yes:
return False
- self.closeDocument()
+ if self.docEditor.docChanged:
+ self.saveDocument()
+
if self.theProject.projChanged:
- saveOK = self.saveProject()
+ saveOK = self.saveProject()
+ doBackup = False
+ if self.theProject.doBackup and self.mainConf.backupOnClose:
+ doBackup = True
+ if self.mainConf.showGUI and self.mainConf.askBeforeBackup:
+ msgBox = QMessageBox()
+ msgRes = msgBox.question(
+ self, "Backup Project", "Backup current project?"
+ )
+ if msgRes != QMessageBox.Yes:
+ doBackup = False
+ if doBackup:
+ self.backupProject()
else:
saveOK = True
if saveOK:
+ self.closeDocument()
self.theProject.closeProject()
self.theIndex.clearIndex()
self.clearGUI()
self.hasProject = False
-
+
return saveOK
def openProject(self, projFile=None):
@@ -279,6 +295,11 @@ class GuiMain(QMainWindow):
return True
+ def backupProject(self):
+ theBackup = NWBackup(self, self.theProject)
+ theBackup.zipIt()
+ return True
+
##
# Document Actions
##
diff --git a/nw/project/backup.py b/nw/project/backup.py
new file mode 100644
index 00000000..75235b85
--- /dev/null
+++ b/nw/project/backup.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+"""novelWriter Project Backup
+
+ novelWriter – Project Backup
+==============================
+ Class handling project backups
+
+ File History:
+ Created: 2019-06-16 [0.1.5]
+
+"""
+
+import logging
+import nw
+
+from os import path, mkdir, listdir
+from shutil import make_archive
+from datetime import datetime
+
+from nw.enum import nwAlert
+
+logger = logging.getLogger(__name__)
+
+class NWBackup():
+
+ def __init__(self, theParent, theProject):
+
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.theProject = theProject
+
+ return
+
+ def zipIt(self):
+
+ if self.mainConf.backupPath is None:
+ self.theParent.makeAlert("Cannot backup project because no backup path is set.",nwAlert.WARN)
+ return False
+
+ if self.theProject.projName is None:
+ self.theParent.makeAlert("Cannot backup project because no project name is set.",nwAlert.WARN)
+ return False
+
+ logger.info("Backing up project")
+ self.theParent.statusBar.setStatus("Backing up project ...")
+
+ archName = ""
+ for c in self.theProject.projName:
+ if c.isalnum():
+ archName += c
+
+ archName = archName+"_"+datetime.now().strftime("%Y%m%d-%H%M%S")
+ baseName = path.join(self.mainConf.backupPath, archName)
+
+ try:
+ make_archive(baseName, "zip", self.theProject.projPath, ".")
+ except Exception as e:
+ self.theParent.makeAlert(["Could not write backup archive.",str(e)],nwAlert.ERROR)
+ return False
+
+ self.theParent.statusBar.setStatus("Project backup complete")
+
+ return True
+
+# END Class NWBackup
diff --git a/nw/project/project.py b/nw/project/project.py
index 8cc6bf9b..bdc1b8b3 100644
--- a/nw/project/project.py
+++ b/nw/project/project.py
@@ -67,6 +67,7 @@ class NWProject():
self.lastViewed = None
self.lastWCount = 0
self.currWCount = 0
+ self.doBackup = True
# Set Defaults
self.clearProject()
@@ -221,6 +222,8 @@ class NWProject():
elif xItem.tag == "author":
logger.verbose("Author: '%s'" % xItem.text)
self.bookAuthors.append(xItem.text)
+ elif xItem.tag == "backup":
+ self.doBackup = checkBool(xItem.text,False)
elif xChild.tag == "settings":
logger.debug("Found project settings")
for xItem in xChild:
@@ -295,6 +298,7 @@ class NWProject():
self._saveProjectValue(xProject,"name", self.projName, True)
self._saveProjectValue(xProject,"title", self.bookTitle, True)
self._saveProjectValue(xProject,"author",self.bookAuthors)
+ self._saveProjectValue(xProject,"backup",self.doBackup)
# Save Project Settings
xSettings = etree.SubElement(nwXML,"settings")
@@ -375,6 +379,24 @@ class NWProject():
self.setProjectChanged(True)
return True
+ def setProjBackup(self, doBackup):
+ self.doBackup = False
+ if doBackup:
+ if not path.isdir(self.mainConf.backupPath):
+ self.theParent.makeAlert(
+ "You must set a valid backup path in preferences
to use the automatic project backup feature.",
+ nwAlert.ERROR
+ )
+ return False
+ if self.projName == "":
+ self.theParent.makeAlert(
+ "You must set a valid project name in project settings
to use the automatic project backup feature.",
+ nwAlert.ERROR
+ )
+ return False
+ self.doBackup = True
+ return True
+
def setSpellCheck(self, theMode):
if self.spellCheck != theMode:
self.spellCheck = theMode
diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx
index 549fab53..d7d364cd 100644
--- a/sample/sampleNovel/nwProject.nwx
+++ b/sample/sampleNovel/nwProject.nwx
@@ -1,10 +1,11 @@
-
+
Sample Project
Sample Project
Jane Smith
Jay Doh
+ False
True
diff --git a/tests/reference/gui/0_nwProject.nwx b/tests/reference/gui/0_nwProject.nwx
index 19443161..c3337adb 100644
--- a/tests/reference/gui/0_nwProject.nwx
+++ b/tests/reference/gui/0_nwProject.nwx
@@ -1,8 +1,9 @@
-
+
+ True
False
diff --git a/tests/reference/gui/1_nwProject.nwx b/tests/reference/gui/1_nwProject.nwx
index 67cd383d..193087e6 100644
--- a/tests/reference/gui/1_nwProject.nwx
+++ b/tests/reference/gui/1_nwProject.nwx
@@ -1,8 +1,9 @@
-
+
+ True
True
diff --git a/tests/reference/gui/2_nwProject.nwx b/tests/reference/gui/2_nwProject.nwx
index dd2b6333..02c51167 100644
--- a/tests/reference/gui/2_nwProject.nwx
+++ b/tests/reference/gui/2_nwProject.nwx
@@ -5,6 +5,7 @@
Project Title
Jane Doe
John Doh
+ True
False
diff --git a/tests/reference/gui/3_nwProject.nwx b/tests/reference/gui/3_nwProject.nwx
index 7ae54e07..503c011c 100644
--- a/tests/reference/gui/3_nwProject.nwx
+++ b/tests/reference/gui/3_nwProject.nwx
@@ -3,6 +3,7 @@
+ True
False
diff --git a/tests/reference/novelwriter.conf b/tests/reference/novelwriter.conf
index c0eb784e..8b6bff87 100644
--- a/tests/reference/novelwriter.conf
+++ b/tests/reference/novelwriter.conf
@@ -1,5 +1,5 @@
[Main]
-timestamp = 2019-06-15 23:10:43
+timestamp = 2019-06-27 20:26:43
theme = default
syntax = default_light
@@ -32,6 +32,11 @@ fmtsinglequote = ‘, ’
fmtdoublequote = “, ”
spellcheck = en_GB
+[Backup]
+backuppath =
+backuponclose = False
+askbeforebackup = True
+
[Path]
recent0 =
recent1 =
diff --git a/tests/reference/proj/1_nwProject.nwx b/tests/reference/proj/1_nwProject.nwx
index a9c82564..4960024b 100644
--- a/tests/reference/proj/1_nwProject.nwx
+++ b/tests/reference/proj/1_nwProject.nwx
@@ -3,6 +3,7 @@
+ True
False
diff --git a/tests/reference/proj/2_nwProject.nwx b/tests/reference/proj/2_nwProject.nwx
index f7bd904d..b78c14a4 100644
--- a/tests/reference/proj/2_nwProject.nwx
+++ b/tests/reference/proj/2_nwProject.nwx
@@ -3,6 +3,7 @@
+ True
False
diff --git a/tests/test_gui.py b/tests/test_gui.py
index 5954ebbe..f7840805 100644
--- a/tests/test_gui.py
+++ b/tests/test_gui.py
@@ -287,6 +287,7 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef):
# Create new, save, open project
nwGUI.theProject.handleSeed = 42
assert nwGUI.newProject(nwTempGUI, True)
+ nwGUI.mainConf.backupPath = nwTempGUI
projEdit = GuiProjectEditor(nwGUI, nwGUI.theProject)
qtbot.addWidget(projEdit)