Added test for main preferences and improved the Preferences dialog a bit
This commit is contained in:
+41
-78
@@ -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
|
||||
|
||||
+14
-6
@@ -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 += "<br>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 += "<br>This is a bug!"
|
||||
msgBox.critical(self, "Internal Error", popMsg)
|
||||
|
||||
return
|
||||
|
||||
|
||||
+1
-1
@@ -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("")
|
||||
|
||||
@@ -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 =
|
||||
|
||||
+149
-1
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user