Make build settings re-orderable (#1542)

This commit is contained in:
Veronica Berglyd Olsen
2023-11-10 22:03:38 +01:00
parent f9fd3512b7
commit 2c5947eeaa
3 changed files with 50 additions and 24 deletions
+39 -21
View File
@@ -156,6 +156,7 @@ class BuildSettings:
self._uuid = str(uuid.uuid4())
self._path = Path.home()
self._build = ""
self._order = 0
self._format = nwBuildFmt.ODT
self._skipRoot = set()
self._excluded = set()
@@ -164,20 +165,32 @@ class BuildSettings:
self._changed = False
return
@classmethod
def fromDict(cls, data: dict) -> BuildSettings:
"""Create a build settings object from a dict."""
cls = BuildSettings()
cls.unpack(data)
return cls
##
# Properties
##
@property
def name(self) -> str:
"""The build name."""
"""Return the build name."""
return self._name
@property
def buildID(self) -> str:
"""The build ID as a UUID."""
"""Return the build ID as a UUID."""
return self._uuid
@property
def order(self) -> int:
"""Return the build order."""
return self._order
@property
def lastPath(self) -> Path:
"""The last used build path."""
@@ -251,6 +264,12 @@ class BuildSettings:
self._uuid = value
return
def setOrder(self, value: int) -> None:
"""Set the build order."""
if isinstance(value, int):
self._order = value
return
def setLastPath(self, path: Path | str | None) -> None:
"""Set the last used build path."""
if isinstance(path, str):
@@ -398,6 +417,7 @@ class BuildSettings:
"uuid": self._uuid,
"path": str(self._path),
"build": self._build,
"order": self._order,
"format": self._format.name,
"settings": self._settings.copy(),
"content": {
@@ -409,14 +429,15 @@ class BuildSettings:
def unpack(self, data: dict) -> None:
"""Unpack a dictionary and populate the class."""
content = data.get("content", {})
settings = data.get("settings", {})
content = data.get("content", {})
included = content.get("included", [])
excluded = content.get("excluded", [])
skipRoot = content.get("skipRoot", [])
self.setName(data.get("name", ""))
self.setBuildID(data.get("uuid", ""))
self.setOrder(data.get("order", 0))
self.setLastPath(data.get("path", None))
self.setLastBuildName(data.get("build", ""))
@@ -453,9 +474,9 @@ class BuildCollection:
def __init__(self, project: NWProject) -> None:
self._project = project
self._builds = {}
self._lastBuild = ""
self._defaultBuild = ""
self._builds: dict[str, BuildSettings] = {}
self._loadCollection()
return
@@ -483,21 +504,19 @@ class BuildCollection:
def getBuild(self, buildID: str) -> BuildSettings | None:
"""Get a specific build settings object."""
if buildID not in self._builds:
return None
build = BuildSettings()
build.unpack(self._builds[buildID])
return build
return self._builds.get(buildID, None)
##
# Setters
##
def setLastBuild(self, buildID: str) -> None:
def setBuildsState(self, lastBuild: str, order: list[str]) -> None:
"""Set the last active build id."""
if buildID != self._lastBuild:
self._lastBuild = buildID
self._saveCollection()
for i, key in enumerate(order):
if build := self._builds.get(key):
build.setOrder(i)
self._lastBuild = lastBuild
self._saveCollection()
return
def setDefaultBuild(self, buildID: str) -> None:
@@ -510,8 +529,7 @@ class BuildCollection:
def setBuild(self, build: BuildSettings) -> None:
"""Set build settings data in the collection."""
if isinstance(build, BuildSettings):
buildID = build.buildID
self._builds[buildID] = build.pack()
self._builds[build.buildID] = build
self._saveCollection()
return
@@ -520,15 +538,15 @@ class BuildCollection:
##
def removeBuild(self, buildID: str) -> None:
"""Remove the a build from the collection."""
"""Remove a build from the collection."""
self._builds.pop(buildID, None)
self._saveCollection()
return
def builds(self) -> Iterable[tuple[str, str]]:
"""Iterate over all available builds."""
for buildID in self._builds:
yield buildID, self._builds[buildID].get("name", "")
for buildID, build in sorted(self._builds.items(), key=lambda x: x[1].order):
yield buildID, build.name
return
##
@@ -567,7 +585,7 @@ class BuildCollection:
elif key == "defaultBuild":
self._defaultBuild = str(entry)
elif isinstance(entry, dict):
self._builds[key] = entry
self._builds[key] = BuildSettings.fromDict(entry)
return True
@@ -579,11 +597,11 @@ class BuildCollection:
logger.debug("Saving builds file")
try:
data = {
data: dict[str, str | dict] = {
"lastBuild": self._lastBuild,
"defaultBuild": self._defaultBuild,
}
data.update(self._builds)
data.update({k: b.pack() for k, b in self._builds.items()})
with open(buildsFile, mode="w+", encoding="utf-8") as outFile:
outFile.write(jsonEncode({"novelWriter.builds": data}, nmax=4))
except Exception:
+10 -2
View File
@@ -144,6 +144,8 @@ class GuiManuscript(QDialog):
self.buildList.setIconSize(QSize(iPx, iPx))
self.buildList.doubleClicked.connect(self._editSelectedBuild)
self.buildList.currentItemChanged.connect(self._updateBuildDetails)
self.buildList.setSelectionMode(QAbstractItemView.SingleSelection)
self.buildList.setDragDropMode(QAbstractItemView.InternalMove)
self.buildDetails = _DetailsWidget(self)
self.buildDetails.setColumnWidth(
@@ -417,9 +419,15 @@ class GuiManuscript(QDialog):
"""Save the user GUI settings."""
logger.debug("Saving GuiManuscript settings")
buildOrder = []
for i in range(self.buildList.count()):
if item := self.buildList.item(i):
buildOrder.append(item.data(self.D_KEY))
current = self.buildList.currentItem()
if isinstance(current, QListWidgetItem):
self._builds.setLastBuild(current.data(self.D_KEY))
lastBuild = current.data(self.D_KEY) if isinstance(current, QListWidgetItem) else ""
self._builds.setBuildsState(lastBuild, buildOrder)
winWidth = CONFIG.rpxInt(self.width())
winHeight = CONFIG.rpxInt(self.height())
+1 -1
View File
@@ -435,7 +435,7 @@ def testCoreBuildSettings_Collection(monkeypatch, mockGUI, fncPath: Path, mockRn
(buildIDTwo, "Build Two"),
(buildIDOne, "Build One"),
]
builds.setLastBuild(buildIDOne)
builds.setBuildsState(buildIDOne, [buildIDTwo, buildIDOne])
builds.setDefaultBuild(buildIDTwo)
# Check errors: No valid path