1125 lines
43 KiB
Python
1125 lines
43 KiB
Python
"""
|
||
novelWriter – GUI Preferences
|
||
=============================
|
||
|
||
File History:
|
||
Created: 2019-06-10 [0.1.5] GuiPreferences
|
||
Rewritten: 2024-01-08 [2.3b1] GuiPreferences
|
||
|
||
This file is a part of novelWriter
|
||
Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful, but
|
||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
""" # noqa
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
|
||
from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot
|
||
from PyQt6.QtGui import QAction, QCloseEvent, QKeyEvent, QKeySequence
|
||
from PyQt6.QtWidgets import (
|
||
QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout, QLineEdit, QMenu,
|
||
QPushButton, QVBoxLayout, QWidget
|
||
)
|
||
|
||
from novelwriter import CONFIG, SHARED
|
||
from novelwriter.common import compact, describeFont, processDialogSymbols, uniqueCompact
|
||
from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT, DEF_ICONS, DEF_TREECOL
|
||
from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst
|
||
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
||
from novelwriter.enum import nwStandardButton
|
||
from novelwriter.extensions.configlayout import NColorLabel, NScrollableForm
|
||
from novelwriter.extensions.modified import (
|
||
NComboBox, NDialog, NDoubleSpinBox, NIconToolButton, NSpinBox
|
||
)
|
||
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
||
from novelwriter.extensions.switch import NSwitch
|
||
from novelwriter.types import QtAlignCenter, QtRoleAccept, QtRoleReject
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class GuiPreferences(NDialog):
|
||
"""GUI: Preferences Dialog."""
|
||
|
||
newPreferencesReady = pyqtSignal(bool, bool, bool, bool)
|
||
|
||
def __init__(self, parent: QWidget) -> None:
|
||
super().__init__(parent=parent)
|
||
|
||
logger.debug("Create: GuiPreferences")
|
||
self.setObjectName("GuiPreferences")
|
||
self.setWindowTitle(self.tr("Preferences"))
|
||
self.setMinimumSize(600, 500)
|
||
self.resize(*CONFIG.prefsWinSize)
|
||
|
||
# Title
|
||
self.titleLabel = NColorLabel(
|
||
self.tr("Preferences"), self, color=SHARED.theme.helpText,
|
||
scale=NColorLabel.HEADER_SCALE, indent=4,
|
||
)
|
||
|
||
# Search Box
|
||
self.searchAction = QAction(SHARED.theme.getIcon("search"), "")
|
||
self.searchAction.triggered.connect(self._gotoSearch)
|
||
|
||
self.searchText = QLineEdit(self)
|
||
self.searchText.setPlaceholderText(self.tr("Search"))
|
||
self.searchText.setMinimumWidth(200)
|
||
self.searchText.addAction(self.searchAction, QLineEdit.ActionPosition.TrailingPosition)
|
||
|
||
# SideBar
|
||
self.sidebar = NPagedSideBar(self)
|
||
self.sidebar.setLabelColor(SHARED.theme.helpText)
|
||
self.sidebar.setAccessibleName(self.titleLabel.text())
|
||
self.sidebar.buttonClicked.connect(self._sidebarClicked)
|
||
|
||
# Form
|
||
self.mainForm = NScrollableForm(self)
|
||
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
||
|
||
# Buttons
|
||
self.btnSave = SHARED.theme.getStandardButton(nwStandardButton.SAVE, self)
|
||
self.btnSave.clicked.connect(self._doSave)
|
||
|
||
self.btnCancel = SHARED.theme.getStandardButton(nwStandardButton.CANCEL, self)
|
||
self.btnCancel.clicked.connect(self.reject)
|
||
|
||
self.btnBox = QDialogButtonBox(self)
|
||
self.btnBox.addButton(self.btnSave, QtRoleAccept)
|
||
self.btnBox.addButton(self.btnCancel, QtRoleReject)
|
||
|
||
# Assemble
|
||
self.searchBox = QHBoxLayout()
|
||
self.searchBox.addWidget(self.titleLabel)
|
||
self.searchBox.addStretch(1)
|
||
self.searchBox.addWidget(self.searchText, 1)
|
||
|
||
self.mainBox = QHBoxLayout()
|
||
self.mainBox.addWidget(self.sidebar)
|
||
self.mainBox.addWidget(self.mainForm)
|
||
self.mainBox.setContentsMargins(0, 0, 0, 0)
|
||
|
||
self.outerBox = QVBoxLayout()
|
||
self.outerBox.addLayout(self.searchBox)
|
||
self.outerBox.addLayout(self.mainBox)
|
||
self.outerBox.addWidget(self.btnBox)
|
||
self.outerBox.setSpacing(8)
|
||
|
||
self.setLayout(self.outerBox)
|
||
self.setSizeGripEnabled(True)
|
||
|
||
# Build Form
|
||
self.buildForm()
|
||
|
||
# Populate Search
|
||
self.searchCompleter = QCompleter(self.mainForm.labels, self)
|
||
self.searchCompleter.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
|
||
self.searchCompleter.setFilterMode(Qt.MatchFlag.MatchContains)
|
||
self.searchCompleter.activated.connect(self._gotoSearch)
|
||
|
||
self.searchText.setCompleter(self.searchCompleter)
|
||
|
||
logger.debug("Ready: GuiPreferences")
|
||
|
||
def __del__(self) -> None: # pragma: no cover
|
||
logger.debug("Delete: GuiPreferences")
|
||
|
||
def buildForm(self) -> None:
|
||
"""Build the settings form."""
|
||
section = 0
|
||
iSz = SHARED.theme.baseIconSize
|
||
boxFixed = 6*SHARED.theme.textNWidth
|
||
|
||
# Temporary Variables
|
||
self._guiFont = CONFIG.guiFont
|
||
self._textFont = CONFIG.textFont
|
||
|
||
# Label
|
||
self.sidebar.addLabel(self.tr("General"))
|
||
|
||
# Appearance
|
||
# ==========
|
||
|
||
title = self.tr("Appearance")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Display Language
|
||
self.guiLocale = NComboBox(self, scrollable=False)
|
||
self.guiLocale.setMinimumWidth(200)
|
||
for lang, name in CONFIG.listLanguages(CONFIG.LANG_NW):
|
||
self.guiLocale.addItem(name, lang)
|
||
self.guiLocale.setCurrentData(CONFIG.guiLocale, "en_GB")
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Display language"), self.guiLocale,
|
||
self.tr("Requires restart to take effect."), stretch=(3, 2)
|
||
)
|
||
|
||
# Colour Theme
|
||
self.lightTheme = NComboBox(self, scrollable=False)
|
||
self.lightTheme.setMinimumWidth(200)
|
||
self.darkTheme = NComboBox(self, scrollable=False)
|
||
self.darkTheme.setMinimumWidth(200)
|
||
for key, theme in SHARED.theme.colourThemes.items():
|
||
if theme.dark:
|
||
self.darkTheme.addItem(theme.name, key)
|
||
else:
|
||
self.lightTheme.addItem(theme.name, key)
|
||
|
||
self.lightTheme.setCurrentData(CONFIG.lightTheme, DEF_GUI_LIGHT)
|
||
self.darkTheme.setCurrentData(CONFIG.darkTheme, DEF_GUI_DARK)
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Light colour theme"), self.lightTheme,
|
||
self.tr("You can change theme mode from the sidebar."), stretch=(3, 2)
|
||
)
|
||
self.mainForm.addRow(
|
||
self.tr("Dark colour theme"), self.darkTheme,
|
||
self.tr("You can change theme mode from the sidebar."), stretch=(3, 2)
|
||
)
|
||
|
||
# Icon Theme
|
||
self.iconTheme = NComboBox(self, scrollable=False)
|
||
self.iconTheme.setMinimumWidth(200)
|
||
for key, theme in SHARED.theme.iconCache.iconThemes.items():
|
||
self.iconTheme.addItem(theme.name, key)
|
||
|
||
self.iconTheme.setCurrentData(CONFIG.iconTheme, DEF_ICONS)
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Icon theme"), self.iconTheme,
|
||
self.tr("User interface icon theme."), stretch=(3, 2)
|
||
)
|
||
|
||
# Application Font Family
|
||
self.guiFont = QLineEdit(self)
|
||
self.guiFont.setReadOnly(True)
|
||
self.guiFont.setMinimumWidth(162)
|
||
self.guiFont.setText(describeFont(self._guiFont))
|
||
self.guiFont.setCursorPosition(0)
|
||
self.guiFontButton = NIconToolButton(self, iSz, "font")
|
||
self.guiFontButton.clicked.connect(self._selectGuiFont)
|
||
self.mainForm.addRow(
|
||
self.tr("Application font"), self.guiFont,
|
||
self.tr("Requires restart to take effect."), stretch=(3, 2),
|
||
button=self.guiFontButton
|
||
)
|
||
|
||
# Vertical Scrollbars
|
||
self.hideVScroll = NSwitch(self)
|
||
self.hideVScroll.setChecked(CONFIG.hideVScroll)
|
||
self.mainForm.addRow(
|
||
self.tr("Hide vertical scroll bars in main windows"), self.hideVScroll,
|
||
self.tr("Scrolling available with mouse wheel and keys only.")
|
||
)
|
||
|
||
# Horizontal Scrollbars
|
||
self.hideHScroll = NSwitch(self)
|
||
self.hideHScroll.setChecked(CONFIG.hideHScroll)
|
||
self.mainForm.addRow(
|
||
self.tr("Hide horizontal scroll bars in main windows"), self.hideHScroll,
|
||
self.tr("Scrolling available with mouse wheel and keys only.")
|
||
)
|
||
|
||
# Native Font Dialog
|
||
self.nativeFont = NSwitch(self)
|
||
self.nativeFont.setChecked(CONFIG.nativeFont)
|
||
self.mainForm.addRow(
|
||
self.tr("Use the system's font selection dialog"), self.nativeFont,
|
||
self.tr("Turn off to use the Qt font dialog, which may have more options.")
|
||
)
|
||
|
||
# Use Character Count
|
||
self.useCharCount = NSwitch(self)
|
||
self.useCharCount.setChecked(CONFIG.useCharCount)
|
||
self.mainForm.addRow(
|
||
self.tr("Prefer character count over word count"), self.useCharCount,
|
||
self.tr("Display character count instead where available.")
|
||
)
|
||
|
||
# Document Style
|
||
# ==============
|
||
|
||
title = self.tr("Document Style")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Document Font Family
|
||
self.textFont = QLineEdit(self)
|
||
self.textFont.setReadOnly(True)
|
||
self.textFont.setMinimumWidth(162)
|
||
self.textFont.setText(describeFont(CONFIG.textFont))
|
||
self.textFont.setCursorPosition(0)
|
||
self.textFontButton = NIconToolButton(self, iSz, "font")
|
||
self.textFontButton.clicked.connect(self._selectTextFont)
|
||
self.mainForm.addRow(
|
||
self.tr("Document font"), self.textFont,
|
||
self.tr("Applies to both document editor and viewer."), stretch=(3, 2),
|
||
button=self.textFontButton
|
||
)
|
||
|
||
# Document Path
|
||
self.showFullPath = NSwitch(self)
|
||
self.showFullPath.setChecked(CONFIG.showFullPath)
|
||
self.mainForm.addRow(
|
||
self.tr("Show full path in document header"), self.showFullPath,
|
||
self.tr("Add the parent folder names to the header.")
|
||
)
|
||
|
||
# Include Notes in Word Count
|
||
self.incNotesWCount = NSwitch(self)
|
||
self.incNotesWCount.setChecked(CONFIG.incNotesWCount)
|
||
self.mainForm.addRow(
|
||
self.tr("Include project notes in status bar word count"), self.incNotesWCount
|
||
)
|
||
|
||
# Project View
|
||
# ============
|
||
|
||
title = self.tr("Project View")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Tree Icon Colours
|
||
self.iconColTree = NComboBox(self)
|
||
self.iconColTree.setMinimumWidth(200)
|
||
self.iconColTree.addItem(self.tr("Theme Colours"), DEF_TREECOL)
|
||
for key, label in nwLabels.THEME_COLORS.items():
|
||
self.iconColTree.addItem(trConst(label), key)
|
||
self.iconColTree.setCurrentData(CONFIG.iconColTree, DEF_TREECOL)
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Project tree icon colours"), self.iconColTree,
|
||
self.tr("Override colours for project icons."), stretch=(3, 2)
|
||
)
|
||
|
||
# Keep Theme Colours on Documents
|
||
self.iconColDocs = NSwitch(self)
|
||
self.iconColDocs.setChecked(CONFIG.iconColDocs)
|
||
self.mainForm.addRow(
|
||
self.tr("Keep theme colours on documents"), self.iconColDocs,
|
||
self.tr("Only override icon colours for folders.")
|
||
)
|
||
|
||
# Emphasise Labels
|
||
self.emphLabels = NSwitch(self)
|
||
self.emphLabels.setChecked(CONFIG.emphLabels)
|
||
self.mainForm.addRow(
|
||
self.tr("Emphasise partition and chapter labels"), self.emphLabels,
|
||
self.tr("Makes them stand out in the project tree."),
|
||
)
|
||
|
||
# Behaviour
|
||
# =========
|
||
|
||
title = self.tr("Behaviour")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Document Save Timer
|
||
self.autoSaveDoc = NSpinBox(self)
|
||
self.autoSaveDoc.setMinimum(5)
|
||
self.autoSaveDoc.setMaximum(600)
|
||
self.autoSaveDoc.setSingleStep(1)
|
||
self.autoSaveDoc.setValue(CONFIG.autoSaveDoc)
|
||
self.mainForm.addRow(
|
||
self.tr("Save document interval"), self.autoSaveDoc,
|
||
self.tr("How often the document is automatically saved."), unit=self.tr("seconds")
|
||
)
|
||
|
||
# Project Save Timer
|
||
self.autoSaveProj = NSpinBox(self)
|
||
self.autoSaveProj.setMinimum(5)
|
||
self.autoSaveProj.setMaximum(600)
|
||
self.autoSaveProj.setSingleStep(1)
|
||
self.autoSaveProj.setValue(CONFIG.autoSaveProj)
|
||
self.mainForm.addRow(
|
||
self.tr("Save project interval"), self.autoSaveProj,
|
||
self.tr("How often the project is automatically saved."), unit=self.tr("seconds")
|
||
)
|
||
|
||
# Ask before exiting novelWriter
|
||
self.askBeforeExit = NSwitch(self)
|
||
self.askBeforeExit.setChecked(CONFIG.askBeforeExit)
|
||
self.mainForm.addRow(
|
||
self.tr("Ask before exiting novelWriter"), self.askBeforeExit,
|
||
self.tr("Only applies when a project is open.")
|
||
)
|
||
|
||
# Project Backup
|
||
# ==============
|
||
|
||
title = self.tr("Project Backup")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Backup Path
|
||
self.backupPath = CONFIG.backupPath()
|
||
self.backupGetPath = QPushButton(SHARED.theme.getIcon("browse"), self.tr("Browse"), self)
|
||
self.backupGetPath.setIconSize(iSz)
|
||
self.backupGetPath.clicked.connect(self._backupFolder)
|
||
self.mainForm.addRow(
|
||
self.tr("Backup storage location"), self.backupGetPath,
|
||
self.tr("Path: {0}").format(self.backupPath), editable="backupPath"
|
||
)
|
||
|
||
# Run When Closing
|
||
self.backupOnClose = NSwitch(self)
|
||
self.backupOnClose.setChecked(CONFIG.backupOnClose)
|
||
self.backupOnClose.toggled.connect(self._toggledBackupOnClose)
|
||
self.mainForm.addRow(
|
||
self.tr("Run backup when the project is closed"), self.backupOnClose,
|
||
self.tr("Can be overridden for individual projects in Project Settings.")
|
||
)
|
||
|
||
# Ask Before Backup
|
||
# Only enabled when "Run when closing" is checked
|
||
self.askBeforeBackup = NSwitch(self)
|
||
self.askBeforeBackup.setChecked(CONFIG.askBeforeBackup)
|
||
self.askBeforeBackup.setEnabled(CONFIG.backupOnClose)
|
||
self.mainForm.addRow(
|
||
self.tr("Ask before running backup"), self.askBeforeBackup,
|
||
self.tr("If off, backups will run in the background.")
|
||
)
|
||
|
||
# Session Timer
|
||
# =============
|
||
|
||
title = self.tr("Session Timer")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Pause When Idle
|
||
self.stopWhenIdle = NSwitch(self)
|
||
self.stopWhenIdle.setChecked(CONFIG.stopWhenIdle)
|
||
self.mainForm.addRow(
|
||
self.tr("Pause the session timer when not writing"), self.stopWhenIdle,
|
||
self.tr("Also pauses when the application window does not have focus.")
|
||
)
|
||
|
||
# Inactive Time for Idle
|
||
self.userIdleTime = NDoubleSpinBox(self)
|
||
self.userIdleTime.setMinimum(0.5)
|
||
self.userIdleTime.setMaximum(600.0)
|
||
self.userIdleTime.setSingleStep(0.5)
|
||
self.userIdleTime.setDecimals(1)
|
||
self.userIdleTime.setValue(CONFIG.userIdleTime/60.0)
|
||
self.mainForm.addRow(
|
||
self.tr("Editor inactive time before pausing timer"), self.userIdleTime,
|
||
self.tr("User activity includes typing and changing the content."),
|
||
unit=self.tr("minutes")
|
||
)
|
||
|
||
# Label
|
||
self.sidebar.addLabel(self.tr("Writing"))
|
||
|
||
# Text Flow
|
||
# =========
|
||
|
||
title = self.tr("Text Flow")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Max Text Width in Normal Mode
|
||
self.textWidth = NSpinBox(self)
|
||
self.textWidth.setMinimum(0)
|
||
self.textWidth.setMaximum(10000)
|
||
self.textWidth.setSingleStep(10)
|
||
self.textWidth.setValue(CONFIG.textWidth)
|
||
self.mainForm.addRow(
|
||
self.tr('Maximum text width in "Normal Mode"'), self.textWidth,
|
||
self.tr("Set to 0 to disable this feature."), unit=self.tr("px")
|
||
)
|
||
|
||
# Max Text Width in Focus Mode
|
||
self.focusWidth = NSpinBox(self)
|
||
self.focusWidth.setMinimum(200)
|
||
self.focusWidth.setMaximum(10000)
|
||
self.focusWidth.setSingleStep(10)
|
||
self.focusWidth.setValue(CONFIG.focusWidth)
|
||
self.mainForm.addRow(
|
||
self.tr('Maximum text width in "Focus Mode"'), self.focusWidth,
|
||
self.tr("The maximum width cannot be disabled."), unit=self.tr("px")
|
||
)
|
||
|
||
# Focus Mode Footer
|
||
self.hideFocusFooter = NSwitch(self)
|
||
self.hideFocusFooter.setChecked(CONFIG.hideFocusFooter)
|
||
self.mainForm.addRow(
|
||
self.tr('Hide document footer in "Focus Mode"'), self.hideFocusFooter,
|
||
self.tr("Hide the information bar in the document editor.")
|
||
)
|
||
|
||
# Justify Text
|
||
self.doJustify = NSwitch(self)
|
||
self.doJustify.setChecked(CONFIG.doJustify)
|
||
self.mainForm.addRow(
|
||
self.tr("Justify the text margins"), self.doJustify,
|
||
self.tr("Applies to both document editor and viewer."),
|
||
)
|
||
|
||
# Document Margins
|
||
self.textMargin = NSpinBox(self)
|
||
self.textMargin.setMinimum(0)
|
||
self.textMargin.setMaximum(900)
|
||
self.textMargin.setSingleStep(1)
|
||
self.textMargin.setValue(CONFIG.textMargin)
|
||
self.mainForm.addRow(
|
||
self.tr("Minimum text margin"), self.textMargin,
|
||
self.tr("Applies to both document editor and viewer."),
|
||
unit=self.tr("px")
|
||
)
|
||
|
||
# Tab Width
|
||
self.tabWidth = NSpinBox(self)
|
||
self.tabWidth.setMinimum(0)
|
||
self.tabWidth.setMaximum(200)
|
||
self.tabWidth.setSingleStep(1)
|
||
self.tabWidth.setValue(CONFIG.tabWidth)
|
||
self.mainForm.addRow(
|
||
self.tr("Tab width"), self.tabWidth,
|
||
self.tr("The width of a tab key press in the editor and viewer."),
|
||
unit=self.tr("px")
|
||
)
|
||
|
||
# Text Editing
|
||
# ============
|
||
|
||
title = self.tr("Text Editing")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Spell Checking
|
||
self.spellLanguage = NComboBox(self, scrollable=False)
|
||
self.spellLanguage.setMinimumWidth(200)
|
||
|
||
if CONFIG.hasEnchant:
|
||
for tag, language in SHARED.spelling.listDictionaries():
|
||
self.spellLanguage.addItem(language, tag)
|
||
else:
|
||
self.spellLanguage.addItem(nwUnicode.U_EMDASH, "")
|
||
self.spellLanguage.setEnabled(False)
|
||
|
||
if (idx := self.spellLanguage.findData(CONFIG.spellLanguage)) != -1:
|
||
self.spellLanguage.setCurrentIndex(idx)
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Spell check language"), self.spellLanguage,
|
||
self.tr("Available languages are determined by your system."), stretch=(3, 2)
|
||
)
|
||
|
||
# Auto-Select Word Under Cursor
|
||
self.autoSelect = NSwitch(self)
|
||
self.autoSelect.setChecked(CONFIG.autoSelect)
|
||
self.mainForm.addRow(
|
||
self.tr("Auto-select word under cursor"), self.autoSelect,
|
||
self.tr("Apply formatting to word under cursor if no selection is made.")
|
||
)
|
||
|
||
# Cursor Width
|
||
self.cursorWidth = NSpinBox(self)
|
||
self.cursorWidth.setMinimum(1)
|
||
self.cursorWidth.setMaximum(20)
|
||
self.cursorWidth.setSingleStep(1)
|
||
self.cursorWidth.setValue(CONFIG.cursorWidth)
|
||
self.mainForm.addRow(
|
||
self.tr("Cursor width"), self.cursorWidth,
|
||
self.tr("The width of the text cursor of the editor."),
|
||
unit=self.tr("px")
|
||
)
|
||
|
||
# Highlight Current Line
|
||
self.lineHighlight = NSwitch(self)
|
||
self.lineHighlight.setChecked(CONFIG.lineHighlight)
|
||
self.mainForm.addRow(
|
||
self.tr("Highlight current line"), self.lineHighlight
|
||
)
|
||
|
||
# Show Tabs and Spaces
|
||
self.showTabsNSpaces = NSwitch(self)
|
||
self.showTabsNSpaces.setChecked(CONFIG.showTabsNSpaces)
|
||
self.mainForm.addRow(
|
||
self.tr("Show tabs and spaces"), self.showTabsNSpaces
|
||
)
|
||
|
||
# Show Line Endings
|
||
self.showLineEndings = NSwitch(self)
|
||
self.showLineEndings.setChecked(CONFIG.showLineEndings)
|
||
self.mainForm.addRow(
|
||
self.tr("Show line endings"), self.showLineEndings
|
||
)
|
||
|
||
# Editor Scrolling
|
||
# ================
|
||
|
||
title = self.tr("Editor Scrolling")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Scroll Past End
|
||
self.scrollPastEnd = NSwitch(self)
|
||
self.scrollPastEnd.setChecked(CONFIG.scrollPastEnd)
|
||
self.mainForm.addRow(
|
||
self.tr("Scroll past the end of the document"), self.scrollPastEnd,
|
||
self.tr("Also centres the cursor when scrolling.")
|
||
)
|
||
|
||
# Typewriter Scrolling
|
||
self.autoScroll = NSwitch(self)
|
||
self.autoScroll.setChecked(CONFIG.autoScroll)
|
||
self.mainForm.addRow(
|
||
self.tr("Typewriter style scrolling when you type"), self.autoScroll,
|
||
self.tr("Keeps the cursor at a fixed vertical position.")
|
||
)
|
||
|
||
# Typewriter Position
|
||
self.autoScrollPos = NSpinBox(self)
|
||
self.autoScrollPos.setMinimum(10)
|
||
self.autoScrollPos.setMaximum(90)
|
||
self.autoScrollPos.setSingleStep(1)
|
||
self.autoScrollPos.setValue(int(CONFIG.autoScrollPos))
|
||
self.mainForm.addRow(
|
||
self.tr("Minimum position for Typewriter scrolling"), self.autoScrollPos,
|
||
self.tr("Percentage of the editor height from the top."), unit="%"
|
||
)
|
||
|
||
# Text Highlighting
|
||
# =================
|
||
|
||
title = self.tr("Text Highlighting")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Dialogue Quotes
|
||
self.dialogStyle = NComboBox(self)
|
||
self.dialogStyle.addItem(self.tr("None"), 0)
|
||
self.dialogStyle.addItem(self.tr("Single Quotes"), 1)
|
||
self.dialogStyle.addItem(self.tr("Double Quotes"), 2)
|
||
self.dialogStyle.addItem(self.tr("Both"), 3)
|
||
self.dialogStyle.setCurrentData(CONFIG.dialogStyle, 2)
|
||
self.mainForm.addRow(
|
||
self.tr("Highlight dialogue"), self.dialogStyle,
|
||
self.tr("Applies to the selected quote styles.")
|
||
)
|
||
|
||
# Open-Ended Dialogue
|
||
self.allowOpenDial = NSwitch(self)
|
||
self.allowOpenDial.setChecked(CONFIG.allowOpenDial)
|
||
self.mainForm.addRow(
|
||
self.tr("Allow open-ended dialogue"), self.allowOpenDial,
|
||
self.tr("Highlight dialogue line with no closing quote.")
|
||
)
|
||
|
||
# Alternative Dialogue
|
||
self.altDialogOpen = QLineEdit(self)
|
||
self.altDialogOpen.setMaxLength(4)
|
||
self.altDialogOpen.setFixedWidth(boxFixed)
|
||
self.altDialogOpen.setAlignment(QtAlignCenter)
|
||
self.altDialogOpen.setText(CONFIG.altDialogOpen)
|
||
|
||
self.altDialogClose = QLineEdit(self)
|
||
self.altDialogClose.setMaxLength(4)
|
||
self.altDialogClose.setFixedWidth(boxFixed)
|
||
self.altDialogClose.setAlignment(QtAlignCenter)
|
||
self.altDialogClose.setText(CONFIG.altDialogClose)
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Alternative dialogue symbols"), [self.altDialogOpen, self.altDialogClose],
|
||
self.tr("Custom highlighting of dialogue text.")
|
||
)
|
||
|
||
# Dialogue Line
|
||
self.mnLineSymbols = QMenu(self)
|
||
for symbol in nwQuotes.ALLOWED:
|
||
label = trConst(nwQuotes.SYMBOLS.get(symbol, nwQuotes.DASHES.get(symbol, "None")))
|
||
self.mnLineSymbols.addAction(
|
||
f"[ {symbol } ] {label}",
|
||
lambda symbol=symbol: self._insertDialogLineSymbol(symbol)
|
||
)
|
||
|
||
self.dialogLine = QLineEdit(self)
|
||
self.dialogLine.setMinimumWidth(100)
|
||
self.dialogLine.setAlignment(QtAlignCenter)
|
||
self.dialogLine.setText(" ".join(CONFIG.dialogLine))
|
||
|
||
self.dialogLineButton = NIconToolButton(self, iSz, "add", "green")
|
||
self.dialogLineButton.setMenu(self.mnLineSymbols)
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Dialogue line symbols"), self.dialogLine,
|
||
self.tr("Lines starting with any of these symbols are dialogue."),
|
||
button=self.dialogLineButton
|
||
)
|
||
|
||
# Narrator Break
|
||
self.narratorBreak = NComboBox(self)
|
||
self.narratorDialog = NComboBox(self)
|
||
for key, value in nwQuotes.DASHES.items():
|
||
label = trConst(value)
|
||
self.narratorBreak.addItem(label, key)
|
||
self.narratorDialog.addItem(label, key)
|
||
|
||
self.narratorBreak.setCurrentData(CONFIG.narratorBreak, "")
|
||
self.narratorDialog.setCurrentData(CONFIG.narratorDialog, "")
|
||
|
||
self.mainForm.addRow(
|
||
self.tr("Narrator break symbol"), self.narratorBreak,
|
||
self.tr("Symbol to indicate a narrator break in dialogue.")
|
||
)
|
||
self.mainForm.addRow(
|
||
self.tr("Alternating dialogue/narration symbol"), self.narratorDialog,
|
||
self.tr("Alternates dialogue highlighting within any paragraph.")
|
||
)
|
||
|
||
# Emphasis
|
||
self.highlightEmph = NSwitch(self)
|
||
self.highlightEmph.setChecked(CONFIG.highlightEmph)
|
||
self.mainForm.addRow(
|
||
self.tr("Add highlight colour to emphasised text"), self.highlightEmph,
|
||
self.tr("Applies to the document editor only.")
|
||
)
|
||
|
||
# Additional Spaces
|
||
self.showMultiSpaces = NSwitch(self)
|
||
self.showMultiSpaces.setChecked(CONFIG.showMultiSpaces)
|
||
self.mainForm.addRow(
|
||
self.tr("Highlight multiple spaces between words"), self.showMultiSpaces,
|
||
self.tr("Applies to the document editor only.")
|
||
)
|
||
|
||
# Text Automation
|
||
# ===============
|
||
|
||
title = self.tr("Text Automation")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Auto-Replace as You Type Main Switch
|
||
self.doReplace = NSwitch(self)
|
||
self.doReplace.setChecked(CONFIG.doReplace)
|
||
self.doReplace.toggled.connect(self._toggleAutoReplaceMain)
|
||
self.mainForm.addRow(
|
||
self.tr("Auto-replace text as you type"), self.doReplace,
|
||
self.tr("Allow the editor to replace symbols as you type.")
|
||
)
|
||
|
||
# Auto-Replace Single Quotes
|
||
self.doReplaceSQuote = NSwitch(self)
|
||
self.doReplaceSQuote.setChecked(CONFIG.doReplaceSQuote)
|
||
self.doReplaceSQuote.setEnabled(CONFIG.doReplace)
|
||
self.mainForm.addRow(
|
||
self.tr("Auto-replace single quotes"), self.doReplaceSQuote,
|
||
self.tr("Try to guess which is an opening or a closing quote.")
|
||
)
|
||
|
||
# Auto-Replace Double Quotes
|
||
self.doReplaceDQuote = NSwitch(self)
|
||
self.doReplaceDQuote.setChecked(CONFIG.doReplaceDQuote)
|
||
self.doReplaceDQuote.setEnabled(CONFIG.doReplace)
|
||
self.mainForm.addRow(
|
||
self.tr("Auto-replace double quotes"), self.doReplaceDQuote,
|
||
self.tr("Try to guess which is an opening or a closing quote.")
|
||
)
|
||
|
||
# Auto-Replace Hyphens
|
||
self.doReplaceDash = NSwitch(self)
|
||
self.doReplaceDash.setChecked(CONFIG.doReplaceDash)
|
||
self.doReplaceDash.setEnabled(CONFIG.doReplace)
|
||
self.mainForm.addRow(
|
||
self.tr("Auto-replace dashes"), self.doReplaceDash,
|
||
self.tr("Double and triple hyphens become short and long dashes.")
|
||
)
|
||
|
||
# Auto-Replace Dots
|
||
self.doReplaceDots = NSwitch(self)
|
||
self.doReplaceDots.setChecked(CONFIG.doReplaceDots)
|
||
self.doReplaceDots.setEnabled(CONFIG.doReplace)
|
||
self.mainForm.addRow(
|
||
self.tr("Auto-replace dots"), self.doReplaceDots,
|
||
self.tr("Three consecutive dots become ellipsis.")
|
||
)
|
||
|
||
# Pad Before
|
||
self.fmtPadBefore = QLineEdit(self)
|
||
self.fmtPadBefore.setMaxLength(32)
|
||
self.fmtPadBefore.setMinimumWidth(150)
|
||
self.fmtPadBefore.setText(CONFIG.fmtPadBefore)
|
||
self.mainForm.addRow(
|
||
self.tr("Insert non-breaking space before"), self.fmtPadBefore,
|
||
self.tr("Automatically add space before any of these symbols."), stretch=(2, 1)
|
||
)
|
||
|
||
# Pad After
|
||
self.fmtPadAfter = QLineEdit(self)
|
||
self.fmtPadAfter.setMaxLength(32)
|
||
self.fmtPadAfter.setMinimumWidth(150)
|
||
self.fmtPadAfter.setText(CONFIG.fmtPadAfter)
|
||
self.mainForm.addRow(
|
||
self.tr("Insert non-breaking space after"), self.fmtPadAfter,
|
||
self.tr("Automatically add space after any of these symbols."), stretch=(2, 1)
|
||
)
|
||
|
||
# Use Thin Space
|
||
self.fmtPadThin = NSwitch(self)
|
||
self.fmtPadThin.setChecked(CONFIG.fmtPadThin)
|
||
self.fmtPadThin.setEnabled(CONFIG.doReplace)
|
||
self.mainForm.addRow(
|
||
self.tr("Use thin space instead"), self.fmtPadThin,
|
||
self.tr("Inserts a thin space instead of a regular space.")
|
||
)
|
||
|
||
# Quotation Style
|
||
# ===============
|
||
|
||
title = self.tr("Quotation Style")
|
||
section += 1
|
||
self.sidebar.addButton(title, section)
|
||
self.mainForm.addGroupLabel(title, section)
|
||
|
||
# Single Quote Style
|
||
self.fmtSQuoteOpen = QLineEdit(self)
|
||
self.fmtSQuoteOpen.setMaxLength(1)
|
||
self.fmtSQuoteOpen.setReadOnly(True)
|
||
self.fmtSQuoteOpen.setFixedWidth(boxFixed)
|
||
self.fmtSQuoteOpen.setAlignment(QtAlignCenter)
|
||
self.fmtSQuoteOpen.setText(CONFIG.fmtSQuoteOpen)
|
||
self.btnSQuoteOpen = NIconToolButton(self, iSz, "quote")
|
||
self.btnSQuoteOpen.clicked.connect(self._changeSingleQuoteOpen)
|
||
self.mainForm.addRow(
|
||
self.tr("Single quote open style"), self.fmtSQuoteOpen,
|
||
self.tr("The symbol to use for a leading single quote."),
|
||
button=self.btnSQuoteOpen
|
||
)
|
||
|
||
self.fmtSQuoteClose = QLineEdit(self)
|
||
self.fmtSQuoteClose.setMaxLength(1)
|
||
self.fmtSQuoteClose.setReadOnly(True)
|
||
self.fmtSQuoteClose.setFixedWidth(boxFixed)
|
||
self.fmtSQuoteClose.setAlignment(QtAlignCenter)
|
||
self.fmtSQuoteClose.setText(CONFIG.fmtSQuoteClose)
|
||
self.btnSQuoteClose = NIconToolButton(self, iSz, "quote")
|
||
self.btnSQuoteClose.clicked.connect(self._changeSingleQuoteClose)
|
||
self.mainForm.addRow(
|
||
self.tr("Single quote close style"), self.fmtSQuoteClose,
|
||
self.tr("The symbol to use for a trailing single quote."),
|
||
button=self.btnSQuoteClose
|
||
)
|
||
|
||
# Double Quote Style
|
||
self.fmtDQuoteOpen = QLineEdit(self)
|
||
self.fmtDQuoteOpen.setMaxLength(1)
|
||
self.fmtDQuoteOpen.setReadOnly(True)
|
||
self.fmtDQuoteOpen.setFixedWidth(boxFixed)
|
||
self.fmtDQuoteOpen.setAlignment(QtAlignCenter)
|
||
self.fmtDQuoteOpen.setText(CONFIG.fmtDQuoteOpen)
|
||
self.btnDQuoteOpen = NIconToolButton(self, iSz, "quote")
|
||
self.btnDQuoteOpen.clicked.connect(self._changeDoubleQuoteOpen)
|
||
self.mainForm.addRow(
|
||
self.tr("Double quote open style"), self.fmtDQuoteOpen,
|
||
self.tr("The symbol to use for a leading double quote."),
|
||
button=self.btnDQuoteOpen
|
||
)
|
||
|
||
self.fmtDQuoteClose = QLineEdit(self)
|
||
self.fmtDQuoteClose.setMaxLength(1)
|
||
self.fmtDQuoteClose.setReadOnly(True)
|
||
self.fmtDQuoteClose.setFixedWidth(boxFixed)
|
||
self.fmtDQuoteClose.setAlignment(QtAlignCenter)
|
||
self.fmtDQuoteClose.setText(CONFIG.fmtDQuoteClose)
|
||
self.btnDQuoteClose = NIconToolButton(self, iSz, "quote")
|
||
self.btnDQuoteClose.clicked.connect(self._changeDoubleQuoteClose)
|
||
self.mainForm.addRow(
|
||
self.tr("Double quote close style"), self.fmtDQuoteClose,
|
||
self.tr("The symbol to use for a trailing double quote."),
|
||
button=self.btnDQuoteClose
|
||
)
|
||
|
||
self.mainForm.finalise()
|
||
self.sidebar.setSelected(1)
|
||
|
||
##
|
||
# Events
|
||
##
|
||
|
||
def closeEvent(self, event: QCloseEvent) -> None:
|
||
"""Capture the close event and perform cleanup."""
|
||
logger.debug("Close: GuiPreferences")
|
||
self._saveWindowSize()
|
||
event.accept()
|
||
self.softDelete()
|
||
|
||
def keyPressEvent(self, event: QKeyEvent) -> None:
|
||
"""Overload keyPressEvent and only accept escape. The main
|
||
purpose here is to prevent Enter/Return from closing the dialog
|
||
as it is used for the search box.
|
||
"""
|
||
if event.matches(QKeySequence.StandardKey.Cancel):
|
||
self.close()
|
||
event.ignore()
|
||
|
||
##
|
||
# Private Slots
|
||
##
|
||
|
||
@pyqtSlot(int)
|
||
def _sidebarClicked(self, section: int) -> None:
|
||
"""Process a user request to switch page."""
|
||
self.mainForm.scrollToSection(section)
|
||
|
||
@pyqtSlot()
|
||
def _gotoSearch(self) -> None:
|
||
"""Go to the setting indicated by the search text."""
|
||
self.mainForm.scrollToLabel(self.searchText.text().strip())
|
||
|
||
@pyqtSlot()
|
||
def _selectGuiFont(self) -> None:
|
||
"""Open the QFontDialog and set a font for the font style."""
|
||
font, status = SHARED.getFont(self._guiFont, self.nativeFont.isChecked())
|
||
if status:
|
||
self.guiFont.setText(describeFont(font))
|
||
self.guiFont.setCursorPosition(0)
|
||
self._guiFont = font
|
||
|
||
@pyqtSlot()
|
||
def _selectTextFont(self) -> None:
|
||
"""Open the QFontDialog and set a font for the font style."""
|
||
font, status = SHARED.getFont(self._textFont, self.nativeFont.isChecked())
|
||
if status:
|
||
self.textFont.setText(describeFont(font))
|
||
self.textFont.setCursorPosition(0)
|
||
self._textFont = font
|
||
|
||
@pyqtSlot()
|
||
def _backupFolder(self) -> None:
|
||
"""Open a dialog to select the backup folder."""
|
||
if path := QFileDialog.getExistingDirectory(
|
||
self, self.tr("Backup Directory"), str(self.backupPath) or "",
|
||
options=QFileDialog.Option.ShowDirsOnly
|
||
):
|
||
self.backupPath = path
|
||
self.mainForm.setHelpText("backupPath", self.tr("Path: {0}").format(path))
|
||
|
||
@pyqtSlot(bool)
|
||
def _toggledBackupOnClose(self, state: bool) -> None:
|
||
"""Toggle switch that depends on the backup on close switch."""
|
||
self.askBeforeBackup.setEnabled(state)
|
||
|
||
@pyqtSlot(str)
|
||
def _insertDialogLineSymbol(self, symbol: str) -> None:
|
||
"""Insert a symbol in the dialogue line box."""
|
||
current = self.dialogLine.text()
|
||
values = processDialogSymbols(f"{current} {symbol}")
|
||
self.dialogLine.setText(" ".join(values))
|
||
|
||
@pyqtSlot(bool)
|
||
def _toggleAutoReplaceMain(self, state: bool) -> None:
|
||
"""Toggle switches controlled by the auto replace switch."""
|
||
self.doReplaceSQuote.setEnabled(state)
|
||
self.doReplaceDQuote.setEnabled(state)
|
||
self.doReplaceDash.setEnabled(state)
|
||
self.doReplaceDots.setEnabled(state)
|
||
self.fmtPadThin.setEnabled(state)
|
||
|
||
@pyqtSlot()
|
||
def _changeSingleQuoteOpen(self) -> None:
|
||
"""Change single quote open style."""
|
||
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtSQuoteOpen.text())
|
||
if status:
|
||
self.fmtSQuoteOpen.setText(quote)
|
||
|
||
@pyqtSlot()
|
||
def _changeSingleQuoteClose(self) -> None:
|
||
"""Change single quote close style."""
|
||
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtSQuoteClose.text())
|
||
if status:
|
||
self.fmtSQuoteClose.setText(quote)
|
||
|
||
@pyqtSlot()
|
||
def _changeDoubleQuoteOpen(self) -> None:
|
||
"""Change double quote open style."""
|
||
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtDQuoteOpen.text())
|
||
if status:
|
||
self.fmtDQuoteOpen.setText(quote)
|
||
|
||
@pyqtSlot()
|
||
def _changeDoubleQuoteClose(self) -> None:
|
||
"""Change double quote close style."""
|
||
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtDQuoteClose.text())
|
||
if status:
|
||
self.fmtDQuoteClose.setText(quote)
|
||
|
||
##
|
||
# Internal Functions
|
||
##
|
||
|
||
def _saveWindowSize(self) -> None:
|
||
"""Save the dialog window size."""
|
||
CONFIG.setPreferencesWinSize(self.width(), self.height())
|
||
|
||
def _doSave(self) -> None:
|
||
"""Save the values set in the form."""
|
||
updateTheme = False
|
||
needsRestart = False
|
||
updateSyntax = False
|
||
refreshTree = False
|
||
|
||
# Appearance
|
||
guiLocale = self.guiLocale.currentData()
|
||
lightTheme = self.lightTheme.currentData()
|
||
darkTheme = self.darkTheme.currentData()
|
||
iconTheme = self.iconTheme.currentData()
|
||
useCharCount = self.useCharCount.isChecked()
|
||
|
||
updateTheme |= CONFIG.lightTheme != lightTheme
|
||
updateTheme |= CONFIG.darkTheme != darkTheme
|
||
updateTheme |= CONFIG.iconTheme != iconTheme
|
||
needsRestart |= CONFIG.guiLocale != guiLocale
|
||
needsRestart |= CONFIG.guiFont != self._guiFont
|
||
refreshTree |= CONFIG.useCharCount != useCharCount
|
||
updateSyntax |= CONFIG.lightTheme != lightTheme
|
||
updateSyntax |= CONFIG.darkTheme != darkTheme
|
||
|
||
CONFIG.guiLocale = guiLocale
|
||
CONFIG.lightTheme = lightTheme
|
||
CONFIG.darkTheme = darkTheme
|
||
CONFIG.iconTheme = iconTheme
|
||
CONFIG.hideVScroll = self.hideVScroll.isChecked()
|
||
CONFIG.hideHScroll = self.hideHScroll.isChecked()
|
||
CONFIG.nativeFont = self.nativeFont.isChecked()
|
||
CONFIG.useCharCount = useCharCount
|
||
CONFIG.setGuiFont(self._guiFont)
|
||
|
||
# Document Style
|
||
CONFIG.showFullPath = self.showFullPath.isChecked()
|
||
CONFIG.incNotesWCount = self.incNotesWCount.isChecked()
|
||
CONFIG.setTextFont(self._textFont)
|
||
|
||
# Project View
|
||
iconColTree = self.iconColTree.currentData()
|
||
iconColDocs = self.iconColDocs.isChecked()
|
||
emphLabels = self.emphLabels.isChecked()
|
||
|
||
updateTheme |= CONFIG.iconColTree != iconColTree
|
||
updateTheme |= CONFIG.iconColDocs != iconColDocs
|
||
refreshTree |= CONFIG.emphLabels != emphLabels
|
||
|
||
CONFIG.iconColTree = iconColTree
|
||
CONFIG.iconColDocs = iconColDocs
|
||
CONFIG.emphLabels = emphLabels
|
||
|
||
# Behaviour
|
||
CONFIG.autoSaveDoc = self.autoSaveDoc.value()
|
||
CONFIG.autoSaveProj = self.autoSaveProj.value()
|
||
CONFIG.askBeforeExit = self.askBeforeExit.isChecked()
|
||
|
||
# Project Backup
|
||
CONFIG.setBackupPath(self.backupPath)
|
||
CONFIG.backupOnClose = self.backupOnClose.isChecked()
|
||
CONFIG.askBeforeBackup = self.askBeforeBackup.isChecked()
|
||
|
||
# Session Timer
|
||
CONFIG.stopWhenIdle = self.stopWhenIdle.isChecked()
|
||
CONFIG.userIdleTime = round(self.userIdleTime.value() * 60)
|
||
|
||
# Text Flow
|
||
CONFIG.textWidth = self.textWidth.value()
|
||
CONFIG.focusWidth = self.focusWidth.value()
|
||
CONFIG.hideFocusFooter = self.hideFocusFooter.isChecked()
|
||
CONFIG.doJustify = self.doJustify.isChecked()
|
||
CONFIG.textMargin = self.textMargin.value()
|
||
CONFIG.tabWidth = self.tabWidth.value()
|
||
|
||
# Text Editing
|
||
lineHighlight = self.lineHighlight.isChecked()
|
||
|
||
updateSyntax |= CONFIG.lineHighlight != lineHighlight
|
||
|
||
CONFIG.spellLanguage = self.spellLanguage.currentData()
|
||
CONFIG.autoSelect = self.autoSelect.isChecked()
|
||
CONFIG.cursorWidth = self.cursorWidth.value()
|
||
CONFIG.lineHighlight = lineHighlight
|
||
CONFIG.showTabsNSpaces = self.showTabsNSpaces.isChecked()
|
||
CONFIG.showLineEndings = self.showLineEndings.isChecked()
|
||
|
||
# Editor Scrolling
|
||
CONFIG.autoScroll = self.autoScroll.isChecked()
|
||
CONFIG.autoScrollPos = self.autoScrollPos.value()
|
||
CONFIG.scrollPastEnd = self.scrollPastEnd.isChecked()
|
||
|
||
# Text Highlighting
|
||
dialogueStyle = self.dialogStyle.currentData()
|
||
allowOpenDial = self.allowOpenDial.isChecked()
|
||
dialogueLine = processDialogSymbols(self.dialogLine.text())
|
||
narratorBreak = self.narratorBreak.currentData()
|
||
narratorDialog = self.narratorDialog.currentData()
|
||
altDialogOpen = compact(self.altDialogOpen.text())
|
||
altDialogClose = compact(self.altDialogClose.text())
|
||
highlightEmph = self.highlightEmph.isChecked()
|
||
showMultiSpaces = self.showMultiSpaces.isChecked()
|
||
|
||
updateSyntax |= CONFIG.dialogStyle != dialogueStyle
|
||
updateSyntax |= CONFIG.allowOpenDial != allowOpenDial
|
||
updateSyntax |= CONFIG.dialogLine != dialogueLine
|
||
updateSyntax |= CONFIG.narratorBreak != narratorBreak
|
||
updateSyntax |= CONFIG.narratorDialog != narratorDialog
|
||
updateSyntax |= CONFIG.altDialogOpen != altDialogOpen
|
||
updateSyntax |= CONFIG.altDialogClose != altDialogClose
|
||
updateSyntax |= CONFIG.highlightEmph != highlightEmph
|
||
updateSyntax |= CONFIG.showMultiSpaces != showMultiSpaces
|
||
|
||
CONFIG.dialogStyle = dialogueStyle
|
||
CONFIG.allowOpenDial = allowOpenDial
|
||
CONFIG.dialogLine = dialogueLine
|
||
CONFIG.narratorBreak = narratorBreak
|
||
CONFIG.narratorDialog = narratorDialog
|
||
CONFIG.altDialogOpen = altDialogOpen
|
||
CONFIG.altDialogClose = altDialogClose
|
||
CONFIG.highlightEmph = highlightEmph
|
||
CONFIG.showMultiSpaces = showMultiSpaces
|
||
|
||
# Text Automation
|
||
CONFIG.doReplace = self.doReplace.isChecked()
|
||
CONFIG.doReplaceSQuote = self.doReplaceSQuote.isChecked()
|
||
CONFIG.doReplaceDQuote = self.doReplaceDQuote.isChecked()
|
||
CONFIG.doReplaceDash = self.doReplaceDash.isChecked()
|
||
CONFIG.doReplaceDots = self.doReplaceDots.isChecked()
|
||
CONFIG.fmtPadBefore = uniqueCompact(self.fmtPadBefore.text())
|
||
CONFIG.fmtPadAfter = uniqueCompact(self.fmtPadAfter.text())
|
||
CONFIG.fmtPadThin = self.fmtPadThin.isChecked()
|
||
|
||
# Quotation Style
|
||
CONFIG.fmtSQuoteOpen = self.fmtSQuoteOpen.text()
|
||
CONFIG.fmtSQuoteClose = self.fmtSQuoteClose.text()
|
||
CONFIG.fmtDQuoteOpen = self.fmtDQuoteOpen.text()
|
||
CONFIG.fmtDQuoteClose = self.fmtDQuoteClose.text()
|
||
|
||
# Finalise
|
||
CONFIG.saveConfig()
|
||
self.newPreferencesReady.emit(needsRestart, refreshTree, updateTheme, updateSyntax)
|
||
|
||
self.close()
|