Add import/export for status labels

This commit is contained in:
Veronica Berglyd Olsen
2024-12-31 00:14:47 +01:00
parent 136939d391
commit 9461eea03a
2 changed files with 84 additions and 16 deletions
+14
View File
@@ -174,6 +174,20 @@ class NWStatus:
"""Yield entries from the status icons."""
yield from self._store.items()
def fromRaw(self, data: list[str]) -> StatusEntry | None:
"""Create a StatusEntry from a list of three strings consisting
of shape, colour, and name. This entry is not automatically
added to the list of entries.
"""
try:
shape = nwStatusShape[str(data[0])]
color = QColor(str(data[1]))
icon = NWStatus.createIcon(self._height, color, shape)
return StatusEntry(simplified(data[2]), color, shape, icon)
except Exception:
logger.error("Could not parse entry %s", str(data))
return None
@staticmethod
def createIcon(height: int, color: QColor, shape: nwStatusShape) -> QIcon:
"""Generate an icon for a status label."""
+70 -16
View File
@@ -24,18 +24,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import csv
import logging
from pathlib import Path
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, QTreeWidget,
QTreeWidgetItem, QVBoxLayout, QWidget
QFileDialog, QGridLayout, QHBoxLayout, QLineEdit, QMenu, QStackedWidget,
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import qtLambda, simplified
from novelwriter.common import formatFileFilter, qtLambda, simplified
from novelwriter.constants import nwLabels, trConst
from novelwriter.core.status import NWStatus, StatusEntry
from novelwriter.enum import nwStatusShape
@@ -310,11 +313,13 @@ class _StatusPage(NFixedPage):
super().__init__(parent=parent)
if isStatus:
status = SHARED.project.data.itemStatus
self._kind = self.tr("Status")
self._store = SHARED.project.data.itemStatus
pageLabel = self.tr("Novel Document Status Levels")
colSetting = "statusColW"
else:
status = SHARED.project.data.itemImport
self._kind = self.tr("Importance")
self._store = SHARED.project.data.itemImport
pageLabel = self.tr("Project Note Importance Levels")
colSetting = "importColW"
@@ -354,21 +359,33 @@ class _StatusPage(NFixedPage):
self.listBox.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.listBox.itemSelectionChanged.connect(self._onSelectionChanged)
for key, entry in status.iterItems():
for key, entry in self._store.iterItems():
self._addItem(key, StatusEntry.duplicate(entry))
# List Controls
self.addButton = NIconToolButton(self, iSz, "add")
self.addButton.setToolTip(self.tr("Add Label"))
self.addButton.clicked.connect(self._onItemCreate)
self.delButton = NIconToolButton(self, iSz, "remove")
self.delButton.setToolTip(self.tr("Delete Label"))
self.delButton.clicked.connect(self._onItemDelete)
self.upButton = NIconToolButton(self, iSz, "up")
self.upButton.setToolTip(self.tr("Move Up"))
self.upButton.clicked.connect(qtLambda(self._moveItem, -1))
self.dnButton = NIconToolButton(self, iSz, "down")
self.dnButton.clicked.connect(qtLambda(self._moveItem, 1))
self.downButton = NIconToolButton(self, iSz, "down")
self.downButton.setToolTip(self.tr("Move Down"))
self.downButton.clicked.connect(qtLambda(self._moveItem, 1))
self.importButton = NIconToolButton(self, iSz, "import")
self.importButton.setToolTip(self.tr("Import Labels"))
self.importButton.clicked.connect(self._importLabels)
self.exportButton = NIconToolButton(self, iSz, "export")
self.exportButton.setToolTip(self.tr("Export Labels"))
self.exportButton.clicked.connect(self._exportLabels)
# Edit Form
self.labelText = QLineEdit(self)
@@ -414,21 +431,22 @@ class _StatusPage(NFixedPage):
self.listControls.addWidget(self.addButton)
self.listControls.addWidget(self.delButton)
self.listControls.addWidget(self.upButton)
self.listControls.addWidget(self.dnButton)
self.listControls.addWidget(self.downButton)
self.listControls.addStretch(1)
self.listControls.addWidget(self.importButton)
self.listControls.addWidget(self.exportButton)
self.editBox = QHBoxLayout()
self.editBox.addWidget(self.labelText, 1)
self.editBox.addWidget(self.colorButton, 0)
self.editBox.addWidget(self.shapeButton, 0)
self.mainBox = QVBoxLayout()
self.mainBox.addWidget(self.listBox, 1)
self.mainBox.addLayout(self.editBox, 0)
self.innerBox = QHBoxLayout()
self.innerBox.addLayout(self.mainBox, 1)
self.innerBox.addLayout(self.listControls, 0)
self.innerBox = QGridLayout()
self.innerBox.addWidget(self.listBox, 0, 0)
self.innerBox.addLayout(self.listControls, 0, 1)
self.innerBox.addLayout(self.editBox, 1, 0)
self.innerBox.setRowStretch(0, 1)
self.innerBox.setColumnStretch(1, 0)
self.outerBox = QVBoxLayout()
self.outerBox.addWidget(self.pageTitle, 0)
@@ -540,6 +558,42 @@ class _StatusPage(NFixedPage):
self.shapeButton.setEnabled(False)
return
@pyqtSlot()
def _importLabels(self) -> None:
"""Import labels from file."""
if path := QFileDialog.getOpenFileName(
self, self.tr("Import File"),
str(CONFIG.homePath()), filter=formatFileFilter(["*.csv", "*"]),
)[0]:
try:
with open(path, mode="r", encoding="utf-8") as fo:
for row in csv.reader(fo):
if entry := self._store.fromRaw(row):
self._addItem(None, entry)
except Exception as exc:
SHARED.error("Could not read file.", exc=exc)
return
return
@pyqtSlot()
def _exportLabels(self) -> None:
"""Export labels to file."""
name = f"{SHARED.project.data.fileSafeName} - {self._kind}.csv"
if path := QFileDialog.getSaveFileName(
self, self.tr("Export File"), str(CONFIG.homePath() / name),
)[0]:
try:
path = Path(path).with_suffix(".csv")
with open(path, mode="w", encoding="utf-8") as fo:
writer = csv.writer(fo)
for n in range(self.listBox.topLevelItemCount()):
if item := self.listBox.topLevelItem(n):
entry: StatusEntry = item.data(self.C_DATA, self.D_ENTRY)
writer.writerow([entry.shape.name, entry.color.name(), entry.name])
except Exception as exc:
SHARED.error("Could not write file.", exc=exc)
return
##
# Internal Functions
##