diff --git a/novelwriter/core/buildsettings.py b/novelwriter/core/buildsettings.py index 7c62c5b9..d390d2d2 100644 --- a/novelwriter/core/buildsettings.py +++ b/novelwriter/core/buildsettings.py @@ -178,7 +178,6 @@ SETTINGS_LABELS = { } RENAMED = { - "odt.addColours": "doc.addColours", "odt.pageHeader": "doc.pageHeader", "odt.pageCountOffset": "doc.pageCountOffset", } diff --git a/novelwriter/dialogs/about.py b/novelwriter/dialogs/about.py index cb132ce1..6cc7b8e1 100644 --- a/novelwriter/dialogs/about.py +++ b/novelwriter/dialogs/about.py @@ -32,7 +32,7 @@ from PyQt6.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.common import cssCol, readTextFile -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.modified import NDialog from novelwriter.extensions.versioninfo import VersionInfoWidget from novelwriter.types import QtAlignRightTop, QtDialogClose @@ -68,7 +68,7 @@ class GuiAbout(NDialog): self.nwLicence.setOpenExternalLinks(True) # Credits - self.lblCredits = NColourLabel( + self.lblCredits = NColorLabel( self.tr("Credits"), self, scale=1.6, bold=True ) diff --git a/novelwriter/dialogs/docmerge.py b/novelwriter/dialogs/docmerge.py index 2033b118..d2e5e686 100644 --- a/novelwriter/dialogs/docmerge.py +++ b/novelwriter/dialogs/docmerge.py @@ -33,7 +33,7 @@ from PyQt6.QtWidgets import ( ) from novelwriter import SHARED -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.modified import NDialog from novelwriter.extensions.switch import NSwitch from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk, QtDialogReset, QtUserRole @@ -56,7 +56,7 @@ class GuiDocMerge(NDialog): self.headLabel = QLabel(self.tr("Documents to Merge"), self) self.headLabel.setFont(SHARED.theme.guiFontB) - self.helpLabel = NColourLabel( + self.helpLabel = NColorLabel( self.tr("Drag and drop items to change the order, or uncheck to exclude."), self, color=SHARED.theme.helpText, wrap=True ) diff --git a/novelwriter/dialogs/docsplit.py b/novelwriter/dialogs/docsplit.py index 4707eb51..a123bbe4 100644 --- a/novelwriter/dialogs/docsplit.py +++ b/novelwriter/dialogs/docsplit.py @@ -33,7 +33,7 @@ from PyQt6.QtWidgets import ( ) from novelwriter import SHARED -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.modified import NDialog from novelwriter.extensions.switch import NSwitch from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk, QtUserRole @@ -60,7 +60,7 @@ class GuiDocSplit(NDialog): self.headLabel = QLabel(self.tr("Document Headings"), self) self.headLabel.setFont(SHARED.theme.guiFontB) - self.helpLabel = NColourLabel( + self.helpLabel = NColorLabel( self.tr("Select the maximum level to split into files."), self, color=SHARED.theme.helpText, wrap=True ) diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index bd14c589..bf5ae277 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -38,7 +38,7 @@ from novelwriter.common import compact, describeFont, uniqueCompact from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL from novelwriter.constants import nwLabels, nwUnicode, trConst from novelwriter.dialogs.quotes import GuiQuoteSelect -from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm +from novelwriter.extensions.configlayout import NColorLabel, NScrollableForm from novelwriter.extensions.modified import ( NComboBox, NDialog, NDoubleSpinBox, NIconToolButton, NSpinBox ) @@ -63,9 +63,9 @@ class GuiPreferences(NDialog): self.resize(*CONFIG.prefsWinSize) # Title - self.titleLabel = NColourLabel( + self.titleLabel = NColorLabel( self.tr("Preferences"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE, indent=4, + scale=NColorLabel.HEADER_SCALE, indent=4, ) # Search Box diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index 414edaa3..810df7a0 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -42,7 +42,7 @@ from novelwriter.common import formatFileFilter, qtLambda, simplified from novelwriter.constants import nwLabels, trConst from novelwriter.core.status import NWStatus, StatusEntry from novelwriter.enum import nwStatusShape -from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm +from novelwriter.extensions.configlayout import NColorLabel, NFixedPage, NScrollableForm from novelwriter.extensions.modified import NComboBox, NDialog, NIconToolButton from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.switch import NSwitch @@ -78,9 +78,9 @@ class GuiProjectSettings(NDialog): ) # Title - self.titleLabel = NColourLabel( + self.titleLabel = NColorLabel( self.tr("Project Settings"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE, indent=4, + scale=NColorLabel.HEADER_SCALE, indent=4, ) # SideBar @@ -339,9 +339,9 @@ class _StatusPage(NFixedPage): self.trSelColor = self.tr("Select Colour") # Title - self.pageTitle = NColourLabel( + self.pageTitle = NColorLabel( pageLabel, self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE + scale=NColorLabel.HEADER_SCALE ) # List Box @@ -398,7 +398,7 @@ class _StatusPage(NFixedPage): self.colorButton.setSizePolicy(QtSizeMinimum, QtSizeMinimumExpanding) self.colorButton.setStyleSheet(buttonStyle) self.colorButton.setEnabled(False) - self.colorButton.clicked.connect(self._onColourSelect) + self.colorButton.clicked.connect(self._onColorSelect) def buildMenu(menu: QMenu | None, items: dict[nwStatusShape, str]) -> None: if menu is not None: @@ -494,7 +494,7 @@ class _StatusPage(NFixedPage): return @pyqtSlot() - def _onColourSelect(self) -> None: + def _onColorSelect(self) -> None: """Open a dialog to select the status icon colour.""" if (color := QColorDialog.getColor(self._color, self, self.trSelColor)).isValid(): self._color = color @@ -675,9 +675,9 @@ class _ReplacePage(NFixedPage): wCol0 = SHARED.project.options.getInt("GuiProjectSettings", "replaceColW", 130) # Title - self.pageTitle = NColourLabel( + self.pageTitle = NColorLabel( self.tr("Text Auto-Replace for Preview and Build"), self, - color=SHARED.theme.helpText, scale=NColourLabel.HEADER_SCALE + color=SHARED.theme.helpText, scale=NColorLabel.HEADER_SCALE ) # List Box diff --git a/novelwriter/dialogs/wordlist.py b/novelwriter/dialogs/wordlist.py index cf91b491..65d19193 100644 --- a/novelwriter/dialogs/wordlist.py +++ b/novelwriter/dialogs/wordlist.py @@ -37,7 +37,7 @@ from PyQt6.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.common import formatFileFilter from novelwriter.core.spellcheck import UserDictionary -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.modified import NDialog, NIconToolButton from novelwriter.types import QtDialogClose, QtDialogSave @@ -65,9 +65,9 @@ class GuiWordList(NDialog): ) # Header - self.headLabel = NColourLabel( + self.headLabel = NColorLabel( self.tr("Project Word List"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE + scale=NColorLabel.HEADER_SCALE ) self.importButton = NIconToolButton(self, iSz, "import", "green") diff --git a/novelwriter/extensions/configlayout.py b/novelwriter/extensions/configlayout.py index f9a0d940..8183f9a9 100644 --- a/novelwriter/extensions/configlayout.py +++ b/novelwriter/extensions/configlayout.py @@ -101,7 +101,7 @@ class NScrollableForm(QScrollArea): self._indent = 12 self._sections: dict[int, QLabel] = {} - self._editable: dict[str, NColourLabel] = {} + self._editable: dict[str, NColorLabel] = {} self._index: dict[str, QWidget] = {} self._layout = QVBoxLayout() @@ -216,7 +216,7 @@ class NScrollableForm(QScrollArea): qLabel.setBuddy(qWidget) if helpText: - qHelp = NColourLabel( + qHelp = NColorLabel( str(helpText), self, color=self._helpCol, scale=self._fontScale, wrap=True, indent=self._indent ) @@ -257,7 +257,7 @@ class NScrollableForm(QScrollArea): return -class NColourLabel(QLabel): +class NColorLabel(QLabel): """Extension: A Coloured Label A custom widget that draws a label in a specific colour, and diff --git a/novelwriter/extensions/progressbars.py b/novelwriter/extensions/progressbars.py index 358501ac..456d1550 100644 --- a/novelwriter/extensions/progressbars.py +++ b/novelwriter/extensions/progressbars.py @@ -56,7 +56,7 @@ class NProgressCircle(QProgressBar): self._cRect = QRect(point, point, size - 2*point, size - 2*point) self._dPen = QPen(QtTransparent) self._dBrush = QBrush(QtTransparent) - self.setColours( + self.setColors( track=self.palette().alternateBase().color(), bar=self.palette().highlight().color(), text=self.palette().text().color() @@ -66,8 +66,10 @@ class NProgressCircle(QProgressBar): self.setFixedHeight(size) return - def setColours(self, back: QColor | None = None, track: QColor | None = None, - bar: QColor | None = None, text: QColor | None = None) -> None: + def setColors( + self, back: QColor | None = None, track: QColor | None = None, + bar: QColor | None = None, text: QColor | None = None + ) -> None: """Set the colours of the widget.""" if isinstance(back, QColor): self._dPen = QPen(back) diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 101859b8..753168c1 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -61,7 +61,7 @@ from novelwriter.enum import ( nwChange, nwComment, nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwItemType, nwTrinary ) -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.eventfilters import WheelEventFilter from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton from novelwriter.gui.dochighlight import BLOCK_META, BLOCK_TITLE @@ -219,7 +219,7 @@ class GuiDocEditor(QPlainTextEdit): self.changeFocusState = self.docHeader.changeFocusState # Finalise - self.updateSyntaxColours() + self.updateSyntaxColors() self.initEditor() logger.debug("Ready: GuiDocEditor") @@ -287,7 +287,7 @@ class GuiDocEditor(QPlainTextEdit): self.docToolBar.updateTheme() return - def updateSyntaxColours(self) -> None: + def updateSyntaxColors(self) -> None: """Update the syntax highlighting theme.""" syntax = SHARED.theme.syntaxTheme @@ -303,8 +303,8 @@ class GuiDocEditor(QPlainTextEdit): palette.setColor(QPalette.ColorRole.Text, syntax.text) viewport.setPalette(palette) - self.docHeader.matchColours() - self.docFooter.matchColours() + self.docHeader.matchColors() + self.docFooter.matchColors() return @@ -339,14 +339,12 @@ class GuiDocEditor(QPlainTextEdit): # Also set the document text options for the document text flow options = QTextOption() - if CONFIG.doJustify: options.setAlignment(QtAlignJustify) if CONFIG.showTabsNSpaces: options.setFlags(options.flags() | QTextOption.Flag.ShowTabsAndSpaces) if CONFIG.showLineEndings: options.setFlags(options.flags() | QTextOption.Flag.ShowLineAndParagraphSeparators) - self._qDocument.setDefaultTextOption(options) # Scrolling @@ -379,19 +377,19 @@ class GuiDocEditor(QPlainTextEdit): """Load text from a document into the editor. If we have an I/O error, we must handle this and clear the editor so that we don't risk overwriting the file if it exists. This can for instance - happen of the file contains binary elements or an encoding that + happen if the file contains binary elements or an encoding that novelWriter does not support. If loading is successful, or the document is new (empty string), we set up the editor for editing the file. """ self._nwDocument = SHARED.project.storage.getDocument(tHandle) self._nwItem = self._nwDocument.nwItem - if not ((nwItem := self._nwItem) and nwItem.itemType == nwItemType.FILE): + if not (self._nwItem and self._nwItem.itemType == nwItemType.FILE): logger.debug("Requested item '%s' is not a document", tHandle) self.clearEditor() return False - if (docText := self._nwDocument.readDocument()) is None: + if (text := self._nwDocument.readDocument()) is None: # There was an I/O error self.clearEditor() return False @@ -400,7 +398,7 @@ class GuiDocEditor(QPlainTextEdit): self._docHandle = tHandle self._allowAutoReplace(False) - self._qDocument.setTextContent(docText, tHandle) + self._qDocument.setTextContent(text, tHandle) self._allowAutoReplace(True) QApplication.processEvents() @@ -415,7 +413,7 @@ class GuiDocEditor(QPlainTextEdit): if isinstance(tLine, int): self.setCursorLine(tLine) else: - self.setCursorPosition(nwItem.cursorPos) + self.setCursorPosition(self._nwItem.cursorPos) self.docHeader.setHandle(tHandle) self.docFooter.setHandle(tHandle) @@ -438,7 +436,7 @@ class GuiDocEditor(QPlainTextEdit): # Finalise QApplication.restoreOverrideCursor() self.updateStatusMessage.emit( - self.tr("Opened Document: {0}").format(nwItem.itemName) + self.tr("Opened Document: {0}").format(self._nwItem.itemName) ) return True @@ -469,19 +467,17 @@ class GuiDocEditor(QPlainTextEdit): ) return False - docText = self.getText() - cC, wC, pC = standardCounter(docText) + text = self.getText() + cC, wC, pC = standardCounter(text) self._updateDocCounts(cC, wC, pC) - if not self._nwDocument.writeDocument(docText): + if not self._nwDocument.writeDocument(text): saveOk = False - if self._nwDocument.hashError: - msgYes = SHARED.question(self.tr( - "This document has been changed outside of novelWriter " - "while it was open. Overwrite the file on disk?" - )) - if msgYes: - saveOk = self._nwDocument.writeDocument(docText, forceWrite=True) + if self._nwDocument.hashError and SHARED.question(self.tr( + "This document has been changed outside of novelWriter " + "while it was open. Overwrite the file on disk?" + )): + saveOk = self._nwDocument.writeDocument(text, forceWrite=True) if not saveOk: SHARED.error( @@ -494,10 +490,8 @@ class GuiDocEditor(QPlainTextEdit): self.setDocumentChanged(False) self.docTextChanged.emit(self._docHandle, self._lastEdit) - oldHeader = self._nwItem.mainHeading oldCount = SHARED.project.index.getHandleHeaderCount(tHandle) - SHARED.project.index.scanText(tHandle, docText) - newHeader = self._nwItem.mainHeading + SHARED.project.index.scanText(tHandle, text) newCount = SHARED.project.index.getHandleHeaderCount(tHandle) if self._nwItem.itemClass == nwItemClass.NOVEL: @@ -506,9 +500,6 @@ class GuiDocEditor(QPlainTextEdit): else: self.novelStructureChanged.emit() - if oldHeader != newHeader: - self.docFooter.updateInfo() - # Update the status bar self.updateStatusMessage.emit(self.tr("Saved Document: {0}").format(self._nwItem.itemName)) @@ -589,7 +580,7 @@ class GuiDocEditor(QPlainTextEdit): QTextDocument->toRawText instead of toPlainText. The former preserves non-breaking spaces, the latter does not. We still want to get rid of paragraph and line separators though. - See: https://doc.qt.io/qt-5/qtextdocument.html#toPlainText + See: https://doc.qt.io/qt-6/qtextdocument.html#toPlainText """ text = self._qDocument.toRawText() text = text.replace(nwUnicode.U_LSEP, "\n") # Line separators @@ -627,10 +618,9 @@ class GuiDocEditor(QPlainTextEdit): def setCursorPosition(self, position: int) -> None: """Move the cursor to a given position in the document.""" - nChars = self._qDocument.characterCount() - if nChars > 1 and isinstance(position, int): + if (chars := self._qDocument.characterCount()) > 1 and isinstance(position, int): cursor = self.textCursor() - cursor.setPosition(minmax(position, 0, nChars-1)) + cursor.setPosition(minmax(position, 0, chars-1)) self.setTextCursor(cursor) self.centerCursor() return @@ -693,12 +683,10 @@ class GuiDocEditor(QPlainTextEdit): def spellCheckDocument(self) -> None: """Rerun the highlighter to update spell checking status of the - currently loaded text. The fastest way to do this, at least as - of Qt 5.13, is to clear the text and put it back. This clears - the undo stack, so we only do it for big documents. + currently loaded text. """ - logger.debug("Running spell checker") start = time() + logger.debug("Running spell checker") QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) self._qDocument.syntaxHighlighter.rehighlight() QApplication.restoreOverrideCursor() @@ -939,9 +927,7 @@ class GuiDocEditor(QPlainTextEdit): * We also handle automatic scrolling here. """ self._lastActive = time() - isReturn = event.key() == Qt.Key.Key_Return - isReturn |= event.key() == Qt.Key.Key_Enter - if isReturn and self.docSearch.anyFocus(): + if self.docSearch.anyFocus() and event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter): return elif event == QKeySequence.StandardKey.Redo: self.docAction(nwDocAction.REDO) @@ -1094,7 +1080,7 @@ class GuiDocEditor(QPlainTextEdit): if (block := self._qDocument.findBlock(pos)).isValid(): text = block.text() if text.startswith("@") and added + removed == 1: - # Only run on single keypresses, otherwise it will trigger + # Only run on single character changes, or it will trigger # at unwanted times when other changes are made to the document cursor = self.textCursor() bPos = cursor.positionInBlock() @@ -1106,10 +1092,10 @@ class GuiDocEditor(QPlainTextEdit): else: self._completer.setVisible(False) - if self._doReplace and added == 1: - cursor = self.textCursor() - if self._autoReplace.process(text, cursor): - self._qDocument.syntaxHighlighter.rehighlightBlock(cursor.block()) + if self._doReplace and added == 1: + cursor = self.textCursor() + if self._autoReplace.process(text, cursor): + self._qDocument.syntaxHighlighter.rehighlightBlock(cursor.block()) return @@ -1123,11 +1109,10 @@ class GuiDocEditor(QPlainTextEdit): def _insertCompletion(self, pos: int, length: int, text: str) -> None: """Insert choice from the completer menu.""" cursor = self.textCursor() - block = cursor.block() - if block.isValid(): - pos += block.position() - cursor.setPosition(pos, QtMoveAnchor) - cursor.setPosition(pos + length, QtKeepAnchor) + if (block := cursor.block()).isValid(): + check = pos + block.position() + cursor.setPosition(check, QtMoveAnchor) + cursor.setPosition(check + length, QtKeepAnchor) cursor.insertText(text) self._completer.hide() return @@ -1220,7 +1205,8 @@ class GuiDocEditor(QPlainTextEdit): # Execute the context menu if viewport := self.viewport(): ctxMenu.exec(viewport.mapToGlobal(pos)) - ctxMenu.deleteLater() + + ctxMenu.setParent(None) return @@ -1277,15 +1263,11 @@ class GuiDocEditor(QPlainTextEdit): @pyqtSlot() def _runSelCounter(self) -> None: """Update the selection word count.""" - if self._docHandle is None: - return - - if self._wCounterSel.isRunning(): - logger.debug("Selection word counter is busy") - return - - SHARED.runInThreadPool(self._wCounterSel) - + if self._docHandle: + if self._wCounterSel.isRunning(): + logger.debug("Selection word counter is busy") + return + SHARED.runInThreadPool(self._wCounterSel) return @pyqtSlot(int, int, int) @@ -1565,8 +1547,10 @@ class GuiDocEditor(QPlainTextEdit): return - def _wrapSelection(self, before: str, after: str | None = None, pos: int | None = None, - select: _SelectAction = _SelectAction.NO_DECISION) -> None: + def _wrapSelection( + self, before: str, after: str | None = None, pos: int | None = None, + select: _SelectAction = _SelectAction.NO_DECISION + ) -> None: """Wrap the selected text in whatever is in tBefore and tAfter. If there is no selection, the autoSelect setting decides the action. AutoSelect will select the word under the cursor before @@ -1928,8 +1912,9 @@ class GuiDocEditor(QPlainTextEdit): self._qDocument.syntaxHighlighter.rehighlightBlock(block) return - def _processTag(self, cursor: QTextCursor | None = None, - follow: bool = True, create: bool = False) -> nwTrinary: + def _processTag( + self, cursor: QTextCursor | None = None, follow: bool = True, create: bool = False + ) -> nwTrinary: """Activated by Ctrl+Enter. Checks that we're in a block starting with '@'. We then find the tag under the cursor and check that it is not the tag itself. If all this is fine, we @@ -2163,13 +2148,10 @@ class BackgroundWordCounter(QRunnable): def __init__(self, docEditor: GuiDocEditor, forSelection: bool = False) -> None: super().__init__() - self._docEditor = docEditor self._forSelection = forSelection self._isRunning = False - self.signals = BackgroundWordCounterSignals() - return def isRunning(self) -> bool: @@ -2851,7 +2833,7 @@ class GuiDocEditHeader(QWidget): self.setAutoFillBackground(True) # Title Label - self.itemTitle = NColourLabel("", self, faded=SHARED.theme.fadedText) + self.itemTitle = NColorLabel("", self, faded=SHARED.theme.fadedText) self.itemTitle.setMargin(0) self.itemTitle.setContentsMargins(0, 0, 0, 0) self.itemTitle.setAutoFillBackground(True) @@ -2969,11 +2951,11 @@ class GuiDocEditHeader(QWidget): self.minmaxButton.setStyleSheet(buttonStyle) self.closeButton.setStyleSheet(buttonStyle) - self.matchColours() + self.matchColors() return - def matchColours(self) -> None: + def matchColors(self) -> None: """Update the colours of the widget to match those of the syntax theme rather than the main GUI. """ @@ -3079,42 +3061,30 @@ class GuiDocEditFooter(QWidget): # Status self.statusIcon = QLabel("", self) - self.statusIcon.setContentsMargins(0, 0, 0, 0) self.statusIcon.setFixedHeight(iPx) self.statusIcon.setAlignment(QtAlignLeftTop) - self.statusText = QLabel(self.tr("Status"), self) - self.statusText.setIndent(0) - self.statusText.setMargin(0) - self.statusText.setContentsMargins(0, 0, 0, 0) + self.statusText = QLabel("", self) self.statusText.setAutoFillBackground(True) self.statusText.setFixedHeight(fPx) self.statusText.setAlignment(QtAlignLeftTop) # Lines self.linesIcon = QLabel("", self) - self.linesIcon.setContentsMargins(0, 0, 0, 0) self.linesIcon.setFixedHeight(iPx) self.linesIcon.setAlignment(QtAlignLeftTop) self.linesText = QLabel("", self) - self.linesText.setIndent(0) - self.linesText.setMargin(0) - self.linesText.setContentsMargins(0, 0, 0, 0) self.linesText.setAutoFillBackground(True) self.linesText.setFixedHeight(fPx) self.linesText.setAlignment(QtAlignLeftTop) # Words self.wordsIcon = QLabel("", self) - self.wordsIcon.setContentsMargins(0, 0, 0, 0) self.wordsIcon.setFixedHeight(iPx) self.wordsIcon.setAlignment(QtAlignLeftTop) self.wordsText = QLabel("", self) - self.wordsText.setIndent(0) - self.wordsText.setMargin(0) - self.wordsText.setContentsMargins(0, 0, 0, 0) self.wordsText.setAutoFillBackground(True) self.wordsText.setFixedHeight(fPx) self.wordsText.setAlignment(QtAlignLeftTop) @@ -3167,10 +3137,10 @@ class GuiDocEditFooter(QWidget): iPx = round(0.9*SHARED.theme.baseIconHeight) self.linesIcon.setPixmap(SHARED.theme.getPixmap("lines", (iPx, iPx))) self.wordsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx))) - self.matchColours() + self.matchColors() return - def matchColours(self) -> None: + def matchColors(self) -> None: """Update the colours of the widget to match those of the syntax theme rather than the main GUI. """ diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index 0be61bf4..b94043d1 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -45,7 +45,7 @@ from novelwriter.common import decodeMimeHandles, qtAddAction, qtLambda from novelwriter.constants import nwConst, nwStyles, nwUnicode from novelwriter.enum import nwChange, nwDocAction, nwDocMode, nwItemType from novelwriter.error import logException -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.eventfilters import WheelEventFilter from novelwriter.extensions.modified import NIconToolButton from novelwriter.formats.shared import TextDocumentTheme @@ -167,8 +167,8 @@ class GuiDocViewer(QTextBrowser): palette.setColor(QPalette.ColorRole.Base, syntax.back) palette.setColor(QPalette.ColorRole.Text, syntax.text) viewport.setPalette(palette) - self.docHeader.matchColours() - self.docFooter.matchColours() + self.docHeader.matchColors() + self.docFooter.matchColors() # Update theme colours self._docTheme.text = syntax.text @@ -424,7 +424,8 @@ class GuiDocViewer(QTextBrowser): # Open the context menu if viewport := self.viewport(): ctxMenu.exec(viewport.mapToGlobal(point)) - ctxMenu.deleteLater() + + ctxMenu.setParent(None) return @@ -643,7 +644,7 @@ class GuiDocViewHeader(QWidget): self.setAutoFillBackground(True) # Title Label - self.itemTitle = NColourLabel("", self, faded=SHARED.theme.fadedText) + self.itemTitle = NColorLabel("", self, faded=SHARED.theme.fadedText) self.itemTitle.setMargin(0) self.itemTitle.setContentsMargins(0, 0, 0, 0) self.itemTitle.setAutoFillBackground(True) @@ -774,11 +775,11 @@ class GuiDocViewHeader(QWidget): self.refreshButton.setStyleSheet(buttonStyle) self.closeButton.setStyleSheet(buttonStyle) - self.matchColours() + self.matchColors() return - def matchColours(self) -> None: + def matchColors(self) -> None: """Update the colours of the widget to match those of the syntax theme rather than the main GUI. """ @@ -960,11 +961,11 @@ class GuiDocViewFooter(QWidget): self.showComments.setStyleSheet(buttonStyle) self.showSynopsis.setStyleSheet(buttonStyle) - self.matchColours() + self.matchColors() return - def matchColours(self) -> None: + def matchColors(self) -> None: """Update the colours of the widget to match those of the syntax theme rather than the main GUI. """ diff --git a/novelwriter/gui/itemdetails.py b/novelwriter/gui/itemdetails.py index bb33b65d..0b33645a 100644 --- a/novelwriter/gui/itemdetails.py +++ b/novelwriter/gui/itemdetails.py @@ -90,6 +90,7 @@ class GuiItemDetails(QWidget): self.statusData = QLabel("", self) self.statusData.setFont(fntValue) self.statusData.setAlignment(QtAlignLeft) + self.statusData.setWordWrap(True) # Class self.className = QLabel(self.tr("Class"), self) diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index 8b1e9a0d..594a9280 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -46,7 +46,7 @@ from novelwriter.common import checkInt, formatFileFilter from novelwriter.constants import nwKeyWords, nwLabels, nwStats, nwStyles, trConst from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline from novelwriter.error import logException -from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.extensions.configlayout import NColorLabel from novelwriter.extensions.novelselector import NovelSelector from novelwriter.types import ( QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration, @@ -222,8 +222,8 @@ class GuiOutlineToolBar(QToolBar): stretch.setSizePolicy(QtSizeExpanding, QtSizeExpanding) # Novel Selector - self.novelLabel = NColourLabel( - self.tr("Outline of"), self, scale=NColourLabel.HEADER_SCALE, bold=True + self.novelLabel = NColorLabel( + self.tr("Outline of"), self, scale=NColorLabel.HEADER_SCALE, bold=True ) self.novelLabel.setContentsMargins(0, 0, 12, 0) diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 181f6f31..20878bc4 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -969,7 +969,8 @@ class GuiProjectTree(QTreeView): if viewport := self.viewport(): ctxMenu.exec(viewport.mapToGlobal(point)) - ctxMenu.deleteLater() + + ctxMenu.setParent(None) return diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 70156dc7..2aaacda3 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -250,26 +250,26 @@ class GuiTheme: # Icons sec = "Icons" if parser.has_section(sec): - self.iconCache.setIconColor("default", self._parseColour(parser, sec, "default")) - self.iconCache.setIconColor("faded", self._parseColour(parser, sec, "faded")) - self.iconCache.setIconColor("red", self._parseColour(parser, sec, "red")) - self.iconCache.setIconColor("orange", self._parseColour(parser, sec, "orange")) - self.iconCache.setIconColor("yellow", self._parseColour(parser, sec, "yellow")) - self.iconCache.setIconColor("green", self._parseColour(parser, sec, "green")) - self.iconCache.setIconColor("aqua", self._parseColour(parser, sec, "aqua")) - self.iconCache.setIconColor("blue", self._parseColour(parser, sec, "blue")) - self.iconCache.setIconColor("purple", self._parseColour(parser, sec, "purple")) + self.iconCache.setIconColor("default", self._parseColor(parser, sec, "default")) + self.iconCache.setIconColor("faded", self._parseColor(parser, sec, "faded")) + self.iconCache.setIconColor("red", self._parseColor(parser, sec, "red")) + self.iconCache.setIconColor("orange", self._parseColor(parser, sec, "orange")) + self.iconCache.setIconColor("yellow", self._parseColor(parser, sec, "yellow")) + self.iconCache.setIconColor("green", self._parseColor(parser, sec, "green")) + self.iconCache.setIconColor("aqua", self._parseColor(parser, sec, "aqua")) + self.iconCache.setIconColor("blue", self._parseColor(parser, sec, "blue")) + self.iconCache.setIconColor("purple", self._parseColor(parser, sec, "purple")) # Project sec = "Project" if parser.has_section(sec): - self.iconCache.setIconColor("root", self._parseColour(parser, sec, "root")) - self.iconCache.setIconColor("folder", self._parseColour(parser, sec, "folder")) - self.iconCache.setIconColor("file", self._parseColour(parser, sec, "file")) - self.iconCache.setIconColor("title", self._parseColour(parser, sec, "title")) - self.iconCache.setIconColor("chapter", self._parseColour(parser, sec, "chapter")) - self.iconCache.setIconColor("scene", self._parseColour(parser, sec, "scene")) - self.iconCache.setIconColor("note", self._parseColour(parser, sec, "note")) + self.iconCache.setIconColor("root", self._parseColor(parser, sec, "root")) + self.iconCache.setIconColor("folder", self._parseColor(parser, sec, "folder")) + self.iconCache.setIconColor("file", self._parseColor(parser, sec, "file")) + self.iconCache.setIconColor("title", self._parseColor(parser, sec, "title")) + self.iconCache.setIconColor("chapter", self._parseColor(parser, sec, "chapter")) + self.iconCache.setIconColor("scene", self._parseColor(parser, sec, "scene")) + self.iconCache.setIconColor("note", self._parseColor(parser, sec, "note")) # Palette sec = "Palette" @@ -292,9 +292,9 @@ class GuiTheme: # GUI sec = "GUI" if parser.has_section(sec): - self.helpText = self._parseColour(parser, sec, "helptext") - self.fadedText = self._parseColour(parser, sec, "fadedtext") - self.errorText = self._parseColour(parser, sec, "errortext") + self.helpText = self._parseColor(parser, sec, "helptext") + self.fadedText = self._parseColor(parser, sec, "fadedtext") + self.errorText = self._parseColor(parser, sec, "errortext") # Update Dependant Colours # Based on: https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qplatformtheme.cpp @@ -399,26 +399,26 @@ class GuiTheme: sec = "Syntax" syntax = SyntaxColors() if parser.has_section(sec): - syntax.back = self._parseColour(parser, sec, "background") - syntax.text = self._parseColour(parser, sec, "text") - syntax.link = self._parseColour(parser, sec, "link") - syntax.head = self._parseColour(parser, sec, "headertext") - syntax.headH = self._parseColour(parser, sec, "headertag") - syntax.emph = self._parseColour(parser, sec, "emphasis") - syntax.dialN = self._parseColour(parser, sec, "dialog") - syntax.dialA = self._parseColour(parser, sec, "altdialog") - syntax.hidden = self._parseColour(parser, sec, "hidden") - syntax.note = self._parseColour(parser, sec, "note") - syntax.code = self._parseColour(parser, sec, "shortcode") - syntax.key = self._parseColour(parser, sec, "keyword") - syntax.tag = self._parseColour(parser, sec, "tag") - syntax.val = self._parseColour(parser, sec, "value") - syntax.opt = self._parseColour(parser, sec, "optional") - syntax.spell = self._parseColour(parser, sec, "spellcheckline") - syntax.error = self._parseColour(parser, sec, "errorline") - syntax.repTag = self._parseColour(parser, sec, "replacetag") - syntax.mod = self._parseColour(parser, sec, "modifier") - syntax.mark = self._parseColour(parser, sec, "texthighlight") + syntax.back = self._parseColor(parser, sec, "background") + syntax.text = self._parseColor(parser, sec, "text") + syntax.link = self._parseColor(parser, sec, "link") + syntax.head = self._parseColor(parser, sec, "headertext") + syntax.headH = self._parseColor(parser, sec, "headertag") + syntax.emph = self._parseColor(parser, sec, "emphasis") + syntax.dialN = self._parseColor(parser, sec, "dialog") + syntax.dialA = self._parseColor(parser, sec, "altdialog") + syntax.hidden = self._parseColor(parser, sec, "hidden") + syntax.note = self._parseColor(parser, sec, "note") + syntax.code = self._parseColor(parser, sec, "shortcode") + syntax.key = self._parseColor(parser, sec, "keyword") + syntax.tag = self._parseColor(parser, sec, "tag") + syntax.val = self._parseColor(parser, sec, "value") + syntax.opt = self._parseColor(parser, sec, "optional") + syntax.spell = self._parseColor(parser, sec, "spellcheckline") + syntax.error = self._parseColor(parser, sec, "errorline") + syntax.repTag = self._parseColor(parser, sec, "replacetag") + syntax.mod = self._parseColor(parser, sec, "modifier") + syntax.mark = self._parseColor(parser, sec, "texthighlight") self.syntaxMeta = meta self.syntaxTheme = syntax @@ -513,7 +513,7 @@ class GuiTheme: return - def _parseColour(self, parser: NWConfigParser, section: str, name: str) -> QColor: + def _parseColor(self, parser: NWConfigParser, section: str, name: str) -> QColor: """Parse a colour value from a config string.""" return QColor(*parser.rdIntList(section, name, [0, 0, 0, 255])) @@ -521,7 +521,7 @@ class GuiTheme: self, parser: NWConfigParser, section: str, name: str, value: QPalette.ColorRole ) -> None: """Set a palette colour value from a config string.""" - self._guiPalette.setBrush(value, self._parseColour(parser, section, name)) + self._guiPalette.setBrush(value, self._parseColor(parser, section, name)) return def _buildStyleSheets(self, palette: QPalette) -> None: diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 47d85a4a..4dfcbf07 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -1064,7 +1064,7 @@ class GuiMain(QMainWindow): if syntax: SHARED.theme.loadSyntax() - self.docEditor.updateSyntaxColours() + self.docEditor.updateSyntaxColors() self.docEditor.initEditor() self.docViewer.initViewer() diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index d0d0708c..af50cfd3 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -773,7 +773,7 @@ class _PreviewWidget(QTextBrowser): self.buildProgress.setVisible(False) self.buildProgress.setMaximum(1) self.buildProgress.setValue(0) - self.buildProgress.setColours( + self.buildProgress.setColors( back=QColor(255, 255, 255, 224), track=QColor(196, 196, 196, 128), text=QColor(0, 0, 0) diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py index 78d59725..dbc64771 100644 --- a/novelwriter/tools/manussettings.py +++ b/novelwriter/tools/manussettings.py @@ -41,7 +41,7 @@ from novelwriter.common import describeFont, fontMatcher, qtAddAction, qtLambda from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles, trConst from novelwriter.core.buildsettings import BuildSettings, FilterMode from novelwriter.extensions.configlayout import ( - NColourLabel, NFixedPage, NScrollableForm, NScrollablePage + NColorLabel, NFixedPage, NScrollableForm, NScrollablePage ) from novelwriter.extensions.modified import ( NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox, NToolDialog @@ -92,9 +92,9 @@ class GuiBuildSettings(NToolDialog): ) # Title - self.titleLabel = NColourLabel( + self.titleLabel = NColorLabel( self.tr("Manuscript Build Settings"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE, indent=4, + scale=NColorLabel.HEADER_SCALE, indent=4, ) # Settings Name diff --git a/novelwriter/tools/noveldetails.py b/novelwriter/tools/noveldetails.py index c23a513e..84692407 100644 --- a/novelwriter/tools/noveldetails.py +++ b/novelwriter/tools/noveldetails.py @@ -37,7 +37,7 @@ from PyQt6.QtWidgets import ( from novelwriter import SHARED from novelwriter.common import formatTime, numberToRoman from novelwriter.constants import nwUnicode -from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage +from novelwriter.extensions.configlayout import NColorLabel, NFixedPage, NScrollablePage from novelwriter.extensions.modified import NNonBlockingDialog from novelwriter.extensions.novelselector import NovelSelector from novelwriter.extensions.pagedsidebar import NPagedSideBar @@ -67,9 +67,9 @@ class GuiNovelDetails(NNonBlockingDialog): ) # Title - self.titleLabel = NColourLabel( + self.titleLabel = NColorLabel( self.tr("Novel Details"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE, indent=4, + scale=NColorLabel.HEADER_SCALE, indent=4, ) # Novel Selector @@ -188,9 +188,9 @@ class _OverviewPage(NScrollablePage): super().__init__(parent=parent) # Project Info - self.projLabel = NColourLabel( + self.projLabel = NColorLabel( self.tr("Project"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE + scale=NColorLabel.HEADER_SCALE ) self.projName = QLabel("", self) @@ -212,9 +212,9 @@ class _OverviewPage(NScrollablePage): self.projForm.setVerticalSpacing(4) # Novel Info - self.novelLabel = NColourLabel( + self.novelLabel = NColorLabel( self.tr("Selected Novel"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE + scale=NColorLabel.HEADER_SCALE ) self.novelName = QLabel("", self) @@ -302,9 +302,9 @@ class _ContentsPage(NFixedPage): options = SHARED.project.options # Title - self.contentLabel = NColourLabel( + self.contentLabel = NColorLabel( self.tr("Table of Contents"), self, color=SHARED.theme.helpText, - scale=NColourLabel.HEADER_SCALE + scale=NColorLabel.HEADER_SCALE ) # Contents Tree diff --git a/novelwriter/tools/welcome.py b/novelwriter/tools/welcome.py index 354b206d..287fd416 100644 --- a/novelwriter/tools/welcome.py +++ b/novelwriter/tools/welcome.py @@ -366,7 +366,7 @@ class _OpenProjectPage(QWidget): action = qtAddAction(ctxMenu, self.tr("Remove Project")) action.triggered.connect(self._deleteSelectedItem) ctxMenu.exec(self.mapToGlobal(pos)) - ctxMenu.deleteLater() + ctxMenu.setParent(None) return ## diff --git a/tests/test_ext/test_ext_progressbars.py b/tests/test_ext/test_ext_progressbars.py index f3872735..f0d1e292 100644 --- a/tests/test_ext/test_ext_progressbars.py +++ b/tests/test_ext/test_ext_progressbars.py @@ -42,7 +42,7 @@ def testExtProgressBars_NProgressCircle(qtbot): dialog.show() dialog.resize(200, 200) - progress.setColours( + progress.setColors( QColor(255, 255, 255), QColor(255, 192, 192), QColor(255, 0, 0), QColor(0, 0, 0), ) diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index 428807f3..2546a9c2 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -333,6 +333,7 @@ def testGuiEditor_MetaData(qtbot, nwGUI, projPath, mockRnd): def testGuiEditor_ContextMenu(monkeypatch, qtbot, nwGUI, projPath, mockRnd): """Test the editor context menu.""" monkeypatch.setattr(QMenu, "exec", lambda *a: None) + monkeypatch.setattr(QMenu, "setParent", lambda *a: None) buildTestProject(nwGUI, projPath) assert nwGUI.openDocument(C.hSceneDoc) is True @@ -475,6 +476,7 @@ def testGuiEditor_ContextMenu(monkeypatch, qtbot, nwGUI, projPath, mockRnd): def testGuiEditor_SpellChecking(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd): """Test the document spell checker.""" monkeypatch.setattr(QMenu, "exec", lambda *a: None) + monkeypatch.setattr(QMenu, "setParent", lambda *a: None) buildTestProject(nwGUI, projPath) assert nwGUI.openDocument(C.hSceneDoc) is True diff --git a/tests/test_gui/test_gui_theme.py b/tests/test_gui/test_gui_theme.py index 825a85ee..e93fbba7 100644 --- a/tests/test_gui/test_gui_theme.py +++ b/tests/test_gui/test_gui_theme.py @@ -79,12 +79,12 @@ def testGuiTheme_Main(qtbot, nwGUI, tstPaths): } # Test the parser for several valid and invalid values - assert mainTheme._parseColour(parser, "Palette", "colour1").getRgb() == (100, 150, 200, 255) - assert mainTheme._parseColour(parser, "Palette", "colour2").getRgb() == (100, 150, 200, 250) - assert mainTheme._parseColour(parser, "Palette", "colour3").getRgb() == (100, 150, 200, 250) - assert mainTheme._parseColour(parser, "Palette", "colour4").getRgb() == (250, 250, 0, 255) - assert mainTheme._parseColour(parser, "Palette", "colour5").getRgb() == (0, 0, 0, 0) - assert mainTheme._parseColour(parser, "Palette", "colour6").getRgb() == (0, 127, 255, 255) + assert mainTheme._parseColor(parser, "Palette", "colour1").getRgb() == (100, 150, 200, 255) + assert mainTheme._parseColor(parser, "Palette", "colour2").getRgb() == (100, 150, 200, 250) + assert mainTheme._parseColor(parser, "Palette", "colour3").getRgb() == (100, 150, 200, 250) + assert mainTheme._parseColor(parser, "Palette", "colour4").getRgb() == (250, 250, 0, 255) + assert mainTheme._parseColor(parser, "Palette", "colour5").getRgb() == (0, 0, 0, 0) + assert mainTheme._parseColor(parser, "Palette", "colour6").getRgb() == (0, 127, 255, 255) # The palette should load with the parsed values mainTheme._setPalette(parser, "Palette", "colour1", QPalette.ColorRole.Window) diff --git a/tests/test_tools/test_tools_welcome.py b/tests/test_tools/test_tools_welcome.py index 228b162f..a999f2ee 100644 --- a/tests/test_tools/test_tools_welcome.py +++ b/tests/test_tools/test_tools_welcome.py @@ -70,6 +70,7 @@ def testToolWelcome_Main(qtbot, monkeypatch, nwGUI, fncPath): def testToolWelcome_Open(qtbot, monkeypatch, nwGUI, fncPath): """Test the open tab in the Welcome window.""" monkeypatch.setattr(QMenu, "exec", lambda *a: None) + monkeypatch.setattr(QMenu, "setParent", lambda *a: None) CONFIG.recentProjects.update("/stuff/project_one", "Project One", 12345, 1690000000) CONFIG.recentProjects.update("/stuff/project_two", "Project Two", 54321, 1700000000)