diff --git a/novelwriter/dialogs/docmerge.py b/novelwriter/dialogs/docmerge.py index 0e5a313f..2d9246b4 100644 --- a/novelwriter/dialogs/docmerge.py +++ b/novelwriter/dialogs/docmerge.py @@ -26,8 +26,8 @@ from __future__ import annotations import logging -from PyQt5.QtGui import QCloseEvent from PyQt5.QtCore import Qt, pyqtSlot +from PyQt5.QtGui import QCloseEvent from PyQt5.QtWidgets import ( QAbstractItemView, QDialog, QDialogButtonBox, QGridLayout, QLabel, QListWidget, QListWidgetItem, QVBoxLayout, QWidget @@ -36,13 +36,14 @@ from PyQt5.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.types import QtUserRole logger = logging.getLogger(__name__) class GuiDocMerge(QDialog): - D_HANDLE = Qt.ItemDataRole.UserRole + D_HANDLE = QtUserRole def __init__(self, parent: QWidget, sHandle: str, itemList: list[str]) -> None: super().__init__(parent=parent) @@ -120,7 +121,7 @@ class GuiDocMerge(QDialog): finalItems = [] for i in range(self.listBox.count()): item = self.listBox.item(i) - if item is not None and item.checkState() == Qt.Checked: + if item is not None and item.checkState() == Qt.CheckState.Checked: finalItems.append(item.data(self.D_HANDLE)) self._data["moveToTrash"] = self.trashSwitch.isChecked() @@ -175,7 +176,7 @@ class GuiDocMerge(QDialog): newItem.setIcon(itemIcon) newItem.setText(nwItem.itemName) newItem.setData(self.D_HANDLE, tHandle) - newItem.setCheckState(Qt.Checked) + newItem.setCheckState(Qt.CheckState.Checked) self.listBox.addItem(newItem) diff --git a/novelwriter/dialogs/docsplit.py b/novelwriter/dialogs/docsplit.py index 1ad639f9..5a443d60 100644 --- a/novelwriter/dialogs/docsplit.py +++ b/novelwriter/dialogs/docsplit.py @@ -26,8 +26,8 @@ from __future__ import annotations import logging +from PyQt5.QtCore import pyqtSlot from PyQt5.QtGui import QCloseEvent -from PyQt5.QtCore import Qt, pyqtSlot from PyQt5.QtWidgets import ( QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, QGridLayout, QLabel, QListWidget, QListWidgetItem, QVBoxLayout, QWidget @@ -36,15 +36,16 @@ from PyQt5.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.configlayout import NColourLabel +from novelwriter.types import QtUserRole logger = logging.getLogger(__name__) class GuiDocSplit(QDialog): - LINE_ROLE = Qt.ItemDataRole.UserRole - LEVEL_ROLE = Qt.ItemDataRole.UserRole + 1 - LABEL_ROLE = Qt.ItemDataRole.UserRole + 2 + LINE_ROLE = QtUserRole + LEVEL_ROLE = QtUserRole + 1 + LABEL_ROLE = QtUserRole + 2 def __init__(self, parent: QWidget, sHandle: str) -> None: super().__init__(parent=parent) diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index 4672f1cc..8fa1ea12 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -40,6 +40,7 @@ from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrol from novelwriter.extensions.modified import NComboBox, NIconToolButton from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.switch import NSwitch +from novelwriter.types import QtUserRole logger = logging.getLogger(__name__) @@ -305,9 +306,9 @@ class _StatusPage(NFixedPage): COL_LABEL = 0 COL_USAGE = 1 - KEY_ROLE = Qt.ItemDataRole.UserRole - COL_ROLE = Qt.ItemDataRole.UserRole + 1 - NUM_ROLE = Qt.ItemDataRole.UserRole + 2 + KEY_ROLE = QtUserRole + COL_ROLE = QtUserRole + 1 + NUM_ROLE = QtUserRole + 2 def __init__(self, parent: QWidget, isStatus: bool) -> None: super().__init__(parent=parent) @@ -614,7 +615,7 @@ class _ReplacePage(NFixedPage): newItem = QTreeWidgetItem(["<%s>" % aKey, aVal]) self.listBox.addTopLevelItem(newItem) - self.listBox.sortByColumn(self.COL_KEY, Qt.AscendingOrder) + self.listBox.sortByColumn(self.COL_KEY, Qt.SortOrder.AscendingOrder) self.listBox.setSortingEnabled(True) # List Controls diff --git a/novelwriter/dialogs/quotes.py b/novelwriter/dialogs/quotes.py index ec7257b5..2e6dcbae 100644 --- a/novelwriter/dialogs/quotes.py +++ b/novelwriter/dialogs/quotes.py @@ -26,7 +26,7 @@ from __future__ import annotations import logging from PyQt5.QtGui import QFontMetrics -from PyQt5.QtCore import QSize, Qt, pyqtSlot +from PyQt5.QtCore import QSize, pyqtSlot from PyQt5.QtWidgets import ( QDialog, QDialogButtonBox, QFrame, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QVBoxLayout, QWidget @@ -34,7 +34,7 @@ from PyQt5.QtWidgets import ( from novelwriter import CONFIG from novelwriter.constants import trConst, nwQuotes -from novelwriter.types import QtAlignCenter, QtAlignTop +from novelwriter.types import QtAlignCenter, QtAlignTop, QtUserRole logger = logging.getLogger(__name__) @@ -43,7 +43,7 @@ class GuiQuoteSelect(QDialog): _selected = "" - D_KEY = Qt.ItemDataRole.UserRole + D_KEY = QtUserRole def __init__(self, parent: QWidget, current: str = '"') -> None: super().__init__(parent=parent) diff --git a/novelwriter/dialogs/wordlist.py b/novelwriter/dialogs/wordlist.py index 2aaad24f..f5714d18 100644 --- a/novelwriter/dialogs/wordlist.py +++ b/novelwriter/dialogs/wordlist.py @@ -157,7 +157,7 @@ class GuiWordList(QDialog): self.newEntry.setText("") self.listBox.clearSelection() self._addWord(word) - if items := self.listBox.findItems(word, Qt.MatchExactly): + if items := self.listBox.findItems(word, Qt.MatchFlag.MatchExactly): self.listBox.setCurrentItem(items[0]) self.listBox.scrollToItem(items[0], QAbstractItemView.ScrollHint.PositionAtCenter) return @@ -244,7 +244,7 @@ class GuiWordList(QDialog): def _addWord(self, word: str) -> None: """Add a single word to the list.""" - if word and not self.listBox.findItems(word, Qt.MatchExactly): + if word and not self.listBox.findItems(word, Qt.MatchFlag.MatchExactly): self.listBox.addItem(word) self._changed = True return diff --git a/novelwriter/extensions/circularprogress.py b/novelwriter/extensions/circularprogress.py index 70d84f31..9e95cd03 100644 --- a/novelwriter/extensions/circularprogress.py +++ b/novelwriter/extensions/circularprogress.py @@ -25,11 +25,11 @@ from __future__ import annotations from math import ceil +from PyQt5.QtCore import QRect from PyQt5.QtGui import QBrush, QColor, QPaintEvent, QPainter, QPen -from PyQt5.QtCore import QRect, Qt from PyQt5.QtWidgets import QProgressBar, QSizePolicy, QWidget -from novelwriter.types import QtAlignCenter +from novelwriter.types import QtAlignCenter, QtRoundCap, QtSolidLine, QtTransparent class NProgressCircle(QProgressBar): @@ -50,8 +50,8 @@ class NProgressCircle(QProgressBar): self._point = point self._dRect = QRect(0, 0, size, size) self._cRect = QRect(point, point, size - 2*point, size - 2*point) - self._dPen = QPen(Qt.transparent) - self._dBrush = QBrush(Qt.transparent) + self._dPen = QPen(QtTransparent) + self._dBrush = QBrush(QtTransparent) self.setColours( track=self.palette().alternateBase().color(), bar=self.palette().highlight().color(), @@ -69,9 +69,9 @@ class NProgressCircle(QProgressBar): self._dPen = QPen(back) self._dBrush = QBrush(back) if isinstance(bar, QColor): - self._cPen = QPen(QBrush(bar), self._point, Qt.SolidLine, Qt.RoundCap) + self._cPen = QPen(QBrush(bar), self._point, QtSolidLine, QtRoundCap) if isinstance(track, QColor): - self._bPen = QPen(QBrush(track), self._point, Qt.SolidLine, Qt.RoundCap) + self._bPen = QPen(QBrush(track), self._point, QtSolidLine, QtRoundCap) if isinstance(text, QColor): self._tColor = text return diff --git a/novelwriter/extensions/pagedsidebar.py b/novelwriter/extensions/pagedsidebar.py index 5fb15516..316b5ec2 100644 --- a/novelwriter/extensions/pagedsidebar.py +++ b/novelwriter/extensions/pagedsidebar.py @@ -32,7 +32,7 @@ from PyQt5.QtWidgets import ( QStyleOptionToolButton, QToolBar, QToolButton, QWidget ) -from novelwriter.types import QtAlignLeft +from novelwriter.types import QtAlignLeft, QtNoBrush, QtNoPen class NPagedSideBar(QToolBar): @@ -56,7 +56,7 @@ class NPagedSideBar(QToolBar): self._group.buttonClicked.connect(self._buttonClicked) self.setMovable(False) - self.setOrientation(Qt.Vertical) + self.setOrientation(Qt.Orientation.Vertical) stretch = QWidget(self) stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) @@ -146,8 +146,8 @@ class _NPagedToolButton(QToolButton): paint = QPainter(self) paint.setRenderHint(QPainter.Antialiasing, True) - paint.setPen(Qt.NoPen) - paint.setBrush(Qt.NoBrush) + paint.setPen(QtNoPen) + paint.setBrush(QtNoBrush) width = self.width() height = self.height() @@ -215,7 +215,7 @@ class _NPagedToolLabel(QLabel): """ paint = QPainter(self) paint.setRenderHint(QPainter.Antialiasing, True) - paint.setPen(Qt.NoPen) + paint.setPen(QtNoPen) width = self.width() height = self.height() diff --git a/novelwriter/extensions/switch.py b/novelwriter/extensions/switch.py index 5d020385..2fba1250 100644 --- a/novelwriter/extensions/switch.py +++ b/novelwriter/extensions/switch.py @@ -28,6 +28,7 @@ from PyQt5.QtCore import QEvent, QPropertyAnimation, Qt, pyqtProperty from PyQt5.QtWidgets import QAbstractButton, QSizePolicy, QWidget from novelwriter import CONFIG, SHARED +from novelwriter.types import QtMouseLeft, QtNoPen class NSwitch(QAbstractButton): @@ -90,7 +91,7 @@ class NSwitch(QAbstractButton): """Drawing the switch itself.""" painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) - painter.setPen(Qt.NoPen) + painter.setPen(QtNoPen) palette = self.palette() if self.isChecked(): @@ -119,7 +120,7 @@ class NSwitch(QAbstractButton): def mouseReleaseEvent(self, event: QMouseEvent) -> None: """Animate the switch on mouse release.""" super().mouseReleaseEvent(event) - if event.button() == Qt.LeftButton: + if event.button() == QtMouseLeft: anim = QPropertyAnimation(self, b"offset", self) anim.setDuration(120) anim.setStartValue(self._offset) @@ -129,7 +130,7 @@ class NSwitch(QAbstractButton): def enterEvent(self, event: QEvent) -> None: """Change the cursor when hovering the button.""" - self.setCursor(Qt.PointingHandCursor) + self.setCursor(Qt.CursorShape.PointingHandCursor) super().enterEvent(event) return diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 26654124..f692a448 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -64,7 +64,8 @@ from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON from novelwriter.text.counting import standardCounter from novelwriter.tools.lipsum import GuiLipsum from novelwriter.types import ( - QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop, QtAlignRight + QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop, + QtAlignRight, QtModCtrl, QtMouseLeft, QtModeNone, QtModShift ) if TYPE_CHECKING: # pragma: no cover @@ -181,12 +182,12 @@ class GuiDocEditor(QPlainTextEdit): self.keyContext.activated.connect(self._openContextFromCursor) self.followTag1 = QShortcut(self) - self.followTag1.setKey(Qt.Key.Key_Return | Qt.KeyboardModifier.ControlModifier) + self.followTag1.setKey(Qt.Key.Key_Return | QtModCtrl) self.followTag1.setContext(Qt.ShortcutContext.WidgetShortcut) self.followTag1.activated.connect(self._processTag) self.followTag2 = QShortcut(self) - self.followTag2.setKey(Qt.Key.Key_Enter | Qt.KeyboardModifier.ControlModifier) + self.followTag2.setKey(Qt.Key.Key_Enter | QtModCtrl) self.followTag2.setContext(Qt.ShortcutContext.WidgetShortcut) self.followTag2.activated.connect(self._processTag) @@ -962,7 +963,7 @@ class GuiDocEditor(QPlainTextEdit): super().keyPressEvent(event) nPos = self.cursorRect().topLeft().y() kMod = event.modifiers() - okMod = kMod in (Qt.KeyboardModifier.NoModifier, Qt.KeyboardModifier.ShiftModifier) + okMod = kMod in (QtModeNone, QtModShift) okKey = event.key() not in self.MOVE_KEYS if nPos != cPos and okMod and okKey: mPos = CONFIG.autoScrollPos*0.01 * self.viewport().height() @@ -991,7 +992,7 @@ class GuiDocEditor(QPlainTextEdit): pressed, check if we're clicking on a tag, and trigger the follow tag function. """ - if QApplication.keyboardModifiers() == Qt.KeyboardModifier.ControlModifier: + if QApplication.keyboardModifiers() == QtModCtrl: self._processTag(self.cursorForPosition(event.pos())) super().mouseReleaseEvent(event) return @@ -2713,9 +2714,7 @@ class GuiDocEditSearch(QFrame): @pyqtSlot() def _doSearch(self) -> None: """Call the search action function for the document editor.""" - self.docEditor.findNext(goBack=( - QApplication.keyboardModifiers() == Qt.KeyboardModifier.ShiftModifier) - ) + self.docEditor.findNext(goBack=(QApplication.keyboardModifiers() == QtModShift)) return @pyqtSlot() @@ -3002,7 +3001,7 @@ class GuiDocEditHeader(QWidget): """Capture a click on the title and ensure that the item is selected in the project tree. """ - if event.button() == Qt.MouseButton.LeftButton: + if event.button() == QtMouseLeft: self.docEditor.requestProjectItemSelected.emit(self._docHandle or "", True) return diff --git a/novelwriter/gui/dochighlight.py b/novelwriter/gui/dochighlight.py index 6e65ac0d..8b479174 100644 --- a/novelwriter/gui/dochighlight.py +++ b/novelwriter/gui/dochighlight.py @@ -402,16 +402,16 @@ class GuiDocHighlighter(QSyntaxHighlighter): if style is not None: styles = style.split(",") if "bold" in styles: - charFormat.setFontWeight(QFont.Bold) + charFormat.setFontWeight(QFont.Weight.Bold) if "italic" in styles: charFormat.setFontItalic(True) if "strike" in styles: charFormat.setFontStrikeOut(True) if "errline" in styles: charFormat.setUnderlineColor(SHARED.theme.colError) - charFormat.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline) + charFormat.setUnderlineStyle(QTextCharFormat.UnderlineStyle.SpellCheckUnderline) if "background" in styles and color is not None: - charFormat.setBackground(QBrush(color, Qt.SolidPattern)) + charFormat.setBackground(QBrush(color, Qt.BrushStyle.SolidPattern)) if size is not None: charFormat.setFontPointSize(int(round(size*CONFIG.textSize))) diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index 724da61f..ebb31429 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -49,7 +49,7 @@ from novelwriter.error import logException from novelwriter.extensions.eventfilters import WheelEventFilter from novelwriter.extensions.modified import NIconToolButton from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON -from novelwriter.types import QtAlignCenterTop, QtAlignJustify +from novelwriter.types import QtAlignCenterTop, QtAlignJustify, QtMouseLeft logger = logging.getLogger(__name__) @@ -826,7 +826,7 @@ class GuiDocViewHeader(QWidget): """Capture a click on the title and ensure that the item is selected in the project tree. """ - if event.button() == Qt.MouseButton.LeftButton: + if event.button() == QtMouseLeft: self.docViewer.requestProjectItemSelected.emit(self._docHandle, True) return diff --git a/novelwriter/gui/docviewerpanel.py b/novelwriter/gui/docviewerpanel.py index 0292e177..f96e44e6 100644 --- a/novelwriter/gui/docviewerpanel.py +++ b/novelwriter/gui/docviewerpanel.py @@ -40,6 +40,7 @@ from novelwriter.core.index import IndexHeading, IndexItem from novelwriter.enum import nwDocMode, nwItemClass from novelwriter.extensions.modified import NIconToolButton from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON +from novelwriter.types import QtDecoration, QtUserRole logger = logging.getLogger(__name__) @@ -232,7 +233,7 @@ class _ViewPanelBackRefs(QTreeWidget): C_VIEW = 2 C_TITLE = 3 - D_HANDLE = Qt.ItemDataRole.UserRole + D_HANDLE = QtUserRole def __init__(self, parent: GuiDocViewerPanel) -> None: super().__init__(parent=parent) @@ -349,7 +350,7 @@ class _ViewPanelBackRefs(QTreeWidget): trItem.setToolTip(self.C_DOC, nwItem.itemName) trItem.setIcon(self.C_EDIT, self._editIcon) trItem.setIcon(self.C_VIEW, self._viewIcon) - trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec) + trItem.setData(self.C_TITLE, QtDecoration, hDec) trItem.setText(self.C_TITLE, hItem.title) trItem.setToolTip(self.C_TITLE, hItem.title) trItem.setData(self.C_DATA, self.D_HANDLE, tHandle) @@ -374,7 +375,7 @@ class _ViewPanelKeyWords(QTreeWidget): C_TITLE = 5 C_SHORT = 6 - D_TAG = Qt.ItemDataRole.UserRole + D_TAG = QtUserRole def __init__(self, parent: GuiDocViewerPanel, itemClass: nwItemClass) -> None: super().__init__(parent=parent) @@ -468,7 +469,7 @@ class _ViewPanelKeyWords(QTreeWidget): trItem.setIcon(self.C_DOC, docIcon) trItem.setText(self.C_DOC, nwItem.itemName) trItem.setToolTip(self.C_DOC, nwItem.itemName) - trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec) + trItem.setData(self.C_TITLE, QtDecoration, hDec) trItem.setText(self.C_TITLE, hItem.title) trItem.setToolTip(self.C_TITLE, hItem.title) trItem.setText(self.C_SHORT, hItem.synopsis) diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py index cb05df4d..ef52577d 100644 --- a/novelwriter/gui/noveltree.py +++ b/novelwriter/gui/noveltree.py @@ -31,8 +31,8 @@ from enum import Enum from time import time from typing import TYPE_CHECKING -from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSlot, pyqtSignal +from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent from PyQt5.QtWidgets import ( QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView, QInputDialog, QMenu, QSizePolicy, QToolTip, QTreeWidget, QTreeWidgetItem, @@ -47,7 +47,7 @@ from novelwriter.enum import nwDocMode, nwItemClass, nwOutline from novelwriter.extensions.modified import NIconToolButton from novelwriter.extensions.novelselector import NovelSelector from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON -from novelwriter.types import QtAlignRight +from novelwriter.types import QtAlignRight, QtDecoration, QtMouseLeft, QtMouseMiddle, QtUserRole if TYPE_CHECKING: # pragma: no cover from novelwriter.guimain import GuiMain @@ -364,10 +364,10 @@ class GuiNovelTree(QTreeWidget): C_EXTRA = 2 C_MORE = 3 - D_HANDLE = Qt.ItemDataRole.UserRole - D_TITLE = Qt.ItemDataRole.UserRole + 1 - D_KEY = Qt.ItemDataRole.UserRole + 2 - D_EXTRA = Qt.ItemDataRole.UserRole + 3 + D_HANDLE = QtUserRole + D_TITLE = QtUserRole + 1 + D_KEY = QtUserRole + 2 + D_EXTRA = QtUserRole + 3 def __init__(self, novelView: GuiNovelView) -> None: super().__init__(parent=novelView) @@ -583,12 +583,12 @@ class GuiNovelTree(QTreeWidget): """ super().mousePressEvent(event) - if event.button() == Qt.MouseButton.LeftButton: + if event.button() == QtMouseLeft: selItem = self.indexAt(event.pos()) if not selItem.isValid(): self.clearSelection() - elif event.button() == Qt.MouseButton.MiddleButton: + elif event.button() == QtMouseMiddle: selItem = self.itemAt(event.pos()) if not isinstance(selItem, QTreeWidgetItem): return @@ -697,11 +697,11 @@ class GuiNovelTree(QTreeWidget): iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0) hDec = SHARED.theme.getHeaderDecoration(iLevel) - trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec) + trItem.setData(self.C_TITLE, QtDecoration, hDec) trItem.setText(self.C_TITLE, idxItem.title) trItem.setFont(self.C_TITLE, self._hFonts[iLevel]) trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}") - trItem.setData(self.C_MORE, Qt.ItemDataRole.DecorationRole, self._pMore) + trItem.setData(self.C_MORE, QtDecoration, self._pMore) # Custom column mW = int(self._lastColSize * self.viewport().width()) diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index fc5c9ac9..6eadbf0a 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -48,7 +48,9 @@ from novelwriter.error import logException from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels from novelwriter.extensions.novelselector import NovelSelector -from novelwriter.types import QtAlignLeftTop, QtAlignRight, QtAlignRightTop +from novelwriter.types import ( + QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration, QtUserRole +) logger = logging.getLogger(__name__) @@ -68,7 +70,7 @@ class GuiOutlineView(QWidget): self.outlineBar = GuiOutlineToolBar(self) self.outlineBar.setEnabled(False) - self.splitOutline = QSplitter(Qt.Vertical) + self.splitOutline = QSplitter(Qt.Orientation.Vertical) self.splitOutline.addWidget(self.outlineTree) self.splitOutline.addWidget(self.outlineData) self.splitOutline.setOpaqueResize(False) @@ -354,8 +356,8 @@ class GuiOutlineTree(QTreeWidget): nwOutline.SYNOP: False, } - D_HANDLE = Qt.ItemDataRole.UserRole - D_TITLE = Qt.ItemDataRole.UserRole + 1 + D_HANDLE = QtUserRole + D_TITLE = QtUserRole + 1 hiddenStateChanged = pyqtSignal() activeItemChanged = pyqtSignal(str, str) @@ -692,7 +694,7 @@ class GuiOutlineTree(QTreeWidget): trItem = QTreeWidgetItem() hDec = SHARED.theme.getHeaderDecoration(iLevel) - trItem.setData(self._colIdx[nwOutline.TITLE], Qt.ItemDataRole.DecorationRole, hDec) + trItem.setData(self._colIdx[nwOutline.TITLE], QtDecoration, hDec) trItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title) trItem.setData(self._colIdx[nwOutline.TITLE], self.D_HANDLE, tHandle) trItem.setData(self._colIdx[nwOutline.TITLE], self.D_TITLE, sTitle) diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 52131dc6..7287ff38 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -32,10 +32,10 @@ from enum import Enum from time import time from typing import TYPE_CHECKING +from PyQt5.QtCore import QPoint, QTimer, Qt, pyqtSignal, pyqtSlot from PyQt5.QtGui import ( QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette ) -from PyQt5.QtCore import QPoint, QTimer, Qt, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( QAbstractItemView, QAction, QDialog, QFrame, QHBoxLayout, QHeaderView, QLabel, QMenu, QShortcut, QSizePolicy, QTreeWidget, QTreeWidgetItem, @@ -54,7 +54,7 @@ from novelwriter.dialogs.projectsettings import GuiProjectSettings from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout from novelwriter.extensions.modified import NIconToolButton from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON -from novelwriter.types import QtAlignLeft, QtAlignRight +from novelwriter.types import QtAlignLeft, QtAlignRight, QtMouseLeft, QtMouseMiddle, QtUserRole if TYPE_CHECKING: # pragma: no cover from novelwriter.guimain import GuiMain @@ -487,8 +487,8 @@ class GuiProjectTree(QTreeWidget): C_ACTIVE = 2 C_STATUS = 3 - D_HANDLE = Qt.ItemDataRole.UserRole - D_WORDS = Qt.ItemDataRole.UserRole + 1 + D_HANDLE = QtUserRole + D_WORDS = QtUserRole + 1 itemRefreshed = pyqtSignal(str, NWItem, QIcon) @@ -1256,11 +1256,11 @@ class GuiProjectTree(QTreeWidget): for viewing if the user middle-clicked. """ super().mousePressEvent(event) - if event.button() == Qt.MouseButton.LeftButton: + if event.button() == QtMouseLeft: selItem = self.indexAt(event.pos()) if not selItem.isValid(): self.clearSelection() - elif event.button() == Qt.MouseButton.MiddleButton: + elif event.button() == QtMouseMiddle: selItem = self.itemAt(event.pos()) if selItem: tHandle = selItem.data(self.C_DATA, self.D_HANDLE) @@ -1268,7 +1268,7 @@ class GuiProjectTree(QTreeWidget): self.projView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", False) return - def startDrag(self, dropAction: Qt.DropActions) -> None: + def startDrag(self, dropAction: Qt.DropAction) -> None: """Capture the drag and drop handling to pop alerts.""" super().startDrag(dropAction) if self._popAlert: diff --git a/novelwriter/gui/search.py b/novelwriter/gui/search.py index 5dfb1253..79c0bdd0 100644 --- a/novelwriter/gui/search.py +++ b/novelwriter/gui/search.py @@ -38,7 +38,7 @@ from novelwriter import CONFIG, SHARED from novelwriter.common import checkInt, cssCol from novelwriter.core.coretools import DocSearch from novelwriter.core.item import NWItem -from novelwriter.types import QtAlignMiddle, QtAlignRight +from novelwriter.types import QtAlignMiddle, QtAlignRight, QtUserRole logger = logging.getLogger(__name__) @@ -49,8 +49,8 @@ class GuiProjectSearch(QWidget): C_RESULT = 0 C_COUNT = 1 - D_HANDLE = Qt.ItemDataRole.UserRole - D_RESULT = Qt.ItemDataRole.UserRole + 1 + D_HANDLE = QtUserRole + D_RESULT = QtUserRole + 1 selectedItemChanged = pyqtSignal(str) openDocumentSelectRequest = pyqtSignal(str, int, int, bool) diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 8fe569c7..cadc1d1e 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -148,7 +148,7 @@ class GuiMain(QMainWindow): self.treePane.setLayout(self.treeBox) # Splitter : Document Viewer / Document Meta - self.splitView = QSplitter(Qt.Vertical, self) + self.splitView = QSplitter(Qt.Orientation.Vertical, self) self.splitView.addWidget(self.docViewer) self.splitView.addWidget(self.docViewerPanel) self.splitView.setHandleWidth(hWd) @@ -158,7 +158,7 @@ class GuiMain(QMainWindow): self.splitView.setCollapsible(1, False) # Splitter : Document Editor / Document Viewer - self.splitDocs = QSplitter(Qt.Horizontal, self) + self.splitDocs = QSplitter(Qt.Orientation.Horizontal, self) self.splitDocs.addWidget(self.docEditor) self.splitDocs.addWidget(self.splitView) self.splitDocs.setOpaqueResize(False) @@ -167,7 +167,7 @@ class GuiMain(QMainWindow): self.splitDocs.setCollapsible(1, False) # Splitter : Project Tree / Document Area - self.splitMain = QSplitter(Qt.Horizontal) + self.splitMain = QSplitter(Qt.Orientation.Horizontal) self.splitMain.setContentsMargins(0, 0, 0, 0) self.splitMain.addWidget(self.treePane) self.splitMain.addWidget(self.splitDocs) @@ -205,7 +205,7 @@ class GuiMain(QMainWindow): self.setMenuBar(self.mainMenu) self.setCentralWidget(self.mainWidget) self.setStatusBar(self.mainStatus) - self.setContextMenuPolicy(Qt.NoContextMenu) # Issue #1147 + self.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu) # Issue #1147 # Connect Signals # =============== @@ -738,7 +738,7 @@ class GuiMain(QMainWindow): """Rebuild the entire index.""" if SHARED.hasProject: logger.info("Rebuilding index ...") - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor)) tStart = time() self.projView.saveProjectTasks() @@ -899,7 +899,8 @@ class GuiMain(QMainWindow): CONFIG.setViewPanePos(self.splitView.sizes()) CONFIG.showViewerPanel = self.docViewerPanel.isVisible() - if self.windowState() & Qt.WindowFullScreen != Qt.WindowFullScreen: + wFull = Qt.WindowState.WindowFullScreen + if self.windowState() & wFull != wFull: # Ignore window size if in full screen mode CONFIG.setMainWinSize(self.width(), self.height()) @@ -936,7 +937,7 @@ class GuiMain(QMainWindow): def toggleFullScreenMode(self) -> None: """Toggle full screen mode""" - self.setWindowState(self.windowState() ^ Qt.WindowFullScreen) + self.setWindowState(self.windowState() ^ Qt.WindowState.WindowFullScreen) return ## @@ -1212,7 +1213,7 @@ class GuiMain(QMainWindow): if SHARED.hasProject: currTime = time() editIdle = currTime - self.docEditor.lastActive > CONFIG.userIdleTime - userIdle = QApplication.applicationState() != Qt.ApplicationActive + userIdle = QApplication.applicationState() != Qt.ApplicationState.ApplicationActive self.mainStatus.setUserIdle(editIdle or userIdle) SHARED.updateIdleTime(currTime, editIdle or userIdle) self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime) diff --git a/novelwriter/tools/manusbuild.py b/novelwriter/tools/manusbuild.py index 5eef8aef..d40ee787 100644 --- a/novelwriter/tools/manusbuild.py +++ b/novelwriter/tools/manusbuild.py @@ -27,8 +27,8 @@ import logging from pathlib import Path +from PyQt5.QtCore import QTimer, pyqtSlot from PyQt5.QtGui import QCloseEvent -from PyQt5.QtCore import QTimer, Qt, pyqtSlot from PyQt5.QtWidgets import ( QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem, @@ -44,7 +44,7 @@ from novelwriter.core.item import NWItem from novelwriter.enum import nwBuildFmt from novelwriter.extensions.modified import NIconToolButton from novelwriter.extensions.simpleprogress import NProgressSimple -from novelwriter.types import QtAlignCenter +from novelwriter.types import QtAlignCenter, QtUserRole logger = logging.getLogger(__name__) @@ -56,7 +56,7 @@ class GuiManuscriptBuild(QDialog): independently of the Manuscript Build Tool. """ - D_KEY = Qt.ItemDataRole.UserRole + D_KEY = QtUserRole def __init__(self, parent: QWidget, build: BuildSettings): super().__init__(parent=parent) diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index 554ef1b9..99425e62 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -53,7 +53,8 @@ from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON from novelwriter.tools.manusbuild import GuiManuscriptBuild from novelwriter.tools.manussettings import GuiBuildSettings from novelwriter.types import ( - QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignRight, QtAlignTop + QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignRight, QtAlignTop, + QtUserRole ) if TYPE_CHECKING: # pragma: no cover @@ -70,7 +71,7 @@ class GuiManuscript(QDialog): a document directly to disk. """ - D_KEY = Qt.ItemDataRole.UserRole + D_KEY = QtUserRole def __init__(self, mainGui: GuiMain) -> None: super().__init__(parent=mainGui) @@ -661,7 +662,7 @@ class _DetailsWidget(QWidget): class _OutlineWidget(QWidget): - D_LINE = Qt.ItemDataRole.UserRole + D_LINE = QtUserRole outlineEntryClicked = pyqtSignal(str) diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py index a575fead..dfb47659 100644 --- a/novelwriter/tools/manussettings.py +++ b/novelwriter/tools/manussettings.py @@ -46,7 +46,7 @@ from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NIconTool from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switchbox import NSwitchBox -from novelwriter.types import QtAlignLeft +from novelwriter.types import QtAlignLeft, QtUserRole if TYPE_CHECKING: # pragma: no cover from novelwriter.guimain import GuiMain @@ -289,8 +289,8 @@ class _FilterTab(NFixedPage): C_ACTIVE = 1 C_STATUS = 2 - D_HANDLE = Qt.ItemDataRole.UserRole - D_FILE = Qt.ItemDataRole.UserRole + 1 + D_HANDLE = QtUserRole + D_FILE = QtUserRole + 1 F_NONE = 0 F_FILTERED = 1 diff --git a/novelwriter/tools/noveldetails.py b/novelwriter/tools/noveldetails.py index 17780c0c..1f42917c 100644 --- a/novelwriter/tools/noveldetails.py +++ b/novelwriter/tools/noveldetails.py @@ -26,8 +26,8 @@ from __future__ import annotations import math import logging +from PyQt5.QtCore import pyqtSlot from PyQt5.QtGui import QCloseEvent -from PyQt5.QtCore import Qt, pyqtSlot from PyQt5.QtWidgets import ( QAbstractItemView, QDialog, QDialogButtonBox, QFormLayout, QGridLayout, QHBoxLayout, QLabel, QSpinBox, QStackedWidget, QTreeWidget, @@ -41,7 +41,7 @@ from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrol from novelwriter.extensions.novelselector import NovelSelector from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.switch import NSwitch -from novelwriter.types import QtAlignRight +from novelwriter.types import QtAlignRight, QtDecoration logger = logging.getLogger(__name__) @@ -485,7 +485,7 @@ class _ContentsPage(NFixedPage): if tTitle.strip() == "": tTitle = self.tr("Untitled") - newItem.setData(self.C_TITLE, Qt.DecorationRole, hDec) + newItem.setData(self.C_TITLE, QtDecoration, hDec) newItem.setText(self.C_TITLE, tTitle) newItem.setText(self.C_WORDS, f"{wCount:n}") newItem.setText(self.C_PAGES, f"{pCount:n}") diff --git a/novelwriter/tools/writingstats.py b/novelwriter/tools/writingstats.py index a9846b81..544603fe 100644 --- a/novelwriter/tools/writingstats.py +++ b/novelwriter/tools/writingstats.py @@ -42,7 +42,7 @@ from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax from novelwriter.constants import nwConst from novelwriter.error import formatException from novelwriter.extensions.switch import NSwitch -from novelwriter.types import QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle +from novelwriter.types import QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle, QtDecoration if TYPE_CHECKING: # pragma: no cover from novelwriter.guimain import GuiMain @@ -122,10 +122,11 @@ class GuiWritingStats(QDialog): hHeader.setTextAlignment(self.C_IDLE, QtAlignRight) hHeader.setTextAlignment(self.C_COUNT, QtAlignRight) + sDec = Qt.SortOrder.DescendingOrder + sAsc = Qt.SortOrder.AscendingOrder sortCol = minmax(pOptions.getInt("GuiWritingStats", "sortCol", 0), 0, 2) sortOrder = checkIntTuple( - pOptions.getInt("GuiWritingStats", "sortOrder", Qt.DescendingOrder), - (Qt.AscendingOrder, Qt.DescendingOrder), Qt.DescendingOrder + pOptions.getInt("GuiWritingStats", "sortOrder", sDec), (sAsc, sDec), sDec ) self.listBox.sortByColumn(sortCol, sortOrder) # type: ignore self.listBox.setSortingEnabled(True) @@ -571,6 +572,8 @@ class GuiWritingStats(QDialog): pcTotal = wcTotal # Populate the list + mTrans = Qt.TransformationMode.FastTransformation + mAspect = Qt.AspectRatioMode.IgnoreAspectRatio showIdleTime = self.showIdleTime.isChecked() for _, sStart, sDiff, nWords, _, _, sIdle in self.filterData: @@ -589,11 +592,9 @@ class GuiWritingStats(QDialog): if nWords > 0 and listMax > 0: wBar = self.barImage.scaled( int(200*min(nWords, histMax)/listMax), - self.barHeight, - Qt.IgnoreAspectRatio, - Qt.FastTransformation + self.barHeight, mAspect, mTrans ) - newItem.setData(self.C_BAR, Qt.DecorationRole, wBar) + newItem.setData(self.C_BAR, QtDecoration, wBar) newItem.setTextAlignment(self.C_LENGTH, QtAlignRight) newItem.setTextAlignment(self.C_IDLE, QtAlignRight) diff --git a/novelwriter/types.py b/novelwriter/types.py index eb20dce3..25b762ce 100644 --- a/novelwriter/types.py +++ b/novelwriter/types.py @@ -24,6 +24,7 @@ along with this program. If not, see . from __future__ import annotations from PyQt5.QtCore import Qt +from PyQt5.QtGui import QColor # Qt Alignment Flags @@ -41,3 +42,24 @@ QtAlignRightBase = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignBaseline QtAlignRightMiddle = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter QtAlignRightTop = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop QtAlignTop = Qt.AlignmentFlag.AlignTop + +# Qt Painter Types + +QtTransparent = QColor(0, 0, 0, 0) +QtNoBrush = Qt.BrushStyle.NoBrush +QtNoPen = Qt.PenStyle.NoPen +QtRoundCap = Qt.PenCapStyle.RoundCap +QtSolidLine = Qt.PenStyle.SolidLine + +# Qt Tree and Table Types + +QtDecoration = Qt.ItemDataRole.DecorationRole +QtUserRole = Qt.ItemDataRole.UserRole + +# Keyboard and Mouse Buttons + +QtModCtrl = Qt.KeyboardModifier.ControlModifier +QtModeNone = Qt.KeyboardModifier.NoModifier +QtModShift = Qt.KeyboardModifier.ShiftModifier +QtMouseLeft = Qt.MouseButton.LeftButton +QtMouseMiddle = Qt.MouseButton.MiddleButton diff --git a/tests/test_dialogs/test_dlg_docmerge.py b/tests/test_dialogs/test_dlg_docmerge.py index 090c2319..2653f256 100644 --- a/tests/test_dialogs/test_dlg_docmerge.py +++ b/tests/test_dialogs/test_dlg_docmerge.py @@ -27,6 +27,7 @@ from tools import buildTestProject, C from PyQt5.QtCore import Qt from novelwriter.dialogs.docmerge import GuiDocMerge +from novelwriter.types import QtUserRole @pytest.mark.gui @@ -53,11 +54,11 @@ def testDlgMerge_Main(qtbot, nwGUI, projPath, mockRnd): itemOne = nwMerge.listBox.item(0) itemTwo = nwMerge.listBox.item(1) - assert itemOne.data(Qt.ItemDataRole.UserRole) == C.hChapterDoc - assert itemTwo.data(Qt.ItemDataRole.UserRole) == C.hSceneDoc + assert itemOne.data(QtUserRole) == C.hChapterDoc + assert itemTwo.data(QtUserRole) == C.hSceneDoc - assert itemOne.checkState() == Qt.Checked - assert itemTwo.checkState() == Qt.Checked + assert itemOne.checkState() == Qt.CheckState.Checked + assert itemTwo.checkState() == Qt.CheckState.Checked data = nwMerge.getData() assert data["sHandle"] == C.hChapterDir @@ -66,7 +67,7 @@ def testDlgMerge_Main(qtbot, nwGUI, projPath, mockRnd): assert data["finalItems"] == [C.hChapterDoc, C.hSceneDoc] # Uncheck second item and toggle trash switch - itemTwo.setCheckState(Qt.Unchecked) + itemTwo.setCheckState(Qt.CheckState.Unchecked) nwMerge.trashSwitch.setChecked(True) data = nwMerge.getData() diff --git a/tests/test_dialogs/test_dlg_preferences.py b/tests/test_dialogs/test_dlg_preferences.py index 85330f87..39ec2353 100644 --- a/tests/test_dialogs/test_dlg_preferences.py +++ b/tests/test_dialogs/test_dlg_preferences.py @@ -30,6 +30,7 @@ from novelwriter import CONFIG, SHARED from novelwriter.constants import nwConst, nwUnicode from novelwriter.dialogs.preferences import GuiPreferences from novelwriter.dialogs.quotes import GuiQuoteSelect +from novelwriter.types import QtModeNone KEY_DELAY = 1 @@ -141,7 +142,7 @@ def testDlgPreferences_Actions(qtbot, monkeypatch, nwGUI): # Close Using Escape Key prefs.show() with qtbot.waitSignal(prefs.finished) as status: - event = QKeyEvent(QEvent.Type.KeyPress, Qt.Key.Key_Escape, Qt.KeyboardModifier.NoModifier) + event = QKeyEvent(QEvent.Type.KeyPress, Qt.Key.Key_Escape, QtModeNone) prefs.keyPressEvent(event) assert status.args == [nwConst.DLG_FINISHED] diff --git a/tests/test_dialogs/test_dlg_projectsettings.py b/tests/test_dialogs/test_dlg_projectsettings.py index 20eb84fe..29f51b48 100644 --- a/tests/test_dialogs/test_dlg_projectsettings.py +++ b/tests/test_dialogs/test_dlg_projectsettings.py @@ -24,14 +24,15 @@ import pytest from tools import C, buildTestProject -from PyQt5.QtGui import QColor from PyQt5.QtCore import Qt +from PyQt5.QtGui import QColor from PyQt5.QtWidgets import QDialog, QAction, QColorDialog from novelwriter import CONFIG, SHARED -from novelwriter.enum import nwItemType from novelwriter.dialogs.editlabel import GuiEditLabel from novelwriter.dialogs.projectsettings import GuiProjectSettings +from novelwriter.enum import nwItemType +from novelwriter.types import QtMouseLeft KEY_DELAY = 1 @@ -188,13 +189,13 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn # Can't delete the first item (it's in use) status.listBox.clearSelection() status.listBox.setCurrentItem(status.listBox.topLevelItem(0)) - qtbot.mouseClick(status.delButton, Qt.LeftButton) + qtbot.mouseClick(status.delButton, QtMouseLeft) assert status.listBox.topLevelItemCount() == 4 # Can delete the second item status.listBox.clearSelection() status.listBox.setCurrentItem(status.listBox.topLevelItem(1)) - qtbot.mouseClick(status.delButton, Qt.LeftButton) + qtbot.mouseClick(status.delButton, QtMouseLeft) assert status.listBox.topLevelItemCount() == 3 # Add a new item @@ -270,21 +271,21 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn # Delete unused entry importance.listBox.clearSelection() importance.listBox.setCurrentItem(importance.listBox.topLevelItem(1)) - qtbot.mouseClick(importance.delButton, Qt.LeftButton) + qtbot.mouseClick(importance.delButton, QtMouseLeft) assert importance.listBox.topLevelItemCount() == 3 # Add a new entry with monkeypatch.context() as mp: mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40)) - qtbot.mouseClick(importance.addButton, Qt.LeftButton) + qtbot.mouseClick(importance.addButton, QtMouseLeft) importance.listBox.clearSelection() importance.listBox.setCurrentItem(importance.listBox.topLevelItem(3)) for _ in range(8): - qtbot.keyClick(importance.editName, Qt.Key_Backspace, delay=KEY_DELAY) + qtbot.keyClick(importance.editName, Qt.Key.Key_Backspace, delay=KEY_DELAY) for c in "Final": qtbot.keyClick(importance.editName, c, delay=KEY_DELAY) - qtbot.mouseClick(importance.colButton, Qt.LeftButton) - qtbot.mouseClick(importance.saveButton, Qt.LeftButton) + qtbot.mouseClick(importance.colButton, QtMouseLeft) + qtbot.mouseClick(importance.saveButton, QtMouseLeft) assert importance.listBox.topLevelItemCount() == 4 assert importance.wasChanged is True @@ -367,7 +368,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd): assert replace.listBox.topLevelItemCount() == 2 # Create a new entry - qtbot.mouseClick(replace.addButton, Qt.LeftButton) + qtbot.mouseClick(replace.addButton, QtMouseLeft) assert replace.listBox.topLevelItemCount() == 3 assert replace.listBox.topLevelItem(2).text(0) == "" # type: ignore assert replace.listBox.topLevelItem(2).text(1) == "" # type: ignore @@ -380,13 +381,13 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd): replace.editValue.setText("") for c in "With This Stuff ": qtbot.keyClick(replace.editValue, c, delay=KEY_DELAY) - qtbot.mouseClick(replace.saveButton, Qt.LeftButton) + qtbot.mouseClick(replace.saveButton, QtMouseLeft) assert replace.listBox.topLevelItem(2).text(0) == "" # type: ignore assert replace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore # Create a new entry again replace.listBox.clearSelection() - qtbot.mouseClick(replace.addButton, Qt.LeftButton) + qtbot.mouseClick(replace.addButton, QtMouseLeft) assert replace.listBox.topLevelItemCount() == 4 # The list is sorted, so we must find it @@ -399,7 +400,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd): # Then delete the new item replace.listBox.setCurrentItem(replace.listBox.topLevelItem(newIdx)) - qtbot.mouseClick(replace.delButton, Qt.LeftButton) + qtbot.mouseClick(replace.delButton, QtMouseLeft) assert replace.listBox.topLevelItemCount() == 3 # Check Project diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index e2485c0e..a95cef92 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -37,7 +37,7 @@ from novelwriter.enum import ( ) from novelwriter.gui.doceditor import GuiDocEditor, GuiDocToolBar from novelwriter.text.counting import standardCounter -from novelwriter.types import QtAlignJustify, QtAlignLeft +from novelwriter.types import QtAlignJustify, QtAlignLeft, QtMouseLeft KEY_DELAY = 1 @@ -95,7 +95,7 @@ def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd): # Select item from header with qtbot.waitSignal(nwGUI.docEditor.requestProjectItemSelected, timeout=1000) as signal: - qtbot.mouseClick(nwGUI.docEditor.docHeader, Qt.MouseButton.LeftButton) + qtbot.mouseClick(nwGUI.docEditor.docHeader, QtMouseLeft) assert signal.args == [nwGUI.docEditor.docHeader._docHandle, True] # Close from header @@ -109,7 +109,7 @@ def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd): # Select item from header with qtbot.waitSignal(nwGUI.docEditor.requestProjectItemSelected, timeout=1000) as signal: - qtbot.mouseClick(nwGUI.docEditor.docHeader, Qt.MouseButton.LeftButton) + qtbot.mouseClick(nwGUI.docEditor.docHeader, QtMouseLeft) assert signal.args == ["", True] # qtbot.stop() @@ -1788,7 +1788,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum): assert abs(docEditor.getCursorPosition() - 1299) < 3 # Find next by button - qtbot.mouseClick(docSearch.searchButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docSearch.searchButton, QtMouseLeft, delay=KEY_DELAY) assert abs(docEditor.getCursorPosition() - 1513) < 3 # Activate loop search @@ -1806,14 +1806,14 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum): docEditor.setCursorPosition(15) # Toggle search again with header button - qtbot.mouseClick(docEditor.docHeader.searchButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docEditor.docHeader.searchButton, QtMouseLeft, delay=KEY_DELAY) docSearch.setSearchText("") assert docSearch.isVisible() is True # Search for non-existing docEditor.setCursorPosition(0) docSearch.setSearchText("abcdef") - qtbot.mouseClick(docSearch.searchButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docSearch.searchButton, QtMouseLeft, delay=KEY_DELAY) assert docEditor.getCursorPosition() < 3 # No result # Enable RegEx search @@ -1824,19 +1824,19 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum): # Set invalid RegEx docEditor.setCursorPosition(0) docSearch.setSearchText(r"\bSus[") - qtbot.mouseClick(docSearch.searchButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docSearch.searchButton, QtMouseLeft, delay=KEY_DELAY) assert docEditor.getCursorPosition() < 3 # No result # Set dangerous RegEx (issue #1015) # If this doesn't get caught, the app will hang docEditor.setCursorPosition(0) docSearch.setSearchText(r".*") - qtbot.mouseClick(docSearch.searchButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docSearch.searchButton, QtMouseLeft, delay=KEY_DELAY) assert abs(docEditor.getCursorPosition() - 14) < 3 # Set valid RegEx docSearch.setSearchText(r"\bSus") - qtbot.mouseClick(docSearch.searchButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docSearch.searchButton, QtMouseLeft, delay=KEY_DELAY) assert abs(docEditor.getCursorPosition() - 223) < 3 # Find next and then prev @@ -1887,7 +1887,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum): assert abs(docEditor.getCursorPosition() - 223) < 3 # Replace "sus" with "foo" via replace button - qtbot.mouseClick(docSearch.replaceButton, Qt.LeftButton, delay=KEY_DELAY) + qtbot.mouseClick(docSearch.replaceButton, QtMouseLeft, delay=KEY_DELAY) assert docEditor.getText()[220:228] == "foocipit" # Revert last two replaces diff --git a/tests/test_gui/test_gui_docviewer.py b/tests/test_gui/test_gui_docviewer.py index 9eaf3c4a..dd0f72ef 100644 --- a/tests/test_gui/test_gui_docviewer.py +++ b/tests/test_gui/test_gui_docviewer.py @@ -24,14 +24,15 @@ import pytest from mocked import causeException -from PyQt5.QtGui import QMouseEvent, QTextCursor from PyQt5.QtCore import QEvent, QPoint, Qt, QUrl +from PyQt5.QtGui import QMouseEvent, QTextCursor from PyQt5.QtWidgets import QAction, QApplication, QMenu from novelwriter import CONFIG, SHARED from novelwriter.enum import nwDocAction from novelwriter.core.tohtml import ToHtml from novelwriter.gui.docviewer import GuiDocViewer +from novelwriter.types import QtMouseLeft, QtModeNone @pytest.mark.gui @@ -59,8 +60,8 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, prjLipsum): assert nwGUI.projView.projTree.getSelectedHandle() is None # Re-select via header click - button = Qt.MouseButton.LeftButton - modifier = Qt.KeyboardModifier.NoModifier + button = QtMouseLeft + modifier = QtModeNone event = QMouseEvent(QEvent.MouseButtonPress, QPoint(), button, button, modifier) docViewer.docHeader.mousePressEvent(event) assert nwGUI.projView.projTree.getSelectedHandle() == "88243afbe5ed8" @@ -164,7 +165,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, prjLipsum): assert docViewer.docHandle == "88243afbe5ed8" qtbot.mouseClick(docViewer.viewport(), Qt.ForwardButton, pos=rect.center(), delay=100) assert docViewer.docHandle == "4c4f28287af27" - qtbot.mouseClick(docViewer.viewport(), Qt.LeftButton, pos=rect.center(), delay=100) + qtbot.mouseClick(docViewer.viewport(), QtMouseLeft, pos=rect.center(), delay=100) assert docViewer.docHandle == "4c4f28287af27" # Scroll bar default on empty document diff --git a/tests/test_gui/test_gui_mainmenu.py b/tests/test_gui/test_gui_mainmenu.py index b0a0351f..2d65c162 100644 --- a/tests/test_gui/test_gui_mainmenu.py +++ b/tests/test_gui/test_gui_mainmenu.py @@ -25,13 +25,13 @@ import pytest from tools import C, writeFile, buildTestProject from PyQt5.QtGui import QTextCursor, QTextBlock -from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox from novelwriter import CONFIG, SHARED -from novelwriter.enum import nwDocAction, nwDocInsert from novelwriter.constants import nwKeyWords, nwUnicode +from novelwriter.enum import nwDocAction, nwDocInsert from novelwriter.gui.doceditor import GuiDocEditor +from novelwriter.types import QtMouseLeft @pytest.mark.gui @@ -359,7 +359,7 @@ def testGuiMenu_ContextMenus(qtbot, nwGUI, prjLipsum): rect = nwGUI.docEditor.cursorRect() nwGUI.docEditor._openContextMenu(rect.bottomRight()) - qtbot.mouseClick(nwGUI.docEditor, Qt.LeftButton, pos=rect.topLeft()) + qtbot.mouseClick(nwGUI.docEditor, QtMouseLeft, pos=rect.topLeft()) nwGUI.docEditor._makePosSelection(QTextCursor.WordUnderCursor, rect.center()) cursor = nwGUI.docEditor.textCursor() @@ -386,7 +386,7 @@ def testGuiMenu_ContextMenus(qtbot, nwGUI, prjLipsum): rect = nwGUI.docViewer.cursorRect() nwGUI.docViewer._openContextMenu(rect.bottomRight()) - qtbot.mouseClick(nwGUI.docViewer, Qt.LeftButton, pos=rect.topLeft()) + qtbot.mouseClick(nwGUI.docViewer, QtMouseLeft, pos=rect.topLeft()) nwGUI.docViewer._makePosSelection(QTextCursor.WordUnderCursor, rect.center()) cursor = nwGUI.docViewer.textCursor() @@ -410,12 +410,12 @@ def testGuiMenu_ContextMenus(qtbot, nwGUI, prjLipsum): assert nwGUI.docViewer.docHeader.backButton.isEnabled() assert not nwGUI.docViewer.docHeader.forwardButton.isEnabled() - qtbot.mouseClick(nwGUI.docViewer.docHeader.backButton, Qt.LeftButton) + qtbot.mouseClick(nwGUI.docViewer.docHeader.backButton, QtMouseLeft) assert nwGUI.docViewer.docHandle == "4c4f28287af27" assert not nwGUI.docViewer.docHeader.backButton.isEnabled() assert nwGUI.docViewer.docHeader.forwardButton.isEnabled() - qtbot.mouseClick(nwGUI.docViewer.docHeader.forwardButton, Qt.LeftButton) + qtbot.mouseClick(nwGUI.docViewer.docHeader.forwardButton, QtMouseLeft) assert nwGUI.docViewer.docHandle == "04468803b92e1" assert nwGUI.docViewer.docHeader.backButton.isEnabled() assert not nwGUI.docViewer.docHeader.forwardButton.isEnabled() diff --git a/tests/test_gui/test_gui_noveltree.py b/tests/test_gui/test_gui_noveltree.py index 120b66be..b1ca3145 100644 --- a/tests/test_gui/test_gui_noveltree.py +++ b/tests/test_gui/test_gui_noveltree.py @@ -26,14 +26,15 @@ from pathlib import Path from tools import C, buildTestProject -from PyQt5.QtGui import QFocusEvent from PyQt5.QtCore import QPoint, Qt, QEvent +from PyQt5.QtGui import QFocusEvent from PyQt5.QtWidgets import QInputDialog, QToolTip from novelwriter import CONFIG, SHARED +from novelwriter.dialogs.editlabel import GuiEditLabel from novelwriter.enum import nwWidget, nwItemType from novelwriter.gui.noveltree import GuiNovelTree, NovelTreeColumn -from novelwriter.dialogs.editlabel import GuiEditLabel +from novelwriter.types import QtMouseLeft @pytest.mark.gui @@ -112,7 +113,7 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd): # Clear selection with mouse vPort = novelTree.viewport() - qtbot.mouseClick(vPort, Qt.LeftButton, pos=vPort.rect().center(), delay=10) + qtbot.mouseClick(vPort, QtMouseLeft, pos=vPort.rect().center(), delay=10) assert not scItem.isSelected() # Double-click item diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py index 9fda0ca6..530b63d0 100644 --- a/tests/test_gui/test_gui_projtree.py +++ b/tests/test_gui/test_gui_projtree.py @@ -23,23 +23,24 @@ from __future__ import annotations import pytest from pathlib import Path -from novelwriter.core.project import NWProject -from tools import C, buildTestProject from mocked import causeOSError +from tools import C, buildTestProject -from PyQt5.QtGui import QDragEnterEvent, QDragMoveEvent, QDropEvent, QMouseEvent from PyQt5.QtCore import QEvent, QMimeData, QPoint, QTimer, Qt +from PyQt5.QtGui import QDragEnterEvent, QDragMoveEvent, QDropEvent, QMouseEvent from PyQt5.QtWidgets import QMessageBox, QMenu, QTreeWidget, QTreeWidgetItem, QDialog from novelwriter import CONFIG, SHARED -from novelwriter.enum import nwItemLayout, nwItemType, nwItemClass, nwWidget -from novelwriter.guimain import GuiMain from novelwriter.core.item import NWItem -from novelwriter.gui.projtree import GuiProjectTree, GuiProjectView, _TreeContextMenu +from novelwriter.core.project import NWProject from novelwriter.dialogs.docmerge import GuiDocMerge from novelwriter.dialogs.docsplit import GuiDocSplit from novelwriter.dialogs.editlabel import GuiEditLabel +from novelwriter.enum import nwItemLayout, nwItemType, nwItemClass, nwWidget +from novelwriter.gui.projtree import GuiProjectTree, GuiProjectView, _TreeContextMenu +from novelwriter.guimain import GuiMain +from novelwriter.types import QtMouseLeft, QtMouseMiddle, QtModeNone @pytest.mark.gui @@ -821,8 +822,8 @@ def testGuiProjTree_AutoScroll(qtbot, monkeypatch, nwGUI: GuiMain, projPath, moc action = Qt.DropAction.MoveAction mime = QMimeData() - mouse = Qt.MouseButton.LeftButton - modifier = Qt.KeyboardModifier.NoModifier + mouse = QtMouseLeft + modifier = QtModeNone # Scroll Down h = projTree.height() @@ -880,8 +881,8 @@ def testGuiProjTree_DragAndDrop(qtbot, monkeypatch, caplog, nwGUI: GuiMain, proj nPos = projTree.visualItemRect(projTree._getTreeItem(C.hNovelRoot)).bottomLeft() action = Qt.DropAction.MoveAction mime = QMimeData() - mouse = Qt.MouseButton.LeftButton - modifier = Qt.KeyboardModifier.NoModifier + mouse = QtMouseLeft + modifier = QtModeNone projTree.saveTreeOrder() treeOrder = SHARED.project.tree._order @@ -1082,8 +1083,8 @@ def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI: GuiMain, projPath, mockRnd) eType = QEvent.Type.MouseButtonPress pos = projTree.visualItemRect(projTree._getTreeItem(C.hChapterDoc)).center() - button = Qt.MouseButton.MiddleButton - modifier = Qt.KeyboardModifier.NoModifier + button = QtMouseMiddle + modifier = QtModeNone # Trigger the viewer event = QMouseEvent(eType, pos, button, button, modifier) @@ -1092,7 +1093,7 @@ def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI: GuiMain, projPath, mockRnd) # Trigger the left click clear pos = QPoint(5000, 5000) - button = Qt.MouseButton.LeftButton + button = QtMouseLeft event = QMouseEvent(eType, pos, button, button, modifier) projTree.setSelectedHandle(C.hChapterDoc) projTree.mousePressEvent(event) diff --git a/tests/test_tools/test_tools_welcome.py b/tests/test_tools/test_tools_welcome.py index 1603007c..71bf14de 100644 --- a/tests/test_tools/test_tools_welcome.py +++ b/tests/test_tools/test_tools_welcome.py @@ -26,13 +26,14 @@ from pathlib import Path from datetime import datetime from pytestqt.qtbot import QtBot -from PyQt5.QtCore import QPoint, Qt +from PyQt5.QtCore import QPoint from PyQt5.QtWidgets import QAction, QFileDialog, QMenu from novelwriter import CONFIG, SHARED from novelwriter.enum import nwItemClass from novelwriter.constants import nwFiles from novelwriter.tools.welcome import GuiWelcome +from novelwriter.types import QtMouseLeft @pytest.mark.gui @@ -100,19 +101,19 @@ def testToolWelcome_Open(qtbot: QtBot, monkeypatch, nwGUI, fncPath): # Single click item assert tabOpen.selectedPath.text() == "Path: /stuff/project_two" - qtbot.mouseClick(vPort, Qt.MouseButton.LeftButton, pos=posTwo, delay=10) + qtbot.mouseClick(vPort, QtMouseLeft, pos=posTwo, delay=10) assert tabOpen.selectedPath.text() == "Path: /stuff/project_one" # Double click item - qtbot.mouseClick(vPort, Qt.MouseButton.LeftButton, pos=posTwo, delay=10) + qtbot.mouseClick(vPort, QtMouseLeft, pos=posTwo, delay=10) with monkeypatch.context() as mp: mp.setattr(welcome, "close", lambda *a: None) with qtbot.waitSignal(welcome.openProjectRequest, timeout=5000) as signal: - qtbot.mouseDClick(vPort, Qt.MouseButton.LeftButton, pos=posTwo, delay=10) + qtbot.mouseDClick(vPort, QtMouseLeft, pos=posTwo, delay=10) assert signal.args and signal.args[0] == Path("/stuff/project_one") # Press open button - qtbot.mouseClick(vPort, Qt.MouseButton.LeftButton, pos=posTwo, delay=10) + qtbot.mouseClick(vPort, QtMouseLeft, pos=posTwo, delay=10) with monkeypatch.context() as mp: mp.setattr(welcome, "close", lambda *a: None) with qtbot.waitSignal(welcome.openProjectRequest, timeout=5000) as signal: @@ -128,7 +129,7 @@ def testToolWelcome_Open(qtbot: QtBot, monkeypatch, nwGUI, fncPath): return obj return None - qtbot.mouseClick(vPort, Qt.MouseButton.LeftButton, pos=posOne, delay=10) + qtbot.mouseClick(vPort, QtMouseLeft, pos=posOne, delay=10) ctxMenu = getMenuForPos(posOne) assert isinstance(ctxMenu, QMenu) assert ctxMenu.actions()[0].text() == "Open Project" diff --git a/tests/test_tools/test_tools_writingstats.py b/tests/test_tools/test_tools_writingstats.py index 0524174a..ef76dbaf 100644 --- a/tests/test_tools/test_tools_writingstats.py +++ b/tests/test_tools/test_tools_writingstats.py @@ -25,15 +25,15 @@ import pytest from pathlib import Path -from tools import buildTestProject from mocked import causeOSError +from tools import buildTestProject -from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QAction, QFileDialog from novelwriter import SHARED from novelwriter.constants import nwFiles from novelwriter.tools.writingstats import GuiWritingStats +from novelwriter.types import QtMouseLeft @pytest.mark.gui @@ -97,11 +97,11 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths): monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda *a, **k: ("", "")) assert not sessLog._saveData(sessLog.FMT_CSV) assert not sessLog._saveData(sessLog.FMT_JSON) - assert not sessLog._saveData(None) + assert not sessLog._saveData(None) # type: ignore # Make the save succeed monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda ss, tt, pp, options: (pp, "")) - sessLog.listBox.sortByColumn(sessLog.C_TIME, 0) + sessLog.listBox.sortByColumn(sessLog.C_TIME, 0) # type: ignore assert sessLog.novelWords.text() == "{:n}".format(600) assert sessLog.notesWords.text() == "{:n}".format(275) @@ -156,7 +156,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths): # ============ # No Novel Files - qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) + qtbot.mouseClick(sessLog.incNovel, QtMouseLeft) assert sessLog._saveData(sessLog.FMT_JSON) jsonStats = tstPaths.tmpDir / "sessionStats.json" @@ -201,8 +201,8 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths): ] # No Note Files - qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) - qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) + qtbot.mouseClick(sessLog.incNovel, QtMouseLeft) + qtbot.mouseClick(sessLog.incNotes, QtMouseLeft) assert sessLog._saveData(sessLog.FMT_JSON) jsonStats = tstPaths.tmpDir / "sessionStats.json" @@ -247,8 +247,8 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths): ] # No Negative Entries - qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) - qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton) + qtbot.mouseClick(sessLog.incNotes, QtMouseLeft) + qtbot.mouseClick(sessLog.hideNegative, QtMouseLeft) assert sessLog._saveData(sessLog.FMT_JSON) # qtbot.stop() @@ -279,8 +279,8 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths): ] # Un-hide Zero Entries - qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton) - qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton) + qtbot.mouseClick(sessLog.hideNegative, QtMouseLeft) + qtbot.mouseClick(sessLog.hideZeros, QtMouseLeft) assert sessLog._saveData(sessLog.FMT_JSON) jsonStats = tstPaths.tmpDir / "sessionStats.json" @@ -333,7 +333,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths): ] # Group by Day - qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton) + qtbot.mouseClick(sessLog.groupByDay, QtMouseLeft) assert sessLog._saveData(sessLog.FMT_JSON) jsonStats = tstPaths.tmpDir / "sessionStats.json"