diff --git a/novelwriter/constants.py b/novelwriter/constants.py index a1e2b84a..04eea148 100644 --- a/novelwriter/constants.py +++ b/novelwriter/constants.py @@ -25,7 +25,7 @@ from __future__ import annotations from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP -from novelwriter.enum import nwBuildFmt, nwItemClass, nwItemLayout, nwOutline +from novelwriter.enum import nwBuildFmt, nwItemClass, nwItemLayout, nwOutline, nwStatusShape def trConst(text: str) -> str: @@ -268,6 +268,15 @@ class nwLabels: nwBuildFmt.J_HTML: ".json", nwBuildFmt.J_NWD: ".json", } + STATUS_SHAPES = { + nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("Constant", "Square"), + nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("Constant", "Circle"), + nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("Constant", "Triangle"), + nwStatusShape.DIAMOND: QT_TRANSLATE_NOOP("Constant", "Diamond"), + nwStatusShape.PENTAGON: QT_TRANSLATE_NOOP("Constant", "Pentagon"), + nwStatusShape.STAR: QT_TRANSLATE_NOOP("Constant", "Star"), + nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("Constant", "Pacman"), + } FILE_FILTERS = { "*.txt": QT_TRANSLATE_NOOP("Constant", "Text files"), "*.md": QT_TRANSLATE_NOOP("Constant", "Markdown files"), diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index e4543864..c6b5281a 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -30,12 +30,13 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap from PyQt5.QtWidgets import ( QApplication, QColorDialog, QDialog, QDialogButtonBox, QHBoxLayout, - QLineEdit, QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, - QVBoxLayout, QWidget + QLineEdit, QPushButton, QSizePolicy, QStackedWidget, QTreeWidget, + QTreeWidgetItem, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED from novelwriter.common import simplified +from novelwriter.constants import nwLabels from novelwriter.core.status import NWStatus, StatusEntry from novelwriter.enum import nwStatusShape from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm @@ -182,14 +183,17 @@ class GuiProjectSettings(QDialog): rebuildTrees = False if self.statusPage.changed: + logger.debug("Updating status labels") project.data.itemStatus.update(self.statusPage.getNewList()) rebuildTrees = True if self.importPage.changed: + logger.debug("Updating importance labels") project.data.itemImport.update(self.importPage.getNewList()) rebuildTrees = True if self.replacePage.changed: + logger.debug("Updating auto-replace settings") project.data.setAutoReplace(self.replacePage.getNewList()) self.newProjectSettingsReady.emit(rebuildTrees) @@ -324,7 +328,7 @@ class _StatusPage(NFixedPage): ) self._changed = False - self._selColour = QColor(100, 100, 100) + self._color = QColor(100, 100, 100) self._iPx = SHARED.theme.baseIconHeight iSz = SHARED.theme.baseIconSize @@ -334,6 +338,7 @@ class _StatusPage(NFixedPage): self.trCountNone = self.tr("Not in use") self.trCountOne = self.tr("Used once") self.trCountMore = self.tr("Used by {0} items") + self.trSelColor = self.tr("Select Colour") # Title self.pageTitle = NColourLabel( @@ -370,15 +375,22 @@ class _StatusPage(NFixedPage): self.editName.setPlaceholderText(self.tr("Select item to edit")) self.editName.setEnabled(False) - self.colPixmap = QPixmap(self._iPx, self._iPx) - self.colPixmap.fill(QColor(100, 100, 100)) - self.colButton = QPushButton(QIcon(self.colPixmap), self.tr("Colour"), self) - self.colButton.setIconSize(bSz) + self.colButton = QPushButton("", self) self.colButton.setEnabled(False) + self.colButton.setIconSize(bSz) + self.colButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.colButton.clicked.connect(self._selectColour) + self._setColButton(self._color) + + self.shapeList = NComboBox(self) + self.shapeList.setEnabled(False) + self.shapeList.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) + for shape, label in nwLabels.STATUS_SHAPES.items(): + self.shapeList.addItem(label, shape) self.saveButton = QPushButton(self.tr("Save"), self) self.saveButton.setEnabled(False) + self.saveButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.saveButton.clicked.connect(self._saveItem) # Assemble @@ -390,13 +402,14 @@ class _StatusPage(NFixedPage): self.listControls.addStretch(1) self.editBox = QHBoxLayout() - self.editBox.addWidget(self.editName) - self.editBox.addWidget(self.colButton) - self.editBox.addWidget(self.saveButton) + self.editBox.addWidget(self.editName, 1) + self.editBox.addWidget(self.colButton, 0) + self.editBox.addWidget(self.shapeList, 0) + self.editBox.addWidget(self.saveButton, 0) self.mainBox = QVBoxLayout() - self.mainBox.addWidget(self.listBox) - self.mainBox.addLayout(self.editBox) + self.mainBox.addWidget(self.listBox, 1) + self.mainBox.addLayout(self.editBox, 0) self.innerBox = QHBoxLayout() self.innerBox.addLayout(self.mainBox) @@ -442,16 +455,9 @@ class _StatusPage(NFixedPage): @pyqtSlot() def _selectColour(self) -> None: """Open a dialog to select the status icon colour.""" - if self._selColour is not None: - newCol = QColorDialog.getColor( - self._selColour, self, self.tr("Select Colour") - ) - if newCol.isValid(): - self._selColour = newCol - pixmap = QPixmap(self._iPx, self._iPx) - pixmap.fill(newCol) - self.colButton.setIcon(QIcon(pixmap)) - self.colButton.setIconSize(pixmap.rect().size()) + if (color := QColorDialog.getColor(self._color, self, self.trSelColor)).isValid(): + self._color = color + self._setColButton(color) return @pyqtSlot() @@ -484,16 +490,20 @@ class _StatusPage(NFixedPage): entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY) name = simplified(self.editName.text()) - shape = nwStatusShape.SQUARE - icon = NWStatus.createIcon(self._iPx, self._selColour, shape) + selected = self.shapeList.currentData() + shape = selected if isinstance(selected, nwStatusShape) else nwStatusShape.SQUARE + icon = NWStatus.createIcon(self._iPx, self._color, shape) + entry.name = name + entry.color = self._color entry.shape = shape - entry.color = self._selColour entry.icon = icon item.setText(self.C_LABEL, name) item.setIcon(self.C_LABEL, icon) + self._changed = True + return @pyqtSlot() @@ -503,21 +513,28 @@ class _StatusPage(NFixedPage): """ if item := self._getSelectedItem(): entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY) - self._selColour = entry.color + self._color = entry.color + self._setColButton(entry.color) + self.editName.setText(entry.name) - self.colButton.setIcon(entry.icon) self.editName.selectAll() self.editName.setFocus() + self.shapeList.setCurrentData(entry.shape, nwStatusShape.SQUARE) + self.editName.setEnabled(True) self.colButton.setEnabled(True) + self.shapeList.setEnabled(True) self.saveButton.setEnabled(True) + else: - self._selColour = QColor(100, 100, 100) - icon = NWStatus.createIcon(self._iPx, self._selColour, nwStatusShape.SQUARE) + self._color = QColor(100, 100, 100) + self._setColButton(self._color) self.editName.setText("") - self.colButton.setIcon(icon) + self.shapeList.setCurrentIndex(0) + self.editName.setEnabled(False) self.colButton.setEnabled(False) + self.shapeList.setEnabled(False) self.saveButton.setEnabled(False) return @@ -564,6 +581,14 @@ class _StatusPage(NFixedPage): else: return self.trCountMore.format(count) + def _setColButton(self, color: QColor) -> None: + """Set the colour of the colour button.""" + pixmap = QPixmap(self._iPx, self._iPx) + pixmap.fill(color) + self.colButton.setIcon(QIcon(pixmap)) + self.colButton.setIconSize(pixmap.rect().size()) + return + # END Class _StatusPage diff --git a/novelwriter/extensions/modified.py b/novelwriter/extensions/modified.py index 4eb50cff..b83a2662 100644 --- a/novelwriter/extensions/modified.py +++ b/novelwriter/extensions/modified.py @@ -25,6 +25,8 @@ along with this program. If not, see . """ from __future__ import annotations +from enum import Enum + from PyQt5.QtCore import QSize, Qt from PyQt5.QtGui import QWheelEvent from PyQt5.QtWidgets import QComboBox, QDoubleSpinBox, QSpinBox, QToolButton, QWidget @@ -46,7 +48,7 @@ class NComboBox(QComboBox): event.ignore() return - def setCurrentData(self, data: str, default: str) -> None: + def setCurrentData(self, data: str | Enum, default: str | 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) diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index 24170a34..3f64c4c7 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,6 +1,6 @@ - - + + Sample Project Jane Smith @@ -20,19 +20,19 @@ D - New - Notes - Started - 1st Draft - 2nd Draft - 3rd Draft - Finished + New + Notes + Started + 1st Draft + 2nd Draft + 3rd Draft + Finished - None - Minor - Major - Main + None + Minor + Major + Main