Add search bar to preferences

This commit is contained in:
Veronica Berglyd Olsen
2024-01-08 21:08:33 +01:00
parent 1fbd50334d
commit 671d7130e1
2 changed files with 96 additions and 13 deletions
+63 -7
View File
@@ -26,12 +26,12 @@ from __future__ import annotations
import logging import logging
from PyQt5.QtGui import QCloseEvent, QFont from PyQt5.QtGui import QCloseEvent, QColor, QFont, QKeyEvent, QKeySequence, QPalette
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractButton, QDialog, QHBoxLayout, QVBoxLayout, QWidget, QComboBox, QAbstractButton, QComboBox, QCompleter, QDialog, QDialogButtonBox,
QSpinBox, QPushButton, QDialogButtonBox, QLineEdit, QFileDialog, QDoubleSpinBox, QFileDialog, QFontDialog, QHBoxLayout, QLabel, QLineEdit,
QFontDialog, QDoubleSpinBox, qApp QPushButton, QSpinBox, QVBoxLayout, QWidget, qApp
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
@@ -58,37 +58,80 @@ class GuiPreferences(QDialog):
self.setMinimumSize(CONFIG.pxInt(600), CONFIG.pxInt(500)) self.setMinimumSize(CONFIG.pxInt(600), CONFIG.pxInt(500))
self.resize(*CONFIG.preferencesWinSize) self.resize(*CONFIG.preferencesWinSize)
# Title
font = self.font()
font.setPointSizeF(1.5*SHARED.theme.fontPointSize)
palette = self.palette()
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.helpText))
self.titleLabel = QLabel(self.tr("Preferences"), self)
self.titleLabel.setFont(font)
self.titleLabel.setPalette(palette)
self.titleLabel.setIndent(CONFIG.pxInt(4))
# SideBar # SideBar
self.sidebar = NPagedSideBar(self) self.sidebar = NPagedSideBar(self)
self.sidebar.setLabelColor(SHARED.theme.helpText) self.sidebar.setLabelColor(SHARED.theme.helpText)
self.sidebar.addLabel(self.tr("Preferences"))
self.sidebar.buttonClicked.connect(self._sidebarClicked) self.sidebar.buttonClicked.connect(self._sidebarClicked)
# Search Box
self.searchText = QLineEdit(self)
self.searchText.setPlaceholderText(self.tr("Search"))
self.searchText.setMinimumWidth(CONFIG.pxInt(200))
self.searchAction = self.searchText.addAction(
SHARED.theme.getIcon("search"), QLineEdit.ActionPosition.TrailingPosition
)
self.searchAction.triggered.connect(self._gotoSearch)
self.searchBox = QHBoxLayout()
self.searchBox.addWidget(self.titleLabel)
self.searchBox.addStretch(1)
self.searchBox.addWidget(self.searchText, 1)
# Form # Form
self.mainForm = NScrollableForm(self) self.mainForm = NScrollableForm(self)
self.mainForm.setHelpTextStyle(SHARED.theme.helpText) self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
# Buttons # Buttons
self.buttonBox = QDialogButtonBox( self.buttonBox = QDialogButtonBox(
QDialogButtonBox.Apply | QDialogButtonBox.Save | QDialogButtonBox.Close QDialogButtonBox.StandardButton.Apply
| QDialogButtonBox.StandardButton.Save
| QDialogButtonBox.StandardButton.Close
) )
self.buttonBox.clicked.connect(self._dialogButtonClicked) self.buttonBox.clicked.connect(self._dialogButtonClicked)
# Assemble # Assemble
self.mainSearch = QVBoxLayout()
self.mainSearch.addItem(self.searchBox)
self.mainSearch.addWidget(self.mainForm)
self.mainBox = QHBoxLayout() self.mainBox = QHBoxLayout()
self.mainBox.addWidget(self.sidebar) self.mainBox.addWidget(self.sidebar)
# self.mainBox.addLayout(self.mainSearch)
self.mainBox.addWidget(self.mainForm) self.mainBox.addWidget(self.mainForm)
self.mainBox.setContentsMargins(0, 0, 0, 0) self.mainBox.setContentsMargins(0, 0, 0, 0)
self.outerBox = QVBoxLayout() self.outerBox = QVBoxLayout()
self.outerBox.addLayout(self.searchBox)
self.outerBox.addLayout(self.mainBox) self.outerBox.addLayout(self.mainBox)
self.outerBox.addWidget(self.buttonBox) self.outerBox.addWidget(self.buttonBox)
self.outerBox.setSpacing(CONFIG.pxInt(8)) self.outerBox.setSpacing(CONFIG.pxInt(8))
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.setSizeGripEnabled(True) self.setSizeGripEnabled(True)
# Build Form
self.buildForm() self.buildForm()
# Populate Search
self.searchCompleter = QCompleter(self.mainForm.labels, self)
self.searchCompleter.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
self.searchCompleter.setFilterMode(Qt.MatchFlag.MatchContains)
self.searchCompleter.activated.connect(self._gotoSearch)
self.searchText.setCompleter(self.searchCompleter)
logger.debug("Ready: GuiPreferences") logger.debug("Ready: GuiPreferences")
return return
@@ -768,9 +811,17 @@ class GuiPreferences(QDialog):
logger.debug("Close: GuiPreferences") logger.debug("Close: GuiPreferences")
self._saveWindowSize() self._saveWindowSize()
event.accept() event.accept()
qApp.processEvents()
self.deleteLater() self.deleteLater()
return return
def keyPressEvent(self, event: QKeyEvent) -> None:
"""Overload keyPressEvent to block enter key to save."""
if event.matches(QKeySequence.Cancel):
self.reject()
event.ignore()
return
## ##
# Private Slots # Private Slots
## ##
@@ -794,6 +845,12 @@ class GuiPreferences(QDialog):
self.mainForm.scrollToSection(section) self.mainForm.scrollToSection(section)
return return
@pyqtSlot()
def _gotoSearch(self) -> None:
"""Go to the setting indicated by the search text."""
self.mainForm.scrollToLabel(self.searchText.text().strip())
return
@pyqtSlot() @pyqtSlot()
def _selectGuiFont(self) -> None: def _selectGuiFont(self) -> None:
"""Open the QFontDialog and set a font for the font style.""" """Open the QFontDialog and set a font for the font style."""
@@ -972,7 +1029,6 @@ class GuiPreferences(QDialog):
# Finalise # Finalise
CONFIG.saveConfig() CONFIG.saveConfig()
self.newPreferencesReady.emit(needsRestart, refreshTree, updateTheme, updateSyntax) self.newPreferencesReady.emit(needsRestart, refreshTree, updateTheme, updateSyntax)
qApp.processEvents()
return return
+33 -6
View File
@@ -3,7 +3,9 @@ novelWriter Custom Widget: Config Layout
========================================== ==========================================
File History: File History:
Created: 2020-05-03 [0.4.5] Created: 2020-05-03 [0.4.5] NConfigLayout, NHelpLabel
Created: 2023-05-23 [2.1b1] NSimpleLayout
Created: 2024-01-08 [2.3b1] NScrollableForm
This file is a part of novelWriter This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen Copyright 20182024, Veronica Berglyd Olsen
@@ -45,6 +47,7 @@ class NScrollableForm(QScrollArea):
self._fontScale = FONT_SCALE self._fontScale = FONT_SCALE
self._sections: dict[int, QLabel] = {} self._sections: dict[int, QLabel] = {}
self._editable: dict[str, NHelpLabel] = {} self._editable: dict[str, NHelpLabel] = {}
self._index: dict[str, QWidget] = {}
self._layout = QVBoxLayout() self._layout = QVBoxLayout()
self._layout.setSpacing(CONFIG.pxInt(12)) self._layout.setSpacing(CONFIG.pxInt(12))
@@ -59,6 +62,18 @@ class NScrollableForm(QScrollArea):
return return
##
# Properties
##
@property
def labels(self) -> list[str]:
return list(self._index.keys())
##
# Setters
##
def setHelpTextStyle(self, color: QColor | list | tuple, scale: float = FONT_SCALE) -> None: def setHelpTextStyle(self, color: QColor | list | tuple, scale: float = FONT_SCALE) -> None:
"""Set the text color for the help text.""" """Set the text color for the help text."""
self._helpCol = color if isinstance(color, QColor) else QColor(*color) self._helpCol = color if isinstance(color, QColor) else QColor(*color)
@@ -71,18 +86,24 @@ class NScrollableForm(QScrollArea):
qHelp.setText(text) qHelp.setText(text)
return return
def finalise(self) -> None: ##
"""Finalise the layout when the form is built.""" # Methods
self._layout.addStretch(1) ##
return
def scrollToSection(self, identifier: int, offset: int = 50) -> None: def scrollToSection(self, identifier: int) -> None:
"""Scroll to the requested section identifier.""" """Scroll to the requested section identifier."""
if identifier in self._sections: if identifier in self._sections:
yPos = self._sections[identifier].pos().y() - CONFIG.pxInt(8) yPos = self._sections[identifier].pos().y() - CONFIG.pxInt(8)
self.verticalScrollBar().setValue(yPos) self.verticalScrollBar().setValue(yPos)
return return
def scrollToLabel(self, label: str) -> None:
"""Scroll to the requested label."""
if label in self._index:
yPos = self._index[label].pos().y() - CONFIG.pxInt(8)
self.verticalScrollBar().setValue(yPos)
return
def addGroupLabel(self, label: str, identifier: int) -> None: def addGroupLabel(self, label: str, identifier: int) -> None:
"""Add a text label to separate groups of settings.""" """Add a text label to separate groups of settings."""
hM = CONFIG.pxInt(4) hM = CONFIG.pxInt(4)
@@ -124,9 +145,15 @@ class NScrollableForm(QScrollArea):
row.addWidget(button) row.addWidget(button)
self._layout.addLayout(row) self._layout.addLayout(row)
self._index[label.strip()] = widget
return return
def finalise(self) -> None:
"""Finalise the layout when the form is built."""
self._layout.addStretch(1)
return
# END Class NScrollableForm # END Class NScrollableForm