Move recent cache out of config, and update all tests

This commit is contained in:
Veronica Berglyd Olsen
2022-11-09 20:54:13 +01:00
parent 8721d53ab2
commit cb755ba820
5 changed files with 313 additions and 305 deletions
+114 -92
View File
@@ -74,8 +74,8 @@ class Config:
self._appPath = self._appRoot
# Runtime Settings and Variables
self.hasError = False # True if the config class encountered an error
self.errData = [] # List of error messages
self._hasError = False # True if the config class encountered an error
self._errData = [] # List of error messages
self.confChanged = False # True whenever the config has chenged, false after save
self.cmdOpen = None # Path from command line for project to be opened on launch
@@ -92,6 +92,8 @@ class Config:
# User Settings
# =============
self._recentProj = RecentProjects(self._dataPath)
# General GUI Settings
self.guiLang = self._qLocal.name()
self.guiTheme = "" # GUI theme
@@ -245,6 +247,18 @@ class Config:
return
##
# Properties
##
@property
def hasError(self):
return self._hasError
@property
def recentProjects(self):
return self._recentProj
##
# Methods
##
@@ -282,6 +296,15 @@ class Config:
return self._lastPath
return Path.home().absolute()
def errorText(self):
"""Compile and return error messages from the initialisation of
the Config class, and clear the error buffer.
"""
errMessage = "<br>".join(self._errData)
self._hasError = False
self._errData = []
return errMessage
##
# Config Actions
##
@@ -321,12 +344,12 @@ class Config:
else:
self.saveConfig()
self.loadRecentCache()
self._recentProj.loadCache()
self._checkOptionalPackages()
logger.debug("Config initialisation complete")
return True
return
def initLocalisation(self, nwApp):
"""Initialise the localisation of the GUI.
@@ -345,7 +368,7 @@ class Config:
qTrans = QTranslator()
lngFile = "%s_%s" % (lngBase, lngCode.replace("-", "_"))
if lngFile not in self._qtTrans:
if qTrans.load(lngFile, lngPath):
if qTrans.load(lngFile, str(lngPath)):
logger.debug("Loaded: %s", os.path.join(lngPath, lngFile))
nwApp.installTranslator(qTrans)
self._qtTrans[lngFile] = qTrans
@@ -367,12 +390,12 @@ class Config:
else:
return []
for qmFile in os.listdir(self._nwLangPath):
if not os.path.isfile(os.path.join(self._nwLangPath, qmFile)):
for qmFile in Path(self._nwLangPath).iterdir():
qmName = qmFile.name
if not (qmFile.is_file() and qmName.startswith(fPre) and qmName.endswith(fExt)):
continue
if not qmFile.startswith(fPre) or not qmFile.endswith(fExt):
continue
qmLang = qmFile[len(fPre):-len(fExt)]
qmLang = qmName[len(fPre):-len(fExt)]
qmName = QLocale(qmLang).nativeLanguageName().title()
if qmLang and qmName and qmLang != "en_GB":
langList[qmLang] = qmName
@@ -392,9 +415,9 @@ class Config:
except Exception as exc:
logger.error("Could not load config file")
logException()
self.hasError = True
self.errData.append("Could not load config file")
self.errData.append(formatException(exc))
self._hasError = True
self._errData.append("Could not load config file")
self._errData.append(formatException(exc))
return False
# Main
@@ -606,80 +629,13 @@ class Config:
except Exception as exc:
logger.error("Could not save config file")
logException()
self.hasError = True
self.errData.append("Could not save config file")
self.errData.append(formatException(exc))
self._hasError = True
self._errData.append("Could not save config file")
self._errData.append(formatException(exc))
return False
return True
def loadRecentCache(self):
"""Load the cache file for recent projects.
"""
self.recentProj = {}
cacheFile = self._dataPath / nwFiles.RECENT_FILE
if not os.path.isfile(cacheFile):
return True
try:
with open(cacheFile, mode="r", encoding="utf-8") as inFile:
theData = json.load(inFile)
for projPath, theEntry in theData.items():
self.recentProj[projPath] = {
"title": theEntry.get("title", ""),
"time": theEntry.get("time", 0),
"words": theEntry.get("words", 0),
}
except Exception as exc:
self.hasError = True
self.errData.append("Could not load recent project cache")
self.errData.append(formatException(exc))
return False
return True
def saveRecentCache(self):
"""Save the cache dictionary of recent projects.
"""
cacheFile = self._dataPath / nwFiles.RECENT_FILE
cacheTemp = cacheFile.with_suffix(".tmp")
try:
with open(cacheTemp, mode="w+", encoding="utf-8") as outFile:
json.dump(self.recentProj, outFile, indent=2)
cacheTemp.replace(cacheFile)
except Exception as exc:
self.hasError = True
self.errData.append("Could not save recent project cache")
self.errData.append(formatException(exc))
return False
return True
def updateRecentCache(self, projPath, projTitle, wordCount, saveTime):
"""Add or update recent cache information on a given project.
"""
self.recentProj[os.path.abspath(projPath)] = {
"title": projTitle,
"time": int(saveTime),
"words": int(wordCount),
}
return True
def removeFromRecentCache(self, thePath):
"""Trying to remove a path from the recent projects cache.
"""
if thePath in self.recentProj:
del self.recentProj[thePath]
logger.debug("Removed recent: %s", thePath)
self.saveRecentCache()
else:
logger.error("Unknown recent: %s", thePath)
return False
return True
##
# Setters
##
@@ -828,15 +784,6 @@ class Config:
def getTabWidth(self):
return self.pxInt(max(self.tabWidth, 0))
def getErrData(self):
"""Compile and return error messages from the initialisation of
the Config class, and clear the error buffer.
"""
errMessage = "<br>".join(self.errData)
self.hasError = False
self.errData = []
return errMessage
##
# Internal Functions
##
@@ -872,3 +819,78 @@ class Config:
return
# END Class Config
class RecentProjects:
def __init__(self, dataPath):
self._dataPath = dataPath
self._data = {}
return
def loadCache(self):
"""Load the cache file for recent projects.
"""
self._data = {}
cacheFile = self._dataPath / nwFiles.RECENT_FILE
if not cacheFile.is_file():
return True
try:
with open(cacheFile, mode="r", encoding="utf-8") as inFile:
theData = json.load(inFile)
for projPath, theEntry in theData.items():
self._data[projPath] = {
"title": theEntry.get("title", ""),
"words": theEntry.get("words", 0),
"time": theEntry.get("time", 0),
}
except Exception:
logger.error("Could not load recent project cache")
logException()
return False
return True
def saveCache(self):
"""Save the cache dictionary of recent projects.
"""
cacheFile = self._dataPath / nwFiles.RECENT_FILE
cacheTemp = cacheFile.with_suffix(".tmp")
try:
with open(cacheTemp, mode="w+", encoding="utf-8") as outFile:
json.dump(self._data, outFile, indent=2)
cacheTemp.replace(cacheFile)
except Exception:
logger.error("Could not save recent project cache")
logException()
return False
return True
def listEntries(self):
"""List all items in the cache.
"""
return [(k, e["title"], e["words"], e["time"]) for k, e in self._data.items()]
def update(self, projPath, projTitle, wordCount, saveTime):
"""Add or update recent cache information on a given project.
"""
self._data[str(projPath)] = {
"title": projTitle,
"words": int(wordCount),
"time": int(saveTime),
}
self.saveCache()
return
def remove(self, projPath):
"""Try to remove a path from the recent projects cache.
"""
if self._data.pop(str(projPath), None) is not None:
logger.debug("Removed recent: %s", projPath)
self.saveCache()
return
# END Class RecentProjects
+2 -4
View File
@@ -354,10 +354,9 @@ class NWProject(QObject):
self._loadProjectLocalisation()
# Update recent projects
self.mainConf.updateRecentCache(
self.mainConf.recentProjects.update(
self._storage.storagePath, self._data.name, sum(self._data.initCounts), time()
)
self.mainConf.saveRecentCache()
# Check the project tree consistency
for tItem in self._tree:
@@ -424,10 +423,9 @@ class NWProject(QObject):
self._storage.runPostSaveTasks(autoSave=autoSave)
# Update recent projects
self.mainConf.updateRecentCache(
self.mainConf.recentProjects.update(
self._storage.storagePath, self._data.name, sum(self._data.currCounts), saveTime
)
self.mainConf.saveRecentCache()
self._storage.writeLockFile()
self.mainGui.setStatus(self.tr("Saved Project: {0}").format(self._data.name))
+10 -16
View File
@@ -229,7 +229,7 @@ class GuiProjectLoad(QDialog):
).format(projName)
)
if msgYes:
self.mainConf.removeFromRecentCache(
self.mainConf.recentProjects.remove(
selList[0].data(self.C_NAME, Qt.UserRole)
)
self._populateList()
@@ -264,23 +264,17 @@ class GuiProjectLoad(QDialog):
def _populateList(self):
"""Populate the list box with recent project data.
"""
dataList = []
for projPath in self.mainConf.recentProj:
theEntry = self.mainConf.recentProj[projPath]
theTitle = theEntry.get("title", "")
theTime = theEntry.get("time", 0)
theWords = theEntry.get("words", 0)
dataList.append([theTitle, theTime, theWords, projPath])
self.listBox.clear()
sortList = sorted(dataList, key=lambda x: x[1], reverse=True)
for theTitle, theTime, theWords, projPath in sortList:
dataList = self.mainConf.recentProjects.listEntries()
sortList = sorted(dataList, key=lambda x: x[3], reverse=True)
nwxIcon = self.mainGui.mainTheme.getIcon("proj_nwx")
for path, title, words, time in sortList:
newItem = QTreeWidgetItem([""]*4)
newItem.setIcon(self.C_NAME, self.mainGui.mainTheme.getIcon("proj_nwx"))
newItem.setText(self.C_NAME, theTitle)
newItem.setData(self.C_NAME, Qt.UserRole, projPath)
newItem.setText(self.C_COUNT, formatInt(theWords))
newItem.setText(self.C_TIME, datetime.fromtimestamp(theTime).strftime("%x %X"))
newItem.setIcon(self.C_NAME, nwxIcon)
newItem.setText(self.C_NAME, title)
newItem.setData(self.C_NAME, Qt.UserRole, path)
newItem.setText(self.C_COUNT, formatInt(words))
newItem.setText(self.C_TIME, datetime.fromtimestamp(time).strftime("%x %X"))
newItem.setTextAlignment(self.C_NAME, Qt.AlignLeft | Qt.AlignVCenter)
newItem.setTextAlignment(self.C_COUNT, Qt.AlignRight | Qt.AlignVCenter)
newItem.setTextAlignment(self.C_TIME, Qt.AlignRight | Qt.AlignVCenter)
+1 -1
View File
@@ -1144,7 +1144,7 @@ class GuiMain(QMainWindow):
errors since it is initialised before the GUI itself.
"""
if self.mainConf.hasError:
self.makeAlert(self.mainConf.getErrData(), nwAlert.ERROR)
self.makeAlert(self.mainConf.errorText(), nwAlert.ERROR)
return True
return False