diff --git a/nw/gui/preferences.py b/nw/gui/preferences.py
index d1e21c20..188bb819 100644
--- a/nw/gui/preferences.py
+++ b/nw/gui/preferences.py
@@ -104,7 +104,7 @@ class GuiPreferences(PagedDialog):
validEntries &= retA
needsRestart |= retB
- if needsRestart:
+ if needsRestart and self.mainConf.showGUI:
msgBox = QMessageBox()
msgBox.information(
self, "Preferences",
@@ -817,69 +817,70 @@ class GuiConfigEditAutoReplaceTab(QWidget):
qWidth = self.mainConf.pxInt(40)
bWidth = int(2.5*self.theTheme.getTextWidth("..."))
+ self.quoteSym = {}
## Single Quote Style
- self.quoteSingleStyleO = QLineEdit()
- self.quoteSingleStyleO.setMaxLength(1)
- self.quoteSingleStyleO.setReadOnly(True)
- self.quoteSingleStyleO.setFixedWidth(qWidth)
- self.quoteSingleStyleO.setAlignment(Qt.AlignCenter)
- self.quoteSingleStyleO.setText(self.mainConf.fmtSingleQuotes[0])
+ self.quoteSym["SO"] = QLineEdit()
+ self.quoteSym["SO"].setMaxLength(1)
+ self.quoteSym["SO"].setReadOnly(True)
+ self.quoteSym["SO"].setFixedWidth(qWidth)
+ self.quoteSym["SO"].setAlignment(Qt.AlignCenter)
+ self.quoteSym["SO"].setText(self.mainConf.fmtSingleQuotes[0])
self.btnSingleStyleO = QPushButton("...")
self.btnSingleStyleO.setMaximumWidth(bWidth)
- self.btnSingleStyleO.clicked.connect(self._getSingleOpen)
+ self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
self.mainForm.addRow(
"Single quote open style",
- self.quoteSingleStyleO,
+ self.quoteSym["SO"],
"Auto-replaces apostrophe before words.",
theButton=self.btnSingleStyleO
)
- self.quoteSingleStyleC = QLineEdit()
- self.quoteSingleStyleC.setMaxLength(1)
- self.quoteSingleStyleC.setReadOnly(True)
- self.quoteSingleStyleC.setFixedWidth(qWidth)
- self.quoteSingleStyleC.setAlignment(Qt.AlignCenter)
- self.quoteSingleStyleC.setText(self.mainConf.fmtSingleQuotes[1])
+ self.quoteSym["SC"] = QLineEdit()
+ self.quoteSym["SC"].setMaxLength(1)
+ self.quoteSym["SC"].setReadOnly(True)
+ self.quoteSym["SC"].setFixedWidth(qWidth)
+ self.quoteSym["SC"].setAlignment(Qt.AlignCenter)
+ self.quoteSym["SC"].setText(self.mainConf.fmtSingleQuotes[1])
self.btnSingleStyleC = QPushButton("...")
self.btnSingleStyleC.setMaximumWidth(bWidth)
- self.btnSingleStyleC.clicked.connect(self._getSingleClose)
+ self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
self.mainForm.addRow(
"Single quote close style",
- self.quoteSingleStyleC,
+ self.quoteSym["SC"],
"Auto-replaces apostrophe after words.",
theButton=self.btnSingleStyleC
)
## Double Quote Style
- self.quoteDoubleStyleO = QLineEdit()
- self.quoteDoubleStyleO.setMaxLength(1)
- self.quoteDoubleStyleO.setReadOnly(True)
- self.quoteDoubleStyleO.setFixedWidth(qWidth)
- self.quoteDoubleStyleO.setAlignment(Qt.AlignCenter)
- self.quoteDoubleStyleO.setText(self.mainConf.fmtDoubleQuotes[0])
+ self.quoteSym["DO"] = QLineEdit()
+ self.quoteSym["DO"].setMaxLength(1)
+ self.quoteSym["DO"].setReadOnly(True)
+ self.quoteSym["DO"].setFixedWidth(qWidth)
+ self.quoteSym["DO"].setAlignment(Qt.AlignCenter)
+ self.quoteSym["DO"].setText(self.mainConf.fmtDoubleQuotes[0])
self.btnDoubleStyleO = QPushButton("...")
self.btnDoubleStyleO.setMaximumWidth(bWidth)
- self.btnDoubleStyleO.clicked.connect(self._getDoubleOpen)
+ self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
self.mainForm.addRow(
"Double quote open style",
- self.quoteDoubleStyleO,
+ self.quoteSym["DO"],
"Auto-replaces straight quotes before words.",
theButton=self.btnDoubleStyleO
)
- self.quoteDoubleStyleC = QLineEdit()
- self.quoteDoubleStyleC.setMaxLength(1)
- self.quoteDoubleStyleC.setReadOnly(True)
- self.quoteDoubleStyleC.setFixedWidth(qWidth)
- self.quoteDoubleStyleC.setAlignment(Qt.AlignCenter)
- self.quoteDoubleStyleC.setText(self.mainConf.fmtDoubleQuotes[1])
+ self.quoteSym["DC"] = QLineEdit()
+ self.quoteSym["DC"].setMaxLength(1)
+ self.quoteSym["DC"].setReadOnly(True)
+ self.quoteSym["DC"].setFixedWidth(qWidth)
+ self.quoteSym["DC"].setAlignment(Qt.AlignCenter)
+ self.quoteSym["DC"].setText(self.mainConf.fmtDoubleQuotes[1])
self.btnDoubleStyleC = QPushButton("...")
self.btnDoubleStyleC.setMaximumWidth(bWidth)
- self.btnDoubleStyleC.clicked.connect(self._getDoubleClose)
+ self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
self.mainForm.addRow(
"Double quote close style",
- self.quoteDoubleStyleC,
+ self.quoteSym["DC"],
"Auto-replaces straight quotes after words.",
theButton=self.btnDoubleStyleC
)
@@ -906,10 +907,10 @@ class GuiConfigEditAutoReplaceTab(QWidget):
self.mainConf.doReplaceDash = doReplaceDash
self.mainConf.doReplaceDots = doReplaceDots
- fmtSingleQuotesO = self.quoteSingleStyleO.text()
- fmtSingleQuotesC = self.quoteSingleStyleC.text()
- fmtDoubleQuotesO = self.quoteDoubleStyleO.text()
- fmtDoubleQuotesC = self.quoteDoubleStyleC.text()
+ fmtSingleQuotesO = self.quoteSym["SO"].text()
+ fmtSingleQuotesC = self.quoteSym["SC"].text()
+ fmtDoubleQuotesO = self.quoteSym["DO"].text()
+ fmtDoubleQuotesC = self.quoteSym["DC"].text()
self.mainConf.fmtSingleQuotes[0] = fmtSingleQuotesO
self.mainConf.fmtSingleQuotes[1] = fmtSingleQuotesC
@@ -934,50 +935,12 @@ class GuiConfigEditAutoReplaceTab(QWidget):
self.autoReplaceDots.setEnabled(theState)
return
- def _getSingleOpen(self):
+ def _getQuote(self, qType):
"""Dialog for single quote open.
"""
- qtBox = QuotesDialog(self, currentQuote=self.quoteSingleStyleO.text())
+ qtBox = QuotesDialog(self, currentQuote=self.quoteSym[qType].text())
if qtBox.exec_() == QDialog.Accepted:
- self.quoteSingleStyleO.setText(qtBox.selectedQuote)
+ self.quoteSym[qType].setText(qtBox.selectedQuote)
return
- def _getSingleClose(self):
- """Dialog for single quote close.
- """
- qtBox = QuotesDialog(self, currentQuote=self.quoteSingleStyleC.text())
- if qtBox.exec_() == QDialog.Accepted:
- self.quoteSingleStyleC.setText(qtBox.selectedQuote)
- return
-
- def _getDoubleOpen(self):
- """Dialog for double quote open.
- """
- qtBox = QuotesDialog(self, currentQuote=self.quoteDoubleStyleO.text())
- if qtBox.exec_() == QDialog.Accepted:
- self.quoteDoubleStyleO.setText(qtBox.selectedQuote)
- return
-
- def _getDoubleClose(self):
- """Dialog for double quote close.
- """
- qtBox = QuotesDialog(self, currentQuote=self.quoteDoubleStyleC.text())
- if qtBox.exec_() == QDialog.Accepted:
- self.quoteDoubleStyleC.setText(qtBox.selectedQuote)
- return
-
- ##
- # Internal Functions
- ##
-
- def _checkQuoteSymbol(self, toCheck):
- """Check that the quote symbols entered are in nwQuotes and is
- therefore a valid quote symbol for this app.
- """
- if len(toCheck) != 1:
- return False
- if toCheck in nwQuotes.SYMBOLS:
- return True
- return False
-
# END Class GuiConfigEditAutoReplaceTab
diff --git a/nw/guimain.py b/nw/guimain.py
index de340304..0da4f5a0 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -855,24 +855,32 @@ class GuiMain(QMainWindow):
popMsg = theMessage
logMsg = [theMessage]
- msgBox = QMessageBox()
+ # Write to Log
if theLevel == nwAlert.INFO:
for msgLine in logMsg:
logger.info(msgLine)
- msgBox.information(self, "Information", popMsg)
elif theLevel == nwAlert.WARN:
for msgLine in logMsg:
logger.warning(msgLine)
- msgBox.warning(self, "Warning", popMsg)
elif theLevel == nwAlert.ERROR:
for msgLine in logMsg:
logger.error(msgLine)
- msgBox.critical(self, "Error", popMsg)
elif theLevel == nwAlert.BUG:
for msgLine in logMsg:
logger.error(msgLine)
- popMsg += "
This is a bug!"
- msgBox.critical(self, "Internal Error", popMsg)
+
+ # Popup
+ if self.mainConf.showGUI:
+ msgBox = QMessageBox()
+ if theLevel == nwAlert.INFO:
+ msgBox.information(self, "Information", popMsg)
+ elif theLevel == nwAlert.WARN:
+ msgBox.warning(self, "Warning", popMsg)
+ elif theLevel == nwAlert.ERROR:
+ msgBox.critical(self, "Error", popMsg)
+ elif theLevel == nwAlert.BUG:
+ popMsg += "
This is a bug!"
+ msgBox.critical(self, "Internal Error", popMsg)
return
diff --git a/tests/conftest.py b/tests/conftest.py
index 021c888b..61bd1211 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -36,7 +36,7 @@ def nwConf(nwRef, nwTemp):
return theConf
@pytest.fixture(scope="session")
-def tmpConf(nwRef, nwTemp):
+def tmpConf(nwTemp):
theConf = Config()
theConf.initConfig(nwTemp, nwTemp)
theConf.setLastPath("")
diff --git a/tests/reference/prefs_novelwriter.conf b/tests/reference/prefs_novelwriter.conf
new file mode 100644
index 00000000..6b894f55
--- /dev/null
+++ b/tests/reference/prefs_novelwriter.conf
@@ -0,0 +1,69 @@
+[Main]
+timestamp = 2020-06-29 17:34:15
+theme = default
+syntax = default_light
+icons = typicons_colour_light
+guidark = True
+guifont = Cantarell
+guifontsize = 12
+
+[Sizes]
+geometry = 1100, 650
+treecols = 120, 30, 50
+projcols = 140, 55, 140
+mainpane = 300, 800
+docpane = 400, 400
+viewpane = 500, 150
+outlinepane = 500, 150
+fullscreen = False
+
+[Project]
+autosaveproject = 40
+autosavedoc = 20
+
+[Editor]
+textfont = Cantarell
+textsize = 13
+fixedwidth = False
+width = 700
+margin = 45
+tabwidth = 45
+focuswidth = 900
+hidefocusfooter = True
+justify = False
+autoselect = False
+autoreplace = False
+repsquotes = True
+repdquotes = True
+repdash = True
+repdots = True
+fmtsinglequote = ‘, ’
+fmtdoublequote = “, ”
+spelltool = internal
+spellcheck = en
+showtabsnspaces = True
+showlineendings = True
+bigdoclimit = 500
+showfullpath = False
+highlightquotes = False
+highlightemph = False
+
+[Backup]
+backuppath =
+backuponclose = True
+askbeforebackup = True
+
+[State]
+showrefpanel = False
+viewcomments = True
+viewsynopsis = True
+searchcase = False
+searchword = False
+searchregex = False
+searchloop = False
+searchnextfile = False
+searchmatchcap = False
+
+[Path]
+lastpath =
+
diff --git a/tests/test_dialogs.py b/tests/test_dialogs.py
index 53e36c6b..8b6b62d3 100644
--- a/tests/test_dialogs.py
+++ b/tests/test_dialogs.py
@@ -15,7 +15,7 @@ from PyQt5.QtWidgets import QDialogButtonBox, QTreeWidgetItem
from nw.gui import (
GuiProjectSettings, GuiItemEditor, GuiAbout, GuiBuildNovel,
GuiDocMerge, GuiDocSplit, GuiWritingStats, GuiProjectWizard,
- GuiProjectLoad
+ GuiProjectLoad, GuiPreferences
)
from nw.constants import nwItemType, nwItemLayout, nwItemClass
@@ -765,3 +765,151 @@ def testLoadProject(qtbot, nwMinimal, nwTemp):
nwLoad.close()
# qtbot.stopForInteraction()
nwGUI.closeMain()
+
+@pytest.mark.gui
+def testPreferences(qtbot, nwMinimal, nwTemp, nwRef, tmpConf):
+ nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
+ qtbot.addWidget(nwGUI)
+ nwGUI.show()
+ qtbot.waitForWindowShown(nwGUI)
+ qtbot.wait(stepDelay)
+
+ assert nwGUI.openProject(nwMinimal)
+ nwPrefs = GuiPreferences(nwGUI, nwGUI.theProject)
+ nwPrefs.show()
+
+ # Override Config
+ tmpConf.showGUI = False
+ tmpConf.confPath = nwMinimal
+ nwGUI.mainConf = tmpConf
+ nwPrefs.mainConf = tmpConf
+ nwPrefs.tabGeneral.mainConf = tmpConf
+ nwPrefs.tabLayout.mainConf = tmpConf
+ nwPrefs.tabEditing.mainConf = tmpConf
+ nwPrefs.tabAutoRep.mainConf = tmpConf
+
+ # General Settings
+ qtbot.wait(keyDelay)
+ tabGeneral = nwPrefs.tabGeneral
+ nwPrefs._tabBox.setCurrentWidget(tabGeneral)
+ tabGeneral.backupPath = nwTemp
+
+ qtbot.wait(keyDelay)
+ assert not tabGeneral.preferDarkIcons.isChecked()
+ qtbot.mouseClick(tabGeneral.preferDarkIcons, Qt.LeftButton)
+ assert tabGeneral.preferDarkIcons.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert tabGeneral.showFullPath.isChecked()
+ qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton)
+ assert not tabGeneral.showFullPath.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert not tabGeneral.backupOnClose.isChecked()
+ qtbot.mouseClick(tabGeneral.backupOnClose, Qt.LeftButton)
+ assert tabGeneral.backupOnClose.isChecked()
+
+ qtbot.wait(keyDelay)
+ tabGeneral.guiFontSize.setValue(12)
+ tabGeneral.autoSaveDoc.setValue(20)
+ tabGeneral.autoSaveProj.setValue(40)
+
+ # Text Layour Settings
+ qtbot.wait(keyDelay)
+ tabLayout = nwPrefs.tabLayout
+ nwPrefs._tabBox.setCurrentWidget(tabLayout)
+
+ qtbot.wait(keyDelay)
+ tabLayout.textStyleSize.setValue(13)
+ tabLayout.textFlowMax.setValue(700)
+ tabLayout.focusDocWidth.setValue(900)
+ tabLayout.textMargin.setValue(45)
+ tabLayout.tabWidth.setValue(45)
+
+ qtbot.wait(keyDelay)
+ assert not tabLayout.textFlowFixed.isChecked()
+ qtbot.mouseClick(tabLayout.textFlowFixed, Qt.LeftButton)
+ assert tabLayout.textFlowFixed.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert not tabLayout.hideFocusFooter.isChecked()
+ qtbot.mouseClick(tabLayout.hideFocusFooter, Qt.LeftButton)
+ assert tabLayout.hideFocusFooter.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert tabLayout.textJustify.isChecked()
+ qtbot.mouseClick(tabLayout.textJustify, Qt.LeftButton)
+ assert not tabLayout.textJustify.isChecked()
+
+ # Editor Settings
+ qtbot.wait(keyDelay)
+ tabEditing = nwPrefs.tabEditing
+ nwPrefs._tabBox.setCurrentWidget(tabEditing)
+
+ qtbot.wait(keyDelay)
+ assert tabEditing.highlightQuotes.isChecked()
+ qtbot.mouseClick(tabEditing.highlightQuotes, Qt.LeftButton)
+ assert not tabEditing.highlightQuotes.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert tabEditing.highlightEmph.isChecked()
+ qtbot.mouseClick(tabEditing.highlightEmph, Qt.LeftButton)
+ assert not tabEditing.highlightEmph.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert not tabEditing.showTabsNSpaces.isChecked()
+ qtbot.mouseClick(tabEditing.showTabsNSpaces, Qt.LeftButton)
+ assert tabEditing.showTabsNSpaces.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert not tabEditing.showLineEndings.isChecked()
+ qtbot.mouseClick(tabEditing.showLineEndings, Qt.LeftButton)
+ assert tabEditing.showLineEndings.isChecked()
+
+ qtbot.wait(keyDelay)
+ tabEditing.bigDocLimit.setValue(500)
+
+ # Auto-Replace Settings
+ qtbot.wait(keyDelay)
+ tabAutoRep = nwPrefs.tabAutoRep
+ nwPrefs._tabBox.setCurrentWidget(tabAutoRep)
+
+ qtbot.wait(keyDelay)
+ assert tabAutoRep.autoSelect.isChecked()
+ qtbot.mouseClick(tabAutoRep.autoSelect, Qt.LeftButton)
+ assert not tabAutoRep.autoSelect.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert tabAutoRep.autoReplaceMain.isChecked()
+ qtbot.mouseClick(tabAutoRep.autoReplaceMain, Qt.LeftButton)
+ assert not tabAutoRep.autoReplaceMain.isChecked()
+
+ qtbot.wait(keyDelay)
+ assert not tabAutoRep.autoReplaceSQ.isEnabled()
+ assert not tabAutoRep.autoReplaceDQ.isEnabled()
+ assert not tabAutoRep.autoReplaceDash.isEnabled()
+ assert not tabAutoRep.autoReplaceDots.isEnabled()
+
+ # Save and Check Config
+ # qtbot.stopForInteraction()
+ qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton)
+
+ assert tmpConf.confChanged
+ assert tmpConf.backupPath == nwTemp
+ tmpConf.backupPath = ""
+ tmpConf.lastPath = ""
+
+ assert nwGUI.mainConf.saveConfig()
+
+ nwGUI.closeMain()
+
+ refConf = path.join(nwRef, "prefs_novelwriter.conf")
+ projConf = path.join(nwGUI.mainConf.confPath, "novelwriter.conf")
+ testConf = path.join(nwTemp, "prefs_novelwriter.conf")
+ copyfile(projConf, testConf)
+ ignoreLines = [
+ 2, # Timestamp
+ 11, 12, 13, 14, 15, 16, 17, # Window sizes
+ 7, 25, # Fonts (depends in system default)
+ ]
+ assert cmpFiles(testConf, refConf, ignoreLines)