Remove "Apply" buttons in Project Settings (#2151)

This commit is contained in:
Veronica Berglyd Olsen
2024-12-30 17:00:18 +01:00
committed by GitHub
3 changed files with 80 additions and 97 deletions
+75 -80
View File
@@ -30,7 +30,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QColor
from PyQt5.QtWidgets import (
QAbstractItemView, QApplication, QColorDialog, QDialogButtonBox,
QHBoxLayout, QLineEdit, QMenu, QStackedWidget, QToolButton, QTreeWidget,
QHBoxLayout, QLineEdit, QMenu, QStackedWidget, QTreeWidget,
QTreeWidgetItem, QVBoxLayout, QWidget
)
@@ -352,17 +352,17 @@ class _StatusPage(NFixedPage):
self.listBox.setIndentation(0)
self.listBox.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.listBox.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.listBox.itemSelectionChanged.connect(self._selectionChanged)
self.listBox.itemSelectionChanged.connect(self._onSelectionChanged)
for key, entry in status.iterItems():
self._addItem(key, StatusEntry.duplicate(entry))
# List Controls
self.addButton = NIconToolButton(self, iSz, "add")
self.addButton.clicked.connect(self._newItem)
self.addButton.clicked.connect(self._onItemCreate)
self.delButton = NIconToolButton(self, iSz, "remove")
self.delButton.clicked.connect(self._delItem)
self.delButton.clicked.connect(self._onItemDelete)
self.upButton = NIconToolButton(self, iSz, "up")
self.upButton.clicked.connect(qtLambda(self._moveItem, -1))
@@ -371,10 +371,11 @@ class _StatusPage(NFixedPage):
self.dnButton.clicked.connect(qtLambda(self._moveItem, 1))
# Edit Form
self.editName = QLineEdit(self)
self.editName.setMaxLength(40)
self.editName.setPlaceholderText(self.tr("Select item to edit"))
self.editName.setEnabled(False)
self.labelText = QLineEdit(self)
self.labelText.setMaxLength(40)
self.labelText.setPlaceholderText(self.tr("Select item to edit"))
self.labelText.setEnabled(False)
self.labelText.textEdited.connect(self._onNameEdit)
buttonStyle = (
f"QToolButton {{padding: 0 {bPd}px;}} "
@@ -386,13 +387,13 @@ class _StatusPage(NFixedPage):
self.colorButton.setSizePolicy(QtSizeMinimum, QtSizeMinimumExpanding)
self.colorButton.setStyleSheet(buttonStyle)
self.colorButton.setEnabled(False)
self.colorButton.clicked.connect(self._selectColour)
self.colorButton.clicked.connect(self._onColourSelect)
def buildMenu(menu: QMenu, items: dict[nwStatusShape, str]) -> None:
for shape, label in items.items():
icon = NWStatus.createIcon(self._iPx, iColor, shape)
action = menu.addAction(icon, trConst(label))
action.triggered.connect(lambda _, shape=shape: self._selectShape(shape))
action.triggered.connect(qtLambda(self._selectShape, shape))
self._icons[shape] = icon
self.shapeMenu = QMenu(self)
@@ -408,12 +409,6 @@ class _StatusPage(NFixedPage):
self.shapeButton.setStyleSheet(buttonStyle)
self.shapeButton.setEnabled(False)
self.applyButton = QToolButton(self)
self.applyButton.setText(self.tr("Apply"))
self.applyButton.setSizePolicy(QtSizeMinimum, QtSizeMinimumExpanding)
self.applyButton.setEnabled(False)
self.applyButton.clicked.connect(self._applyChanges)
# Assemble
self.listControls = QVBoxLayout()
self.listControls.addWidget(self.addButton)
@@ -423,10 +418,9 @@ class _StatusPage(NFixedPage):
self.listControls.addStretch(1)
self.editBox = QHBoxLayout()
self.editBox.addWidget(self.editName, 1)
self.editBox.addWidget(self.labelText, 1)
self.editBox.addWidget(self.colorButton, 0)
self.editBox.addWidget(self.shapeButton, 0)
self.editBox.addWidget(self.applyButton, 0)
self.mainBox = QVBoxLayout()
self.mainBox.addWidget(self.listBox, 1)
@@ -474,16 +468,28 @@ class _StatusPage(NFixedPage):
# Private Slots
##
@pyqtSlot(str)
def _onNameEdit(self, text: str) -> None:
"""Update the status label text."""
if item := self._getSelectedItem():
name = simplified(text)
entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY)
entry.name = name
item.setText(self.C_LABEL, name)
self._changed = True
return
@pyqtSlot()
def _selectColour(self) -> None:
def _onColourSelect(self) -> None:
"""Open a dialog to select the status icon colour."""
if (color := QColorDialog.getColor(self._color, self, self.trSelColor)).isValid():
self._color = color
self._setButtonIcons()
self._updateIcon()
return
@pyqtSlot()
def _newItem(self) -> None:
def _onItemCreate(self) -> None:
"""Create a new status item."""
color = QColor(100, 100, 100)
shape = nwStatusShape.SQUARE
@@ -493,7 +499,7 @@ class _StatusPage(NFixedPage):
return
@pyqtSlot()
def _delItem(self) -> None:
def _onItemDelete(self) -> None:
"""Delete a status item."""
if item := self._getSelectedItem():
iRow = self.listBox.indexOfTopLevelItem(item)
@@ -506,28 +512,7 @@ class _StatusPage(NFixedPage):
return
@pyqtSlot()
def _applyChanges(self) -> None:
"""Save changes made to a status item."""
if item := self._getSelectedItem():
entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY)
name = simplified(self.editName.text())
icon = NWStatus.createIcon(self._iPx, self._color, self._shape)
entry.name = name
entry.color = self._color
entry.shape = self._shape
entry.icon = icon
item.setText(self.C_LABEL, name)
item.setIcon(self.C_LABEL, icon)
self._changed = True
return
@pyqtSlot()
def _selectionChanged(self) -> None:
def _onSelectionChanged(self) -> None:
"""Extract the info of a selected item and populate the settings
boxes and button. If no item is selected, clear the form.
"""
@@ -537,25 +522,22 @@ class _StatusPage(NFixedPage):
self._shape = entry.shape
self._setButtonIcons()
self.editName.setText(entry.name)
self.editName.selectAll()
self.editName.setFocus()
self.labelText.setText(entry.name)
self.labelText.selectAll()
self.labelText.setFocus()
self.editName.setEnabled(True)
self.labelText.setEnabled(True)
self.colorButton.setEnabled(True)
self.shapeButton.setEnabled(True)
self.applyButton.setEnabled(True)
else:
self._color = QColor(100, 100, 100)
self._shape = nwStatusShape.SQUARE
self._setButtonIcons()
self.editName.setText("")
self.labelText.setText("")
self.editName.setEnabled(False)
self.labelText.setEnabled(False)
self.colorButton.setEnabled(False)
self.shapeButton.setEnabled(False)
self.applyButton.setEnabled(False)
return
##
@@ -566,6 +548,19 @@ class _StatusPage(NFixedPage):
"""Set the current shape."""
self._shape = shape
self._setButtonIcons()
self._updateIcon()
return
def _updateIcon(self) -> None:
"""Apply changes made to a status icon."""
if item := self._getSelectedItem():
icon = NWStatus.createIcon(self._iPx, self._color, self._shape)
entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY)
entry.color = self._color
entry.shape = self._shape
entry.icon = icon
item.setIcon(self.C_LABEL, icon)
self._changed = True
return
def _addItem(self, key: str | None, entry: StatusEntry) -> None:
@@ -644,7 +639,7 @@ class _ReplacePage(NFixedPage):
self.listBox.setIndentation(0)
self.listBox.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.listBox.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.listBox.itemSelectionChanged.connect(self._selectionChanged)
self.listBox.itemSelectionChanged.connect(self._onSelectionChanged)
for aKey, aVal in SHARED.project.data.autoReplace.items():
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
@@ -655,25 +650,22 @@ class _ReplacePage(NFixedPage):
# List Controls
self.addButton = NIconToolButton(self, iSz, "add")
self.addButton.clicked.connect(self._addEntry)
self.addButton.clicked.connect(self._onEntryCreated)
self.delButton = NIconToolButton(self, iSz, "remove")
self.delButton.clicked.connect(self._delEntry)
self.delButton.clicked.connect(self._onEntryDeleted)
# Edit Form
self.editKey = QLineEdit(self)
self.editKey.setPlaceholderText(self.tr("Select item to edit"))
self.editKey.setEnabled(False)
self.editKey.setMaxLength(40)
self.editKey.textEdited.connect(self._onKeyEdit)
self.editValue = QLineEdit(self)
self.editValue.setEnabled(False)
self.editValue.setMaxLength(80)
self.applyButton = QToolButton(self)
self.applyButton.setText(self.tr("Apply"))
self.applyButton.setSizePolicy(QtSizeMinimum, QtSizeMinimumExpanding)
self.applyButton.clicked.connect(self._applyChanges)
self.editValue.setMaxLength(250)
self.editValue.textEdited.connect(self._onValueEdit)
# Assemble
self.listControls = QVBoxLayout()
@@ -684,7 +676,6 @@ class _ReplacePage(NFixedPage):
self.editBox = QHBoxLayout()
self.editBox.addWidget(self.editKey, 4)
self.editBox.addWidget(self.editValue, 5)
self.editBox.addWidget(self.applyButton, 0)
self.mainBox = QVBoxLayout()
self.mainBox.addWidget(self.listBox, 1)
@@ -716,7 +707,7 @@ class _ReplacePage(NFixedPage):
new = {}
for n in range(self.listBox.topLevelItemCount()):
if item := self.listBox.topLevelItem(n):
if key := self._stripNotAllowed(item.text(self.C_KEY)):
if key := self._stripKey(item.text(self.C_KEY)):
new[key] = item.text(self.C_REPL)
return new
@@ -728,13 +719,29 @@ class _ReplacePage(NFixedPage):
# Private Slots
##
@pyqtSlot(str)
def _onKeyEdit(self, text: str) -> None:
"""Update the key text."""
if (item := self._getSelectedItem()) and (key := self._stripKey(text)):
item.setText(self.C_KEY, f"<{key}>")
self._changed = True
return
@pyqtSlot(str)
def _onValueEdit(self, text: str) -> None:
"""Update the value text."""
if item := self._getSelectedItem():
item.setText(self.C_REPL, text)
self._changed = True
return
@pyqtSlot()
def _selectionChanged(self) -> None:
def _onSelectionChanged(self) -> None:
"""Extract the details from the selected item and populate the
edit form.
"""
if item := self._getSelectedItem():
self.editKey.setText(self._stripNotAllowed(item.text(self.C_KEY)))
self.editKey.setText(self._stripKey(item.text(self.C_KEY)))
self.editValue.setText(item.text(self.C_REPL))
self.editKey.setEnabled(True)
self.editValue.setEnabled(True)
@@ -748,26 +755,14 @@ class _ReplacePage(NFixedPage):
return
@pyqtSlot()
def _applyChanges(self) -> None:
"""Save the form data into the list widget."""
if item := self._getSelectedItem():
key = self._stripNotAllowed(self.editKey.text())
value = self.editValue.text()
if key and value:
item.setText(self.C_KEY, f"<{key}>")
item.setText(self.C_REPL, value)
self._changed = True
return
@pyqtSlot()
def _addEntry(self) -> None:
def _onEntryCreated(self) -> None:
"""Add a new list entry."""
key = f"<keyword{self.listBox.topLevelItemCount() + 1:d}>"
self.listBox.addTopLevelItem(QTreeWidgetItem([key, ""]))
return
@pyqtSlot()
def _delEntry(self) -> None:
def _onEntryDeleted(self) -> None:
"""Delete the selected entry."""
if item := self._getSelectedItem():
self.listBox.takeTopLevelItem(self.listBox.indexOfTopLevelItem(item))
@@ -784,6 +779,6 @@ class _ReplacePage(NFixedPage):
return items[0]
return None
def _stripNotAllowed(self, key: str) -> str:
def _stripKey(self, key: str) -> str:
"""Clean up the replace key string."""
return "".join(c for c in key if c.isalnum())
-4
View File
@@ -957,12 +957,8 @@ class GuiMain(QMainWindow):
docEditor = True
elif self.docViewer.isAncestorOf(new):
docViewer = True
self.docEditor.changeFocusState(docEditor)
self.docViewer.changeFocusState(docViewer)
logger.debug("Main focus switched to: %s", type(new).__name__)
return
@pyqtSlot(bool)
+5 -13
View File
@@ -198,10 +198,9 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
status.addButton.click()
status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
status.editName.setText("Final")
status._onNameEdit("Final")
status.colorButton.click()
status._selectShape(nwStatusShape.CIRCLE)
status.applyButton.click()
assert status.listBox.topLevelItemCount() == 4
assert status.changed is True
@@ -274,10 +273,9 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
importance.addButton.click()
importance.listBox.clearSelection()
importance.listBox.setCurrentItem(importance.listBox.topLevelItem(3))
importance.editName.setText("Final")
importance._onNameEdit("Final")
importance.colorButton.click()
importance._selectShape(nwStatusShape.TRIANGLE)
importance.applyButton.click()
assert importance.listBox.topLevelItemCount() == 4
assert importance.changed is True
@@ -351,8 +349,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
# Nothing to save or delete
replace.listBox.clearSelection()
replace._applyChanges()
replace._delEntry()
replace._onEntryDeleted()
assert replace.listBox.topLevelItemCount() == 2
# Create a new entry
@@ -363,13 +360,8 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
# Edit the entry
replace.listBox.setCurrentItem(replace.listBox.topLevelItem(2))
replace.editKey.setText("")
for c in "Th is ":
qtbot.keyClick(replace.editKey, c, delay=KEY_DELAY)
replace.editValue.setText("")
for c in "With This Stuff ":
qtbot.keyClick(replace.editValue, c, delay=KEY_DELAY)
qtbot.mouseClick(replace.applyButton, QtMouseLeft)
replace._onKeyEdit("Th is ")
replace._onValueEdit("With This Stuff ")
assert replace.listBox.topLevelItem(2).text(0) == "<This>" # type: ignore
assert replace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore