""" novelWriter – GUI Preferences ============================= File History: Created: 2019-06-10 [0.1.5] This file is a part of novelWriter Copyright 2018–2023, Veronica Berglyd Olsen 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 . """ from __future__ import annotations import logging from PyQt5.QtGui import QFont from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QDialog, QWidget, QComboBox, QSpinBox, QPushButton, QDialogButtonBox, QLineEdit, QFileDialog, QFontDialog, QDoubleSpinBox ) from novelwriter import CONFIG, SHARED from novelwriter.dialogs.quotes import GuiQuoteSelect from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.pageddialog import NPagedDialog from novelwriter.extensions.configlayout import NConfigLayout logger = logging.getLogger(__name__) class GuiPreferences(NPagedDialog): def __init__(self, mainGui): super().__init__(parent=mainGui) logger.debug("Create: GuiPreferences") self.setObjectName("GuiPreferences") self.setWindowTitle(self.tr("Preferences")) self.tabGeneral = GuiPreferencesGeneral(self) self.tabProjects = GuiPreferencesProjects(self) self.tabDocs = GuiPreferencesDocuments(self) self.tabEditor = GuiPreferencesEditor(self) self.tabSyntax = GuiPreferencesSyntax(self) self.tabAuto = GuiPreferencesAutomation(self) self.tabQuote = GuiPreferencesQuotes(self) self.addTab(self.tabGeneral, self.tr("General")) self.addTab(self.tabProjects, self.tr("Projects")) self.addTab(self.tabDocs, self.tr("Documents")) self.addTab(self.tabEditor, self.tr("Editor")) self.addTab(self.tabSyntax, self.tr("Highlighting")) self.addTab(self.tabAuto, self.tr("Automation")) self.addTab(self.tabQuote, self.tr("Quotes")) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.accepted.connect(self._doSave) self.buttonBox.rejected.connect(self._doClose) self.addControls(self.buttonBox) self.resize(*CONFIG.preferencesWinSize) # Settings self._updateTheme = False self._updateSyntax = False self._needsRestart = False self._refreshTree = False logger.debug("Ready: GuiPreferences") return def __del__(self): # pragma: no cover logger.debug("Delete: GuiPreferences") return ## # Properties ## @property def updateTheme(self): return self._updateTheme @property def updateSyntax(self): return self._updateSyntax @property def needsRestart(self): return self._needsRestart @property def refreshTree(self): return self._refreshTree ## # Slots ## def _doSave(self): """Trigger all the save functions in the tabs, and collect the status of the saves. """ logger.debug("Saving new preferences") self.tabGeneral.saveValues() self.tabProjects.saveValues() self.tabDocs.saveValues() self.tabEditor.saveValues() self.tabSyntax.saveValues() self.tabAuto.saveValues() self.tabQuote.saveValues() self._saveWindowSize() CONFIG.saveConfig() self.accept() return def _doClose(self): """Close the preferences without saving the changes. """ self._saveWindowSize() self.reject() return ## # Internal Functions ## def _saveWindowSize(self): """Save the dialog window size. """ CONFIG.setPreferencesWinSize(self.width(), self.height()) return # END Class GuiPreferences class GuiPreferencesGeneral(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) self.prefsGui = prefsGui # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) # Look and Feel # ============= self.mainForm.addGroupLabel(self.tr("Look and Feel")) minWidth = CONFIG.pxInt(200) # Select Locale self.guiLocale = QComboBox() self.guiLocale.setMinimumWidth(minWidth) theLangs = CONFIG.listLanguages(CONFIG.LANG_NW) for lang, langName in theLangs: self.guiLocale.addItem(langName, lang) langIdx = self.guiLocale.findData(CONFIG.guiLocale) if langIdx != -1: self.guiLocale.setCurrentIndex(langIdx) self.mainForm.addRow( self.tr("Main GUI language"), self.guiLocale, self.tr("Requires restart to take effect.") ) # Select Theme self.guiTheme = QComboBox() self.guiTheme.setMinimumWidth(minWidth) self.theThemes = SHARED.theme.listThemes() for themeDir, themeName in self.theThemes: self.guiTheme.addItem(themeName, themeDir) themeIdx = self.guiTheme.findData(CONFIG.guiTheme) if themeIdx != -1: self.guiTheme.setCurrentIndex(themeIdx) self.mainForm.addRow( self.tr("Main GUI theme"), self.guiTheme, self.tr("General colour theme and icons.") ) # Editor Theme self.guiSyntax = QComboBox() self.guiSyntax.setMinimumWidth(CONFIG.pxInt(200)) self.theSyntaxes = SHARED.theme.listSyntax() for syntaxFile, syntaxName in self.theSyntaxes: self.guiSyntax.addItem(syntaxName, syntaxFile) syntaxIdx = self.guiSyntax.findData(CONFIG.guiSyntax) if syntaxIdx != -1: self.guiSyntax.setCurrentIndex(syntaxIdx) self.mainForm.addRow( self.tr("Editor theme"), self.guiSyntax, self.tr("Colour theme for the editor and viewer.") ) # Font Family self.guiFont = QLineEdit() self.guiFont.setReadOnly(True) self.guiFont.setFixedWidth(CONFIG.pxInt(162)) self.guiFont.setText(CONFIG.guiFont) self.fontButton = QPushButton("...") self.fontButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("..."))) self.fontButton.clicked.connect(self._selectFont) self.mainForm.addRow( self.tr("Font family"), self.guiFont, self.tr("Requires restart to take effect."), button=self.fontButton ) # Font Size self.guiFontSize = QSpinBox(self) self.guiFontSize.setMinimum(8) self.guiFontSize.setMaximum(60) self.guiFontSize.setSingleStep(1) self.guiFontSize.setValue(CONFIG.guiFontSize) self.mainForm.addRow( self.tr("Font size"), self.guiFontSize, self.tr("Requires restart to take effect."), unit=self.tr("pt") ) # GUI Settings # ============ self.mainForm.addGroupLabel(self.tr("GUI Settings")) self.emphLabels = NSwitch() 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."), ) self.showFullPath = NSwitch() 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.") ) self.hideVScroll = NSwitch() 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.") ) self.hideHScroll = NSwitch() 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.") ) return def saveValues(self): """Save the values set for this tab. """ guiLocale = self.guiLocale.currentData() guiTheme = self.guiTheme.currentData() guiSyntax = self.guiSyntax.currentData() guiFont = self.guiFont.text() guiFontSize = self.guiFontSize.value() emphLabels = self.emphLabels.isChecked() # Update Flags self.prefsGui._updateTheme |= CONFIG.guiTheme != guiTheme self.prefsGui._updateSyntax |= CONFIG.guiSyntax != guiSyntax self.prefsGui._needsRestart |= CONFIG.guiLocale != guiLocale self.prefsGui._needsRestart |= CONFIG.guiFont != guiFont self.prefsGui._needsRestart |= CONFIG.guiFontSize != guiFontSize self.prefsGui._refreshTree |= CONFIG.emphLabels != emphLabels CONFIG.guiLocale = guiLocale CONFIG.guiTheme = guiTheme CONFIG.guiSyntax = guiSyntax CONFIG.guiFont = guiFont CONFIG.guiFontSize = guiFontSize CONFIG.emphLabels = emphLabels CONFIG.showFullPath = self.showFullPath.isChecked() CONFIG.hideVScroll = self.hideVScroll.isChecked() CONFIG.hideHScroll = self.hideHScroll.isChecked() return ## # Slots ## def _selectFont(self): """Open the QFontDialog and set a font for the font style. """ currFont = QFont() currFont.setFamily(CONFIG.guiFont) currFont.setPointSize(CONFIG.guiFontSize) theFont, theStatus = QFontDialog.getFont(currFont, self) if theStatus: self.guiFont.setText(theFont.family()) self.guiFontSize.setValue(theFont.pointSize()) return # END Class GuiPreferencesGeneral class GuiPreferencesProjects(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) # Automatic Save # ============== self.mainForm.addGroupLabel(self.tr("Automatic Save")) # Document Save Timer self.autoSaveDoc = QSpinBox(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 = QSpinBox(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") ) # Project Backup # ============== self.mainForm.addGroupLabel(self.tr("Project Backup")) # Backup Path self.backupPath = CONFIG.backupPath() self.backupGetPath = QPushButton(self.tr("Browse")) self.backupGetPath.clicked.connect(self._backupFolder) self.backupPathRow = self.mainForm.addRow( self.tr("Backup storage location"), self.backupGetPath, self.tr("Path: {0}").format(self.backupPath) ) # Run when closing self.backupOnClose = NSwitch() 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.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 # ============= self.mainForm.addGroupLabel(self.tr("Session Timer")) # Pause when idle self.stopWhenIdle = NSwitch() 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 = QDoubleSpinBox() 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") ) return def saveValues(self): """Save the values set for this tab. """ # Automatic Save CONFIG.autoSaveDoc = self.autoSaveDoc.value() CONFIG.autoSaveProj = self.autoSaveProj.value() # 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) return ## # Slots ## def _backupFolder(self): """Open a dialog to select the backup folder. """ currDir = self.backupPath or "" newDir = QFileDialog.getExistingDirectory( self, self.tr("Backup Directory"), str(currDir), options=QFileDialog.ShowDirsOnly ) if newDir: self.backupPath = newDir self.mainForm.setHelpText( self.backupPathRow, self.tr("Path: {0}").format(self.backupPath) ) return True return False def _toggledBackupOnClose(self, theState): """Enable or disable switch that depends on the backup on close switch. """ self.askBeforeBackup.setEnabled(theState) return # END Class GuiPreferencesProjects class GuiPreferencesDocuments(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) # Text Style # ========== self.mainForm.addGroupLabel(self.tr("Text Style")) # Font Family self.textFont = QLineEdit() self.textFont.setReadOnly(True) self.textFont.setFixedWidth(CONFIG.pxInt(162)) self.textFont.setText(CONFIG.textFont) self.fontButton = QPushButton("...") self.fontButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("..."))) self.fontButton.clicked.connect(self._selectFont) self.mainForm.addRow( self.tr("Font family"), self.textFont, self.tr("Applies to both document editor and viewer."), button=self.fontButton ) # Font Size self.textSize = QSpinBox(self) self.textSize.setMinimum(8) self.textSize.setMaximum(60) self.textSize.setSingleStep(1) self.textSize.setValue(CONFIG.textSize) self.mainForm.addRow( self.tr("Font size"), self.textSize, self.tr("Applies to both document editor and viewer."), unit=self.tr("pt") ) # Text Flow # ========= self.mainForm.addGroupLabel(self.tr("Text Flow")) # Max Text Width in Normal Mode self.textWidth = QSpinBox(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 = QSpinBox(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.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.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 = QSpinBox(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 = QSpinBox(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") ) return def saveValues(self): """Save the values set for this tab. """ # Text Style CONFIG.setTextFont(self.textFont.text(), self.textSize.value()) # 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() return ## # Slots ## def _selectFont(self): """Open the QFontDialog and set a font for the font style. """ currFont = QFont() currFont.setFamily(CONFIG.textFont) currFont.setPointSize(CONFIG.textSize) theFont, theStatus = QFontDialog.getFont(currFont, self) if theStatus: self.textFont.setText(theFont.family()) self.textSize.setValue(theFont.pointSize()) return # END Class GuiPreferencesDocuments class GuiPreferencesEditor(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) mW = CONFIG.pxInt(250) # Spell Checking # ============== self.mainForm.addGroupLabel(self.tr("Spell Checking")) # Spell Check Provider and Language self.spellLanguage = QComboBox(self) self.spellLanguage.setMaximumWidth(mW) if CONFIG.hasEnchant: for tag, language in SHARED.spelling.listDictionaries(): self.spellLanguage.addItem(language, tag) else: self.spellLanguage.addItem(self.tr("None"), "") self.spellLanguage.setEnabled(False) spellIdx = self.spellLanguage.findData(CONFIG.spellLanguage) if spellIdx != -1: self.spellLanguage.setCurrentIndex(spellIdx) self.mainForm.addRow( self.tr("Spell check language"), self.spellLanguage, self.tr("Available languages are determined by your system.") ) # Word Count # ========== self.mainForm.addGroupLabel(self.tr("Word Count")) # Word Count Timer self.wordCountTimer = QDoubleSpinBox(self) self.wordCountTimer.setDecimals(1) self.wordCountTimer.setMinimum(2.0) self.wordCountTimer.setMaximum(600.0) self.wordCountTimer.setSingleStep(0.1) self.wordCountTimer.setValue(CONFIG.wordCountTimer) self.mainForm.addRow( self.tr("Word count interval"), self.wordCountTimer, unit=self.tr("seconds") ) # Include Notes in Word Count self.incNotesWCount = NSwitch() self.incNotesWCount.setChecked(CONFIG.incNotesWCount) self.mainForm.addRow( self.tr("Include project notes in status bar word count"), self.incNotesWCount ) # Writing Guides # ============== self.mainForm.addGroupLabel(self.tr("Writing Guides")) # Show Tabs and Spaces self.showTabsNSpaces = NSwitch() self.showTabsNSpaces.setChecked(CONFIG.showTabsNSpaces) self.mainForm.addRow( self.tr("Show tabs and spaces"), self.showTabsNSpaces ) # Show Line Endings self.showLineEndings = NSwitch() self.showLineEndings.setChecked(CONFIG.showLineEndings) self.mainForm.addRow( self.tr("Show line endings"), self.showLineEndings ) # Scroll Behaviour # ================ self.mainForm.addGroupLabel(self.tr("Scroll Behaviour")) # Typewriter Scrolling self.autoScroll = NSwitch() 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 = QSpinBox(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="%" ) return def saveValues(self): """Save the values set for this tab.""" # Spell Checking CONFIG.spellLanguage = self.spellLanguage.currentData() # Word Count CONFIG.wordCountTimer = self.wordCountTimer.value() CONFIG.incNotesWCount = self.incNotesWCount.isChecked() # Writing Guides CONFIG.showTabsNSpaces = self.showTabsNSpaces.isChecked() CONFIG.showLineEndings = self.showLineEndings.isChecked() # Scroll Behaviour CONFIG.autoScroll = self.autoScroll.isChecked() CONFIG.autoScrollPos = self.autoScrollPos.value() return # END Class GuiPreferencesEditor class GuiPreferencesSyntax(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) self.prefsGui = prefsGui # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) # Quotes & Dialogue # ================= self.mainForm.addGroupLabel(self.tr("Quotes & Dialogue")) self.highlightQuotes = NSwitch() self.highlightQuotes.setChecked(CONFIG.highlightQuotes) self.highlightQuotes.toggled.connect(self._toggleHighlightQuotes) self.mainForm.addRow( self.tr("Highlight text wrapped in quotes"), self.highlightQuotes, self.tr("Applies to the document editor only.") ) self.allowOpenSQuote = NSwitch() self.allowOpenSQuote.setChecked(CONFIG.allowOpenSQuote) self.mainForm.addRow( self.tr("Allow open-ended single quotes"), self.allowOpenSQuote, self.tr("Highlight single-quoted line with no closing quote.") ) self.allowOpenDQuote = NSwitch() self.allowOpenDQuote.setChecked(CONFIG.allowOpenDQuote) self.mainForm.addRow( self.tr("Allow open-ended double quotes"), self.allowOpenDQuote, self.tr("Highlight double-quoted line with no closing quote.") ) # Text Emphasis # ============= self.mainForm.addGroupLabel(self.tr("Text Emphasis")) self.highlightEmph = NSwitch() 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.") ) # Text Errors # =========== self.mainForm.addGroupLabel(self.tr("Text Errors")) self.showMultiSpaces = NSwitch() self.showMultiSpaces.setChecked(CONFIG.showMultiSpaces) self.mainForm.addRow( self.tr("Highlight multiple or trailing spaces"), self.showMultiSpaces, self.tr("Applies to the document editor only.") ) return def saveValues(self): """Save the values set for this tab. """ highlightQuotes = self.highlightQuotes.isChecked() allowOpenSQuote = self.allowOpenSQuote.isChecked() allowOpenDQuote = self.allowOpenDQuote.isChecked() highlightEmph = self.highlightEmph.isChecked() showMultiSpaces = self.showMultiSpaces.isChecked() self.prefsGui._updateSyntax |= CONFIG.highlightQuotes != highlightQuotes self.prefsGui._updateSyntax |= CONFIG.highlightEmph != highlightEmph self.prefsGui._updateSyntax |= CONFIG.showMultiSpaces != showMultiSpaces CONFIG.highlightQuotes = highlightQuotes CONFIG.allowOpenSQuote = allowOpenSQuote CONFIG.allowOpenDQuote = allowOpenDQuote CONFIG.highlightEmph = highlightEmph CONFIG.showMultiSpaces = showMultiSpaces return ## # Slots ## def _toggleHighlightQuotes(self, theState): """Enables or disables switches controlled by the highlight quotes switch. """ self.allowOpenSQuote.setEnabled(theState) self.allowOpenDQuote.setEnabled(theState) return # END Class GuiPreferencesSyntax class GuiPreferencesAutomation(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) # Automatic Features # ================== self.mainForm.addGroupLabel(self.tr("Automatic Features")) # Auto-Select Word Under Cursor self.autoSelect = NSwitch() 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.") ) # Auto-Replace as You Type Main Switch self.doReplace = NSwitch() 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.") ) # Replace as You Type # =================== self.mainForm.addGroupLabel(self.tr("Replace as You Type")) # Auto-Replace Single Quotes self.doReplaceSQuote = NSwitch() 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.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.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.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.") ) # Automatic Padding # ================= self.mainForm.addGroupLabel(self.tr("Automatic Padding")) # Pad Before self.fmtPadBefore = QLineEdit() self.fmtPadBefore.setMaxLength(32) 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."), ) # Pad After self.fmtPadAfter = QLineEdit() self.fmtPadAfter.setMaxLength(32) 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."), ) # Use Thin Space self.fmtPadThin = NSwitch() 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.") ) return def saveValues(self): """Save the values set for this tab. """ # Automatic Features CONFIG.autoSelect = self.autoSelect.isChecked() CONFIG.doReplace = self.doReplace.isChecked() # Replace as You Type CONFIG.doReplaceSQuote = self.doReplaceSQuote.isChecked() CONFIG.doReplaceDQuote = self.doReplaceDQuote.isChecked() CONFIG.doReplaceDash = self.doReplaceDash.isChecked() CONFIG.doReplaceDots = self.doReplaceDots.isChecked() # Automatic Padding CONFIG.fmtPadBefore = self.fmtPadBefore.text().strip() CONFIG.fmtPadAfter = self.fmtPadAfter.text().strip() CONFIG.fmtPadThin = self.fmtPadThin.isChecked() return ## # Slots ## def _toggleAutoReplaceMain(self, theState): """Enables or disables switches controlled by the main auto replace switch. """ self.doReplaceSQuote.setEnabled(theState) self.doReplaceDQuote.setEnabled(theState) self.doReplaceDash.setEnabled(theState) self.doReplaceDots.setEnabled(theState) self.fmtPadThin.setEnabled(theState) return # END Class GuiPreferencesAutomation class GuiPreferencesQuotes(QWidget): def __init__(self, prefsGui): super().__init__(parent=prefsGui) # The Form self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.setLayout(self.mainForm) # Quotation Style # =============== self.mainForm.addGroupLabel(self.tr("Quotation Style")) qWidth = CONFIG.pxInt(40) bWidth = int(2.5*SHARED.theme.getTextWidth("...")) self.quoteSym = {} # Single Quote Style self.quoteSym["SO"] = QLineEdit() self.quoteSym["SO"].setMaxLength(1) self.quoteSym["SO"].setReadOnly(True) self.quoteSym["SO"].setFixedWidth(qWidth) self.quoteSym["SO"].setAlignment(Qt.AlignCenter) self.quoteSym["SO"].setText(CONFIG.fmtSQuoteOpen) self.btnSingleStyleO = QPushButton("...") self.btnSingleStyleO.setMaximumWidth(bWidth) self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO")) self.mainForm.addRow( self.tr("Single quote open style"), self.quoteSym["SO"], self.tr("The symbol to use for a leading single quote."), button=self.btnSingleStyleO ) self.quoteSym["SC"] = QLineEdit() self.quoteSym["SC"].setMaxLength(1) self.quoteSym["SC"].setReadOnly(True) self.quoteSym["SC"].setFixedWidth(qWidth) self.quoteSym["SC"].setAlignment(Qt.AlignCenter) self.quoteSym["SC"].setText(CONFIG.fmtSQuoteClose) self.btnSingleStyleC = QPushButton("...") self.btnSingleStyleC.setMaximumWidth(bWidth) self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC")) self.mainForm.addRow( self.tr("Single quote close style"), self.quoteSym["SC"], self.tr("The symbol to use for a trailing single quote."), button=self.btnSingleStyleC ) # Double Quote Style self.quoteSym["DO"] = QLineEdit() self.quoteSym["DO"].setMaxLength(1) self.quoteSym["DO"].setReadOnly(True) self.quoteSym["DO"].setFixedWidth(qWidth) self.quoteSym["DO"].setAlignment(Qt.AlignCenter) self.quoteSym["DO"].setText(CONFIG.fmtDQuoteOpen) self.btnDoubleStyleO = QPushButton("...") self.btnDoubleStyleO.setMaximumWidth(bWidth) self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO")) self.mainForm.addRow( self.tr("Double quote open style"), self.quoteSym["DO"], self.tr("The symbol to use for a leading double quote."), button=self.btnDoubleStyleO ) self.quoteSym["DC"] = QLineEdit() self.quoteSym["DC"].setMaxLength(1) self.quoteSym["DC"].setReadOnly(True) self.quoteSym["DC"].setFixedWidth(qWidth) self.quoteSym["DC"].setAlignment(Qt.AlignCenter) self.quoteSym["DC"].setText(CONFIG.fmtDQuoteClose) self.btnDoubleStyleC = QPushButton("...") self.btnDoubleStyleC.setMaximumWidth(bWidth) self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC")) self.mainForm.addRow( self.tr("Double quote close style"), self.quoteSym["DC"], self.tr("The symbol to use for a trailing double quote."), button=self.btnDoubleStyleC ) return def saveValues(self): """Save the values set for this tab. """ # Quotation Style CONFIG.fmtSQuoteOpen = self.quoteSym["SO"].text() CONFIG.fmtSQuoteClose = self.quoteSym["SC"].text() CONFIG.fmtDQuoteOpen = self.quoteSym["DO"].text() CONFIG.fmtDQuoteClose = self.quoteSym["DC"].text() return ## # Slots ## def _getQuote(self, qType): """Dialog for single quote open. """ qtBox = GuiQuoteSelect(self, currentQuote=self.quoteSym[qType].text()) if qtBox.exec_() == QDialog.Accepted: self.quoteSym[qType].setText(qtBox.selectedQuote) return # END Class GuiPreferencesQuotes