235 lines
7.7 KiB
Python
235 lines
7.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""novelWriter Config Class
|
||
|
||
novelWriter – Config Class
|
||
============================
|
||
This class reads and store the main preferences of the application
|
||
|
||
File History:
|
||
Created: 2018-0+-22 [0.0.1]
|
||
|
||
"""
|
||
|
||
import logging
|
||
import configparser
|
||
import nw
|
||
|
||
from os import path, mkdir, getcwd
|
||
from appdirs import user_config_dir
|
||
from datetime import datetime
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
class Config:
|
||
|
||
WIN_WIDTH = 0
|
||
WIN_HEIGHT = 1
|
||
|
||
def __init__(self):
|
||
|
||
# Set Application Variables
|
||
self.appName = nw.__package__
|
||
self.appHandle = nw.__package__.lower()
|
||
self.showGUI = True
|
||
self.debugGUI = False
|
||
|
||
# Set Paths
|
||
self.confPath = user_config_dir(self.appHandle)
|
||
self.confFile = self.appHandle+".conf"
|
||
self.homePath = path.expanduser("~")
|
||
self.appPath = path.dirname(__file__)
|
||
self.guiPath = path.join(self.appPath,"gui")
|
||
self.themePath = path.join(self.appPath,"themes")
|
||
self.recentList = [""]*10
|
||
|
||
# If config folder does not exist, make it.
|
||
# This assumes that the os config folder itself exists.
|
||
# TODO: This does not work on Windows
|
||
if not path.isdir(self.confPath):
|
||
mkdir(self.confPath)
|
||
|
||
# Set default values
|
||
self.confChanged = False
|
||
|
||
## General
|
||
self.guiTheme = "default"
|
||
self.winGeometry = [1100, 650]
|
||
self.treeColWidth = [120, 30, 50]
|
||
self.mainPanePos = [300, 800]
|
||
|
||
## Text Editor
|
||
self.textFixedW = True
|
||
self.textWidth = 600
|
||
self.textMargin = [40, 40]
|
||
self.doReplace = True
|
||
self.doReplaceQuote = True
|
||
self.doReplaceDash = True
|
||
self.doReplaceDots = True
|
||
self.replaceQuotes = ["“","”"]
|
||
|
||
# Check if config file exists
|
||
if path.isfile(path.join(self.confPath,self.confFile)):
|
||
self.loadConfig()
|
||
|
||
# Save a copy of the default config if no file exists
|
||
if not path.isfile(path.join(self.confPath,self.confFile)):
|
||
self.saveConfig()
|
||
|
||
return
|
||
|
||
##
|
||
# Actions
|
||
##
|
||
|
||
def loadConfig(self):
|
||
|
||
logger.debug("Loading config file")
|
||
confParser = configparser.ConfigParser()
|
||
confParser.readfp(open(path.join(self.confPath,self.confFile)))
|
||
|
||
# Get options
|
||
|
||
## Sizes
|
||
cnfSec = "Sizes"
|
||
if confParser.has_section(cnfSec):
|
||
if confParser.has_option(cnfSec,"geometry"):
|
||
self.winGeometry = self.unpackList(
|
||
confParser.get(cnfSec,"geometry"), 2, self.winGeometry
|
||
)
|
||
if confParser.has_option(cnfSec,"treecols"):
|
||
self.treeColWidth = self.unpackList(
|
||
confParser.get(cnfSec,"treecols"), 3, self.treeColWidth
|
||
)
|
||
if confParser.has_option(cnfSec,"mainpane"):
|
||
self.mainPanePos = self.unpackList(
|
||
confParser.get(cnfSec,"mainpane"), 2, self.mainPanePos
|
||
)
|
||
|
||
## Editor
|
||
cnfSec = "Editor"
|
||
if confParser.has_section(cnfSec):
|
||
if confParser.has_option(cnfSec,"fixedwidth"):
|
||
self.textFixedW = confParser.getboolean(cnfSec,"fixedwidth")
|
||
if confParser.has_option(cnfSec,"width"):
|
||
self.textWidth = confParser.getint(cnfSec,"width")
|
||
if confParser.has_option(cnfSec,"margins"):
|
||
self.textMargin = self.unpackList(
|
||
confParser.get(cnfSec,"margins"), 2, self.textMargin
|
||
)
|
||
if confParser.has_option(cnfSec,"autoreplace"):
|
||
self.doReplace = confParser.getboolean(cnfSec,"autoreplace")
|
||
if confParser.has_option(cnfSec,"repquotes"):
|
||
self.doReplaceQuote = confParser.getboolean(cnfSec,"repquotes")
|
||
if confParser.has_option(cnfSec,"repdash"):
|
||
self.doReplaceDash = confParser.getboolean(cnfSec,"repdash")
|
||
if confParser.has_option(cnfSec,"repdots"):
|
||
self.doReplaceDots = confParser.getboolean(cnfSec,"repdots")
|
||
if confParser.has_option(cnfSec,"usequotes"):
|
||
self.replaceQuotes = self.unpackList(
|
||
confParser.get(cnfSec,"usequotes"), 2, self.replaceQuotes
|
||
)
|
||
|
||
## Path
|
||
cnfSec = "Path"
|
||
if confParser.has_section(cnfSec):
|
||
for i in range(10):
|
||
if confParser.has_option(cnfSec,"recent%d" % i):
|
||
self.recentList[i] = confParser.get(cnfSec,"recent%d" % i)
|
||
|
||
return
|
||
|
||
def saveConfig(self):
|
||
|
||
logger.debug("Saving config file")
|
||
confParser = configparser.ConfigParser()
|
||
|
||
# Set options
|
||
|
||
## Main
|
||
cnfSec = "Main"
|
||
confParser.add_section(cnfSec)
|
||
confParser.set(cnfSec,"timestamp", datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
||
|
||
## Sizes
|
||
cnfSec = "Sizes"
|
||
confParser.add_section(cnfSec)
|
||
confParser.set(cnfSec,"geometry", self.packList(self.winGeometry))
|
||
confParser.set(cnfSec,"treecols", self.packList(self.treeColWidth))
|
||
confParser.set(cnfSec,"mainpane", self.packList(self.mainPanePos))
|
||
|
||
## Editor
|
||
cnfSec = "Editor"
|
||
confParser.add_section(cnfSec)
|
||
confParser.set(cnfSec,"fixedwidth", str(self.textFixedW))
|
||
confParser.set(cnfSec,"width", str(self.textWidth))
|
||
confParser.set(cnfSec,"margins", self.packList(self.textMargin))
|
||
confParser.set(cnfSec,"autoreplace",str(self.doReplace))
|
||
confParser.set(cnfSec,"repquotes", str(self.doReplaceQuote))
|
||
confParser.set(cnfSec,"repdash", str(self.doReplaceDash))
|
||
confParser.set(cnfSec,"repdots", str(self.doReplaceDots))
|
||
confParser.set(cnfSec,"usequotes", self.packList(self.replaceQuotes))
|
||
|
||
## Path
|
||
cnfSec = "Path"
|
||
confParser.add_section(cnfSec)
|
||
for i in range(10):
|
||
confParser.set(cnfSec,"recent%d" % i, str(self.recentList[i]))
|
||
|
||
# Write config file
|
||
confParser.write(open(path.join(self.confPath,self.confFile),"w"))
|
||
self.confChanged = False
|
||
|
||
return
|
||
|
||
def unpackList(self, inStr, listLen, listDefault, castTo=int):
|
||
inData = inStr.split(",")
|
||
outData = []
|
||
for i in range(listLen):
|
||
try:
|
||
outData.append(castTo(inData[i]))
|
||
except:
|
||
outData.append(listDefault[i])
|
||
return outData
|
||
|
||
def packList(self, inData):
|
||
return ", ".join(str(inVal) for inVal in inData)
|
||
|
||
##
|
||
# Setters
|
||
##
|
||
|
||
def setRecent(self, recentPath):
|
||
if recentPath == "": return
|
||
if recentPath in self.recentList[0:10]:
|
||
self.recentList.remove(recentPath)
|
||
self.recentList.insert(0,recentPath)
|
||
return
|
||
|
||
def setConfPath(self, newPath):
|
||
if newPath is None: return
|
||
if not path.isfile(newPath):
|
||
logger.error("Config: File not found. Using default config path instead.")
|
||
return
|
||
self.confPath = path.dirname(newPath)
|
||
self.confFile = path.basename(newPath)
|
||
return
|
||
|
||
def setWinSize(self, newWidth, newHeight):
|
||
if abs(self.winGeometry[self.WIN_WIDTH] - newWidth) >= 10:
|
||
self.winGeometry[self.WIN_WIDTH] = newWidth
|
||
self.confChanged = True
|
||
if abs(self.winGeometry[self.WIN_HEIGHT] - newHeight) >= 10:
|
||
self.winGeometry[self.WIN_HEIGHT] = newHeight
|
||
self.confChanged = True
|
||
return
|
||
|
||
def setTreeColWidths(self, colWidths):
|
||
self.treeColWidth = colWidths
|
||
return
|
||
|
||
def setMainPanePos(self, panePos):
|
||
self.mainPanePos = panePos
|
||
return
|
||
|
||
# End Class Config
|