Rewrite Preferences dialog (#1652)

This commit is contained in:
Veronica Berglyd Olsen
2024-01-13 18:44:36 +01:00
committed by GitHub
18 changed files with 1122 additions and 975 deletions
@@ -61,6 +61,7 @@ forward = typ_chevron-right.svg
maximise = typ_arrow-maximise.svg
menu = typ_th-dot-menu.svg
minimise = typ_arrow-minimise.svg
more = typ_th-dot-more.svg
noncheckable = mixed_input-none.svg
panel = nw_panel.svg
proj_chapter = mixed_document-chapter.svg
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M 22,12 A 2.6315,2.6315 0 0 0 19.3686,9.3686 2.6315,2.6315 0 0 0 16.7372,12 2.6315,2.6315 0 0 0 19.3686,14.6314 2.6315,2.6315 0 0 0 22,12 Z m -7.3686,0 A 2.6315,2.6315 0 0 0 12,9.3686 2.6315,2.6315 0 0 0 9.3686,12 2.6315,2.6315 0 0 0 12,14.6314 2.6315,2.6315 0 0 0 14.6314,12 Z M 7.2628,12 A 2.6315,2.6315 0 0 0 4.6314,9.3686 2.6315,2.6315 0 0 0 2,12 2.6315,2.6315 0 0 0 4.6314,14.6314 2.6315,2.6315 0 0 0 7.2628,12 Z" fill="#aeaeae" stroke-width=".90909"/>
</svg>

After

Width:  |  Height:  |  Size: 612 B

@@ -61,6 +61,7 @@ forward = typ_chevron-right.svg
maximise = typ_arrow-maximise.svg
menu = typ_th-dot-menu.svg
minimise = typ_arrow-minimise.svg
more = typ_th-dot-more.svg
noncheckable = mixed_input-none.svg
panel = nw_panel.svg
proj_chapter = mixed_document-chapter.svg
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M 22,12 A 2.6315,2.6315 0 0 0 19.3686,9.3686 2.6315,2.6315 0 0 0 16.7372,12 2.6315,2.6315 0 0 0 19.3686,14.6314 2.6315,2.6315 0 0 0 22,12 Z m -7.3686,0 A 2.6315,2.6315 0 0 0 12,9.3686 2.6315,2.6315 0 0 0 9.3686,12 2.6315,2.6315 0 0 0 12,14.6314 2.6315,2.6315 0 0 0 14.6314,12 Z M 7.2628,12 A 2.6315,2.6315 0 0 0 4.6314,9.3686 2.6315,2.6315 0 0 0 2,12 2.6315,2.6315 0 0 0 4.6314,14.6314 2.6315,2.6315 0 0 0 7.2628,12 Z" fill-opacity=".78039" stroke-width=".90909"/>
</svg>

After

Width:  |  Height:  |  Size: 619 B

+1 -5
View File
@@ -150,9 +150,6 @@ class Config:
self.autoScrollPos = 30 # Start point for typewriter-like scrolling
self.scrollPastEnd = True # Scroll past end of document, and centre cursor
self.wordCountTimer = 5.0 # Interval for word count update in seconds
self.incNotesWCount = True # The status bar word count includes notes
self.highlightQuotes = True # Highlight text in quotes
self.allowOpenSQuote = False # Allow open-ended single quotes
self.allowOpenDQuote = True # Allow open-ended double quotes
@@ -160,6 +157,7 @@ class Config:
self.stopWhenIdle = True # Stop the status bar clock when the user is idle
self.userIdleTime = 300 # Time of inactivity to consider user idle
self.incNotesWCount = True # The status bar word count includes notes
# User-Selected Symbol Settings
self.fmtApostrophe = nwUnicode.U_RSQUO
@@ -591,7 +589,6 @@ class Config:
self.showTabsNSpaces = conf.rdBool(sec, "showtabsnspaces", self.showTabsNSpaces)
self.showLineEndings = conf.rdBool(sec, "showlineendings", self.showLineEndings)
self.showMultiSpaces = conf.rdBool(sec, "showmultispaces", self.showMultiSpaces)
self.wordCountTimer = conf.rdFlt(sec, "wordcounttimer", self.wordCountTimer)
self.incNotesWCount = conf.rdBool(sec, "incnoteswcount", self.incNotesWCount)
self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
self.highlightQuotes = conf.rdBool(sec, "highlightquotes", self.highlightQuotes)
@@ -698,7 +695,6 @@ class Config:
"showtabsnspaces": str(self.showTabsNSpaces),
"showlineendings": str(self.showLineEndings),
"showmultispaces": str(self.showMultiSpaces),
"wordcounttimer": str(self.wordCountTimer),
"incnoteswcount": str(self.incNotesWCount),
"showfullpath": str(self.showFullPath),
"highlightquotes": str(self.highlightQuotes),
+3
View File
@@ -56,6 +56,9 @@ class nwConst:
# Gui Settings
STATUS_MSG_TIMEOUT = 15000 # milliseconds
# Dialogs
DLG_FINISHED = 2
# END Class nwConst
File diff suppressed because it is too large Load Diff
+23 -19
View File
@@ -25,7 +25,7 @@ from __future__ import annotations
import logging
from PyQt5.QtGui import QCloseEvent, QFontMetrics
from PyQt5.QtGui import QFontMetrics
from PyQt5.QtCore import QSize, Qt, pyqtSlot
from PyQt5.QtWidgets import (
QDialog, QDialogButtonBox, QFrame, QHBoxLayout, QLabel, QListWidget,
@@ -40,11 +40,11 @@ logger = logging.getLogger(__name__)
class GuiQuoteSelect(QDialog):
selectedQuote = ""
_selected = ""
D_KEY = Qt.ItemDataRole.UserRole
def __init__(self, parent: QWidget, currentQuote: str = '"') -> None:
def __init__(self, parent: QWidget, current: str = '"') -> None:
super().__init__(parent=parent)
logger.debug("Create: GuiQuoteSelect")
@@ -54,7 +54,7 @@ class GuiQuoteSelect(QDialog):
self.innerBox = QHBoxLayout()
self.labelBox = QVBoxLayout()
self.selectedQuote = currentQuote
self._selected = current
qMetrics = QFontMetrics(self.font())
pxW = 7*qMetrics.boundingRectChar("M").width()
@@ -65,7 +65,7 @@ class GuiQuoteSelect(QDialog):
lblFont.setPointSizeF(4*lblFont.pointSizeF())
# Preview Label
self.previewLabel = QLabel(currentQuote)
self.previewLabel = QLabel(current)
self.previewLabel.setFont(lblFont)
self.previewLabel.setFixedSize(QSize(pxW, pxH))
self.previewLabel.setAlignment(Qt.AlignCenter)
@@ -82,7 +82,7 @@ class GuiQuoteSelect(QDialog):
qtItem = QListWidgetItem(theText)
qtItem.setData(self.D_KEY, sKey)
self.listBox.addItem(qtItem)
if sKey == currentQuote:
if sKey == current:
self.listBox.setCurrentItem(qtItem)
self.listBox.setMinimumWidth(minSize + CONFIG.pxInt(40))
@@ -113,15 +113,20 @@ class GuiQuoteSelect(QDialog):
logger.debug("Delete: GuiQuoteSelect")
return
##
# Events
##
@property
def selectedQuote(self) -> str:
"""Return the selected quote symbol."""
return self._selected
def closeEvent(self, event: QCloseEvent) -> None:
"""Capture the close event and perform cleanup."""
event.accept()
self.deleteLater()
return
@classmethod
def getQuote(cls, parent: QWidget, current: str = "") -> tuple[str, bool]:
"""Pop the dialog and return the result."""
cls = GuiQuoteSelect(parent, current=current)
cls.exec_()
quote = cls._selected
accepted = cls.result() == QDialog.DialogCode.Accepted
cls.deleteLater()
return quote, accepted
##
# Private Slots
@@ -130,11 +135,10 @@ class GuiQuoteSelect(QDialog):
@pyqtSlot()
def _selectedSymbol(self) -> None:
"""Update the preview label and the selected quote style."""
selItems = self.listBox.selectedItems()
if selItems:
theSymbol = selItems[0].data(self.D_KEY)
self.previewLabel.setText(theSymbol)
self.selectedQuote = theSymbol
if items := self.listBox.selectedItems():
quote = items[0].data(self.D_KEY)
self.previewLabel.setText(quote)
self._selected = quote
return
# END Class GuiQuoteSelect
+133 -5
View File
@@ -3,7 +3,9 @@ novelWriter Custom Widget: Config Layout
==========================================
File History:
Created: 2020-05-03 [0.4.5]
Created: 2020-05-03 [0.4.5] NConfigLayout, NHelpLabel
Created: 2023-05-23 [2.1b1] NSimpleLayout
Created: 2024-01-08 [2.3b1] NScrollableForm
This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen
@@ -26,7 +28,7 @@ from __future__ import annotations
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QAbstractButton, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QSizePolicy,
QAbstractButton, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QScrollArea, QSizePolicy,
QVBoxLayout, QWidget
)
@@ -37,6 +39,133 @@ RIGHT_TOP = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
LEFT_TOP = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop
class NScrollableForm(QScrollArea):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
self._helpCol = QColor(0, 0, 0)
self._fontScale = FONT_SCALE
self._first = True
self._sections: dict[int, QLabel] = {}
self._editable: dict[str, NHelpLabel] = {}
self._index: dict[str, QWidget] = {}
self._layout = QVBoxLayout()
self._layout.setSpacing(CONFIG.pxInt(12))
self._widget = QWidget(self)
self._widget.setLayout(self._layout)
self.setWidget(self._widget)
self.setWidgetResizable(True)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
return
##
# Properties
##
@property
def labels(self) -> list[str]:
return list(self._index.keys())
##
# Setters
##
def setHelpTextStyle(self, color: QColor | list | tuple, scale: float = FONT_SCALE) -> None:
"""Set the text color for the help text."""
self._helpCol = color if isinstance(color, QColor) else QColor(*color)
self._fontScale = scale
return
def setHelpText(self, key: str, text: str) -> None:
"""Set the text for the help label."""
if qHelp := self._editable.get(key):
qHelp.setText(text)
return
##
# Methods
##
def scrollToSection(self, identifier: int) -> None:
"""Scroll to the requested section identifier."""
if identifier in self._sections:
yPos = self._sections[identifier].pos().y() - CONFIG.pxInt(8)
self.verticalScrollBar().setValue(yPos)
return
def scrollToLabel(self, label: str) -> None:
"""Scroll to the requested label."""
if label in self._index:
yPos = self._index[label].pos().y() - CONFIG.pxInt(8)
self.verticalScrollBar().setValue(yPos)
return
def addGroupLabel(self, label: str, identifier: int) -> None:
"""Add a text label to separate groups of settings."""
hM = CONFIG.pxInt(4)
qLabel = QLabel(f"<b>{label}</b>", self)
qLabel.setContentsMargins(0, hM, 0, hM)
if not self._first:
self._layout.addSpacing(5*hM)
self._layout.addWidget(qLabel)
self._sections[identifier] = qLabel
self._first = False
return
def addRow(self, label: str, widget: QWidget, helpText: str = "", unit: str | None = None,
button: QWidget | None = None, editable: str | None = None) -> None:
"""Add a label and a widget as a new row of the form."""
row = QHBoxLayout()
row.setSpacing(CONFIG.pxInt(4))
mPx = CONFIG.pxInt(12)
qLabel = QLabel(label, self)
qLabel.setIndent(mPx)
qLabel.setBuddy(widget)
if helpText:
qHelp = NHelpLabel(str(helpText), self._helpCol, self._fontScale)
qHelp.setIndent(mPx)
labelBox = QVBoxLayout()
labelBox.addWidget(qLabel)
labelBox.addWidget(qHelp)
labelBox.setSpacing(0)
labelBox.addStretch(1)
row.addLayout(labelBox)
if editable:
self._editable[editable] = qHelp
else:
row.addWidget(qLabel)
row.addSpacing(mPx)
row.addWidget(widget)
if isinstance(unit, str):
row.addWidget(QLabel(unit, self))
elif isinstance(button, QAbstractButton):
row.addWidget(button)
self._layout.addLayout(row)
self._index[label.strip()] = widget
self._first = False
return
def finalise(self) -> None:
"""Finalise the layout when the form is built."""
self._layout.addSpacing(CONFIG.pxInt(20))
self._layout.addStretch(1)
return
# END Class NScrollableForm
class NConfigLayout(QGridLayout):
def __init__(self) -> None:
@@ -58,11 +187,10 @@ class NConfigLayout(QGridLayout):
# Getters and Setters
##
def setHelpTextStyle(self, color: QColor | list | tuple,
fontScale: float = FONT_SCALE) -> None:
def setHelpTextStyle(self, color: QColor | list | tuple, scale: float = FONT_SCALE) -> None:
"""Set the text color for the help text."""
self._helpCol = color if isinstance(color, QColor) else QColor(*color)
self._fontScale = fontScale
self._fontScale = scale
return
def setHelpText(self, row: int, text: str) -> None:
+9 -1
View File
@@ -26,7 +26,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations
from PyQt5.QtGui import QColor, QPaintEvent, QPainter, QPolygon
from PyQt5.QtCore import QPoint, QRectF, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtCore import QPoint, QRectF, QSize, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
QAbstractButton, QAction, QButtonGroup, QLabel, QSizePolicy, QStyle,
QStyleOptionToolButton, QToolBar, QToolButton, QWidget
@@ -63,6 +63,10 @@ class NPagedSideBar(QToolBar):
return
def button(self, buttonId: int) -> _NPagedToolButton:
"""Return a specific button."""
return self._buttons[buttonId]
def setLabelColor(self, color: list | QColor) -> None:
"""Set the text color for the labels."""
self._labelCol = color if isinstance(color, QColor) else QColor(*color)
@@ -136,6 +140,10 @@ class _NPagedToolButton(QToolButton):
return
def sizeHint(self) -> QSize:
"""Return a size hint that includes the arrow."""
return super().sizeHint() + QSize(4*self._aH, 0)
def paintEvent(self, event: QPaintEvent) -> None:
"""Overload the paint event to draw a simple, left aligned text
label, with a highlight when selected and a transparent base
+28 -60
View File
@@ -24,31 +24,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations
from PyQt5.QtGui import QMouseEvent, QPainter, QPaintEvent, QResizeEvent
from PyQt5.QtCore import QEvent, QPropertyAnimation, QRectF, Qt, pyqtProperty
from PyQt5.QtCore import QEvent, QPropertyAnimation, Qt, pyqtProperty
from PyQt5.QtWidgets import QAbstractButton, QSizePolicy, QWidget
from novelwriter import CONFIG
from novelwriter.constants import nwUnicode
class NSwitch(QAbstractButton):
def __init__(self, parent: QWidget | None = None,
width: int | None = None, height: int | None = None) -> None:
__slots__ = ("_xW", "_xH", "_xR", "_rB", "_rH", "_rR", "_offset")
def __init__(self, parent: QWidget | None = None, width: int = 0, height: int = 0) -> None:
super().__init__(parent=parent)
if width is None:
self._xW = CONFIG.pxInt(40)
else:
self._xW = width
if height is None:
self._xH = CONFIG.pxInt(20)
else:
self._xH = height
self._xW = width or CONFIG.pxInt(40)
self._xH = height or CONFIG.pxInt(20)
self._xR = int(self._xH*0.5)
self._xT = int(self._xH*0.6)
self._rB = int(CONFIG.guiScale*2)
self._rH = self._xH - 2*self._rB
self._rR = self._xR - self._rB
@@ -82,10 +73,7 @@ class NSwitch(QAbstractButton):
def setChecked(self, checked: bool) -> None:
"""Overload setChecked to also alter the offset."""
super().setChecked(checked)
if checked:
self._offset = self._xW - self._xR
else:
self._offset = self._xR
self._offset = (self._xW - self._xR) if checked else self._xR
return
##
@@ -95,53 +83,36 @@ class NSwitch(QAbstractButton):
def resizeEvent(self, event: QResizeEvent) -> None:
"""Overload resize to ensure correct offset."""
super().resizeEvent(event)
if self.isChecked():
self._offset = self._xW - self._xR
else:
self._offset = self._xR
self._offset = (self._xW - self._xR) if self.isChecked() else self._xR
return
def paintEvent(self, event: QPaintEvent) -> None:
"""Drawing the switch itself."""
qPaint = QPainter(self)
qPaint.setRenderHint(QPainter.Antialiasing, True)
qPaint.setPen(Qt.NoPen)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setPen(Qt.NoPen)
qPalette = self.palette()
palette = self.palette()
if self.isChecked():
trackBrush = qPalette.highlight()
thumbBrush = qPalette.highlightedText()
textColor = qPalette.highlight().color()
thumbText = nwUnicode.U_CHECK
trackBrush = palette.highlight()
thumbBrush = palette.highlightedText()
else:
trackBrush = qPalette.dark()
thumbBrush = qPalette.light()
textColor = qPalette.dark().color()
thumbText = nwUnicode.U_CROSS
trackBrush = palette.dark()
thumbBrush = palette.light()
if self.isEnabled():
trackOpacity = 1.0
else:
trackOpacity = 0.6
trackBrush = qPalette.shadow()
thumbBrush = qPalette.mid()
textColor = qPalette.shadow().color()
trackBrush = palette.shadow()
thumbBrush = palette.mid()
qPaint.setBrush(trackBrush)
qPaint.setOpacity(trackOpacity)
qPaint.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
painter.setBrush(trackBrush)
painter.setOpacity(trackOpacity)
painter.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
qPaint.setBrush(thumbBrush)
qPaint.drawEllipse(self._offset - self._rR, self._rB, self._rH, self._rH)
font = qPaint.font()
font.setPixelSize(self._xT)
qPaint.setPen(textColor)
qPaint.setFont(font)
qPaint.drawText(
QRectF(self._offset - self._rR, self._rB, self._rH, self._rH),
Qt.AlignCenter, thumbText
)
painter.setBrush(thumbBrush)
painter.drawEllipse(self._offset - self._rR, self._rB, self._rH, self._rH)
return
@@ -149,14 +120,11 @@ class NSwitch(QAbstractButton):
"""Animate the switch on mouse release."""
super().mouseReleaseEvent(event)
if event.button() == Qt.LeftButton:
doAnim = QPropertyAnimation(self, b"offset", self)
doAnim.setDuration(120)
doAnim.setStartValue(self._offset)
if self.isChecked():
doAnim.setEndValue(self._xW - self._xR)
else:
doAnim.setEndValue(self._xR)
doAnim.start()
anim = QPropertyAnimation(self, b"offset", self)
anim.setDuration(120)
anim.setStartValue(self._offset)
anim.setEndValue((self._xW - self._xR) if self.isChecked() else self._xR)
anim.start()
return
def enterEvent(self, event: QEvent) -> None:
+11 -15
View File
@@ -187,13 +187,12 @@ class GuiDocEditor(QPlainTextEdit):
# Set Up Document Word Counter
self.wcTimerDoc = QTimer()
self.wcTimerDoc.timeout.connect(self._runDocCounter)
self.wcTimerDoc.setInterval(5000)
self.wCounterDoc = BackgroundWordCounter(self)
self.wCounterDoc.setAutoDelete(False)
self.wCounterDoc.signals.countsReady.connect(self._updateDocCounts)
self.wcInterval = CONFIG.wordCountTimer
# Set Up Selection Word Counter
self.wcTimerSel = QTimer()
self.wcTimerSel.timeout.connect(self._runSelCounter)
@@ -320,10 +319,10 @@ class GuiDocEditor(QPlainTextEdit):
SHARED.updateSpellCheckLanguage()
# Set font
textFont = QFont()
textFont.setFamily(CONFIG.textFont)
textFont.setPointSize(CONFIG.textSize)
self.setFont(textFont)
font = QFont()
font.setFamily(CONFIG.textFont)
font.setPointSize(CONFIG.textSize)
self.setFont(font)
# Set default text margins
# Due to cursor visibility, a part of the margin must be
@@ -359,17 +358,14 @@ class GuiDocEditor(QPlainTextEdit):
# Refresh the tab stops
self.setTabStopDistance(CONFIG.getTabWidth())
# Configure word count timer
self.wcInterval = CONFIG.wordCountTimer
self.wcTimerDoc.setInterval(int(self.wcInterval*1000))
# If we have a document open, we should reload it in case the
# If we have a document open, we should refresh it in case the
# font changed, otherwise we just clear the editor entirely,
# which makes it read only.
if self._docHandle is None:
self.clearEditor()
else:
if self._docHandle:
self._qDocument.syntaxHighlighter.rehighlight()
self.docHeader.setTitleFromHandle(self._docHandle)
else:
self.clearEditor()
return
@@ -1190,7 +1186,7 @@ class GuiDocEditor(QPlainTextEdit):
logger.debug("Word counter is busy")
return
if time() - self._lastEdit < 5.0 * self.wcInterval:
if time() - self._lastEdit < 25.0:
logger.debug("Running word counter")
SHARED.runInThreadPool(self.wCounterDoc)
+7 -7
View File
@@ -142,10 +142,10 @@ class GuiDocViewer(QTextBrowser):
self._makeStyleSheet()
# Set Font
textFont = QFont()
textFont.setFamily(CONFIG.textFont)
textFont.setPointSize(CONFIG.textSize)
self.setFont(textFont)
font = QFont()
font.setFamily(CONFIG.textFont)
font.setPointSize(CONFIG.textSize)
self.setFont(font)
# Set the widget colours to match syntax theme
mainPalette = self.palette()
@@ -164,10 +164,10 @@ class GuiDocViewer(QTextBrowser):
# Set default text margins
self.document().setDocumentMargin(0)
theOpt = QTextOption()
options = QTextOption()
if CONFIG.doJustify:
theOpt.setAlignment(Qt.AlignmentFlag.AlignJustify)
self.document().setDefaultTextOption(theOpt)
options.setAlignment(Qt.AlignmentFlag.AlignJustify)
self.document().setDefaultTextOption(options)
# Scroll bars
if CONFIG.hideVScroll:
+1 -1
View File
@@ -466,7 +466,7 @@ class GuiIcons:
# General Button Icons
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "cross",
"document", "down", "edit", "export", "forward", "maximise", "menu", "minimise",
"document", "down", "edit", "export", "forward", "maximise", "menu", "minimise", "more",
"noncheckable", "panel", "refresh", "remove", "revert", "search_replace", "search",
"settings", "star", "unchecked", "up", "view",
@@ -57,7 +57,6 @@ spellcheck = en
showtabsnspaces = False
showlineendings = False
showmultispaces = True
wordcounttimer = 5.0
incnoteswcount = True
showfullpath = True
highlightquotes = True
@@ -1,82 +0,0 @@
[Meta]
timestamp = 2023-12-29 14:09:13
[Main]
theme = default
syntax = default_light
font = Cantarell
fontsize = 12
localisation = en_GB
hidevscroll = True
hidehscroll = True
lastnotes = 0x0
lastpath =
[Sizes]
mainwindow = 1200, 650
welcome = 800, 500
preferences = 713, 614
mainpane = 300, 800
viewpane = 500, 150
outlinepane = 500, 150
[Project]
autosaveproject = 40
autosavedoc = 20
emphlabels = True
backuppath = some/dir
backuponclose = True
askbeforebackup = True
[Editor]
textfont = None
textsize = 13
width = 700
margin = 45
tabwidth = 45
focuswidth = 900
hidefocusfooter = True
justify = True
autoselect = False
autoreplace = False
repsquotes = True
repdquotes = True
repdash = True
repdots = True
autoscroll = True
autoscrollpos = 30
scrollpastend = True
fmtsquoteopen =
fmtsquoteclose =
fmtdquoteopen = “
fmtdquoteclose = ”
fmtpadbefore =
fmtpadafter =
fmtpadthin = False
spellcheck = en
showtabsnspaces = True
showlineendings = True
showmultispaces = True
wordcounttimer = 5.0
incnoteswcount = True
showfullpath = False
highlightquotes = False
allowopensquote = False
allowopendquote = True
highlightemph = False
stopwhenidle = True
useridletime = 300
[State]
showviewerpanel = True
showedittoolbar = False
useshortcodes = False
viewcomments = True
viewsynopsis = True
searchcase = False
searchword = False
searchregex = False
searchloop = False
searchnextfile = False
searchmatchcap = False
+14 -3
View File
@@ -31,8 +31,10 @@ from novelwriter.dialogs.editlabel import GuiEditLabel
@pytest.mark.gui
def testDlgOther_QuoteSelect(qtbot, nwGUI):
def testDlgOther_QuoteSelect(qtbot, monkeypatch, nwGUI):
"""Test the quote symbols dialog."""
monkeypatch.setattr(GuiQuoteSelect, "exec_", lambda *a: None)
nwQuot = GuiQuoteSelect(nwGUI)
nwQuot.show()
@@ -41,16 +43,25 @@ def testDlgOther_QuoteSelect(qtbot, nwGUI):
anItem = nwQuot.listBox.item(i)
assert isinstance(anItem, QListWidgetItem)
nwQuot.listBox.clearSelection()
nwQuot.listBox.setCurrentItem(anItem, QItemSelectionModel.Select)
nwQuot.listBox.setCurrentItem(anItem, QItemSelectionModel.SelectionFlag.Select)
lastItem = anItem.text()[2]
assert nwQuot.previewLabel.text() == lastItem
nwQuot.accept()
assert nwQuot.result() == QDialog.Accepted
assert nwQuot.selectedQuote == lastItem
nwQuot.close()
# Test Class Method
with monkeypatch.context() as mp:
mp.setattr(GuiQuoteSelect, "result", lambda *a: QDialog.DialogCode.Accepted)
assert GuiQuoteSelect.getQuote(nwGUI, current="X") == ("X", True)
with monkeypatch.context() as mp:
mp.setattr(GuiQuoteSelect, "result", lambda *a: QDialog.DialogCode.Rejected)
assert GuiQuoteSelect.getQuote(nwGUI, current="X") == ("X", False)
# qtbot.stop()
nwQuot.close()
# END Test testDlgOther_QuoteSelect
+363 -165
View File
@@ -22,191 +22,389 @@ from __future__ import annotations
import pytest
from shutil import copyfile
from tools import cmpFiles, getGuiItem
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog
)
from PyQt5.QtGui import QFontDatabase, QKeyEvent
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtWidgets import QDialogButtonBox, QFileDialog, QFontDialog
from novelwriter import CONFIG, SHARED
from novelwriter.dialogs.quotes import GuiQuoteSelect
from novelwriter.constants import nwConst, nwUnicode
from novelwriter.dialogs.preferences import GuiPreferences
from novelwriter.dialogs.quotes import GuiQuoteSelect
KEY_DELAY = 1
@pytest.mark.gui
def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
"""Test the preferences dialog."""
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
"""Test the preferences dialog loading."""
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
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()
# Load GUI with standard values
prefs = GuiPreferences(nwGUI)
prefs.show()
# General Settings
qtbot.wait(KEY_DELAY)
tabGeneral = nwPrefs.tabGeneral
nwPrefs._tabBox.setCurrentWidget(tabGeneral)
# Check Languages
languages = [prefs.guiLocale.itemData(i) for i in range(prefs.guiLocale.count())]
assert len(languages) > 0
assert "en_GB" in languages
qtbot.wait(KEY_DELAY)
assert tabGeneral.showFullPath.isChecked()
qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton)
assert not tabGeneral.showFullPath.isChecked()
# Check GUI Themes
themes = [prefs.guiTheme.itemData(i) for i in range(prefs.guiTheme.count())]
assert len(themes) >= 5
assert "default" in themes
qtbot.wait(KEY_DELAY)
assert not tabGeneral.hideVScroll.isChecked()
qtbot.mouseClick(tabGeneral.hideVScroll, Qt.LeftButton)
assert tabGeneral.hideVScroll.isChecked()
# Check GUI Syntax
syntax = [prefs.guiSyntax.itemData(i) for i in range(prefs.guiSyntax.count())]
assert len(syntax) >= 10
assert "default_dark" in syntax
assert "default_light" in syntax
qtbot.wait(KEY_DELAY)
assert not tabGeneral.hideHScroll.isChecked()
qtbot.mouseClick(tabGeneral.hideHScroll, Qt.LeftButton)
assert tabGeneral.hideHScroll.isChecked()
# Check Spell Checking
spelling = [prefs.spellLanguage.itemData(i) for i in range(prefs.spellLanguage.count())]
assert len(spelling) == 1
assert spelling == ["en"]
# Check font button
monkeypatch.setattr(QFontDialog, "getFont", lambda font, obj: (font, True))
qtbot.mouseClick(tabGeneral.fontButton, Qt.LeftButton)
prefs.close()
qtbot.wait(KEY_DELAY)
tabGeneral.guiFontSize.setValue(12)
# Check Fallback Values
with monkeypatch.context() as mp:
mp.setattr(CONFIG, "hasEnchant", False)
prefs = GuiPreferences(nwGUI)
prefs.show()
# Projects Settings
qtbot.wait(KEY_DELAY)
tabProjects = nwPrefs.tabProjects
nwPrefs._tabBox.setCurrentWidget(tabProjects)
tabProjects.backupPath = "no/where"
# Check Spell Checking
spelling = [prefs.spellLanguage.itemData(i) for i in range(prefs.spellLanguage.count())]
assert len(spelling) == 1
assert spelling == [""]
qtbot.wait(KEY_DELAY)
assert not tabProjects.backupOnClose.isChecked()
qtbot.mouseClick(tabProjects.backupOnClose, Qt.LeftButton)
assert tabProjects.backupOnClose.isChecked()
# Check Browse button
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "")
assert not tabProjects._backupFolder()
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "some/dir")
qtbot.mouseClick(tabProjects.backupGetPath, Qt.LeftButton)
qtbot.wait(KEY_DELAY)
tabProjects.autoSaveDoc.setValue(20)
tabProjects.autoSaveProj.setValue(40)
# Document Settings
qtbot.wait(KEY_DELAY)
tabDocs = nwPrefs.tabDocs
nwPrefs._tabBox.setCurrentWidget(tabDocs)
qtbot.wait(KEY_DELAY)
qtbot.mouseClick(tabDocs.fontButton, Qt.LeftButton)
qtbot.wait(KEY_DELAY)
tabDocs.textSize.setValue(13)
tabDocs.textWidth.setValue(700)
tabDocs.focusWidth.setValue(900)
tabDocs.textMargin.setValue(45)
tabDocs.tabWidth.setValue(45)
qtbot.wait(KEY_DELAY)
assert not tabDocs.hideFocusFooter.isChecked()
qtbot.mouseClick(tabDocs.hideFocusFooter, Qt.LeftButton)
assert tabDocs.hideFocusFooter.isChecked()
qtbot.wait(KEY_DELAY)
assert not tabDocs.doJustify.isChecked()
qtbot.mouseClick(tabDocs.doJustify, Qt.LeftButton)
assert tabDocs.doJustify.isChecked()
# Editor Settings
qtbot.wait(KEY_DELAY)
tabEditor = nwPrefs.tabEditor
nwPrefs._tabBox.setCurrentWidget(tabEditor)
qtbot.wait(KEY_DELAY)
assert not tabEditor.showTabsNSpaces.isChecked()
qtbot.mouseClick(tabEditor.showTabsNSpaces, Qt.LeftButton)
assert tabEditor.showTabsNSpaces.isChecked()
qtbot.wait(KEY_DELAY)
assert not tabEditor.showLineEndings.isChecked()
qtbot.mouseClick(tabEditor.showLineEndings, Qt.LeftButton)
assert tabEditor.showLineEndings.isChecked()
qtbot.wait(KEY_DELAY)
assert not tabEditor.autoScroll.isChecked()
qtbot.mouseClick(tabEditor.autoScroll, Qt.LeftButton)
assert tabEditor.autoScroll.isChecked()
# Syntax Settings
qtbot.wait(KEY_DELAY)
tabSyntax = nwPrefs.tabSyntax
nwPrefs._tabBox.setCurrentWidget(tabSyntax)
qtbot.wait(KEY_DELAY)
assert tabSyntax.highlightQuotes.isChecked()
qtbot.mouseClick(tabSyntax.highlightQuotes, Qt.LeftButton)
assert not tabSyntax.highlightQuotes.isChecked()
qtbot.wait(KEY_DELAY)
assert tabSyntax.highlightEmph.isChecked()
qtbot.mouseClick(tabSyntax.highlightEmph, Qt.LeftButton)
assert not tabSyntax.highlightEmph.isChecked()
# Automation Settings
qtbot.wait(KEY_DELAY)
tabAuto = nwPrefs.tabAuto
nwPrefs._tabBox.setCurrentWidget(tabAuto)
qtbot.wait(KEY_DELAY)
assert tabAuto.autoSelect.isChecked()
qtbot.mouseClick(tabAuto.autoSelect, Qt.LeftButton)
assert not tabAuto.autoSelect.isChecked()
qtbot.wait(KEY_DELAY)
assert tabAuto.doReplace.isChecked()
qtbot.mouseClick(tabAuto.doReplace, Qt.LeftButton)
assert not tabAuto.doReplace.isChecked()
qtbot.wait(KEY_DELAY)
assert not tabAuto.doReplaceSQuote.isEnabled()
assert not tabAuto.doReplaceDQuote.isEnabled()
assert not tabAuto.doReplaceDash.isEnabled()
assert not tabAuto.doReplaceDots.isEnabled()
# Quotation Style
qtbot.wait(KEY_DELAY)
tabQuote = nwPrefs.tabQuote
nwPrefs._tabBox.setCurrentWidget(tabQuote)
monkeypatch.setattr(GuiQuoteSelect, "selectedQuote", "'")
monkeypatch.setattr(GuiQuoteSelect, "exec_", lambda *a: QDialog.Accepted)
qtbot.mouseClick(tabQuote.btnDoubleStyleC, Qt.LeftButton)
# Save and Check Config
qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton)
assert CONFIG.saveConfig()
projFile = tstPaths.cnfDir / "novelwriter.conf"
testFile = tstPaths.outDir / "guiPreferences_novelwriter.conf"
compFile = tstPaths.refDir / "guiPreferences_novelwriter.conf"
copyfile(projFile, testFile)
ignTuple = (
"timestamp", "font", "lastnotes", "localisation", "geometry",
"preferences", "projcols", "mainpane", "docpane", "viewpane",
"outlinepane", "textfont", "textsize", "lastpath", "backuppath"
)
assert cmpFiles(testFile, compFile, ignoreStart=ignTuple)
# Clean up
nwGUI.closeMain()
prefs.close()
# qtbot.stop()
# END Test testDlgPreferences_Main
@pytest.mark.gui
def testDlgPreferences_Actions(qtbot, monkeypatch, nwGUI):
"""Test the preferences dialog actions."""
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
monkeypatch.setattr(GuiPreferences, "deleteLater", lambda *a: None)
prefs = GuiPreferences(nwGUI)
prefs.show()
# Check Navigation
vBar = prefs.mainForm.verticalScrollBar()
old = -1
with qtbot.waitSignal(vBar.valueChanged) as value:
prefs.sidebar.button(0).click()
assert value.args[0] > old
old = value.args[0]
with qtbot.waitSignal(vBar.valueChanged) as value:
prefs.sidebar.button(1).click()
assert value.args[0] > old
old = value.args[0]
with qtbot.waitSignal(vBar.valueChanged) as value:
prefs.sidebar.button(2).click()
assert value.args[0] > old
old = value.args[0]
# Check Search
prefs.searchText.setText("Display language")
with qtbot.waitSignal(vBar.valueChanged) as value:
prefs._gotoSearch()
assert value.args[0] < old
# Check Apply Button
prefs.show()
with qtbot.waitSignal(prefs.newPreferencesReady) as signal:
prefs.buttonBox.button(QDialogButtonBox.StandardButton.Apply).click()
assert signal.args == [False, False, False, False]
# Check Save Button
prefs.show()
with qtbot.waitSignal(prefs.newPreferencesReady) as signal:
with qtbot.waitSignal(prefs.finished) as status:
prefs.buttonBox.button(QDialogButtonBox.StandardButton.Save).click()
assert signal.args == [False, False, False, False]
assert status.args == [nwConst.DLG_FINISHED]
# Check Close Button
prefs.show()
with qtbot.waitSignal(prefs.finished) as status:
prefs.buttonBox.button(QDialogButtonBox.StandardButton.Close).click()
assert status.args == [nwConst.DLG_FINISHED]
# Close Using Escape Key
prefs.show()
with qtbot.waitSignal(prefs.finished) as status:
event = QKeyEvent(QEvent.Type.KeyPress, Qt.Key.Key_Escape, Qt.KeyboardModifier.NoModifier)
prefs.keyPressEvent(event)
assert status.args == [nwConst.DLG_FINISHED]
# qtbot.stop()
# END Test testDlgPreferences_Actions
@pytest.mark.gui
def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, tstPaths):
"""Test the preferences dialog settings."""
spelling = [("en", "English [en]"), ("de", "Deutch [de]")]
languages = [("en_GB", "British English"), ("en_US", "US English")]
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: spelling)
monkeypatch.setattr(CONFIG, "listLanguages", lambda *a: languages)
monkeypatch.setattr(GuiPreferences, "deleteLater", lambda *a: None)
prefs = GuiPreferences(nwGUI)
prefs.show()
# Mock Font
class MockFont:
def family(self):
return "TestFont"
def pointSize(self):
return 42
# Appearance
prefs.guiLocale.setCurrentIndex(prefs.guiLocale.findData("en_US"))
prefs.guiTheme.setCurrentIndex(prefs.guiTheme.findData("default_dark"))
with monkeypatch.context() as mp:
mp.setattr(QFontDialog, "getFont", lambda *a: (MockFont(), True))
prefs.guiFontButton.click()
prefs.guiFontSize.stepDown() # Should change it to 41
prefs.hideVScroll.setChecked(True)
prefs.hideHScroll.setChecked(True)
assert CONFIG.guiLocale != "en_US"
assert CONFIG.guiTheme != "default_dark"
assert CONFIG.guiFont != "TestFont"
assert CONFIG.guiFontSize < 42
assert CONFIG.hideVScroll is False
assert CONFIG.hideHScroll is False
# Document Style
prefs.guiSyntax.setCurrentIndex(prefs.guiSyntax.findData("default_dark"))
with monkeypatch.context() as mp:
mp.setattr(QFontDialog, "getFont", lambda *a: (MockFont(), True))
prefs.textFontButton.click()
prefs.textSize.stepDown() # Should change it to 41
prefs.emphLabels.setChecked(False)
prefs.showFullPath.setChecked(False)
prefs.incNotesWCount.setChecked(False)
assert CONFIG.guiSyntax != "default_dark"
assert CONFIG.textFont != "testFont"
assert CONFIG.textSize < 42
assert CONFIG.emphLabels is True
assert CONFIG.showFullPath is True
assert CONFIG.incNotesWCount is True
# Auto Save
prefs.autoSaveDoc.stepUp()
prefs.autoSaveProj.stepUp()
assert CONFIG.autoSaveDoc == 30
assert CONFIG.autoSaveProj == 60
# Project Backup
with monkeypatch.context() as mp:
mp.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: str(tstPaths.testDir))
prefs.backupGetPath.click()
assert prefs.backupPath == str(tstPaths.testDir)
prefs.backupOnClose.setChecked(True)
assert prefs.askBeforeBackup.isEnabled() is True
prefs.askBeforeBackup.setChecked(False)
assert CONFIG._backupPath != tstPaths.testDir
assert CONFIG.backupOnClose is False
assert CONFIG.askBeforeBackup is True
# Session Timer
prefs.stopWhenIdle.setChecked(False)
prefs.userIdleTime.stepUp()
assert CONFIG.stopWhenIdle is True
assert CONFIG.userIdleTime == 300
# Text Flow
prefs.textWidth.stepDown()
prefs.focusWidth.stepDown()
prefs.hideFocusFooter.setChecked(True)
prefs.doJustify.setChecked(True)
prefs.textMargin.stepUp()
prefs.tabWidth.stepUp()
assert CONFIG.textWidth == 700
assert CONFIG.focusWidth == 800
assert CONFIG.hideFocusFooter is False
assert CONFIG.doJustify is False
assert CONFIG.textMargin == 40
assert CONFIG.tabWidth == 40
# Text Editing
prefs.spellLanguage.setCurrentIndex(prefs.spellLanguage.findData("de"))
prefs.autoSelect.setChecked(False)
prefs.showTabsNSpaces.setChecked(True)
prefs.showLineEndings.setChecked(True)
assert CONFIG.spellLanguage != "de"
assert CONFIG.autoSelect is True
assert CONFIG.showTabsNSpaces is False
assert CONFIG.showLineEndings is False
# Editor Scrolling
prefs.scrollPastEnd.setChecked(False)
prefs.autoScroll.setChecked(True)
prefs.autoScrollPos.stepUp()
assert CONFIG.scrollPastEnd is True
assert CONFIG.autoScroll is False
assert CONFIG.autoScrollPos == 30
# Text Highlighting
prefs.allowOpenSQuote.setChecked(True)
prefs.allowOpenDQuote.setChecked(False)
prefs.highlightQuotes.setChecked(False)
prefs.highlightEmph.setChecked(False)
prefs.showMultiSpaces.setChecked(False)
assert prefs.allowOpenSQuote.isEnabled() is False
assert prefs.allowOpenDQuote.isEnabled() is False
assert CONFIG.highlightQuotes is True
assert CONFIG.allowOpenSQuote is False
assert CONFIG.allowOpenDQuote is True
assert CONFIG.highlightEmph is True
assert CONFIG.showMultiSpaces is True
# Text Automation
prefs.doReplaceSQuote.setChecked(False)
prefs.doReplaceDQuote.setChecked(False)
prefs.doReplaceDash.setChecked(False)
prefs.doReplaceDots.setChecked(False)
prefs.doReplace.setChecked(False)
prefs.fmtPadBefore.setText("!?:")
prefs.fmtPadAfter.setText("¡¿")
prefs.fmtPadThin.setChecked(True)
assert prefs.doReplaceSQuote.isEnabled() is False
assert prefs.doReplaceDQuote.isEnabled() is False
assert prefs.doReplaceDash.isEnabled() is False
assert prefs.doReplaceDots.isEnabled() is False
assert prefs.fmtPadThin.isEnabled() is False
assert CONFIG.doReplace is True
assert CONFIG.doReplaceSQuote is True
assert CONFIG.doReplaceDQuote is True
assert CONFIG.doReplaceDash is True
assert CONFIG.doReplaceDots is True
assert CONFIG.fmtPadBefore == ""
assert CONFIG.fmtPadAfter == ""
assert CONFIG.fmtPadThin is False
# Quotation Style
with monkeypatch.context() as mp:
mp.setattr(GuiQuoteSelect, "getQuote", lambda *a, **k: (nwUnicode.U_LSAQUO, True))
prefs.btnSingleStyleO.click()
with monkeypatch.context() as mp:
mp.setattr(GuiQuoteSelect, "getQuote", lambda *a, **k: (nwUnicode.U_RSAQUO, True))
prefs.btnSingleStyleC.click()
with monkeypatch.context() as mp:
mp.setattr(GuiQuoteSelect, "getQuote", lambda *a, **k: (nwUnicode.U_LAQUO, True))
prefs.btnDoubleStyleO.click()
with monkeypatch.context() as mp:
mp.setattr(GuiQuoteSelect, "getQuote", lambda *a, **k: (nwUnicode.U_RAQUO, True))
prefs.btnDoubleStyleC.click()
assert CONFIG.fmtSQuoteOpen == nwUnicode.U_LSQUO
assert CONFIG.fmtSQuoteClose == nwUnicode.U_RSQUO
assert CONFIG.fmtDQuoteOpen == nwUnicode.U_LDQUO
assert CONFIG.fmtDQuoteClose == nwUnicode.U_RDQUO
# Save Settings
with monkeypatch.context() as mp:
mp.setattr(QFontDatabase, "families", lambda *a: ["TestFont"])
with qtbot.waitSignal(prefs.newPreferencesReady) as signal:
prefs.buttonBox.button(QDialogButtonBox.StandardButton.Apply).click()
assert signal.args == [True, True, True, True]
# Check Settings
# ==============
# Appearance
assert CONFIG.guiLocale == "en_US"
assert CONFIG.guiTheme == "default_dark"
assert CONFIG.guiFont == "TestFont"
assert CONFIG.guiFontSize == 41
assert CONFIG.hideVScroll is True
assert CONFIG.hideHScroll is True
# Document Style
assert CONFIG.guiSyntax == "default_dark"
assert CONFIG.textFont == "TestFont"
assert CONFIG.textSize == 41
assert CONFIG.emphLabels is False
assert CONFIG.showFullPath is False
assert CONFIG.incNotesWCount is False
# Auto Save
assert CONFIG.autoSaveDoc == 31
assert CONFIG.autoSaveProj == 61
# Project Backup
assert CONFIG._backupPath == tstPaths.testDir
assert CONFIG.backupOnClose is True
assert CONFIG.askBeforeBackup is False
# Session Timer
assert CONFIG.stopWhenIdle is False
assert CONFIG.userIdleTime == 330
# Text Flow
assert CONFIG.textWidth == 690
assert CONFIG.focusWidth == 790
assert CONFIG.hideFocusFooter is True
assert CONFIG.doJustify is True
assert CONFIG.textMargin == 41
assert CONFIG.tabWidth == 41
# Text Editing
assert CONFIG.spellLanguage == "de"
assert CONFIG.autoSelect is False
assert CONFIG.showTabsNSpaces is True
assert CONFIG.showLineEndings is True
# Editor Scrolling
assert CONFIG.scrollPastEnd is False
assert CONFIG.autoScroll is True
assert CONFIG.autoScrollPos == 31
# Text Highlighting
assert CONFIG.highlightQuotes is False
assert CONFIG.allowOpenSQuote is True
assert CONFIG.allowOpenDQuote is False
assert CONFIG.highlightEmph is False
assert CONFIG.showMultiSpaces is False
# Text Automation
assert CONFIG.doReplace is False
assert CONFIG.doReplaceSQuote is False
assert CONFIG.doReplaceDQuote is False
assert CONFIG.doReplaceDash is False
assert CONFIG.doReplaceDots is False
assert CONFIG.fmtPadBefore == "!?:"
assert CONFIG.fmtPadAfter == "¡¿"
assert CONFIG.fmtPadThin is True
# Quotation Style
assert CONFIG.fmtSQuoteOpen == nwUnicode.U_LSAQUO
assert CONFIG.fmtSQuoteClose == nwUnicode.U_RSAQUO
assert CONFIG.fmtDQuoteOpen == nwUnicode.U_LAQUO
assert CONFIG.fmtDQuoteClose == nwUnicode.U_RAQUO
# qtbot.stop()
# END Test testDlgPreferences_Settings