Update linting for main code
This commit is contained in:
@@ -24,7 +24,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from PyQt6.QtGui import QColor, QFont, QPalette, QPixmap
|
||||
@@ -39,7 +39,7 @@ DEFAULT_SCALE = 0.9
|
||||
|
||||
|
||||
class NFixedPage(QFrame):
|
||||
"""Extension: Fixed Page Widget
|
||||
"""Extension: Fixed Page Widget.
|
||||
|
||||
A custom widget that holds a layout. This is just a wrapper around a
|
||||
QFrame that sets the same frame style as the other Page widgets.
|
||||
@@ -49,23 +49,20 @@ class NFixedPage(QFrame):
|
||||
super().__init__(parent=parent)
|
||||
self.setFrameShadow(QFrame.Shadow.Sunken)
|
||||
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
return
|
||||
|
||||
def setCentralLayout(self, layout: QLayout) -> None:
|
||||
"""Set a layout as the central object."""
|
||||
self.setLayout(layout)
|
||||
return
|
||||
|
||||
def setCentralWidget(self, widget: QWidget) -> None:
|
||||
"""Set a layout as the central object."""
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(widget)
|
||||
self.setLayout(layout)
|
||||
return
|
||||
|
||||
|
||||
class NScrollablePage(QScrollArea):
|
||||
"""Extension: Scrollable Page Widget
|
||||
"""Extension: Scrollable Page Widget.
|
||||
|
||||
A custom widget that holds a layout within a scrollable area.
|
||||
"""
|
||||
@@ -79,16 +76,14 @@ class NScrollablePage(QScrollArea):
|
||||
self.setVerticalScrollBarPolicy(QtScrollAsNeeded)
|
||||
self.setFrameShadow(QFrame.Shadow.Sunken)
|
||||
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
return
|
||||
|
||||
def setCentralLayout(self, layout: QLayout) -> None:
|
||||
"""Set the central layout of the scroll page."""
|
||||
self._widget.setLayout(layout)
|
||||
return
|
||||
|
||||
|
||||
class NScrollableForm(QScrollArea):
|
||||
"""Extension: Scrollable Form Widget
|
||||
"""Extension: Scrollable Form Widget.
|
||||
|
||||
A custom widget that creates a form within a scrollable area.
|
||||
"""
|
||||
@@ -117,8 +112,6 @@ class NScrollableForm(QScrollArea):
|
||||
self.setFrameShadow(QFrame.Shadow.Sunken)
|
||||
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Properties
|
||||
##
|
||||
@@ -135,18 +128,15 @@ class NScrollableForm(QScrollArea):
|
||||
"""Set the text color for the help text."""
|
||||
self._helpCol = color
|
||||
self._fontScale = scale
|
||||
return
|
||||
|
||||
def setHelpText(self, key: str, text: str) -> None:
|
||||
"""Set the text for the help label."""
|
||||
if qHelp := self._editable.get(key):
|
||||
qHelp.setText(text)
|
||||
return
|
||||
|
||||
def setRowIndent(self, indent: int) -> None:
|
||||
"""Set the indentation of each row."""
|
||||
self._indent = max(indent, 0)
|
||||
return
|
||||
|
||||
##
|
||||
# Methods
|
||||
@@ -158,7 +148,6 @@ class NScrollableForm(QScrollArea):
|
||||
yPos = self._sections[identifier].pos().y() - 8
|
||||
if vBar := self.verticalScrollBar():
|
||||
vBar.setValue(yPos)
|
||||
return
|
||||
|
||||
def scrollToLabel(self, label: str) -> None:
|
||||
"""Scroll to the requested label."""
|
||||
@@ -166,7 +155,6 @@ class NScrollableForm(QScrollArea):
|
||||
yPos = self._index[label].pos().y() - 8
|
||||
if vBar := self.verticalScrollBar():
|
||||
vBar.setValue(yPos)
|
||||
return
|
||||
|
||||
def addGroupLabel(self, label: str, identifier: int | None = None) -> None:
|
||||
"""Add a text label to separate groups of settings."""
|
||||
@@ -178,7 +166,6 @@ class NScrollableForm(QScrollArea):
|
||||
self._first = False
|
||||
if identifier is not None:
|
||||
self._sections[identifier] = qLabel
|
||||
return
|
||||
|
||||
def addRow(
|
||||
self,
|
||||
@@ -252,17 +239,14 @@ class NScrollableForm(QScrollArea):
|
||||
self._index[label.strip()] = qWidget
|
||||
qLabel.setAccessibleName(text)
|
||||
|
||||
return
|
||||
|
||||
def finalise(self) -> None:
|
||||
"""Finalise the layout when the form is built."""
|
||||
self._layout.addSpacing(20)
|
||||
self._layout.addStretch(1)
|
||||
return
|
||||
|
||||
|
||||
class NColorLabel(QLabel):
|
||||
"""Extension: A Coloured Label
|
||||
"""Extension: A Coloured Label.
|
||||
|
||||
A custom widget that draws a label in a specific colour, and
|
||||
optionally at a specific size, and word wrapped.
|
||||
@@ -298,21 +282,17 @@ class NColorLabel(QLabel):
|
||||
self.setWordWrap(wrap)
|
||||
self.setColorState(True)
|
||||
|
||||
return
|
||||
|
||||
def setTextColors(self, *, color: QColor | None = None, faded: QColor | None = None) -> None:
|
||||
"""Set or update the text colours."""
|
||||
self._color = color or self._color
|
||||
self._faded = faded or self._faded
|
||||
self._refeshTextColor()
|
||||
return
|
||||
|
||||
def setColorState(self, state: bool) -> None:
|
||||
"""Change the colour state."""
|
||||
if self._state is not state:
|
||||
self._state = state
|
||||
self._refeshTextColor()
|
||||
return
|
||||
|
||||
def _refeshTextColor(self) -> None:
|
||||
"""Refresh the colour of the text on the label."""
|
||||
@@ -322,11 +302,10 @@ class NColorLabel(QLabel):
|
||||
self._color if self._state else self._faded,
|
||||
)
|
||||
self.setPalette(palette)
|
||||
return
|
||||
|
||||
|
||||
class NWrappedWidgetBox(QHBoxLayout):
|
||||
"""Extension: A Text-Wrapped Widget Box
|
||||
"""Extension: A Text-Wrapped Widget Box.
|
||||
|
||||
A custom layout box where a widget is wrapped in text labels on
|
||||
either side within a layout box. The widget is inserted at the {0}
|
||||
@@ -341,4 +320,3 @@ class NWrappedWidgetBox(QHBoxLayout):
|
||||
self.addWidget(widget)
|
||||
if after:
|
||||
self.addWidget(QLabel(after.lstrip()))
|
||||
return
|
||||
|
||||
@@ -21,7 +21,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class WheelEventFilter(QObject):
|
||||
"""Extensions: Wheel Event Filter
|
||||
"""Extensions: Wheel Event Filter.
|
||||
|
||||
An event filter that filters mouse wheel events for a widget and
|
||||
forward them to the root widget. This solves the lack of mouse wheel
|
||||
@@ -50,7 +50,6 @@ class WheelEventFilter(QObject):
|
||||
super().__init__(parent=parent)
|
||||
self._parent = parent
|
||||
self._locked = False
|
||||
return
|
||||
|
||||
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
||||
"""Filter events of type QWheelEvent and forward them to the
|
||||
@@ -69,6 +68,7 @@ class WheelEventFilter(QObject):
|
||||
|
||||
|
||||
class StatusTipFilter(QObject):
|
||||
"""Filter: Remove StatusBar ToolTips."""
|
||||
|
||||
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
||||
"""Filter out status tip events on menus."""
|
||||
|
||||
@@ -24,7 +24,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -47,6 +47,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class NDialog(QDialog):
|
||||
"""Custom: Modified QDialog."""
|
||||
|
||||
def softDelete(self) -> None:
|
||||
"""Since calling deleteLater is sometimes not safe from Python,
|
||||
@@ -55,53 +56,54 @@ class NDialog(QDialog):
|
||||
so that it gets garbage collected when it runs out of scope.
|
||||
"""
|
||||
self.setParent(None) # type: ignore
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def reject(self) -> None:
|
||||
"""Overload the reject slot and also call close."""
|
||||
super().reject()
|
||||
self.close()
|
||||
return
|
||||
|
||||
|
||||
class NToolDialog(NDialog):
|
||||
"""Custom: Modified QDialog for Tools."""
|
||||
|
||||
def __init__(self, parent: GuiMain) -> None:
|
||||
super().__init__(parent=parent)
|
||||
self.setModal(False)
|
||||
if CONFIG.osDarwin:
|
||||
self.setWindowFlag(Qt.WindowType.Tool)
|
||||
return
|
||||
|
||||
def activateDialog(self) -> None:
|
||||
"""Helper function to activate dialog on various systems."""
|
||||
"""Activate dialog on various operating systems."""
|
||||
self.show()
|
||||
if CONFIG.osWindows:
|
||||
self.activateWindow()
|
||||
self.raise_()
|
||||
QApplication.processEvents()
|
||||
return
|
||||
|
||||
|
||||
class NNonBlockingDialog(NDialog):
|
||||
"""Custom: Modified Non-Blocking QDialog."""
|
||||
|
||||
def __init__(self, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent=parent)
|
||||
self.setModal(True)
|
||||
return
|
||||
|
||||
def activateDialog(self) -> None:
|
||||
"""Helper function to activate dialog on various systems."""
|
||||
"""Activate dialog on various operating systems."""
|
||||
self.show()
|
||||
if CONFIG.osWindows:
|
||||
self.activateWindow()
|
||||
self.raise_()
|
||||
QApplication.processEvents()
|
||||
return
|
||||
|
||||
|
||||
class NTreeView(QTreeView):
|
||||
"""Custom: Modified QTreeView.
|
||||
|
||||
The main purpose is to provide the middleClicked signal that matches
|
||||
clicked and doubleCLicked.
|
||||
"""
|
||||
|
||||
middleClicked = pyqtSignal(QModelIndex)
|
||||
|
||||
@@ -116,6 +118,12 @@ class NTreeView(QTreeView):
|
||||
|
||||
|
||||
class NComboBox(QComboBox):
|
||||
"""Custom: Modified QComboBox.
|
||||
|
||||
The main purpose is to provide a combo box that doesn't scroll when
|
||||
the mousewheel is active on it while scrolling through a scrollable
|
||||
window of many widgets.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: QWidget | None = None, maxItems: int = 15) -> None:
|
||||
super().__init__(parent=parent)
|
||||
@@ -126,7 +134,30 @@ class NComboBox(QComboBox):
|
||||
# and allows for scrolling of long lists of items
|
||||
self.setStyleSheet("QComboBox {combobox-popup: 0;}")
|
||||
|
||||
return
|
||||
def wheelEvent(self, event: QWheelEvent) -> None:
|
||||
"""Only capture the mouse wheel if the widget has focus."""
|
||||
if self.hasFocus():
|
||||
super().wheelEvent(event)
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def setCurrentData(self, data: str | int | Enum, default: str | int | Enum) -> None:
|
||||
"""Set the current index from data, with a fallback."""
|
||||
idx = self.findData(data)
|
||||
self.setCurrentIndex(self.findData(default) if idx < 0 else idx)
|
||||
|
||||
|
||||
class NSpinBox(QSpinBox):
|
||||
"""Custom: Modified QSpinBox.
|
||||
|
||||
The main purpose is to provide a spin box that doesn't scroll when
|
||||
the mousewheel is active on it while scrolling through a scrollable
|
||||
window of many widgets.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent=parent)
|
||||
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||
|
||||
def wheelEvent(self, event: QWheelEvent) -> None:
|
||||
"""Only capture the mouse wheel if the widget has focus."""
|
||||
@@ -134,31 +165,15 @@ class NComboBox(QComboBox):
|
||||
super().wheelEvent(event)
|
||||
else:
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
def setCurrentData(self, data: str | int | Enum, default: str | int | Enum) -> None:
|
||||
"""Set the current index from data, with a fallback."""
|
||||
idx = self.findData(data)
|
||||
self.setCurrentIndex(self.findData(default) if idx < 0 else idx)
|
||||
return
|
||||
|
||||
|
||||
class NSpinBox(QSpinBox):
|
||||
|
||||
def __init__(self, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent=parent)
|
||||
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||
return
|
||||
|
||||
def wheelEvent(self, event: QWheelEvent) -> None:
|
||||
if self.hasFocus():
|
||||
super().wheelEvent(event)
|
||||
else:
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
|
||||
class NDoubleSpinBox(QDoubleSpinBox):
|
||||
"""Custom: Modified QDoubleSpinBox.
|
||||
|
||||
The main purpose is to provide a float spin box that doesn't scroll
|
||||
when the mousewheel is active on it while scrolling through a
|
||||
scrollable window of many widgets.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -175,17 +190,20 @@ class NDoubleSpinBox(QDoubleSpinBox):
|
||||
self.setMaximum(maxVal)
|
||||
self.setSingleStep(step)
|
||||
self.setDecimals(prec)
|
||||
return
|
||||
|
||||
def wheelEvent(self, event: QWheelEvent) -> None:
|
||||
"""Only capture the mouse wheel if the widget has focus."""
|
||||
if self.hasFocus():
|
||||
super().wheelEvent(event)
|
||||
else:
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
|
||||
class NIconToolButton(QToolButton):
|
||||
"""Custom: Modified QToolButton.
|
||||
|
||||
A quicker way to create a tool button using the app theme.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, parent: QWidget, iconSize: QSize,
|
||||
@@ -197,15 +215,17 @@ class NIconToolButton(QToolButton):
|
||||
self.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
||||
if icon:
|
||||
self.setThemeIcon(icon, color)
|
||||
return
|
||||
|
||||
def setThemeIcon(self, iconKey: str, color: str | None = None) -> None:
|
||||
"""Set an icon from the current theme."""
|
||||
self.setIcon(SHARED.theme.getIcon(iconKey, color))
|
||||
return
|
||||
|
||||
|
||||
class NIconToggleButton(QToolButton):
|
||||
"""Custom: Modified QToolButton.
|
||||
|
||||
A quicker way to create a toggle button using the app theme.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: QWidget, iconSize: QSize, icon: str | None = None) -> None:
|
||||
super().__init__(parent=parent)
|
||||
@@ -216,16 +236,15 @@ class NIconToggleButton(QToolButton):
|
||||
self.setStyleSheet("border: none; background: transparent;")
|
||||
if icon:
|
||||
self.setThemeIcon(icon)
|
||||
return
|
||||
|
||||
def setThemeIcon(self, iconKey: str) -> None:
|
||||
"""Set an icon from the current theme."""
|
||||
iconSize = self.iconSize()
|
||||
self.setIcon(SHARED.theme.getToggleIcon(iconKey, (iconSize.width(), iconSize.height())))
|
||||
return
|
||||
|
||||
|
||||
class NClickableLabel(QLabel):
|
||||
"""Custom: Clickable QLabel."""
|
||||
|
||||
mouseClicked = pyqtSignal()
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
@@ -42,6 +42,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NovelSelector(QComboBox):
|
||||
"""Custom: Novel Root Folder Selector."""
|
||||
|
||||
novelSelectionChanged = pyqtSignal(str)
|
||||
|
||||
@@ -53,7 +54,6 @@ class NovelSelector(QComboBox):
|
||||
self._listFormat = None
|
||||
self.currentIndexChanged.connect(self._indexChanged)
|
||||
self.updateTheme()
|
||||
return
|
||||
|
||||
##
|
||||
# Properties
|
||||
@@ -80,18 +80,15 @@ class NovelSelector(QComboBox):
|
||||
self._blockSignal = blockSignal
|
||||
self.setCurrentIndex(index)
|
||||
self._blockSignal = False
|
||||
return
|
||||
|
||||
def setIncludeAll(self, value: bool) -> None:
|
||||
"""Set flag to add an "All Novel Folders" option."""
|
||||
self._includeAll = value
|
||||
return
|
||||
|
||||
def setListFormat(self, value: str | None) -> None:
|
||||
"""Set a format string for the list entries."""
|
||||
if value is None or "{0}" in value:
|
||||
self._listFormat = value
|
||||
return
|
||||
|
||||
def updateTheme(self) -> None:
|
||||
"""Update theme colours."""
|
||||
@@ -99,7 +96,6 @@ class NovelSelector(QComboBox):
|
||||
palette.setBrush(QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, palette.text())
|
||||
self.setPalette(palette)
|
||||
self.refreshNovelList()
|
||||
return
|
||||
|
||||
##
|
||||
# Public Slots
|
||||
@@ -133,8 +129,6 @@ class NovelSelector(QComboBox):
|
||||
self.setEnabled(self.count() > 1)
|
||||
self._blockSignal = False
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
@@ -144,4 +138,3 @@ class NovelSelector(QComboBox):
|
||||
"""Re-emit the change of selection signal, unless blocked."""
|
||||
if not self._blockSignal:
|
||||
self.novelSelectionChanged.emit(self.currentData())
|
||||
return
|
||||
|
||||
@@ -22,7 +22,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from PyQt6.QtCore import QPoint, QRectF, QSize, Qt, pyqtSignal, pyqtSlot
|
||||
@@ -39,7 +39,7 @@ from novelwriter.types import (
|
||||
|
||||
|
||||
class NPagedSideBar(QToolBar):
|
||||
"""Extensions: Paged Side Bar
|
||||
"""Extensions: Paged Side Bar.
|
||||
|
||||
A side bar widget that holds buttons that mimic tabs. It is designed
|
||||
to be used in combination with a QStackedWidget for options panels.
|
||||
@@ -65,8 +65,6 @@ class NPagedSideBar(QToolBar):
|
||||
stretch.setSizePolicy(QtSizeExpanding, QtSizeExpanding)
|
||||
self._stretchAction = self.addWidget(stretch)
|
||||
|
||||
return
|
||||
|
||||
def button(self, buttonId: int) -> _PagedToolButton:
|
||||
"""Return a specific button."""
|
||||
return self._buttons[buttonId]
|
||||
@@ -74,14 +72,12 @@ class NPagedSideBar(QToolBar):
|
||||
def setLabelColor(self, color: QColor) -> None:
|
||||
"""Set the text color for the labels."""
|
||||
self._labelCol = color
|
||||
return
|
||||
|
||||
def addLabel(self, text: str) -> None:
|
||||
"""Add a new label to the toolbar."""
|
||||
label = _NPagedToolLabel(self, self._labelCol)
|
||||
label.setText(text)
|
||||
self.insertWidget(self._stretchAction, label)
|
||||
return
|
||||
|
||||
def addButton(self, text: str, buttonId: int = -1) -> None:
|
||||
"""Add a new button to the toolbar."""
|
||||
@@ -90,13 +86,11 @@ class NPagedSideBar(QToolBar):
|
||||
self.insertWidget(self._stretchAction, button)
|
||||
self._group.addButton(button, id=buttonId)
|
||||
self._buttons[buttonId] = button
|
||||
return
|
||||
|
||||
def setSelected(self, buttonId: int) -> None:
|
||||
"""Set the selected button."""
|
||||
if button := self._group.button(buttonId):
|
||||
button.setChecked(True)
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
@@ -104,11 +98,10 @@ class NPagedSideBar(QToolBar):
|
||||
|
||||
@pyqtSlot("QAbstractButton*")
|
||||
def _buttonClicked(self, button: QAbstractButton) -> None:
|
||||
"""A button was clicked in the group, emit its id."""
|
||||
"""Handle a button click in the group and emit its id."""
|
||||
buttonId = self._group.id(button)
|
||||
if buttonId != -1:
|
||||
self.buttonClicked.emit(buttonId)
|
||||
return
|
||||
|
||||
|
||||
class _PagedToolButton(QToolButton):
|
||||
@@ -127,8 +120,6 @@ class _PagedToolButton(QToolButton):
|
||||
self._aH = 2*fH//7
|
||||
self.setFixedHeight(self._bH)
|
||||
|
||||
return
|
||||
|
||||
def sizeHint(self) -> QSize:
|
||||
"""Return a size hint that includes the arrow."""
|
||||
return super().sizeHint() + QSize(4*self._aH, 0)
|
||||
@@ -180,8 +171,6 @@ class _PagedToolButton(QToolButton):
|
||||
]))
|
||||
painter.end()
|
||||
|
||||
return
|
||||
|
||||
|
||||
class _NPagedToolLabel(QLabel):
|
||||
|
||||
@@ -199,8 +188,6 @@ class _NPagedToolLabel(QLabel):
|
||||
|
||||
self._textCol = textColor or self.palette().text().color()
|
||||
|
||||
return
|
||||
|
||||
def paintEvent(self, event: QPaintEvent) -> None:
|
||||
"""Overload the paint event to draw a simple, left aligned text
|
||||
label that matches the button style.
|
||||
@@ -215,5 +202,3 @@ class _NPagedToolLabel(QLabel):
|
||||
painter.setOpacity(1.0)
|
||||
painter.drawText(QRectF(4, self._tM, tW, tH), QtAlignLeft, self.text())
|
||||
painter.end()
|
||||
|
||||
return
|
||||
|
||||
@@ -21,7 +21,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from math import ceil
|
||||
@@ -37,7 +37,7 @@ from novelwriter.types import (
|
||||
|
||||
|
||||
class NProgressCircle(QProgressBar):
|
||||
"""Extension: Circular Progress Widget
|
||||
"""Extension: Circular Progress Widget.
|
||||
|
||||
A custom widget that paints a circular progress indicator instead of
|
||||
a straight bar. It is also possible to set custom text for iṫ.
|
||||
@@ -64,7 +64,6 @@ class NProgressCircle(QProgressBar):
|
||||
self.setSizePolicy(QtSizeFixed, QtSizeFixed)
|
||||
self.setFixedWidth(size)
|
||||
self.setFixedHeight(size)
|
||||
return
|
||||
|
||||
def setColors(
|
||||
self, back: QColor | None = None, track: QColor | None = None,
|
||||
@@ -80,16 +79,14 @@ class NProgressCircle(QProgressBar):
|
||||
self._bPen = QPen(QBrush(track), self._point, QtSolidLine, QtRoundCap)
|
||||
if isinstance(text, QColor):
|
||||
self._tColor = text
|
||||
return
|
||||
|
||||
def setCentreText(self, text: str | None) -> None:
|
||||
"""Replace the progress text with a custom string."""
|
||||
self._text = text
|
||||
self.setValue(self.value()) # Triggers a redraw
|
||||
return
|
||||
|
||||
def paintEvent(self, event: QPaintEvent) -> None:
|
||||
"""Custom painter for the progress bar."""
|
||||
"""Paint the progress bar."""
|
||||
progress = 100.0*self.value()/self.maximum()
|
||||
angle = ceil(16*3.6*progress)
|
||||
painter = QPainter(self)
|
||||
@@ -103,21 +100,19 @@ class NProgressCircle(QProgressBar):
|
||||
painter.drawArc(self._cRect, 90*16, -angle)
|
||||
painter.setPen(self._tColor)
|
||||
painter.drawText(self._cRect, QtAlignCenter, self._text or f"{progress:.1f} %")
|
||||
return
|
||||
|
||||
|
||||
class NProgressSimple(QProgressBar):
|
||||
"""Extension: Simple Progress Widget
|
||||
"""Extension: Simple Progress Widget.
|
||||
|
||||
A custom widget that paints a plain bar with no other styling.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
return
|
||||
|
||||
def paintEvent(self, event: QPaintEvent) -> None:
|
||||
"""Custom painter for the progress bar."""
|
||||
"""Paint the progress bar."""
|
||||
if (value := self.value()) > 0:
|
||||
progress = ceil(self.width()*float(value)/self.maximum())
|
||||
painter = QPainter(self)
|
||||
@@ -125,4 +120,3 @@ class NProgressSimple(QProgressBar):
|
||||
painter.setPen(self.palette().highlight().color())
|
||||
painter.setBrush(self.palette().highlight())
|
||||
painter.drawRect(0, 0, progress, self.height())
|
||||
return
|
||||
|
||||
@@ -20,7 +20,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
@@ -34,6 +34,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StatusLED(QAbstractButton):
|
||||
"""Custom: LED Style Indicator."""
|
||||
|
||||
__slots__ = ("_color", "_negative", "_neutral", "_postitve", "_state")
|
||||
|
||||
@@ -46,7 +47,6 @@ class StatusLED(QAbstractButton):
|
||||
self._state = None
|
||||
self.setFixedWidth(sW)
|
||||
self.setFixedHeight(sH)
|
||||
return
|
||||
|
||||
@property
|
||||
def state(self) -> bool | None:
|
||||
@@ -59,7 +59,6 @@ class StatusLED(QAbstractButton):
|
||||
self._postitve = positive
|
||||
self._negative = negative
|
||||
self.setState(self._state)
|
||||
return
|
||||
|
||||
def setState(self, state: bool | None) -> None:
|
||||
"""Set the colour state."""
|
||||
@@ -71,7 +70,6 @@ class StatusLED(QAbstractButton):
|
||||
self._color = self._neutral
|
||||
self._state = state
|
||||
self.update()
|
||||
return
|
||||
|
||||
def paintEvent(self, event: QPaintEvent) -> None:
|
||||
"""Draw the LED."""
|
||||
@@ -82,4 +80,3 @@ class StatusLED(QAbstractButton):
|
||||
painter.setOpacity(1.0)
|
||||
painter.drawEllipse(1, 1, self.width() - 2, self.height() - 2)
|
||||
painter.end()
|
||||
return
|
||||
|
||||
@@ -20,7 +20,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from PyQt6.QtCore import QPropertyAnimation, Qt, pyqtProperty, pyqtSlot # pyright: ignore
|
||||
@@ -32,6 +32,7 @@ from novelwriter.types import QtNoPen, QtPaintAntiAlias, QtSizeFixed
|
||||
|
||||
|
||||
class NSwitch(QAbstractButton):
|
||||
"""Custom: Toggle Switch."""
|
||||
|
||||
__slots__ = ("_cOff", "_cOn", "_offset", "_rH", "_rR", "_xH", "_xR", "_xW")
|
||||
|
||||
@@ -55,8 +56,6 @@ class NSwitch(QAbstractButton):
|
||||
|
||||
self.clicked.connect(self._onClick)
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Properties
|
||||
##
|
||||
@@ -69,7 +68,6 @@ class NSwitch(QAbstractButton):
|
||||
def offset(self, offset: int) -> None:
|
||||
self._offset = offset
|
||||
self.update()
|
||||
return
|
||||
|
||||
##
|
||||
# Getters and Setters
|
||||
@@ -79,7 +77,6 @@ class NSwitch(QAbstractButton):
|
||||
"""Overload setChecked to also alter the offset."""
|
||||
super().setChecked(checked)
|
||||
self._offset = (self._xW - self._xR) if checked else self._xR
|
||||
return
|
||||
|
||||
##
|
||||
# Events
|
||||
@@ -89,7 +86,6 @@ class NSwitch(QAbstractButton):
|
||||
"""Overload resize to ensure correct offset."""
|
||||
super().resizeEvent(event)
|
||||
self._offset = (self._xW - self._xR) if self.isChecked() else self._xR
|
||||
return
|
||||
|
||||
def paintEvent(self, event: QPaintEvent) -> None:
|
||||
"""Drawing the switch itself."""
|
||||
@@ -109,13 +105,10 @@ class NSwitch(QAbstractButton):
|
||||
|
||||
painter.end()
|
||||
|
||||
return
|
||||
|
||||
def enterEvent(self, event: QEnterEvent) -> None:
|
||||
"""Change the cursor when hovering the button."""
|
||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
super().enterEvent(event)
|
||||
return
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def _onClick(self, checked: bool) -> None:
|
||||
@@ -125,4 +118,3 @@ class NSwitch(QAbstractButton):
|
||||
anim.setStartValue(self._offset)
|
||||
anim.setEndValue((self._xW - self._xR) if checked else self._xR)
|
||||
anim.start()
|
||||
return
|
||||
|
||||
@@ -20,7 +20,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -39,7 +39,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class NSwitchBox(QScrollArea):
|
||||
"""Extension: Switch Box Widget
|
||||
"""Extension: Switch Box Widget.
|
||||
|
||||
A widget that can hold a list of switches with labels and optional
|
||||
icons. The switch toggles emits a common signal with a switch key.
|
||||
@@ -55,7 +55,6 @@ class NSwitchBox(QScrollArea):
|
||||
self._sIcon = baseSize
|
||||
self._widgets = []
|
||||
self.clear()
|
||||
return
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Rebuild the content of the core widget."""
|
||||
@@ -72,8 +71,6 @@ class NSwitchBox(QScrollArea):
|
||||
self.setWidgetResizable(True)
|
||||
self.setWidget(self._widget)
|
||||
|
||||
return
|
||||
|
||||
def addLabel(self, text: str) -> None:
|
||||
"""Add a header label to the content box."""
|
||||
label = QLabel(text, self)
|
||||
@@ -83,7 +80,6 @@ class NSwitchBox(QScrollArea):
|
||||
self._content.addWidget(label, self._index, 0, 1, 3, QtAlignLeft)
|
||||
self._widgets.append(label)
|
||||
self._bumpIndex()
|
||||
return
|
||||
|
||||
def addItem(self, qIcon: QIcon, text: str, identifier: str, default: bool = False) -> None:
|
||||
"""Add an item to the content box."""
|
||||
@@ -104,8 +100,6 @@ class NSwitchBox(QScrollArea):
|
||||
self._widgets.append(switch)
|
||||
self._bumpIndex()
|
||||
|
||||
return
|
||||
|
||||
def addSeparator(self) -> None:
|
||||
"""Add a blank entry in the content box."""
|
||||
spacer = QWidget(self)
|
||||
@@ -113,7 +107,6 @@ class NSwitchBox(QScrollArea):
|
||||
self._content.addWidget(spacer, self._index, 0, 1, 3, QtAlignLeft)
|
||||
self._widgets.append(spacer)
|
||||
self._bumpIndex()
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
@@ -122,7 +115,6 @@ class NSwitchBox(QScrollArea):
|
||||
def _emitSwitchSignal(self, identifier: str, state: bool) -> None:
|
||||
"""Emit a signal for a switch toggle."""
|
||||
self.switchToggled.emit(identifier, state)
|
||||
return
|
||||
|
||||
def _bumpIndex(self) -> None:
|
||||
"""Increase the index counter and make sure only the last
|
||||
@@ -131,4 +123,3 @@ class NSwitchBox(QScrollArea):
|
||||
self._content.setRowStretch(self._index, 0)
|
||||
self._content.setRowStretch(self._index + 1, 1)
|
||||
self._index += 1
|
||||
return
|
||||
|
||||
@@ -20,7 +20,7 @@ General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
""" # noqa
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
@@ -45,6 +45,11 @@ API_URL = "https://api.github.com/repos/vkbo/novelwriter/releases/latest"
|
||||
|
||||
|
||||
class VersionInfoWidget(QWidget):
|
||||
"""Custom: version Info Label.
|
||||
|
||||
A custom widget that will show a clickable area for contacting
|
||||
GitHub and pulling the latest release version info.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
@@ -75,8 +80,6 @@ class VersionInfoWidget(QWidget):
|
||||
|
||||
self.setLayout(self._layout)
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
##
|
||||
@@ -93,7 +96,6 @@ class VersionInfoWidget(QWidget):
|
||||
lookup = _Retriever()
|
||||
lookup.signals.dataReady.connect(self._updateReleaseInfo)
|
||||
SHARED.runInThreadPool(lookup)
|
||||
return
|
||||
|
||||
##
|
||||
# Private Slots
|
||||
@@ -109,7 +111,6 @@ class VersionInfoWidget(QWidget):
|
||||
))
|
||||
else:
|
||||
self._lblRelease.setText(self._trLatest.format(reason or self.tr("Failed")))
|
||||
return
|
||||
|
||||
|
||||
class _Retriever(QRunnable):
|
||||
@@ -117,7 +118,6 @@ class _Retriever(QRunnable):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.signals = _RetrieverSignal()
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def run(self) -> None:
|
||||
@@ -140,7 +140,6 @@ class _Retriever(QRunnable):
|
||||
except Exception as e:
|
||||
logger.error("Failed to retrieve release info")
|
||||
self.signals.dataReady.emit("", str(e))
|
||||
return
|
||||
|
||||
|
||||
class _RetrieverSignal(QObject):
|
||||
|
||||
Reference in New Issue
Block a user