From a8f61f2b989c6b527b245226f01650740512fe9f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Thu, 1 Feb 2024 23:35:14 +0100 Subject: [PATCH] Add modified combo and spinboxes that don't scroll on mouse wheel --- novelwriter/dialogs/preferences.py | 35 +++++------ novelwriter/dialogs/projectsettings.py | 7 ++- novelwriter/extensions/modified.py | 81 ++++++++++++++++++++++++++ novelwriter/tools/manussettings.py | 32 +++++----- novelwriter/tools/welcome.py | 13 +++-- 5 files changed, 126 insertions(+), 42 deletions(-) create mode 100644 novelwriter/extensions/modified.py diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index 698d6376..690ad08e 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -29,15 +29,16 @@ import logging from PyQt5.QtGui import QCloseEvent, QFont, QKeyEvent, QKeySequence from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( - QAbstractButton, QComboBox, QCompleter, QDialog, QDialogButtonBox, - QDoubleSpinBox, QFileDialog, QFontDialog, QHBoxLayout, QLineEdit, - QPushButton, QSpinBox, QToolButton, QVBoxLayout, QWidget, qApp + QAbstractButton, QCompleter, QDialog, QDialogButtonBox, QFileDialog, + QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QToolButton, QVBoxLayout, + QWidget, qApp ) from novelwriter import CONFIG, SHARED from novelwriter.constants import nwConst, nwUnicode from novelwriter.dialogs.quotes import GuiQuoteSelect from novelwriter.extensions.switch import NSwitch +from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm from novelwriter.extensions.pagedsidebar import NPagedSideBar @@ -146,7 +147,7 @@ class GuiPreferences(QDialog): self.mainForm.addGroupLabel(title, section) # Display Language - self.guiLocale = QComboBox(self) + self.guiLocale = NComboBox(self) self.guiLocale.setMinimumWidth(minWidth) for lang, name in CONFIG.listLanguages(CONFIG.LANG_NW): self.guiLocale.addItem(name, lang) @@ -159,7 +160,7 @@ class GuiPreferences(QDialog): ) # Colour Theme - self.guiTheme = QComboBox(self) + self.guiTheme = NComboBox(self) self.guiTheme.setMinimumWidth(minWidth) for theme, name in SHARED.theme.listThemes(): self.guiTheme.addItem(name, theme) @@ -186,7 +187,7 @@ class GuiPreferences(QDialog): ) # Application Font Size - self.guiFontSize = QSpinBox(self) + self.guiFontSize = NSpinBox(self) self.guiFontSize.setMinimum(8) self.guiFontSize.setMaximum(60) self.guiFontSize.setSingleStep(1) @@ -221,7 +222,7 @@ class GuiPreferences(QDialog): self.mainForm.addGroupLabel(title, section) # Document Colour Theme - self.guiSyntax = QComboBox(self) + self.guiSyntax = NComboBox(self) self.guiSyntax.setMinimumWidth(CONFIG.pxInt(200)) for syntax, name in SHARED.theme.listSyntax(): self.guiSyntax.addItem(name, syntax) @@ -248,7 +249,7 @@ class GuiPreferences(QDialog): ) # Document Font Size - self.textSize = QSpinBox(self) + self.textSize = NSpinBox(self) self.textSize.setMinimum(8) self.textSize.setMaximum(60) self.textSize.setSingleStep(1) @@ -290,7 +291,7 @@ class GuiPreferences(QDialog): self.mainForm.addGroupLabel(title, section) # Document Save Timer - self.autoSaveDoc = QSpinBox(self) + self.autoSaveDoc = NSpinBox(self) self.autoSaveDoc.setMinimum(5) self.autoSaveDoc.setMaximum(600) self.autoSaveDoc.setSingleStep(1) @@ -301,7 +302,7 @@ class GuiPreferences(QDialog): ) # Project Save Timer - self.autoSaveProj = QSpinBox(self) + self.autoSaveProj = NSpinBox(self) self.autoSaveProj.setMinimum(5) self.autoSaveProj.setMaximum(600) self.autoSaveProj.setSingleStep(1) @@ -364,7 +365,7 @@ class GuiPreferences(QDialog): ) # Inactive Time for Idle - self.userIdleTime = QDoubleSpinBox(self) + self.userIdleTime = NDoubleSpinBox(self) self.userIdleTime.setMinimum(0.5) self.userIdleTime.setMaximum(600.0) self.userIdleTime.setSingleStep(0.5) @@ -388,7 +389,7 @@ class GuiPreferences(QDialog): self.mainForm.addGroupLabel(title, section) # Max Text Width in Normal Mode - self.textWidth = QSpinBox(self) + self.textWidth = NSpinBox(self) self.textWidth.setMinimum(0) self.textWidth.setMaximum(10000) self.textWidth.setSingleStep(10) @@ -399,7 +400,7 @@ class GuiPreferences(QDialog): ) # Max Text Width in Focus Mode - self.focusWidth = QSpinBox(self) + self.focusWidth = NSpinBox(self) self.focusWidth.setMinimum(200) self.focusWidth.setMaximum(10000) self.focusWidth.setSingleStep(10) @@ -426,7 +427,7 @@ class GuiPreferences(QDialog): ) # Document Margins - self.textMargin = QSpinBox(self) + self.textMargin = NSpinBox(self) self.textMargin.setMinimum(0) self.textMargin.setMaximum(900) self.textMargin.setSingleStep(1) @@ -438,7 +439,7 @@ class GuiPreferences(QDialog): ) # Tab Width - self.tabWidth = QSpinBox(self) + self.tabWidth = NSpinBox(self) self.tabWidth.setMinimum(0) self.tabWidth.setMaximum(200) self.tabWidth.setSingleStep(1) @@ -458,7 +459,7 @@ class GuiPreferences(QDialog): self.mainForm.addGroupLabel(title, section) # Spell Checking - self.spellLanguage = QComboBox(self) + self.spellLanguage = NComboBox(self) self.spellLanguage.setMinimumWidth(minWidth) if CONFIG.hasEnchant: @@ -523,7 +524,7 @@ class GuiPreferences(QDialog): ) # Typewriter Position - self.autoScrollPos = QSpinBox(self) + self.autoScrollPos = NSpinBox(self) self.autoScrollPos.setMinimum(10) self.autoScrollPos.setMaximum(90) self.autoScrollPos.setSingleStep(1) diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index c76c9f6b..c9e327cb 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -29,7 +29,7 @@ import logging from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( - QColorDialog, QComboBox, QDialog, QDialogButtonBox, QHBoxLayout, QLineEdit, + QColorDialog, QDialog, QDialogButtonBox, QHBoxLayout, QLineEdit, QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget, qApp ) @@ -37,6 +37,7 @@ from PyQt5.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.common import simplified from novelwriter.extensions.switch import NSwitch +from novelwriter.extensions.modified import NComboBox from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm from novelwriter.extensions.pagedsidebar import NPagedSideBar @@ -257,7 +258,7 @@ class _SettingsPage(NScrollableForm): ) # Project Language - self.projLang = QComboBox(self) + self.projLang = NComboBox(self) self.projLang.setMinimumWidth(xW) for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): self.projLang.addItem(language, tag) @@ -270,7 +271,7 @@ class _SettingsPage(NScrollableForm): self.projLang.setCurrentIndex(idx) # Spell Check Language - self.spellLang = QComboBox(self) + self.spellLang = NComboBox(self) self.spellLang.setMinimumWidth(xW) self.spellLang.addItem(self.tr("Default"), "None") if CONFIG.hasEnchant: diff --git a/novelwriter/extensions/modified.py b/novelwriter/extensions/modified.py new file mode 100644 index 00000000..cebb8b74 --- /dev/null +++ b/novelwriter/extensions/modified.py @@ -0,0 +1,81 @@ +""" +novelWriter – Custom Widget: Modified Widgets +============================================= + +File History: +Created: 2024-02-01 [2.3b1] NComboBox +Created: 2024-02-01 [2.3b1] NSpinBox +Created: 2024-02-01 [2.3b1] NDoubleSpinBox + +This file is a part of novelWriter +Copyright 2018–2024, Veronica Berglyd Olsen + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" +from __future__ import annotations + +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QWheelEvent +from PyQt5.QtWidgets import QComboBox, QDoubleSpinBox, QSpinBox, QWidget + + +class NComboBox(QComboBox): + + 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 + +# END Class NComboBox + + +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 + +# END Class NSpinBox + + +class NDoubleSpinBox(QDoubleSpinBox): + + 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 + +# END Class NDoubleSpinBox diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py index 76709dbf..28404c50 100644 --- a/novelwriter/tools/manussettings.py +++ b/novelwriter/tools/manussettings.py @@ -30,17 +30,17 @@ from typing import TYPE_CHECKING from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument from PyQt5.QtCore import QEvent, QSize, Qt, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( - QAbstractButton, QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, - QDoubleSpinBox, QFontDialog, QFrame, QGridLayout, QHBoxLayout, QHeaderView, - QLabel, QLineEdit, QMenu, QPlainTextEdit, QPushButton, QSpinBox, QSplitter, - QStackedWidget, QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, - QWidget + QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, + QFontDialog, QFrame, QGridLayout, QHBoxLayout, QHeaderView, QLabel, + QLineEdit, QMenu, QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, + QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED from novelwriter.constants import nwHeadFmt, nwLabels, trConst from novelwriter.core.buildsettings import BuildSettings, FilterMode from novelwriter.extensions.switch import NSwitch +from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox from novelwriter.extensions.switchbox import NSwitchBox from novelwriter.extensions.configlayout import ( NColourLabel, NFixedPage, NScrollableForm, NScrollablePage @@ -968,7 +968,7 @@ class _FormatTab(NScrollableForm): ) # Font Size - self.textSize = QSpinBox(self) + self.textSize = NSpinBox(self) self.textSize.setMinimum(8) self.textSize.setMaximum(60) self.textSize.setSingleStep(1) @@ -976,7 +976,7 @@ class _FormatTab(NScrollableForm): self.addRow(self._build.getLabel("format.textSize"), self.textSize, unit="pt") # Line Height - self.lineHeight = QDoubleSpinBox(self) + self.lineHeight = NDoubleSpinBox(self) self.lineHeight.setFixedWidth(spW) self.lineHeight.setMinimum(0.75) self.lineHeight.setMaximum(3.0) @@ -1002,34 +1002,34 @@ class _FormatTab(NScrollableForm): self.addGroupLabel(self._build.getLabel("format.grpPage")) - self.pageUnit = QComboBox(self) + self.pageUnit = NComboBox(self) for key, name in nwLabels.UNIT_NAME.items(): self.pageUnit.addItem(trConst(name), key) - self.pageSize = QComboBox(self) + self.pageSize = NComboBox(self) for key, name in nwLabels.PAPER_NAME.items(): self.pageSize.addItem(trConst(name), key) - self.pageWidth = QDoubleSpinBox(self) + self.pageWidth = NDoubleSpinBox(self) self.pageWidth.setFixedWidth(dbW) self.pageWidth.setMaximum(500.0) self.pageWidth.valueChanged.connect(self._pageSizeValueChanged) - self.pageHeight = QDoubleSpinBox(self) + self.pageHeight = NDoubleSpinBox(self) self.pageHeight.setFixedWidth(dbW) self.pageHeight.setMaximum(500.0) self.pageHeight.valueChanged.connect(self._pageSizeValueChanged) - self.topMargin = QDoubleSpinBox(self) + self.topMargin = NDoubleSpinBox(self) self.topMargin.setFixedWidth(dbW) - self.bottomMargin = QDoubleSpinBox(self) + self.bottomMargin = NDoubleSpinBox(self) self.bottomMargin.setFixedWidth(dbW) - self.leftMargin = QDoubleSpinBox(self) + self.leftMargin = NDoubleSpinBox(self) self.leftMargin.setFixedWidth(dbW) - self.rightMargin = QDoubleSpinBox(self) + self.rightMargin = NDoubleSpinBox(self) self.rightMargin.setFixedWidth(dbW) self.addRow(self._build.getLabel("format.pageUnit"), self.pageUnit) @@ -1232,7 +1232,7 @@ class _OutputTab(NScrollableForm): button=self.btnPageHeader, stretch=(1, 1) ) - self.odtPageCountOffset = QSpinBox(self) + self.odtPageCountOffset = NSpinBox(self) self.odtPageCountOffset.setMinimum(0) self.odtPageCountOffset.setMaximum(999) self.odtPageCountOffset.setSingleStep(1) diff --git a/novelwriter/tools/welcome.py b/novelwriter/tools/welcome.py index c7357c48..98c3520b 100644 --- a/novelwriter/tools/welcome.py +++ b/novelwriter/tools/welcome.py @@ -34,9 +34,9 @@ from PyQt5.QtCore import ( pyqtSignal, pyqtSlot ) from PyQt5.QtWidgets import ( - QComboBox, QDialog, QDialogButtonBox, QFileDialog, QFormLayout, - QHBoxLayout, QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut, - QSpinBox, QStackedWidget, QStyle, QStyleOptionViewItem, QStyledItemDelegate, + QDialog, QDialogButtonBox, QFileDialog, QFormLayout, QHBoxLayout, QLabel, + QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut, + QStackedWidget, QStyle, QStyleOptionViewItem, QStyledItemDelegate, QToolButton, QVBoxLayout, QWidget, qApp ) @@ -46,6 +46,7 @@ from novelwriter.common import formatInt, formatVersion, makeFileNameSafe from novelwriter.constants import nwUnicode from novelwriter.core.coretools import ProjectBuilder from novelwriter.extensions.switch import NSwitch +from novelwriter.extensions.modified import NComboBox, NSpinBox logger = logging.getLogger(__name__) @@ -534,7 +535,7 @@ class _NewProjectForm(QWidget): self.projAuthor.setPlaceholderText(self.tr("Optional")) # Project Language - self.projLang = QComboBox(self) + self.projLang = NComboBox(self) for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): self.projLang.addItem(language, tag) @@ -594,7 +595,7 @@ class _NewProjectForm(QWidget): # Chapters and Scenes # =================== - self.numChapters = QSpinBox() + self.numChapters = NSpinBox(self) self.numChapters.setRange(0, 200) self.numChapters.setValue(5) self.numChapters.setToolTip(self.tr("Set to 0 to only add scenes")) @@ -605,7 +606,7 @@ class _NewProjectForm(QWidget): self.chapterBox.addWidget(QLabel(self.tr("chapter documents"))) self.chapterBox.addStretch(1) - self.numScenes = QSpinBox() + self.numScenes = NSpinBox(self) self.numScenes.setRange(0, 200) self.numScenes.setValue(5)