diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py
index c0230758..3dfecf24 100644
--- a/novelwriter/core/project.py
+++ b/novelwriter/core/project.py
@@ -4,7 +4,8 @@ novelWriter – Project Wrapper
Data class for novelWriter projects
File History:
-Created: 2018-09-29 [0.0.1]
+Created: 2018-09-29 [0.0.1] NWProject
+Created: 2022-10-30 [2.0rc1] NWProjectData
This file is a part of novelWriter
Copyright 2018–2022, Veronica Berglyd Olsen
@@ -32,38 +33,40 @@ import novelwriter
from time import time
from functools import partial
-from PyQt5.QtCore import QCoreApplication
+from PyQt5.QtCore import QCoreApplication, QObject, pyqtSignal
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.error import logException
-from novelwriter.common import (
- checkStringNone, isHandle, formatTimeStamp, makeFileNameSafe, hexToInt,
- minmax, simplified
-)
from novelwriter.constants import trConst, nwFiles, nwLabels
from novelwriter.core.tree import NWTree
from novelwriter.core.item import NWItem
from novelwriter.core.index import NWIndex
+from novelwriter.core.status import NWStatus
from novelwriter.core.options import OptionState
from novelwriter.core.document import NWDoc
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter, XMLReadState
-from novelwriter.core.projectdata import NWProjectData
+from novelwriter.common import (
+ checkBool, checkInt, checkString, checkStringNone, formatTimeStamp, hexToInt, isHandle,
+ makeFileNameSafe, minmax, simplified,
+)
+
logger = logging.getLogger(__name__)
-class NWProject:
+class NWProject(QObject):
- FILE_VERSION = "1.4" # The current project file format version
+ projectStatusChanged = pyqtSignal(bool)
def __init__(self, mainGui):
+ super().__init__(parent=mainGui)
# Internal
self.mainConf = novelwriter.CONFIG
self.mainGui = mainGui
# Project Data
- self._data = NWProjectData()
+ self._data = NWProjectData(self)
# Core Elements
self._optState = OptionState(self) # Project-specific GUI options
@@ -240,7 +243,7 @@ class NWProject:
# Project Tree
self._projTree.clear()
- self._data = NWProjectData()
+ self._data = NWProjectData(self)
# Project Settings
self.projPath = None
@@ -446,7 +449,7 @@ class NWProject:
# Open The Project XML File
# =========================
- self._data = NWProjectData()
+ self._data = NWProjectData(self)
xmlReader = ProjectXMLReader(fileName)
xmlParsed = xmlReader.read(self._data)
@@ -857,13 +860,10 @@ class NWProject:
information to the GUI statusbar.
"""
self._projChanged = bValue
- self.mainGui.mainStatus.doUpdateProjectStatus(bValue)
+ self.projectStatusChanged.emit(self._projChanged)
if bValue is True:
# If we've changed the project at all, this should be True
self._projAltered = True
- else:
- # If we're resetting the status, also reset for data class
- self._data.resetProjectChanged()
return self._projChanged
##
@@ -1310,3 +1310,301 @@ class NWProject:
return True
# END Class NWProject
+
+
+class NWProjectData:
+
+ def __init__(self, theProject):
+
+ self.theProject = theProject
+
+ # Project Meta
+ self._name = ""
+ self._title = ""
+ self._authors = []
+ self._saveCount = 0
+ self._autoCount = 0
+ self._editTime = 0
+
+ # Project Settings
+ self._doBackup = True
+ self._language = None
+ self._spellCheck = False
+ self._spellLang = None
+ self._lastHandle = {
+ "editor": "",
+ "viewer": "",
+ "novelTree": "",
+ "outline": "",
+ }
+ self._lastCount = {}
+ self._currCount = {}
+
+ self._autoReplace = {}
+ self._titleFormat = {
+ "title": "%title%",
+ "chapter": "%title%",
+ "unnumbered": "%title%",
+ "scene": "* * *",
+ "section": "",
+ }
+
+ self._status = NWStatus(NWStatus.STATUS)
+ self._import = NWStatus(NWStatus.IMPORT)
+
+ return
+
+ ##
+ # Properties
+ ##
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def title(self):
+ return self._title
+
+ @property
+ def authors(self):
+ return self._authors
+
+ @property
+ def saveCount(self):
+ return self._saveCount
+
+ @property
+ def autoCount(self):
+ return self._autoCount
+
+ @property
+ def editTime(self):
+ return self._editTime
+
+ @property
+ def doBackup(self):
+ return self._doBackup
+
+ @property
+ def language(self):
+ return self._language
+
+ @property
+ def spellCheck(self):
+ return self._spellCheck
+
+ @property
+ def spellLang(self):
+ return self._spellLang
+
+ @property
+ def lastHandle(self):
+ return self._lastHandle
+
+ @property
+ def autoReplace(self):
+ return self._autoReplace
+
+ @property
+ def titleFormat(self):
+ return self._titleFormat
+
+ @property
+ def itemStatus(self):
+ return self._status
+
+ @property
+ def itemImport(self):
+ return self._import
+
+ ##
+ # Methods
+ ##
+
+ def addAuthor(self, value):
+ """Add an author to the authors list.
+ """
+ self._authors.append(simplified(str(value)))
+ self.theProject.setProjectChanged(True)
+ return
+
+ def incSaveCount(self):
+ """Increment the save count by one.
+ """
+ self._saveCount += 1
+ self.theProject.setProjectChanged(True)
+ return
+
+ def incAutoCount(self):
+ """Increment the auto save count by one.
+ """
+ self._autoCount += 1
+ self.theProject.setProjectChanged(True)
+ return
+
+ ##
+ # Getters
+ ##
+
+ def getLastHandle(self, component):
+ """Retrieve the last used handle for a given component.
+ """
+ return self._lastHandle.get(component, None)
+
+ def getLastCount(self, type):
+ """Retrieve the last word count for a given type.
+ """
+ return self._lastCount.get(type, 0)
+
+ def getCurrCount(self, type):
+ """Retrieve the current word count for a given type.
+ """
+ return self._currCount.get(type, 0)
+
+ def getTitleFormat(self, kind):
+ """Retrieve the title format string for a given kind of header.
+ """
+ return self._titleFormat.get(kind, "%title%")
+
+ ##
+ # Setters
+ ##
+
+ def setName(self, value):
+ """Set a new project name.
+ """
+ if value != self._name:
+ self._name = simplified(str(value))
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setTitle(self, value):
+ """Set a new novel title.
+ """
+ if value != self._title:
+ self._title = simplified(str(value))
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setAuthors(self, value):
+ """Set the list of authors from either a string with one author
+ per line, or a list of authors.
+ """
+ self._authors = []
+ self.theProject.setProjectChanged(True)
+ if isinstance(value, str):
+ for author in value.splitlines():
+ author = simplified(author)
+ if author:
+ self._authors.append(author)
+ self.theProject.setProjectChanged(True)
+ elif isinstance(value, list):
+ self._authors = value
+ return
+
+ def setSaveCount(self, value):
+ """Set the save count from last session.
+ """
+ self._saveCount = checkInt(value, 0)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setAutoCount(self, value):
+ """Set the auto save count from last session.
+ """
+ self._autoCount = checkInt(value, 0)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setEditTime(self, value):
+ """Set tyje edit time from last session.
+ """
+ self._editTime = checkInt(value, 0)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setDoBackup(self, value):
+ """Set the do write backup flag.
+ """
+ if value != self._doBackup:
+ self._doBackup = checkBool(value, False)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setLanguage(self, value):
+ """Set the project language.
+ """
+ if value != self._language:
+ self._language = checkStringNone(value, None)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setSpellCheck(self, value):
+ """Set the spell check flag.
+ """
+ if value != self._spellCheck:
+ self._spellCheck = checkBool(value, False)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setSpellLang(self, value):
+ """Set the spell check language.
+ """
+ if value != self._spellLang:
+ self._spellLang = checkStringNone(value, None)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setLastHandle(self, value, component=None):
+ """Set a last used handle into the handle registry. If component
+ is None, the value is assumed to be the whole dictionary of
+ values.
+ """
+ if isinstance(component, str):
+ self._lastHandle[component] = checkString(value, "")
+ self.theProject.setProjectChanged(True)
+ elif isinstance(value, dict):
+ for key, entry in value.items():
+ if key in self._lastHandle:
+ self._lastHandle[key] = checkString(entry, "")
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setLastCount(self, value, type):
+ """Set the word counts from last session.
+ """
+ self._lastCount[type] = checkInt(value, 0)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setCurrCount(self, value, type):
+ """Set the current word counts.
+ """
+ if value != self._currCount.get(type, 0):
+ self._currCount[type] = checkInt(value, 0)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setAutoReplace(self, value):
+ """Set the auto-replace dictionary.
+ """
+ if isinstance(value, dict):
+ self._autoReplace = {}
+ for key, entry in value.items():
+ if isinstance(entry, str):
+ self._autoReplace[key] = simplified(entry)
+ self.theProject.setProjectChanged(True)
+ return
+
+ def setTitleFormat(self, value):
+ """Set the title formats.
+ """
+ if isinstance(value, dict):
+ for key, entry in value.items():
+ if key in self._titleFormat and isinstance(entry, str):
+ self._titleFormat[key] = simplified(entry)
+ self.theProject.setProjectChanged(True)
+ return
+
+# END Class NWProjectData
diff --git a/novelwriter/core/projectdata.py b/novelwriter/core/projectdata.py
deleted file mode 100644
index d91c39c7..00000000
--- a/novelwriter/core/projectdata.py
+++ /dev/null
@@ -1,271 +0,0 @@
-"""
-novelWriter – Project Data Class
-================================
-Class for holding the project settings
-
-File History:
-Created: 2022-10-30 [2.0rc1]
-
-This file is a part of novelWriter
-Copyright 2018–2022, Veronica Berglyd Olsen
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-import logging
-
-from novelwriter.common import (
- checkBool, checkInt, checkStringNone, simplified
-)
-from novelwriter.core.status import NWStatus
-
-logger = logging.getLogger(__name__)
-
-
-class NWProjectData:
-
- def __init__(self):
-
- # Project Meta
- self._name = ""
- self._title = ""
- self._authors = []
- self._saveCount = 0
- self._autoCount = 0
- self._editTime = 0
-
- # Project Settings
- self._doBackup = True
- self._language = None
- self._spellCheck = False
- self._spellLang = None
- self._lastHandle = {}
- self._lastCount = {}
- self._currCount = {}
-
- self._autoReplace = {}
- self._titleFormat = {
- "title": "%title%",
- "chapter": "%title%",
- "unnumbered": "%title%",
- "scene": "* * *",
- "section": "",
- }
-
- self._status = NWStatus(NWStatus.STATUS)
- self._import = NWStatus(NWStatus.IMPORT)
-
- # Internal
- self._changed = False
-
- return
-
- ##
- # Properties
- ##
-
- @property
- def name(self):
- return self._name
-
- @property
- def title(self):
- return self._title
-
- @property
- def authors(self):
- return self._authors
-
- @property
- def saveCount(self):
- return self._saveCount
-
- @property
- def autoCount(self):
- return self._autoCount
-
- @property
- def editTime(self):
- return self._editTime
-
- @property
- def doBackup(self):
- return self._doBackup
-
- @property
- def language(self):
- return self._language
-
- @property
- def spellCheck(self):
- return self._spellCheck
-
- @property
- def spellLang(self):
- return self._spellLang
-
- @property
- def autoReplace(self):
- return self._autoReplace
-
- @property
- def titleFormat(self):
- return self._titleFormat
-
- @property
- def itemStatus(self):
- return self._status
-
- @property
- def itemImport(self):
- return self._import
-
- @property
- def changed(self):
- return self._changed
-
- ##
- # Methods
- ##
-
- def addAuthor(self, value):
- self._authors.append(simplified(str(value)))
- self._changed = True
- return
-
- def incSaveCount(self):
- self._saveCount += 1
- self._changed = True
- return
-
- def incAutoCount(self):
- self._autoCount += 1
- self._changed = True
- return
-
- def resetProjectChanged(self):
- self._changed = False
-
- ##
- # Getters
- ##
-
- def getLastHandle(self, component):
- return self._lastHandle.get(component, None)
-
- def getLastCount(self, type):
- return self._lastCount.get(type, 0)
-
- def getCurrCount(self, type):
- return self._currCount.get(type, 0)
-
- def getTitleFormat(self, kind):
- return self._titleFormat.get(kind, "%title%")
-
- ##
- # Setters
- ##
-
- def setName(self, value):
- self._name = simplified(str(value))
- self._changed = True
- return
-
- def setTitle(self, value):
- self._title = simplified(str(value))
- self._changed = True
- return
-
- def setAuthors(self, value):
- self._authors = []
- self._changed = True
- if isinstance(value, str):
- for author in value.splitlines():
- author = simplified(author)
- if author:
- self._authors.append(author)
- self._changed = True
- elif isinstance(value, list):
- self._authors = value
- return
-
- def setSaveCount(self, value):
- self._saveCount = checkInt(value, 0)
- self._changed = True
- return
-
- def setAutoCount(self, value):
- self._autoCount = checkInt(value, 0)
- self._changed = True
- return
-
- def setEditTime(self, value):
- self._editTime = checkInt(value, 0)
- self._changed = True
- return
-
- def setDoBackup(self, value):
- self._doBackup = checkBool(value, False)
- self._changed = True
- return
-
- def setLanguage(self, value):
- self._language = checkStringNone(value, None)
- self._changed = True
- return
-
- def setSpellCheck(self, value):
- self._spellCheck = checkBool(value, False)
- self._changed = True
- return
-
- def setSpellLang(self, value):
- self._spellLang = checkStringNone(value, None)
- self._changed = True
- return
-
- def setLastHandle(self, value, component):
- self._lastHandle[component] = checkStringNone(value, None)
- self._changed = True
- return
-
- def setLastCount(self, value, type):
- self._lastCount[type] = checkInt(value, 0)
- self._changed = True
- return
-
- def setCurrCount(self, value, type):
- if value != self._currCount.get(type, 0):
- self._currCount[type] = checkInt(value, 0)
- self._changed = True
- return
-
- def setAutoReplace(self, value):
- if isinstance(value, dict):
- self._autoReplace = {}
- for key, entry in value.items():
- if isinstance(entry, str):
- self._autoReplace[key] = simplified(entry)
- self._changed = True
- return
-
- def setTitleFormat(self, value):
- if isinstance(value, dict):
- for key, entry in value.items():
- if key in self._titleFormat and isinstance(entry, str):
- self._titleFormat[key] = simplified(entry)
- self._changed = True
- return
-
-# END Class NWProjectData
diff --git a/novelwriter/core/projectxml.py b/novelwriter/core/projectxml.py
index 9b56a5d3..e16cca0a 100644
--- a/novelwriter/core/projectxml.py
+++ b/novelwriter/core/projectxml.py
@@ -266,14 +266,10 @@ class ProjectXMLReader:
projData.setSpellCheck(xItem.text)
elif xItem.tag == "spellLang":
projData.setSpellLang(xItem.text)
- elif xItem.tag == "lastEdited":
+ elif xItem.tag == "lastEdited": # Discontinued in 1.4
projData.setLastHandle(xItem.text, "editor")
- elif xItem.tag == "lastViewed":
+ elif xItem.tag == "lastViewed": # Discontinued in 1.4
projData.setLastHandle(xItem.text, "viewer")
- elif xItem.tag == "lastNovel":
- projData.setLastHandle(xItem.text, "noveltree")
- elif xItem.tag == "lastOutline":
- projData.setLastHandle(xItem.text, "outline")
elif xItem.tag == "lastWordCount":
projData.setLastCount(xItem.text, "total")
elif xItem.tag == "novelWordCount":
@@ -284,9 +280,11 @@ class ProjectXMLReader:
self._parseStatusImport(xItem, projData.itemStatus)
elif xItem.tag in ("import", "importance"):
self._parseStatusImport(xItem, projData.itemImport)
+ elif xItem.tag == "lastHandle":
+ projData.setLastHandle(self._parseDictKeyText(xItem, "component"))
elif xItem.tag == "autoReplace":
if self._version >= 0x0102:
- projData.setAutoReplace(self._parseDictKeyText(xItem))
+ projData.setAutoReplace(self._parseDictKeyText(xItem, "key"))
else: # Pre 1.2 format
projData.setAutoReplace(self._parseDictTagText(xItem))
elif xItem.tag == "titleFormat":
@@ -304,13 +302,13 @@ class ProjectXMLReader:
for xItem in xSection:
if xItem.tag == "item":
item = {}
- item["handle"] = xItem.attrib.get("handle", None)
- item["parent"] = xItem.attrib.get("parent", None)
- item["root"] = xItem.attrib.get("root", None)
+ item["handle"] = checkStringNone(xItem.attrib.get("handle", None), None)
+ item["parent"] = checkStringNone(xItem.attrib.get("parent", None), None)
+ item["root"] = checkStringNone(xItem.attrib.get("root", None), None)
item["order"] = checkInt(xItem.attrib.get("order", 0), 0)
- item["type"] = checkString(xItem.attrib.get("type", ""), "")
- item["class"] = checkString(xItem.attrib.get("class", ""), "")
- item["layout"] = checkString(xItem.attrib.get("layout", ""), "")
+ item["type"] = checkString(xItem.attrib.get("type", "NO_TYPE"), "NO_TYPE")
+ item["class"] = checkString(xItem.attrib.get("class", "NO_CLASS"), "NO_CLASS")
+ item["layout"] = checkString(xItem.attrib.get("layout", "NO_LAYOUT"), "NO_LAYOUT")
for xVal in xItem:
if xVal.tag == "meta":
item["expanded"] = checkBool(xVal.attrib.get("expanded", False), False)
@@ -339,7 +337,7 @@ class ProjectXMLReader:
return True
def _parseProjectContentLegacy(self, xSection):
- """Parse the content section of the XML file for older version.
+ """Parse the content section of the XML file for older versions.
"""
logger.debug("Parsing xml (legacy format)")
depLayout = ("TITLE", "PAGE", "BOOK", "PARTITION", "UNNUMBERED", "CHAPTER", "SCENE")
@@ -347,8 +345,8 @@ class ProjectXMLReader:
for xItem in xSection:
item = {}
if xItem.tag == "item":
- item["handle"] = xItem.attrib.get("handle", None)
- item["parent"] = xItem.attrib.get("parent", None)
+ item["handle"] = checkStringNone(xItem.attrib.get("handle", None), None)
+ item["parent"] = checkStringNone(xItem.attrib.get("parent", None), None)
item["root"] = None # Value was added in 1.4
item["order"] = checkInt(xItem.attrib.get("order", 0), 0)
item["heading"] = "H0" # Value was added in 1.4
@@ -421,14 +419,14 @@ class ProjectXMLReader:
self._importMap = {entry["name"]: key for key, entry in projData.itemImport.items()}
return
- def _parseDictKeyText(self, xItem):
+ def _parseDictKeyText(self, xItem, keyName):
"""Parse a dictionary stored with key as an attribute and the
value as the text porperty.
"""
result = {}
for xEntry in xItem:
- if xEntry.tag == "entry" and "key" in xEntry.attrib:
- result[xEntry.attrib["key"]] = checkString(xEntry.text, "")
+ if xEntry.tag == "entry" and keyName in xEntry.attrib:
+ result[xEntry.attrib[keyName]] = checkString(xEntry.text, "")
return result
def _parseDictTagText(self, xItem):
@@ -473,14 +471,11 @@ class ProjectXMLWriter:
self._packSingleValue(xSettings, "language", projData.language)
self._packSingleValue(xSettings, "spellCheck", projData.spellCheck)
self._packSingleValue(xSettings, "spellLang", projData.spellLang)
- self._packSingleValue(xSettings, "lastEdited", projData.getLastHandle("editor"))
- self._packSingleValue(xSettings, "lastViewed", projData.getLastHandle("viewer"))
- self._packSingleValue(xSettings, "lastNovel", projData.getLastHandle("noveltree"))
- self._packSingleValue(xSettings, "lastOutline", projData.getLastHandle("outline"))
self._packSingleValue(xSettings, "lastWordCount", projData.getCurrCount("total"))
self._packSingleValue(xSettings, "novelWordCount", projData.getCurrCount("novel"))
self._packSingleValue(xSettings, "notesWordCount", projData.getCurrCount("notes"))
- self._packDictKeyValue(xSettings, "autoReplace", projData.autoReplace)
+ self._packDictKeyValue(xSettings, "lastHandle", projData.lastHandle, "component")
+ self._packDictKeyValue(xSettings, "autoReplace", projData.autoReplace, "key")
self._packDictTagValue(xSettings, "titleFormat", projData.titleFormat)
# Save Status/Importance
@@ -549,14 +544,15 @@ class ProjectXMLWriter:
self._packSingleValue(xParent, name, value, allowNone=allowNone)
return
- def _packDictKeyValue(self, xParent, name, data):
+ def _packDictKeyValue(self, xParent, name, data, keyName):
"""Pack the entries of a dictionary into an xml element.
"""
xItem = etree.SubElement(xParent, name)
for key, value in data.items():
if len(key) > 0:
- xEntry = etree.SubElement(xItem, "entry", attrib={"key": key})
- xEntry.text = value
+ xEntry = etree.SubElement(xItem, "entry", attrib={keyName: key})
+ if value:
+ xEntry.text = value
return
def _packDictTagValue(self, xParent, name, data):
diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py
index bfa1da1c..64662e17 100644
--- a/novelwriter/gui/noveltree.py
+++ b/novelwriter/gui/noveltree.py
@@ -109,7 +109,7 @@ class GuiNovelView(QWidget):
def refreshTree(self):
"""Refresh the current tree.
"""
- self.novelTree.refreshTree(rootHandle=self.theProject.data.getLastHandle("noveltree"))
+ self.novelTree.refreshTree(rootHandle=self.theProject.data.getLastHandle("novelTree"))
return
def clearProject(self):
@@ -122,7 +122,7 @@ class GuiNovelView(QWidget):
def openProjectTasks(self):
"""Run open project tasks.
"""
- lastNovel = self.theProject.data.getLastHandle("noveltree")
+ lastNovel = self.theProject.data.getLastHandle("novelTree")
if lastNovel not in self.theProject.tree:
lastNovel = self.theProject.tree.findRoot(nwItemClass.NOVEL)
@@ -319,7 +319,7 @@ class GuiNovelToolBar(QWidget):
def _refreshNovelTree(self):
"""Rebuild the current tree.
"""
- rootHandle = self.theProject.data.getLastHandle("noveltree")
+ rootHandle = self.theProject.data.getLastHandle("novelTree")
self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True)
return
@@ -485,7 +485,7 @@ class GuiNovelTree(QTreeWidget):
titleKey = selItem[0].data(self.C_TITLE, self.D_KEY)
self._populateTree(rootHandle)
- self.theProject.data.setLastHandle(rootHandle, "noveltree")
+ self.theProject.data.setLastHandle(rootHandle, "novelTree")
if titleKey is not None and titleKey in self._treeMap:
self._treeMap[titleKey].setSelected(True)
@@ -523,7 +523,7 @@ class GuiNovelTree(QTreeWidget):
self._lastCol = colType
self.setColumnHidden(self.C_EXTRA, colType == NovelTreeColumn.HIDDEN)
if doRefresh:
- lastNovel = self.theProject.data.getLastHandle("noveltree")
+ lastNovel = self.theProject.data.getLastHandle("novelTree")
self.refreshTree(rootHandle=lastNovel, overRide=True)
return
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index 553667f6..9f776210 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -197,6 +197,8 @@ class GuiMain(QMainWindow):
# Connect Signals
# ===============
+ self.theProject.projectStatusChanged.connect(self.mainStatus.doUpdateProjectStatus)
+
self.viewsBar.viewChangeRequested.connect(self._changeView)
self.projView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx
index 6b8d929d..dca0b5a5 100644
--- a/sample/nwProject.nwx
+++ b/sample/nwProject.nwx
@@ -1,26 +1,28 @@
-
+
Sample Project
Sample Project
Jane Smith
Jay Doh
- 1387
+ 1403
236
- 69358
+ 69454
False
en_GB
True
None
- 636b6aa9b697b
- 636b6aa9b697b
- 7031beac91f75
- 7031beac91f75
1363
954
409
+
+ 636b6aa9b697b
+ 636b6aa9b697b
+ 7031beac91f75
+ 7031beac91f75
+
B
E