diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index bef7b2bb..c4a11841 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -26,12 +26,12 @@ from __future__ import annotations import logging -from PyQt5.QtGui import QCloseEvent, QFont, QKeyEvent, QKeySequence from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot +from PyQt5.QtGui import QCloseEvent, QFont, QKeyEvent, QKeySequence from PyQt5.QtWidgets import ( - QAbstractButton, QCompleter, QDialog, QDialogButtonBox, QFileDialog, - QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget, - qApp + QAbstractButton, QApplication, QCompleter, QDialog, QDialogButtonBox, + QFileDialog, QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, + QWidget ) from novelwriter import CONFIG, SHARED @@ -742,7 +742,7 @@ class GuiPreferences(QDialog): logger.debug("Close: GuiPreferences") self._saveWindowSize() event.accept() - qApp.processEvents() + QApplication.processEvents() self.done(nwConst.DLG_FINISHED) self.deleteLater() return diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index c24137fc..4672f1cc 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -26,12 +26,12 @@ from __future__ import annotations import logging -from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot +from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap from PyQt5.QtWidgets import ( - QColorDialog, QDialog, QDialogButtonBox, QHBoxLayout, QLineEdit, - QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout, - QWidget, qApp + QApplication, QColorDialog, QDialog, QDialogButtonBox, QHBoxLayout, + QLineEdit, QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, + QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -195,7 +195,7 @@ class GuiProjectSettings(QDialog): project.data.setAutoReplace(newList) self.newProjectSettingsReady.emit(rebuildTrees) - qApp.processEvents() + QApplication.processEvents() self.close() return diff --git a/novelwriter/dialogs/wordlist.py b/novelwriter/dialogs/wordlist.py index cd2908a9..2aaad24f 100644 --- a/novelwriter/dialogs/wordlist.py +++ b/novelwriter/dialogs/wordlist.py @@ -28,11 +28,11 @@ import logging from typing import TYPE_CHECKING from pathlib import Path -from PyQt5.QtGui import QCloseEvent from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot +from PyQt5.QtGui import QCloseEvent from PyQt5.QtWidgets import ( - QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog, QHBoxLayout, - QLineEdit, QListWidget, QVBoxLayout, qApp + QAbstractItemView, QApplication, QDialog, QDialogButtonBox, QFileDialog, + QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout ) from novelwriter import CONFIG, SHARED @@ -177,7 +177,7 @@ class GuiWordList(QDialog): userDict.add(word) userDict.save() self.newWordListReady.emit() - qApp.processEvents() + QApplication.processEvents() self.close() return diff --git a/novelwriter/error.py b/novelwriter/error.py index 37b40857..e2f10c93 100644 --- a/novelwriter/error.py +++ b/novelwriter/error.py @@ -29,11 +29,11 @@ import logging from typing import TYPE_CHECKING -from PyQt5.QtGui import QFont, QFontDatabase from PyQt5.QtCore import Qt, pyqtSlot +from PyQt5.QtGui import QFont, QFontDatabase from PyQt5.QtWidgets import ( - QWidget, qApp, QDialog, QGridLayout, QStyle, QPlainTextEdit, QLabel, - QDialogButtonBox + QApplication, QWidget, QDialog, QGridLayout, QStyle, QPlainTextEdit, + QLabel, QDialogButtonBox ) if TYPE_CHECKING: # pragma: no cover @@ -74,7 +74,7 @@ class NWErrorMessage(QDialog): # Widgets self.msgIcon = QLabel() self.msgIcon.setPixmap( - qApp.style().standardIcon(QStyle.SP_MessageBoxCritical).pixmap(64, 64) + QApplication.style().standardIcon(QStyle.SP_MessageBoxCritical).pixmap(64, 64) ) self.msgHead = QLabel() self.msgHead.setOpenExternalLinks(True) @@ -179,14 +179,14 @@ class NWErrorMessage(QDialog): def exceptionHandler(exType: type, exValue: BaseException, exTrace: TracebackType) -> None: """Function to catch unhandled global exceptions.""" from traceback import print_tb - from PyQt5.QtWidgets import qApp + from PyQt5.QtWidgets import QApplication logger.critical("%s: %s", exType.__name__, str(exValue)) print_tb(exTrace) try: nwGUI = None - for qWin in qApp.topLevelWidgets(): + for qWin in QApplication.topLevelWidgets(): if qWin.objectName() == "GuiMain": nwGUI = qWin break @@ -209,7 +209,7 @@ def exceptionHandler(exType: type, exValue: BaseException, exTrace: TracebackTyp logger.critical("Could not close the project before exiting") logger.critical(formatException(exc)) - qApp.exit(1) + QApplication.exit(1) except Exception as exc: logger.critical(formatException(exc)) diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index fbf4f224..84b37036 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -47,8 +47,8 @@ from PyQt5.QtGui import ( QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption ) from PyQt5.QtWidgets import ( - QAction, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu, - QPlainTextEdit, QShortcut, QToolBar, QVBoxLayout, QWidget, qApp + QAction, QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, + QMenu, QPlainTextEdit, QShortcut, QToolBar, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -393,13 +393,13 @@ class GuiDocEditor(QPlainTextEdit): self.clearEditor() return False - qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) self._docHandle = tHandle self._allowAutoReplace(False) self._qDocument.setTextContent(docText, tHandle) self._allowAutoReplace(True) - qApp.processEvents() + QApplication.processEvents() self._lastEdit = time() self._lastActive = time() @@ -423,12 +423,12 @@ class GuiDocEditor(QPlainTextEdit): self.setPlainText("") self.setCursorPosition(0) - qApp.processEvents() + QApplication.processEvents() self.setDocumentChanged(False) self._qDocument.clearUndoRedoStacks() self.docToolBar.setVisible(CONFIG.showEditToolBar) - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() # Update the status bar if self._nwItem is not None: @@ -445,11 +445,11 @@ class GuiDocEditor(QPlainTextEdit): """Replace the text of the current document with the provided text. This also clears undo history. """ - qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) self.setPlainText(text) self.updateDocMargins() self.setDocumentChanged(True) - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() return def saveText(self) -> bool: @@ -536,7 +536,7 @@ class GuiDocEditor(QPlainTextEdit): while self.cursorRect().bottom() > vH and count < 100000: vBar.setValue(vBar.value() + 1) count += 1 - qApp.processEvents() + QApplication.processEvents() return def updateDocMargins(self) -> None: @@ -699,9 +699,9 @@ class GuiDocEditor(QPlainTextEdit): """ logger.debug("Running spell checker") start = time() - qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) self._qDocument.syntaxHighlighter.rehighlight() - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() logger.debug("Document highlighted in %.3f ms", 1000*(time() - start)) self.statusMessage.emit(self.tr("Spell check complete")) return @@ -814,7 +814,7 @@ class GuiDocEditor(QPlainTextEdit): def anyFocus(self) -> bool: """Check if any widget or child widget has focus.""" - return self.hasFocus() or self.isAncestorOf(qApp.focusWidget()) + return self.hasFocus() or self.isAncestorOf(QApplication.focusWidget()) def revealLocation(self) -> None: """Tell the user where on the file system the file in the editor @@ -991,7 +991,7 @@ class GuiDocEditor(QPlainTextEdit): pressed, check if we're clicking on a tag, and trigger the follow tag function. """ - if qApp.keyboardModifiers() == Qt.KeyboardModifier.ControlModifier: + if QApplication.keyboardModifiers() == Qt.KeyboardModifier.ControlModifier: self._processTag(self.cursorForPosition(event.pos())) super().mouseReleaseEvent(event) return @@ -1912,7 +1912,7 @@ class GuiDocEditor(QPlainTextEdit): ).format(tag)): itemClass = nwKeyWords.KEY_CLASS.get(tBits[0], nwItemClass.NO_CLASS) self.requestNewNoteCreation.emit(tag, itemClass) - qApp.processEvents() + QApplication.processEvents() self._qDocument.syntaxHighlighter.rehighlightBlock(block) return nwTrinary.POSITIVE if exist else nwTrinary.NEGATIVE @@ -2627,7 +2627,7 @@ class GuiDocEditSearch(QFrame): def updateTheme(self) -> None: """Update theme elements.""" - qPalette = qApp.palette() + qPalette = QApplication.palette() self.setPalette(qPalette) self.searchBox.setPalette(qPalette) self.replaceBox.setPalette(qPalette) @@ -2714,7 +2714,7 @@ class GuiDocEditSearch(QFrame): def _doSearch(self) -> None: """Call the search action function for the document editor.""" self.docEditor.findNext(goBack=( - qApp.keyboardModifiers() == Qt.KeyboardModifier.ShiftModifier) + QApplication.keyboardModifiers() == Qt.KeyboardModifier.ShiftModifier) ) return diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index 4e4eee8d..58cda227 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -36,8 +36,8 @@ from PyQt5.QtGui import ( QTextOption ) from PyQt5.QtWidgets import ( - QAction, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser, QToolButton, - QWidget, qApp + QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser, + QToolButton, QWidget ) from novelwriter import CONFIG, SHARED @@ -195,7 +195,7 @@ class GuiDocViewer(QTextBrowser): return False logger.debug("Generating preview for item '%s'", tHandle) - qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) sPos = self.verticalScrollBar().value() aDoc = ToHtml(SHARED.project) @@ -217,7 +217,7 @@ class GuiDocViewer(QTextBrowser): logger.error("Failed to generate preview for document with handle '%s'", tHandle) logException() self.setText(self.tr("An error occurred while generating the preview.")) - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() return False # Refresh the tab stops @@ -250,7 +250,7 @@ class GuiDocViewer(QTextBrowser): # Since we change the content while it may still be rendering, we mark # the document dirty again to make sure it's re-rendered properly. self.redrawText() - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() self.documentLoaded.emit(tHandle) return True diff --git a/novelwriter/gui/editordocument.py b/novelwriter/gui/editordocument.py index 04babe3f..0bbfd1b5 100644 --- a/novelwriter/gui/editordocument.py +++ b/novelwriter/gui/editordocument.py @@ -25,14 +25,14 @@ from __future__ import annotations import logging -from time import time from collections.abc import Iterable +from time import time from PyQt5.QtGui import QTextBlock, QTextCursor, QTextDocument from PyQt5.QtCore import QObject, pyqtSlot -from PyQt5.QtWidgets import QPlainTextDocumentLayout, qApp -from novelwriter import SHARED +from PyQt5.QtWidgets import QApplication, QPlainTextDocumentLayout +from novelwriter import SHARED from novelwriter.gui.dochighlight import GuiDocHighlighter, TextBlockData logger = logging.getLogger(__name__) @@ -86,7 +86,7 @@ class GuiTextDocument(QTextDocument): self.setUndoRedoEnabled(True) self.blockSignals(False) self._syntax.rehighlight() - qApp.processEvents() + QApplication.processEvents() tEnd = time() diff --git a/novelwriter/gui/search.py b/novelwriter/gui/search.py index 769689ee..5dfb1253 100644 --- a/novelwriter/gui/search.py +++ b/novelwriter/gui/search.py @@ -30,8 +30,8 @@ from time import time from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot from PyQt5.QtGui import QCursor, QKeyEvent from PyQt5.QtWidgets import ( - QFrame, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QToolBar, QTreeWidget, - QTreeWidgetItem, QVBoxLayout, QWidget, qApp + QApplication, QFrame, QHBoxLayout, QHeaderView, QLabel, QLineEdit, + QToolBar, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -257,7 +257,7 @@ class GuiProjectSearch(QWidget): def _processSearch(self) -> None: """Perform a search.""" if not self._blocked: - qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) start = time() SHARED.mainGui.saveDocument() self._blocked = True @@ -271,7 +271,7 @@ class GuiProjectSearch(QWidget): self._displayResultSet(item, results, capped) logger.debug("Search took %.3f ms", 1000*(time() - start)) self._time = time() - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() self._blocked = False return @@ -355,7 +355,7 @@ class GuiProjectSearch(QWidget): for i in range(tItem.childCount()): self.searchResult.setFirstColumnSpanned(i, parent, True) - qApp.processEvents() + QApplication.processEvents() return diff --git a/novelwriter/gui/statusbar.py b/novelwriter/gui/statusbar.py index 85befc60..1d709b69 100644 --- a/novelwriter/gui/statusbar.py +++ b/novelwriter/gui/statusbar.py @@ -25,12 +25,12 @@ from __future__ import annotations import logging +from datetime import datetime from time import time from typing import TYPE_CHECKING, Literal -from datetime import datetime from PyQt5.QtCore import pyqtSlot, QLocale -from PyQt5.QtWidgets import qApp, QStatusBar, QLabel +from PyQt5.QtWidgets import QApplication, QStatusBar, QLabel from novelwriter import CONFIG, SHARED from novelwriter.common import formatTime @@ -198,7 +198,7 @@ class GuiMainStatus(QStatusBar): def setStatusMessage(self, message: str) -> None: """Set the status bar message to display.""" self.showMessage(message, nwConst.STATUS_MSG_TIMEOUT) - qApp.processEvents() + QApplication.processEvents() return @pyqtSlot(str, str) @@ -240,7 +240,7 @@ class GuiMainStatus(QStatusBar): import tracemalloc from collections import Counter - widgets = qApp.allWidgets() + widgets = QApplication.allWidgets() if not self._debugInfo: if tracemalloc.is_tracing(): self._traceMallocRef = "Total" diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index db993cb3..2b2003db 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -30,16 +30,16 @@ from math import ceil from pathlib import Path from PyQt5.QtCore import QSize, Qt -from PyQt5.QtWidgets import qApp from PyQt5.QtGui import ( QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap ) +from PyQt5.QtWidgets import QApplication from novelwriter import CONFIG -from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType -from novelwriter.error import logException from novelwriter.common import NWConfigParser, cssCol, minmax from novelwriter.constants import nwLabels +from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType +from novelwriter.error import logException logger = logging.getLogger(__name__) @@ -144,15 +144,15 @@ class GuiTheme: self.getHeaderDecorationNarrow = self.iconCache.getHeaderDecorationNarrow # Extract Other Info - self.guiDPI = qApp.primaryScreen().logicalDotsPerInchX() - self.guiScale = qApp.primaryScreen().logicalDotsPerInchX()/96.0 + self.guiDPI = QApplication.primaryScreen().logicalDotsPerInchX() + self.guiScale = QApplication.primaryScreen().logicalDotsPerInchX()/96.0 CONFIG.guiScale = self.guiScale logger.debug("GUI DPI: %.1f", self.guiDPI) logger.debug("GUI Scale: %.2f", self.guiScale) # Fonts - self.guiFont = qApp.font() - self.guiFontB = qApp.font() + self.guiFont = QApplication.font() + self.guiFontB = QApplication.font() self.guiFontB.setBold(True) qMetric = QFontMetrics(self.guiFont) @@ -255,7 +255,7 @@ class GuiTheme: self._setPalette(parser, sec, "link", QPalette.ColorRole.Link) self._setPalette(parser, sec, "linkvisited", QPalette.ColorRole.LinkVisited) else: - self._guiPalette = qApp.style().standardPalette() + self._guiPalette = QApplication.style().standardPalette() # GUI sec = "GUI" @@ -284,7 +284,7 @@ class GuiTheme: self.iconCache.loadTheme(self.themeIcons or defaultIcons) # Apply Styles - qApp.setPalette(self._guiPalette) + QApplication.setPalette(self._guiPalette) # Reset stylesheets so that they are regenerated self._buildStyleSheets(self._guiPalette) @@ -408,7 +408,7 @@ class GuiTheme: font.setFamily(CONFIG.guiFont) font.setPointSize(CONFIG.guiFontSize) - qApp.setFont(font) + QApplication.setFont(font) return diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 14f9a494..e52219ef 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -30,11 +30,11 @@ from time import time from pathlib import Path from datetime import datetime -from PyQt5.QtGui import QCloseEvent, QCursor, QIcon from PyQt5.QtCore import Qt, QTimer, pyqtSlot +from PyQt5.QtGui import QCloseEvent, QCursor, QIcon from PyQt5.QtWidgets import ( - QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut, QSplitter, - QStackedWidget, QVBoxLayout, QWidget, qApp + QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut, QSplitter, + QStackedWidget, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED, __hexversion__, __version__ @@ -109,7 +109,7 @@ class GuiMain(QMainWindow): nwIcon = CONFIG.assetPath("icons") / "novelwriter.svg" self.nwIcon = QIcon(str(nwIcon)) if nwIcon.is_file() else QIcon() self.setWindowIcon(self.nwIcon) - qApp.setWindowIcon(self.nwIcon) + QApplication.setWindowIcon(self.nwIcon) # Build the GUI # ============= @@ -328,7 +328,7 @@ class GuiMain(QMainWindow): def postLaunchTasks(self, cmdOpen: str | None) -> None: """Process tasks after the main window has been created.""" if cmdOpen: - qApp.processEvents() + QApplication.processEvents() logger.info("Command line path: %s", cmdOpen) self.openProject(cmdOpen) @@ -474,12 +474,12 @@ class GuiMain(QMainWindow): break if lastEdited is not None: - qApp.processEvents() + QApplication.processEvents() self.openDocument(lastEdited, doScroll=True) lastViewed = SHARED.project.data.getLastHandle("viewer") if lastViewed is not None: - qApp.processEvents() + QApplication.processEvents() self.viewDocument(lastViewed) # Check if we need to rebuild the index @@ -488,7 +488,7 @@ class GuiMain(QMainWindow): self.rebuildIndex() # Make sure the changed status is set to false on things opened - qApp.processEvents() + QApplication.processEvents() self.docEditor.setDocumentChanged(False) SHARED.project.setProjectChanged(False) @@ -738,7 +738,7 @@ class GuiMain(QMainWindow): """Rebuild the entire index.""" if SHARED.hasProject: logger.info("Rebuilding index ...") - qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) tStart = time() self.projView.saveProjectTasks() @@ -752,7 +752,7 @@ class GuiMain(QMainWindow): ) self.docEditor.updateTagHighLighting() self._updateStatusWordCount() - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() if not beQuiet: SHARED.info(self.tr("The project index has been successfully rebuilt.")) @@ -797,7 +797,7 @@ class GuiMain(QMainWindow): dialog.setModal(True) dialog.show() dialog.raise_() - qApp.processEvents() + QApplication.processEvents() dialog.updateValues() return @@ -810,7 +810,7 @@ class GuiMain(QMainWindow): dialog.setModal(False) dialog.show() dialog.raise_() - qApp.processEvents() + QApplication.processEvents() dialog.loadContent() return @@ -832,7 +832,7 @@ class GuiMain(QMainWindow): dialog.setModal(False) dialog.show() dialog.raise_() - qApp.processEvents() + QApplication.processEvents() dialog.populateGUI() return @@ -843,7 +843,7 @@ class GuiMain(QMainWindow): dialog.setModal(True) dialog.show() dialog.raise_() - qApp.processEvents() + QApplication.processEvents() dialog.populateGUI() return @@ -861,7 +861,7 @@ class GuiMain(QMainWindow): dialog.setModal(True) dialog.show() dialog.raise_() - qApp.processEvents() + QApplication.processEvents() if not dialog.initDialog(): dialog.close() SHARED.error(self.tr("Could not initialise the dialog.")) @@ -909,7 +909,7 @@ class GuiMain(QMainWindow): CONFIG.saveConfig() self.reportConfErr() - qApp.quit() + QApplication.quit() return True @@ -1056,7 +1056,7 @@ class GuiMain(QMainWindow): if theme: # We are doing this manually instead of connecting to - # qApp.paletteChanged since the processing order matters + # paletteChanged since the processing order matters SHARED.theme.loadTheme() self.docEditor.updateTheme() self.docViewer.updateTheme() @@ -1115,7 +1115,7 @@ class GuiMain(QMainWindow): @pyqtSlot(Path) def _openProjectFromWelcome(self, path: Path) -> None: """Handle an open project request from the welcome dialog.""" - qApp.processEvents() + QApplication.processEvents() self.openProject(path) if not SHARED.hasProject: self.showWelcomeDialog() @@ -1212,7 +1212,7 @@ class GuiMain(QMainWindow): if SHARED.hasProject: currTime = time() editIdle = currTime - self.docEditor.lastActive > CONFIG.userIdleTime - userIdle = qApp.applicationState() != Qt.ApplicationActive + userIdle = QApplication.applicationState() != Qt.ApplicationActive self.mainStatus.setUserIdle(editIdle or userIdle) SHARED.updateIdleTime(currTime, editIdle or userIdle) self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime) diff --git a/novelwriter/tools/dictionaries.py b/novelwriter/tools/dictionaries.py index 33d0d7af..de3438b8 100644 --- a/novelwriter/tools/dictionaries.py +++ b/novelwriter/tools/dictionaries.py @@ -28,11 +28,11 @@ import logging from pathlib import Path from zipfile import ZipFile -from PyQt5.QtGui import QCloseEvent, QTextCursor from PyQt5.QtCore import pyqtSlot +from PyQt5.QtGui import QCloseEvent, QTextCursor from PyQt5.QtWidgets import ( - QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QLabel, - QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget, qApp + QApplication, QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, + QLabel, QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -158,7 +158,7 @@ class GuiDictionaries(QDialog): "Additional dictionaries found: {0}" ).format(len(self._currDicts))) - qApp.processEvents() + QApplication.processEvents() self.adjustSize() return True diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index 7528477a..01c6801e 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -26,19 +26,19 @@ from __future__ import annotations import json import logging +from datetime import datetime from time import time from typing import TYPE_CHECKING -from datetime import datetime -from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent from PyQt5.QtCore import QTimer, QUrl, Qt, pyqtSignal, pyqtSlot -from PyQt5.QtWidgets import ( - QAbstractItemView, QDialog, QFormLayout, QGridLayout, QHBoxLayout, QLabel, - QListWidget, QListWidgetItem, QPushButton, QSizePolicy, QSplitter, - QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem, - QVBoxLayout, QWidget, qApp -) +from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent from PyQt5.QtPrintSupport import QPrintPreviewDialog, QPrinter +from PyQt5.QtWidgets import ( + QAbstractItemView, QApplication, QDialog, QFormLayout, QGridLayout, + QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton, + QSizePolicy, QSplitter, QStackedWidget, QTabWidget, QTextBrowser, + QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget +) from novelwriter import CONFIG, SHARED from novelwriter.common import checkInt, fuzzyTime @@ -352,7 +352,7 @@ class GuiManuscript(QDialog): self.docPreview.beginNewBuild(len(docBuild)) for step, _ in docBuild.iterBuildHTML(None): self.docPreview.buildStep(step + 1) - qApp.processEvents() + QApplication.processEvents() buildObj = docBuild.lastBuild assert isinstance(buildObj, ToHtml) @@ -486,7 +486,7 @@ class GuiManuscript(QDialog): dlgSettings.setModal(False) dlgSettings.show() dlgSettings.raise_() - qApp.processEvents() + QApplication.processEvents() dlgSettings.loadContent() dlgSettings.newSettingsReady.connect(self._processNewSettings) @@ -850,16 +850,16 @@ class _PreviewWidget(QTextBrowser): def buildStep(self, value: int) -> None: """Update the progress bar value.""" self.buildProgress.setValue(value) - qApp.processEvents() + QApplication.processEvents() return def setContent(self, data: dict) -> None: """Set the content of the preview widget.""" sPos = self.verticalScrollBar().value() - qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) self.buildProgress.setCentreText(self.tr("Processing ...")) - qApp.processEvents() + QApplication.processEvents() styles = "\n".join(data.get("styles", [])) self.document().setDefaultStyleSheet(styles) @@ -867,7 +867,7 @@ class _PreviewWidget(QTextBrowser): html = "".join(data.get("html", [])) html = html.replace("\t", "!!tab!!") self.setHtml(html) - qApp.processEvents() + QApplication.processEvents() while self.find("!!tab!!"): cursor = self.textCursor() cursor.insertText("\t") @@ -881,8 +881,8 @@ class _PreviewWidget(QTextBrowser): self.document().markContentsDirty(0, self.document().characterCount()) self.buildProgress.setCentreText(self.tr("Done")) - qApp.restoreOverrideCursor() - qApp.processEvents() + QApplication.restoreOverrideCursor() + QApplication.processEvents() QTimer.singleShot(300, self._hideProgress) return @@ -904,10 +904,10 @@ class _PreviewWidget(QTextBrowser): @pyqtSlot("QPrinter*") def printPreview(self, printer: QPrinter) -> None: """Connect the print preview painter to the document viewer.""" - qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) printer.setOrientation(QPrinter.Portrait) self.document().print(printer) - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() return @pyqtSlot(str) diff --git a/novelwriter/tools/welcome.py b/novelwriter/tools/welcome.py index 4a680e69..fa2bd022 100644 --- a/novelwriter/tools/welcome.py +++ b/novelwriter/tools/welcome.py @@ -25,19 +25,19 @@ from __future__ import annotations import logging -from pathlib import Path from datetime import datetime +from pathlib import Path -from PyQt5.QtGui import QCloseEvent, QColor, QFont, QPaintEvent, QPainter, QPen from PyQt5.QtCore import ( QAbstractListModel, QEvent, QModelIndex, QObject, QPoint, QSize, Qt, pyqtSignal, pyqtSlot ) +from PyQt5.QtGui import QCloseEvent, QColor, QFont, QPaintEvent, QPainter, QPen from PyQt5.QtWidgets import ( - QAction, QDialog, QFileDialog, QFormLayout, QHBoxLayout, QLabel, QLineEdit, - QListView, QMenu, QPushButton, QScrollArea, QShortcut, QStackedWidget, - QStyle, QStyleOptionViewItem, QStyledItemDelegate, QVBoxLayout, QWidget, - qApp + QAction, QApplication, QDialog, QFileDialog, QFormLayout, QHBoxLayout, + QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut, + QStackedWidget, QStyle, QStyleOptionViewItem, QStyledItemDelegate, + QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -411,11 +411,11 @@ class _ProjectListItem(QStyledItemDelegate): self._pPx = (mPx//2, 3*mPx//2, iPx + mPx, mPx, mPx + tPx) # Painter coordinates self._hPx = 2*mPx + tPx + fPx # Fixed height - self._tFont = qApp.font() + self._tFont = QApplication.font() self._tFont.setPointSizeF(1.2*fPt) self._tFont.setWeight(QFont.Weight.Bold) - self._dFont = qApp.font() + self._dFont = QApplication.font() self._dFont.setPointSizeF(fPt) self._dPen = QPen(SHARED.theme.helpText) @@ -433,7 +433,7 @@ class _ProjectListItem(QStyledItemDelegate): painter.save() if opt.state & QStyle.StateFlag.State_Selected == QStyle.StateFlag.State_Selected: painter.setOpacity(0.25) - painter.fillRect(rect, qApp.palette().highlight()) + painter.fillRect(rect, QApplication.palette().highlight()) painter.setOpacity(1.0) painter.drawPixmap(ix, rect.top() + iy, self._icon) diff --git a/novelwriter/tools/writingstats.py b/novelwriter/tools/writingstats.py index 4a8e09a9..a9846b81 100644 --- a/novelwriter/tools/writingstats.py +++ b/novelwriter/tools/writingstats.py @@ -29,11 +29,12 @@ import logging from datetime import datetime from typing import TYPE_CHECKING -from PyQt5.QtGui import QCloseEvent, QPixmap, QCursor from PyQt5.QtCore import Qt, pyqtSlot +from PyQt5.QtGui import QCloseEvent, QCursor, QPixmap from PyQt5.QtWidgets import ( - qApp, QDialog, QTreeWidget, QTreeWidgetItem, QDialogButtonBox, QGridLayout, - QLabel, QGroupBox, QMenu, QAction, QFileDialog, QSpinBox, QHBoxLayout + QAction, QApplication, QDialog, QDialogButtonBox, QFileDialog, QGridLayout, + QGroupBox, QHBoxLayout, QLabel, QMenu, QSpinBox, QTreeWidget, + QTreeWidgetItem ) from novelwriter import CONFIG, SHARED @@ -301,10 +302,10 @@ class GuiWritingStats(QDialog): def populateGUI(self) -> None: """Populate list box with data from the log file.""" - qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) self._loadLogFile() self._updateListBox() - qApp.restoreOverrideCursor() + QApplication.restoreOverrideCursor() return ## diff --git a/tests/test_base/test_base_error.py b/tests/test_base/test_base_error.py index b4db2d5f..55ba64d5 100644 --- a/tests/test_base/test_base_error.py +++ b/tests/test_base/test_base_error.py @@ -36,13 +36,13 @@ def testBaseError_Dialog(qtbot, monkeypatch, nwGUI): nwErr.show() # Invalid Error Message - nwErr.setMessage(Exception, "Faulty Error", 123) + nwErr.setMessage(Exception, "Faulty Error", 123) # type: ignore assert nwErr.msgBody.toPlainText() == "Failed to generate error report ..." # Valid Error Message with monkeypatch.context() as mp: mp.setattr("PyQt5.QtCore.QSysInfo.kernelVersion", lambda: "1.2.3") - nwErr.setMessage(Exception, "Fine Error", None) + nwErr.setMessage(Exception, "Fine Error", None) # type: ignore message = nwErr.msgBody.toPlainText() assert message != "" assert "Fine Error" in message @@ -52,7 +52,7 @@ def testBaseError_Dialog(qtbot, monkeypatch, nwGUI): # No kernel version retrieved with monkeypatch.context() as mp: mp.setattr("PyQt5.QtCore.QSysInfo.kernelVersion", causeException) - nwErr.setMessage(Exception, "Almost Fine Error", None) + nwErr.setMessage(Exception, "Almost Fine Error", None) # type: ignore message = nwErr.msgBody.toPlainText() assert message != "" assert "(Unknown)" in message @@ -66,36 +66,36 @@ def testBaseError_Dialog(qtbot, monkeypatch, nwGUI): @pytest.mark.base def testBaseError_Handler(qtbot, monkeypatch, nwGUI): - """Test the error handler. This test doesn'thave any asserts, but it - checks that the error handler handles potential exceptions. The test - will fail if exceptions are not handled. + """Test the error handler. This test doesn't have any asserts, but + it checks that the error handler handles potential exceptions. The + test will fail if exceptions are not handled. """ # Normal shutdown with monkeypatch.context() as mp: mp.setattr(NWErrorMessage, "exec_", lambda *a: None) - mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None) - exceptionHandler(Exception, "Error Message", None) + mp.setattr("PyQt5.QtWidgets.QApplication.exit", lambda *a: None) + exceptionHandler(Exception, "Error Message", None) # type: ignore # Should not crash when no GUI is found with monkeypatch.context() as mp: mp.setattr(NWErrorMessage, "exec_", lambda *a: None) - mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None) - mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", lambda: []) - exceptionHandler(Exception, "Error Message", None) + mp.setattr("PyQt5.QtWidgets.QApplication.exit", lambda *a: None) + mp.setattr("PyQt5.QtWidgets.QApplication.topLevelWidgets", lambda: []) + exceptionHandler(Exception, "Error Message", None) # type: ignore - # Should handle qApp failing + # Should handle QApplication failing with monkeypatch.context() as mp: mp.setattr(NWErrorMessage, "exec_", lambda *a: None) - mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None) - mp.setattr("PyQt5.QtWidgets.qApp.topLevelWidgets", causeException) - exceptionHandler(Exception, "Error Message", None) + mp.setattr("PyQt5.QtWidgets.QApplication.exit", lambda *a: None) + mp.setattr("PyQt5.QtWidgets.QApplication.topLevelWidgets", causeException) + exceptionHandler(Exception, "Error Message", None) # type: ignore # Should handle failing to close main GUI with monkeypatch.context() as mp: mp.setattr(NWErrorMessage, "exec_", lambda *a: None) - mp.setattr("PyQt5.QtWidgets.qApp.exit", lambda *a: None) + mp.setattr("PyQt5.QtWidgets.QApplication.exit", lambda *a: None) mp.setattr(nwGUI, "closeMain", causeException) - exceptionHandler(Exception, "Error Message", None) + exceptionHandler(Exception, "Error Message", None) # type: ignore nwGUI.closeMain() diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index fd947cda..ca8e06e4 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -22,12 +22,12 @@ from __future__ import annotations import pytest -from tools import C, buildTestProject from mocked import causeOSError +from tools import C, buildTestProject -from PyQt5.QtGui import QClipboard, QTextBlock, QTextCursor, QTextOption from PyQt5.QtCore import QThreadPool, Qt -from PyQt5.QtWidgets import QAction, QMenu, qApp +from PyQt5.QtGui import QClipboard, QTextBlock, QTextCursor, QTextOption +from PyQt5.QtWidgets import QAction, QApplication, QMenu from novelwriter import CONFIG, SHARED from novelwriter.constants import nwKeyWords, nwUnicode @@ -361,14 +361,14 @@ def testGuiEditor_ContextMenu(monkeypatch, qtbot, nwGUI, projPath, mockRnd): assert actions == [ "Cut", "Copy", "Paste", "Select All", "Select Word", "Select Paragraph" ] - qApp.clipboard().clear() + QApplication.clipboard().clear() ctxMenu.actions()[1].trigger() - assert qApp.clipboard().text(QClipboard.Mode.Clipboard) == "text" + assert QApplication.clipboard().text(QClipboard.Mode.Clipboard) == "text" # Cut Text - qApp.clipboard().clear() + QApplication.clipboard().clear() ctxMenu.actions()[0].trigger() - assert qApp.clipboard().text(QClipboard.Mode.Clipboard) == "text" + assert QApplication.clipboard().text(QClipboard.Mode.Clipboard) == "text" assert "text" not in docEditor.getText() # Paste Text @@ -400,7 +400,7 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd): # Select/Cut/Copy/Paste/Undo/Redo # =============================== - qApp.clipboard().clear() + QApplication.clipboard().clear() # Select All assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL) is True @@ -452,7 +452,7 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd): assert newPara[5] == ipsumText[4] assert newPara[6] == ipsumText[2] - qApp.clipboard().clear() + QApplication.clipboard().clear() # Emphasis/Undo/Redo # ================== diff --git a/tests/test_gui/test_gui_docviewer.py b/tests/test_gui/test_gui_docviewer.py index 47825510..4b3dd176 100644 --- a/tests/test_gui/test_gui_docviewer.py +++ b/tests/test_gui/test_gui_docviewer.py @@ -26,7 +26,7 @@ from mocked import causeException from PyQt5.QtGui import QMouseEvent, QTextCursor from PyQt5.QtCore import QEvent, QPoint, Qt, QUrl -from PyQt5.QtWidgets import QMenu, qApp, QAction +from PyQt5.QtWidgets import QAction, QApplication, QMenu from novelwriter import CONFIG, SHARED from novelwriter.enum import nwDocAction @@ -77,7 +77,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, prjLipsum): docViewer.setTextCursor(cursor) docViewer._makeSelection(QTextCursor.WordUnderCursor) - qClip = qApp.clipboard() + qClip = QApplication.clipboard() qClip.clear() # Cut diff --git a/tests/test_gui/test_gui_i18n.py b/tests/test_gui/test_gui_i18n.py index b8bda559..caaf3141 100644 --- a/tests/test_gui/test_gui_i18n.py +++ b/tests/test_gui/test_gui_i18n.py @@ -23,11 +23,9 @@ from __future__ import annotations import sys import pytest -from collections.abc import Callable - from tools import buildTestProject -from PyQt5.QtWidgets import QDialog, qApp, QMessageBox +from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox from novelwriter import CONFIG, SHARED from novelwriter.dialogs.about import GuiAbout @@ -55,12 +53,12 @@ def testGuiI18n_Localisation(qtbot, monkeypatch, language, nwGUI, projPath): # Set the test language CONFIG.guiLocale = language - CONFIG.initLocalisation(qApp) + CONFIG.initLocalisation(QApplication.instance()) # type: ignore buildTestProject(nwGUI, projPath) nwGUI.show() - def showDialog(func: Callable, dType: QDialog) -> None: + def showDialog(func, dType) -> None: func() qtbot.waitUntil(lambda: SHARED.findTopLevelWidget(dType) is not None, timeout=1000) dialog = SHARED.findTopLevelWidget(dType)