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 maximise = typ_arrow-maximise.svg
menu = typ_th-dot-menu.svg menu = typ_th-dot-menu.svg
minimise = typ_arrow-minimise.svg minimise = typ_arrow-minimise.svg
more = typ_th-dot-more.svg
noncheckable = mixed_input-none.svg noncheckable = mixed_input-none.svg
panel = nw_panel.svg panel = nw_panel.svg
proj_chapter = mixed_document-chapter.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 maximise = typ_arrow-maximise.svg
menu = typ_th-dot-menu.svg menu = typ_th-dot-menu.svg
minimise = typ_arrow-minimise.svg minimise = typ_arrow-minimise.svg
more = typ_th-dot-more.svg
noncheckable = mixed_input-none.svg noncheckable = mixed_input-none.svg
panel = nw_panel.svg panel = nw_panel.svg
proj_chapter = mixed_document-chapter.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.autoScrollPos = 30 # Start point for typewriter-like scrolling
self.scrollPastEnd = True # Scroll past end of document, and centre cursor 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.highlightQuotes = True # Highlight text in quotes
self.allowOpenSQuote = False # Allow open-ended single quotes self.allowOpenSQuote = False # Allow open-ended single quotes
self.allowOpenDQuote = True # Allow open-ended double 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.stopWhenIdle = True # Stop the status bar clock when the user is idle
self.userIdleTime = 300 # Time of inactivity to consider user 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 # User-Selected Symbol Settings
self.fmtApostrophe = nwUnicode.U_RSQUO self.fmtApostrophe = nwUnicode.U_RSQUO
@@ -591,7 +589,6 @@ class Config:
self.showTabsNSpaces = conf.rdBool(sec, "showtabsnspaces", self.showTabsNSpaces) self.showTabsNSpaces = conf.rdBool(sec, "showtabsnspaces", self.showTabsNSpaces)
self.showLineEndings = conf.rdBool(sec, "showlineendings", self.showLineEndings) self.showLineEndings = conf.rdBool(sec, "showlineendings", self.showLineEndings)
self.showMultiSpaces = conf.rdBool(sec, "showmultispaces", self.showMultiSpaces) 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.incNotesWCount = conf.rdBool(sec, "incnoteswcount", self.incNotesWCount)
self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath) self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
self.highlightQuotes = conf.rdBool(sec, "highlightquotes", self.highlightQuotes) self.highlightQuotes = conf.rdBool(sec, "highlightquotes", self.highlightQuotes)
@@ -698,7 +695,6 @@ class Config:
"showtabsnspaces": str(self.showTabsNSpaces), "showtabsnspaces": str(self.showTabsNSpaces),
"showlineendings": str(self.showLineEndings), "showlineendings": str(self.showLineEndings),
"showmultispaces": str(self.showMultiSpaces), "showmultispaces": str(self.showMultiSpaces),
"wordcounttimer": str(self.wordCountTimer),
"incnoteswcount": str(self.incNotesWCount), "incnoteswcount": str(self.incNotesWCount),
"showfullpath": str(self.showFullPath), "showfullpath": str(self.showFullPath),
"highlightquotes": str(self.highlightQuotes), "highlightquotes": str(self.highlightQuotes),
+3
View File
@@ -56,6 +56,9 @@ class nwConst:
# Gui Settings # Gui Settings
STATUS_MSG_TIMEOUT = 15000 # milliseconds STATUS_MSG_TIMEOUT = 15000 # milliseconds
# Dialogs
DLG_FINISHED = 2
# END Class nwConst # 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 import logging
from PyQt5.QtGui import QCloseEvent, QFontMetrics from PyQt5.QtGui import QFontMetrics
from PyQt5.QtCore import QSize, Qt, pyqtSlot from PyQt5.QtCore import QSize, Qt, pyqtSlot
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QDialogButtonBox, QFrame, QHBoxLayout, QLabel, QListWidget, QDialog, QDialogButtonBox, QFrame, QHBoxLayout, QLabel, QListWidget,
@@ -40,11 +40,11 @@ logger = logging.getLogger(__name__)
class GuiQuoteSelect(QDialog): class GuiQuoteSelect(QDialog):
selectedQuote = "" _selected = ""
D_KEY = Qt.ItemDataRole.UserRole 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) super().__init__(parent=parent)
logger.debug("Create: GuiQuoteSelect") logger.debug("Create: GuiQuoteSelect")
@@ -54,7 +54,7 @@ class GuiQuoteSelect(QDialog):
self.innerBox = QHBoxLayout() self.innerBox = QHBoxLayout()
self.labelBox = QVBoxLayout() self.labelBox = QVBoxLayout()
self.selectedQuote = currentQuote self._selected = current
qMetrics = QFontMetrics(self.font()) qMetrics = QFontMetrics(self.font())
pxW = 7*qMetrics.boundingRectChar("M").width() pxW = 7*qMetrics.boundingRectChar("M").width()
@@ -65,7 +65,7 @@ class GuiQuoteSelect(QDialog):
lblFont.setPointSizeF(4*lblFont.pointSizeF()) lblFont.setPointSizeF(4*lblFont.pointSizeF())
# Preview Label # Preview Label
self.previewLabel = QLabel(currentQuote) self.previewLabel = QLabel(current)
self.previewLabel.setFont(lblFont) self.previewLabel.setFont(lblFont)
self.previewLabel.setFixedSize(QSize(pxW, pxH)) self.previewLabel.setFixedSize(QSize(pxW, pxH))
self.previewLabel.setAlignment(Qt.AlignCenter) self.previewLabel.setAlignment(Qt.AlignCenter)
@@ -82,7 +82,7 @@ class GuiQuoteSelect(QDialog):
qtItem = QListWidgetItem(theText) qtItem = QListWidgetItem(theText)
qtItem.setData(self.D_KEY, sKey) qtItem.setData(self.D_KEY, sKey)
self.listBox.addItem(qtItem) self.listBox.addItem(qtItem)
if sKey == currentQuote: if sKey == current:
self.listBox.setCurrentItem(qtItem) self.listBox.setCurrentItem(qtItem)
self.listBox.setMinimumWidth(minSize + CONFIG.pxInt(40)) self.listBox.setMinimumWidth(minSize + CONFIG.pxInt(40))
@@ -113,15 +113,20 @@ class GuiQuoteSelect(QDialog):
logger.debug("Delete: GuiQuoteSelect") logger.debug("Delete: GuiQuoteSelect")
return return
## @property
# Events def selectedQuote(self) -> str:
## """Return the selected quote symbol."""
return self._selected
def closeEvent(self, event: QCloseEvent) -> None: @classmethod
"""Capture the close event and perform cleanup.""" def getQuote(cls, parent: QWidget, current: str = "") -> tuple[str, bool]:
event.accept() """Pop the dialog and return the result."""
self.deleteLater() cls = GuiQuoteSelect(parent, current=current)
return cls.exec_()
quote = cls._selected
accepted = cls.result() == QDialog.DialogCode.Accepted
cls.deleteLater()
return quote, accepted
## ##
# Private Slots # Private Slots
@@ -130,11 +135,10 @@ class GuiQuoteSelect(QDialog):
@pyqtSlot() @pyqtSlot()
def _selectedSymbol(self) -> None: def _selectedSymbol(self) -> None:
"""Update the preview label and the selected quote style.""" """Update the preview label and the selected quote style."""
selItems = self.listBox.selectedItems() if items := self.listBox.selectedItems():
if selItems: quote = items[0].data(self.D_KEY)
theSymbol = selItems[0].data(self.D_KEY) self.previewLabel.setText(quote)
self.previewLabel.setText(theSymbol) self._selected = quote
self.selectedQuote = theSymbol
return return
# END Class GuiQuoteSelect # END Class GuiQuoteSelect
+133 -5
View File
@@ -3,7 +3,9 @@ novelWriter Custom Widget: Config Layout
========================================== ==========================================
File History: 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 This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen Copyright 20182024, Veronica Berglyd Olsen
@@ -26,7 +28,7 @@ from __future__ import annotations
from PyQt5.QtGui import QColor, QPalette from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractButton, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QSizePolicy, QAbstractButton, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QScrollArea, QSizePolicy,
QVBoxLayout, QWidget QVBoxLayout, QWidget
) )
@@ -37,6 +39,133 @@ RIGHT_TOP = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
LEFT_TOP = Qt.AlignmentFlag.AlignLeft | 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): class NConfigLayout(QGridLayout):
def __init__(self) -> None: def __init__(self) -> None:
@@ -58,11 +187,10 @@ class NConfigLayout(QGridLayout):
# Getters and Setters # Getters and Setters
## ##
def setHelpTextStyle(self, color: QColor | list | tuple, def setHelpTextStyle(self, color: QColor | list | tuple, scale: float = FONT_SCALE) -> None:
fontScale: float = FONT_SCALE) -> None:
"""Set the text color for the help text.""" """Set the text color for the help text."""
self._helpCol = color if isinstance(color, QColor) else QColor(*color) self._helpCol = color if isinstance(color, QColor) else QColor(*color)
self._fontScale = fontScale self._fontScale = scale
return return
def setHelpText(self, row: int, text: str) -> None: 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 __future__ import annotations
from PyQt5.QtGui import QColor, QPaintEvent, QPainter, QPolygon 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 ( from PyQt5.QtWidgets import (
QAbstractButton, QAction, QButtonGroup, QLabel, QSizePolicy, QStyle, QAbstractButton, QAction, QButtonGroup, QLabel, QSizePolicy, QStyle,
QStyleOptionToolButton, QToolBar, QToolButton, QWidget QStyleOptionToolButton, QToolBar, QToolButton, QWidget
@@ -63,6 +63,10 @@ class NPagedSideBar(QToolBar):
return return
def button(self, buttonId: int) -> _NPagedToolButton:
"""Return a specific button."""
return self._buttons[buttonId]
def setLabelColor(self, color: list | QColor) -> None: def setLabelColor(self, color: list | QColor) -> None:
"""Set the text color for the labels.""" """Set the text color for the labels."""
self._labelCol = color if isinstance(color, QColor) else QColor(*color) self._labelCol = color if isinstance(color, QColor) else QColor(*color)
@@ -136,6 +140,10 @@ class _NPagedToolButton(QToolButton):
return 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: def paintEvent(self, event: QPaintEvent) -> None:
"""Overload the paint event to draw a simple, left aligned text """Overload the paint event to draw a simple, left aligned text
label, with a highlight when selected and a transparent base 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 __future__ import annotations
from PyQt5.QtGui import QMouseEvent, QPainter, QPaintEvent, QResizeEvent 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 PyQt5.QtWidgets import QAbstractButton, QSizePolicy, QWidget
from novelwriter import CONFIG from novelwriter import CONFIG
from novelwriter.constants import nwUnicode
class NSwitch(QAbstractButton): class NSwitch(QAbstractButton):
def __init__(self, parent: QWidget | None = None, __slots__ = ("_xW", "_xH", "_xR", "_rB", "_rH", "_rR", "_offset")
width: int | None = None, height: int | None = None) -> None:
def __init__(self, parent: QWidget | None = None, width: int = 0, height: int = 0) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
if width is None: self._xW = width or CONFIG.pxInt(40)
self._xW = CONFIG.pxInt(40) self._xH = height or CONFIG.pxInt(20)
else:
self._xW = width
if height is None:
self._xH = CONFIG.pxInt(20)
else:
self._xH = height
self._xR = int(self._xH*0.5) self._xR = int(self._xH*0.5)
self._xT = int(self._xH*0.6)
self._rB = int(CONFIG.guiScale*2) self._rB = int(CONFIG.guiScale*2)
self._rH = self._xH - 2*self._rB self._rH = self._xH - 2*self._rB
self._rR = self._xR - self._rB self._rR = self._xR - self._rB
@@ -82,10 +73,7 @@ class NSwitch(QAbstractButton):
def setChecked(self, checked: bool) -> None: def setChecked(self, checked: bool) -> None:
"""Overload setChecked to also alter the offset.""" """Overload setChecked to also alter the offset."""
super().setChecked(checked) super().setChecked(checked)
if checked: self._offset = (self._xW - self._xR) if checked else self._xR
self._offset = self._xW - self._xR
else:
self._offset = self._xR
return return
## ##
@@ -95,53 +83,36 @@ class NSwitch(QAbstractButton):
def resizeEvent(self, event: QResizeEvent) -> None: def resizeEvent(self, event: QResizeEvent) -> None:
"""Overload resize to ensure correct offset.""" """Overload resize to ensure correct offset."""
super().resizeEvent(event) super().resizeEvent(event)
if self.isChecked(): self._offset = (self._xW - self._xR) if self.isChecked() else self._xR
self._offset = self._xW - self._xR
else:
self._offset = self._xR
return return
def paintEvent(self, event: QPaintEvent) -> None: def paintEvent(self, event: QPaintEvent) -> None:
"""Drawing the switch itself.""" """Drawing the switch itself."""
qPaint = QPainter(self) painter = QPainter(self)
qPaint.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.Antialiasing, True)
qPaint.setPen(Qt.NoPen) painter.setPen(Qt.NoPen)
qPalette = self.palette() palette = self.palette()
if self.isChecked(): if self.isChecked():
trackBrush = qPalette.highlight() trackBrush = palette.highlight()
thumbBrush = qPalette.highlightedText() thumbBrush = palette.highlightedText()
textColor = qPalette.highlight().color()
thumbText = nwUnicode.U_CHECK
else: else:
trackBrush = qPalette.dark() trackBrush = palette.dark()
thumbBrush = qPalette.light() thumbBrush = palette.light()
textColor = qPalette.dark().color()
thumbText = nwUnicode.U_CROSS
if self.isEnabled(): if self.isEnabled():
trackOpacity = 1.0 trackOpacity = 1.0
else: else:
trackOpacity = 0.6 trackOpacity = 0.6
trackBrush = qPalette.shadow() trackBrush = palette.shadow()
thumbBrush = qPalette.mid() thumbBrush = palette.mid()
textColor = qPalette.shadow().color()
qPaint.setBrush(trackBrush) painter.setBrush(trackBrush)
qPaint.setOpacity(trackOpacity) painter.setOpacity(trackOpacity)
qPaint.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR) painter.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
qPaint.setBrush(thumbBrush) painter.setBrush(thumbBrush)
qPaint.drawEllipse(self._offset - self._rR, self._rB, self._rH, self._rH) painter.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
)
return return
@@ -149,14 +120,11 @@ class NSwitch(QAbstractButton):
"""Animate the switch on mouse release.""" """Animate the switch on mouse release."""
super().mouseReleaseEvent(event) super().mouseReleaseEvent(event)
if event.button() == Qt.LeftButton: if event.button() == Qt.LeftButton:
doAnim = QPropertyAnimation(self, b"offset", self) anim = QPropertyAnimation(self, b"offset", self)
doAnim.setDuration(120) anim.setDuration(120)
doAnim.setStartValue(self._offset) anim.setStartValue(self._offset)
if self.isChecked(): anim.setEndValue((self._xW - self._xR) if self.isChecked() else self._xR)
doAnim.setEndValue(self._xW - self._xR) anim.start()
else:
doAnim.setEndValue(self._xR)
doAnim.start()
return return
def enterEvent(self, event: QEvent) -> None: def enterEvent(self, event: QEvent) -> None:
+11 -15
View File
@@ -187,13 +187,12 @@ class GuiDocEditor(QPlainTextEdit):
# Set Up Document Word Counter # Set Up Document Word Counter
self.wcTimerDoc = QTimer() self.wcTimerDoc = QTimer()
self.wcTimerDoc.timeout.connect(self._runDocCounter) self.wcTimerDoc.timeout.connect(self._runDocCounter)
self.wcTimerDoc.setInterval(5000)
self.wCounterDoc = BackgroundWordCounter(self) self.wCounterDoc = BackgroundWordCounter(self)
self.wCounterDoc.setAutoDelete(False) self.wCounterDoc.setAutoDelete(False)
self.wCounterDoc.signals.countsReady.connect(self._updateDocCounts) self.wCounterDoc.signals.countsReady.connect(self._updateDocCounts)
self.wcInterval = CONFIG.wordCountTimer
# Set Up Selection Word Counter # Set Up Selection Word Counter
self.wcTimerSel = QTimer() self.wcTimerSel = QTimer()
self.wcTimerSel.timeout.connect(self._runSelCounter) self.wcTimerSel.timeout.connect(self._runSelCounter)
@@ -320,10 +319,10 @@ class GuiDocEditor(QPlainTextEdit):
SHARED.updateSpellCheckLanguage() SHARED.updateSpellCheckLanguage()
# Set font # Set font
textFont = QFont() font = QFont()
textFont.setFamily(CONFIG.textFont) font.setFamily(CONFIG.textFont)
textFont.setPointSize(CONFIG.textSize) font.setPointSize(CONFIG.textSize)
self.setFont(textFont) self.setFont(font)
# Set default text margins # Set default text margins
# Due to cursor visibility, a part of the margin must be # Due to cursor visibility, a part of the margin must be
@@ -359,17 +358,14 @@ class GuiDocEditor(QPlainTextEdit):
# Refresh the tab stops # Refresh the tab stops
self.setTabStopDistance(CONFIG.getTabWidth()) self.setTabStopDistance(CONFIG.getTabWidth())
# Configure word count timer # If we have a document open, we should refresh it in case the
self.wcInterval = CONFIG.wordCountTimer
self.wcTimerDoc.setInterval(int(self.wcInterval*1000))
# If we have a document open, we should reload it in case the
# font changed, otherwise we just clear the editor entirely, # font changed, otherwise we just clear the editor entirely,
# which makes it read only. # which makes it read only.
if self._docHandle is None: if self._docHandle:
self.clearEditor()
else:
self._qDocument.syntaxHighlighter.rehighlight() self._qDocument.syntaxHighlighter.rehighlight()
self.docHeader.setTitleFromHandle(self._docHandle)
else:
self.clearEditor()
return return
@@ -1190,7 +1186,7 @@ class GuiDocEditor(QPlainTextEdit):
logger.debug("Word counter is busy") logger.debug("Word counter is busy")
return return
if time() - self._lastEdit < 5.0 * self.wcInterval: if time() - self._lastEdit < 25.0:
logger.debug("Running word counter") logger.debug("Running word counter")
SHARED.runInThreadPool(self.wCounterDoc) SHARED.runInThreadPool(self.wCounterDoc)
+7 -7
View File
@@ -142,10 +142,10 @@ class GuiDocViewer(QTextBrowser):
self._makeStyleSheet() self._makeStyleSheet()
# Set Font # Set Font
textFont = QFont() font = QFont()
textFont.setFamily(CONFIG.textFont) font.setFamily(CONFIG.textFont)
textFont.setPointSize(CONFIG.textSize) font.setPointSize(CONFIG.textSize)
self.setFont(textFont) self.setFont(font)
# Set the widget colours to match syntax theme # Set the widget colours to match syntax theme
mainPalette = self.palette() mainPalette = self.palette()
@@ -164,10 +164,10 @@ class GuiDocViewer(QTextBrowser):
# Set default text margins # Set default text margins
self.document().setDocumentMargin(0) self.document().setDocumentMargin(0)
theOpt = QTextOption() options = QTextOption()
if CONFIG.doJustify: if CONFIG.doJustify:
theOpt.setAlignment(Qt.AlignmentFlag.AlignJustify) options.setAlignment(Qt.AlignmentFlag.AlignJustify)
self.document().setDefaultTextOption(theOpt) self.document().setDefaultTextOption(options)
# Scroll bars # Scroll bars
if CONFIG.hideVScroll: if CONFIG.hideVScroll:
+1 -1
View File
@@ -466,7 +466,7 @@ class GuiIcons:
# General Button Icons # General Button Icons
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "cross", "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", "noncheckable", "panel", "refresh", "remove", "revert", "search_replace", "search",
"settings", "star", "unchecked", "up", "view", "settings", "star", "unchecked", "up", "view",
@@ -57,7 +57,6 @@ spellcheck = en
showtabsnspaces = False showtabsnspaces = False
showlineendings = False showlineendings = False
showmultispaces = True showmultispaces = True
wordcounttimer = 5.0
incnoteswcount = True incnoteswcount = True
showfullpath = True showfullpath = True
highlightquotes = 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 @pytest.mark.gui
def testDlgOther_QuoteSelect(qtbot, nwGUI): def testDlgOther_QuoteSelect(qtbot, monkeypatch, nwGUI):
"""Test the quote symbols dialog.""" """Test the quote symbols dialog."""
monkeypatch.setattr(GuiQuoteSelect, "exec_", lambda *a: None)
nwQuot = GuiQuoteSelect(nwGUI) nwQuot = GuiQuoteSelect(nwGUI)
nwQuot.show() nwQuot.show()
@@ -41,16 +43,25 @@ def testDlgOther_QuoteSelect(qtbot, nwGUI):
anItem = nwQuot.listBox.item(i) anItem = nwQuot.listBox.item(i)
assert isinstance(anItem, QListWidgetItem) assert isinstance(anItem, QListWidgetItem)
nwQuot.listBox.clearSelection() nwQuot.listBox.clearSelection()
nwQuot.listBox.setCurrentItem(anItem, QItemSelectionModel.Select) nwQuot.listBox.setCurrentItem(anItem, QItemSelectionModel.SelectionFlag.Select)
lastItem = anItem.text()[2] lastItem = anItem.text()[2]
assert nwQuot.previewLabel.text() == lastItem assert nwQuot.previewLabel.text() == lastItem
nwQuot.accept() nwQuot.accept()
assert nwQuot.result() == QDialog.Accepted assert nwQuot.result() == QDialog.Accepted
assert nwQuot.selectedQuote == lastItem 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() # qtbot.stop()
nwQuot.close()
# END Test testDlgOther_QuoteSelect # END Test testDlgOther_QuoteSelect
+363 -165
View File
@@ -22,191 +22,389 @@ from __future__ import annotations
import pytest import pytest
from shutil import copyfile from PyQt5.QtGui import QFontDatabase, QKeyEvent
from PyQt5.QtCore import QEvent, Qt
from tools import cmpFiles, getGuiItem from PyQt5.QtWidgets import QDialogButtonBox, QFileDialog, QFontDialog
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog
)
from novelwriter import CONFIG, SHARED 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.preferences import GuiPreferences
from novelwriter.dialogs.quotes import GuiQuoteSelect
KEY_DELAY = 1 KEY_DELAY = 1
@pytest.mark.gui @pytest.mark.gui
def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths): def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
"""Test the preferences dialog.""" """Test the preferences dialog loading."""
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")]) monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger) # Load GUI with standard values
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000) prefs = GuiPreferences(nwGUI)
nwPrefs = getGuiItem("GuiPreferences") prefs.show()
assert isinstance(nwPrefs, GuiPreferences)
nwPrefs.show()
# General Settings # Check Languages
qtbot.wait(KEY_DELAY) languages = [prefs.guiLocale.itemData(i) for i in range(prefs.guiLocale.count())]
tabGeneral = nwPrefs.tabGeneral assert len(languages) > 0
nwPrefs._tabBox.setCurrentWidget(tabGeneral) assert "en_GB" in languages
qtbot.wait(KEY_DELAY) # Check GUI Themes
assert tabGeneral.showFullPath.isChecked() themes = [prefs.guiTheme.itemData(i) for i in range(prefs.guiTheme.count())]
qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton) assert len(themes) >= 5
assert not tabGeneral.showFullPath.isChecked() assert "default" in themes
qtbot.wait(KEY_DELAY) # Check GUI Syntax
assert not tabGeneral.hideVScroll.isChecked() syntax = [prefs.guiSyntax.itemData(i) for i in range(prefs.guiSyntax.count())]
qtbot.mouseClick(tabGeneral.hideVScroll, Qt.LeftButton) assert len(syntax) >= 10
assert tabGeneral.hideVScroll.isChecked() assert "default_dark" in syntax
assert "default_light" in syntax
qtbot.wait(KEY_DELAY) # Check Spell Checking
assert not tabGeneral.hideHScroll.isChecked() spelling = [prefs.spellLanguage.itemData(i) for i in range(prefs.spellLanguage.count())]
qtbot.mouseClick(tabGeneral.hideHScroll, Qt.LeftButton) assert len(spelling) == 1
assert tabGeneral.hideHScroll.isChecked() assert spelling == ["en"]
# Check font button prefs.close()
monkeypatch.setattr(QFontDialog, "getFont", lambda font, obj: (font, True))
qtbot.mouseClick(tabGeneral.fontButton, Qt.LeftButton)
qtbot.wait(KEY_DELAY) # Check Fallback Values
tabGeneral.guiFontSize.setValue(12) with monkeypatch.context() as mp:
mp.setattr(CONFIG, "hasEnchant", False)
prefs = GuiPreferences(nwGUI)
prefs.show()
# Projects Settings # Check Spell Checking
qtbot.wait(KEY_DELAY) spelling = [prefs.spellLanguage.itemData(i) for i in range(prefs.spellLanguage.count())]
tabProjects = nwPrefs.tabProjects assert len(spelling) == 1
nwPrefs._tabBox.setCurrentWidget(tabProjects) assert spelling == [""]
tabProjects.backupPath = "no/where"
qtbot.wait(KEY_DELAY) prefs.close()
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()
# qtbot.stop() # qtbot.stop()
# END Test testDlgPreferences_Main # 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