Files
LinkScope_Client/Core/SettingsObject.py

151 lines
7.9 KiB
Python

#!/usr/bin/env python3
from msgpack import dump
from shutil import move
from pathlib import Path
from Core.PathHelper import is_path_exists_or_creatable_portable
from PySide6.QtCore import QSettings
class SettingsObject(dict):
"""
Stores the following session settings:
Project/Name: Self explanatory.
Project/BaseDir: The directory in which the current project is stored.
Program/BaseDir: The directory in which the program is stored.
MainWindow/Geometry: Stores the window size
MainWindow/WindowState: Saves window state (toolbar position etc.)
Logging/Severity: Dictates logging severity
Logging/Logfile: Which file should the software write logs to.
"""
def __init__(self):
super().__init__()
self.globalSettings = QSettings()
self.globalSettings.setValue("Program/Version", "v1.6.1")
self.globalSettings.setValue("Program/TOR Profile Location",
self.globalSettings.value("Program/TOR Profile Location", ""))
self.globalSettings.setValue("Program/BaseDir",
self.globalSettings.value("Program/BaseDir", "Unset"))
self.globalSettings.setValue("Program/Version Check Source",
self.globalSettings.value("Program/Version Check Source",
"https://api.github.com/repos/AccentuSoft/LinkScope_Client/releases/latest"))
self.globalSettings.setValue("Program/Update Source",
self.globalSettings.value("Program/Update Source",
"https://github.com/AccentuSoft/LinkScope_Client/releases/latest/download/"))
# The value '20' equates to logging.INFO
# It's not necessary to set this, but we will for
# the sake of completeness
self.globalSettings.setValue("Logging/Severity",
self.globalSettings.value("Logging/Severity", "20"))
self.globalSettings.setValue("Logging/Logfile",
self.globalSettings.value("Logging/Logfile",
str(Path.home() / 'LinkScope_logfile.log')))
self.globalSettings.setValue("Program/Graph Layout",
self.globalSettings.value("Program/Graph Layout", "dot"))
self.globalSettings.setValue("Program/Graphics/Entity Text Font Type",
self.globalSettings.value("Program/Graphics/Entity Text Font Type", "Mono"))
self.globalSettings.setValue("Program/Graphics/Entity Text Font Size",
self.globalSettings.value("Program/Graphics/Entity Text Font Size", "11"))
self.globalSettings.setValue("Program/Graphics/Entity Text Font Boldness",
self.globalSettings.value("Program/Graphics/Entity Text Font Boldness", "700"))
self.globalSettings.setValue("Program/Graphics/Link Text Font Type",
self.globalSettings.value("Program/Graphics/Link Text Font Type", "Mono"))
self.globalSettings.setValue("Program/Graphics/Link Text Font Size",
self.globalSettings.value("Program/Graphics/Link Text Font Size", "11"))
self.globalSettings.setValue("Program/Graphics/Link Text Font Boldness",
self.globalSettings.value("Program/Graphics/Link Text Font Boldness", "700"))
self.globalSettings.setValue("Program/Graphics/Entity Text Color",
self.globalSettings.value("Program/Graphics/Entity Text Color", "#000000"))
self.globalSettings.setValue("Program/Graphics/Link Text Color",
self.globalSettings.value("Program/Graphics/Link Text Color", "#000000"))
self.globalSettings.setValue("Program/Graphics/Label Fade Scroll Distance",
self.globalSettings.value("Program/Graphics/Label Fade Scroll Distance", "3"))
self.globalSettings.setValue("Program/Usage/First Time Start",
self.globalSettings.value("Program/Usage/First Time Start", 'true'))
self.globalSettings.setValue("Program/Sources/Sources List",
self.globalSettings.value(
"Program/Sources/Sources List",
{}))
self.globalSettings.setValue("Program/Sources/Module Packs List",
self.globalSettings.value(
"Program/Sources/Module Packs List",
{}))
self.setValue("Project/Name", "Untitled")
self.setValue("Project/BaseDir", "")
self.setValue("Project/FilesDir", "")
# For any entity with a Path variable, this dictates whether a copy of the original is made or whether a
# symlink is created. Symlinks however require special permissions or developer mode in Windows.
# To ensure that the software works out-of-the-box on all platforms, the default is set to 'Copy'.
self.setValue("Project/Symlink or Copy Materials", "Copy") # Values are 'Copy' or 'Symlink'.
self.setValue("Project/Resolution Result Grouping Threshold", "15")
self.setValue("Project/Number of Answers Returned", "3")
self.setValue("Project/Question Answering Retriever Value", "10")
self.setValue("Project/Question Answering Reader Value", "10")
self.setValue("Project/Server/Project", "")
self.setValue("Project/Server/Collectors", "{}")
def getGroupSettings(self, settingsGroup: str) -> dict:
if not settingsGroup.endswith('/'):
settingsGroup += '/'
settingsDict = {
setting: self.globalSettings.value(setting)
for setting in self.globalSettings.allKeys()
if setting.startswith(settingsGroup)
}
for setting in self:
if setting.startswith(settingsGroup):
settingsDict[setting] = self[setting]
return dict(sorted(settingsDict.items()))
def setValue(self, key, value) -> None:
if self.globalSettings.contains(key):
self.globalSettings.setValue(key, value)
self[key] = value
def setGlobalValue(self, key, value) -> None:
"""
Helper in the case we want to be explicit in setting a value globally.
"""
self.globalSettings.setValue(key, value)
def value(self, key, alt=None):
if self.globalSettings.contains(key):
return self.globalSettings.value(key)
return self.get(key, alt)
def removeKey(self, key) -> bool:
try:
if self.globalSettings.contains(key):
self.globalSettings.remove(key)
else:
self.pop(key)
return True
except KeyError:
return False
def save(self) -> None:
# Save and then move to prevent corruption if the application closes unexpectedly.
actualSavePath = str(Path(self.value("Project/BaseDir")).joinpath(self.value("Project/Name") + ".linkscope"))
if is_path_exists_or_creatable_portable(actualSavePath):
tempSavePath = f'{actualSavePath}.tmp'
with open(tempSavePath, "wb") as projectFile:
dump(self, projectFile)
move(tempSavePath, actualSavePath)
self.globalSettings.sync()
globalSettingsSavingError = self.globalSettings.status()
if globalSettingsSavingError != self.globalSettings.Status.NoError:
raise ValueError(f'Could not save global settings: {globalSettingsSavingError}')
def load(self, savedDict: dict) -> None:
# No need to do anything with global settings.
for key in savedDict:
self[key] = savedDict[key]