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)