Added autosave and theme to preferences dialog
This commit is contained in:
+4
-2
@@ -43,13 +43,14 @@ class Config:
|
|||||||
self.appPath = None
|
self.appPath = None
|
||||||
self.appRoot = None
|
self.appRoot = None
|
||||||
self.guiPath = None
|
self.guiPath = None
|
||||||
|
self.themeRoot = None
|
||||||
self.themePath = None
|
self.themePath = None
|
||||||
|
|
||||||
# Set default values
|
# Set default values
|
||||||
self.confChanged = False
|
self.confChanged = False
|
||||||
|
|
||||||
## General
|
## General
|
||||||
self.guiTheme = "default"
|
self.guiTheme = "default_dark"
|
||||||
self.winGeometry = [1100, 650]
|
self.winGeometry = [1100, 650]
|
||||||
self.treeColWidth = [120, 30, 50]
|
self.treeColWidth = [120, 30, 50]
|
||||||
self.mainPanePos = [300, 800]
|
self.mainPanePos = [300, 800]
|
||||||
@@ -106,7 +107,8 @@ class Config:
|
|||||||
self.appRoot = path.join(self.appPath,path.pardir)
|
self.appRoot = path.join(self.appPath,path.pardir)
|
||||||
self.helpPath = path.join(self.appRoot,"help","en_GB")
|
self.helpPath = path.join(self.appRoot,"help","en_GB")
|
||||||
self.guiPath = path.join(self.appPath,"gui")
|
self.guiPath = path.join(self.appPath,"gui")
|
||||||
self.themePath = path.join(self.appPath,"themes")
|
self.themeRoot = path.join(self.appPath,"themes")
|
||||||
|
self.themePath = path.join(self.themeRoot)
|
||||||
|
|
||||||
# If config folder does not exist, make it.
|
# If config folder does not exist, make it.
|
||||||
# This assumes that the os config folder itself exists.
|
# This assumes that the os config folder itself exists.
|
||||||
|
|||||||
+73
-8
@@ -20,8 +20,7 @@ from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush, QStandardItemModel
|
|||||||
from PyQt5.QtSvg import QSvgWidget
|
from PyQt5.QtSvg import QSvgWidget
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel,
|
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel,
|
||||||
QWidget, QTabWidget, QDialogButtonBox, QListWidget, QListWidgetItem, QPushButton,
|
QWidget, QTabWidget, QDialogButtonBox, QSpinBox, QGroupBox, QComboBox, QMessageBox
|
||||||
QColorDialog, QAbstractItemView, QTreeWidget, QTreeWidgetItem
|
|
||||||
)
|
)
|
||||||
from nw.enum import nwAlert
|
from nw.enum import nwAlert
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ class GuiConfigEditor(QDialog):
|
|||||||
self.outerBox = QHBoxLayout()
|
self.outerBox = QHBoxLayout()
|
||||||
self.innerBox = QVBoxLayout()
|
self.innerBox = QVBoxLayout()
|
||||||
|
|
||||||
self.setWindowTitle("%s Configuration" % nw.__package__)
|
self.setWindowTitle("Preferences")
|
||||||
|
|
||||||
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","block.svg"))
|
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","block.svg"))
|
||||||
self.svgGradient = QSvgWidget(self.gradPath)
|
self.svgGradient = QSvgWidget(self.gradPath)
|
||||||
@@ -70,8 +69,21 @@ class GuiConfigEditor(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _doSave(self):
|
def _doSave(self):
|
||||||
|
|
||||||
logger.verbose("ConfigEditor save button clicked")
|
logger.verbose("ConfigEditor save button clicked")
|
||||||
self.close()
|
|
||||||
|
needsRestart = False
|
||||||
|
needsRestart |= self.tabMain.saveValues()
|
||||||
|
|
||||||
|
if needsRestart:
|
||||||
|
msgBox = QMessageBox()
|
||||||
|
msgBox.information(
|
||||||
|
self, "Preferences",
|
||||||
|
"Some changes will not be applied until<br>%s has been restarted." % nw.__package__
|
||||||
|
)
|
||||||
|
|
||||||
|
self.accept()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _doClose(self):
|
def _doClose(self):
|
||||||
@@ -86,12 +98,65 @@ class GuiConfigEditGeneral(QWidget):
|
|||||||
def __init__(self, theParent, theProject):
|
def __init__(self, theParent, theProject):
|
||||||
QWidget.__init__(self, theParent)
|
QWidget.__init__(self, theParent)
|
||||||
|
|
||||||
self.theParent = theParent
|
self.mainConf = nw.CONFIG
|
||||||
self.theProject = theProject
|
self.theParent = theParent
|
||||||
self.mainForm = QFormLayout()
|
self.theProject = theProject
|
||||||
|
self.outerBox = QVBoxLayout()
|
||||||
|
|
||||||
self.setLayout(self.mainForm)
|
# User Interface
|
||||||
|
self.guiLook = QGroupBox("User Interface", self)
|
||||||
|
self.guiLookForm = QFormLayout(self)
|
||||||
|
self.guiLook.setLayout(self.guiLookForm)
|
||||||
|
|
||||||
|
self.theThemes = self.theParent.theTheme.listThemes()
|
||||||
|
self.guiLookTheme = QComboBox()
|
||||||
|
for themeDir, themeName in self.theThemes:
|
||||||
|
self.guiLookTheme.addItem(themeName, themeDir)
|
||||||
|
themeIdx = self.guiLookTheme.findData(self.mainConf.guiTheme)
|
||||||
|
if themeIdx != -1:
|
||||||
|
self.guiLookTheme.setCurrentIndex(themeIdx)
|
||||||
|
self.guiLookForm.addRow("Theme", self.guiLookTheme)
|
||||||
|
|
||||||
|
# AutoSave
|
||||||
|
self.autoSave = QGroupBox("Auto-Save", self)
|
||||||
|
self.autoSaveForm = QFormLayout(self)
|
||||||
|
self.autoSave.setLayout(self.autoSaveForm)
|
||||||
|
|
||||||
|
self.autoSaveDoc = QSpinBox(self)
|
||||||
|
self.autoSaveDoc.setMinimum(5)
|
||||||
|
self.autoSaveDoc.setMaximum(600)
|
||||||
|
self.autoSaveDoc.setSingleStep(1)
|
||||||
|
self.autoSaveDoc.setValue(self.mainConf.autoSaveDoc)
|
||||||
|
self.autoSaveForm.addRow("Save Document (seconds)", self.autoSaveDoc)
|
||||||
|
|
||||||
|
self.autoSaveProj = QSpinBox(self)
|
||||||
|
self.autoSaveProj.setMinimum(5)
|
||||||
|
self.autoSaveProj.setMaximum(600)
|
||||||
|
self.autoSaveProj.setSingleStep(1)
|
||||||
|
self.autoSaveProj.setValue(self.mainConf.autoSaveProj)
|
||||||
|
self.autoSaveForm.addRow("Save Project (seconds)", self.autoSaveProj)
|
||||||
|
|
||||||
|
self.outerBox.addWidget(self.guiLook)
|
||||||
|
self.outerBox.addWidget(self.autoSave)
|
||||||
|
self.setLayout(self.outerBox)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def saveValues(self):
|
||||||
|
|
||||||
|
autoSaveDoc = self.autoSaveDoc.value()
|
||||||
|
autoSaveProj = self.autoSaveProj.value()
|
||||||
|
guiTheme = self.guiLookTheme.currentData()
|
||||||
|
|
||||||
|
# Check if restart is needed
|
||||||
|
needsRestart = False
|
||||||
|
needsRestart |= self.mainConf.guiTheme != guiTheme
|
||||||
|
|
||||||
|
self.mainConf.autoSaveDoc = autoSaveDoc
|
||||||
|
self.mainConf.autoSaveProj = autoSaveProj
|
||||||
|
self.mainConf.guiTheme = guiTheme
|
||||||
|
self.mainConf.confChanged = True
|
||||||
|
|
||||||
|
return needsRestart
|
||||||
|
|
||||||
# END Class GuiConfigEditGeneral
|
# END Class GuiConfigEditGeneral
|
||||||
|
|||||||
+15
-8
@@ -19,7 +19,7 @@ from PyQt5.QtCore import Qt, QTimer
|
|||||||
from PyQt5.QtGui import QIcon, QPixmap, QColor
|
from PyQt5.QtGui import QIcon, QPixmap, QColor
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
qApp, QWidget, QMainWindow, QVBoxLayout, QFrame, QSplitter, QFileDialog,
|
qApp, QWidget, QMainWindow, QVBoxLayout, QFrame, QSplitter, QFileDialog,
|
||||||
QShortcut, QMessageBox, QProgressDialog
|
QShortcut, QMessageBox, QProgressDialog, QDialog
|
||||||
)
|
)
|
||||||
|
|
||||||
from nw.gui.doctree import GuiDocTree
|
from nw.gui.doctree import GuiDocTree
|
||||||
@@ -50,7 +50,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
logger.debug("Initialising GUI ...")
|
logger.debug("Initialising GUI ...")
|
||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
self.theTheme = Theme()
|
self.theTheme = Theme(self)
|
||||||
self.theProject = NWProject(self)
|
self.theProject = NWProject(self)
|
||||||
self.theIndex = NWIndex(self.theProject, self)
|
self.theIndex = NWIndex(self.theProject, self)
|
||||||
self.hasProject = False
|
self.hasProject = False
|
||||||
@@ -119,15 +119,11 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
# Set Up Autosaving Project Timer
|
# Set Up Autosaving Project Timer
|
||||||
self.asProjTimer = QTimer()
|
self.asProjTimer = QTimer()
|
||||||
self.asProjTimer.setInterval(int(self.mainConf.autoSaveProj*1000))
|
|
||||||
self.asProjTimer.timeout.connect(self._autoSaveProject)
|
self.asProjTimer.timeout.connect(self._autoSaveProject)
|
||||||
self.asProjTimer.start()
|
|
||||||
|
|
||||||
# Set Up Autosaving Document Timer
|
# Set Up Autosaving Document Timer
|
||||||
self.asDocTimer = QTimer()
|
self.asDocTimer = QTimer()
|
||||||
self.asDocTimer.setInterval(int(self.mainConf.autoSaveDoc*1000))
|
|
||||||
self.asDocTimer.timeout.connect(self._autoSaveDocument)
|
self.asDocTimer.timeout.connect(self._autoSaveDocument)
|
||||||
self.asDocTimer.start()
|
|
||||||
|
|
||||||
# Keyboard Shortcuts
|
# Keyboard Shortcuts
|
||||||
QShortcut(Qt.Key_Return, self.treeView, context=Qt.WidgetShortcut, activated=self._treeKeyPressReturn)
|
QShortcut(Qt.Key_Return, self.treeView, context=Qt.WidgetShortcut, activated=self._treeKeyPressReturn)
|
||||||
@@ -139,6 +135,10 @@ class GuiMain(QMainWindow):
|
|||||||
if self.mainConf.showGUI:
|
if self.mainConf.showGUI:
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
|
self.initMain()
|
||||||
|
self.asProjTimer.start()
|
||||||
|
self.asDocTimer.start()
|
||||||
|
|
||||||
logger.debug("GUI initialisation complete")
|
logger.debug("GUI initialisation complete")
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -150,6 +150,11 @@ class GuiMain(QMainWindow):
|
|||||||
self.statusBar.clearStatus()
|
self.statusBar.clearStatus()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def initMain(self):
|
||||||
|
self.asProjTimer.setInterval(int(self.mainConf.autoSaveProj*1000))
|
||||||
|
self.asDocTimer.setInterval(int(self.mainConf.autoSaveDoc*1000))
|
||||||
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Project Actions
|
# Project Actions
|
||||||
##
|
##
|
||||||
@@ -456,8 +461,10 @@ class GuiMain(QMainWindow):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def editConfigDialog(self):
|
def editConfigDialog(self):
|
||||||
dlgProj = GuiConfigEditor(self, self.theProject)
|
dlgConf = GuiConfigEditor(self, self.theProject)
|
||||||
dlgProj.exec_()
|
if dlgConf.exec_() == QDialog.Accepted:
|
||||||
|
logger.debug("Applying new preferences")
|
||||||
|
self.initMain()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def editProjectDialog(self):
|
def editProjectDialog(self):
|
||||||
|
|||||||
+12
-8
@@ -373,8 +373,9 @@ class NWProject():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def setSpellCheck(self, theMode):
|
def setSpellCheck(self, theMode):
|
||||||
self.spellCheck = theMode
|
if self.spellCheck != theMode:
|
||||||
self.setProjectChanged(True)
|
self.spellCheck = theMode
|
||||||
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setTreeOrder(self, newOrder):
|
def setTreeOrder(self, newOrder):
|
||||||
@@ -385,18 +386,21 @@ class NWProject():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def setLastEdited(self, tHandle):
|
def setLastEdited(self, tHandle):
|
||||||
self.lastEdited = tHandle
|
if self.lastEdited != tHandle:
|
||||||
self.setProjectChanged(True)
|
self.lastEdited = tHandle
|
||||||
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setLastViewed(self, tHandle):
|
def setLastViewed(self, tHandle):
|
||||||
self.lastViewed = tHandle
|
if self.lastViewed != tHandle:
|
||||||
self.setProjectChanged(True)
|
self.lastViewed = tHandle
|
||||||
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setProjectWordCount(self, theCount):
|
def setProjectWordCount(self, theCount):
|
||||||
self.currWCount = theCount
|
if self.currWCount != theCount:
|
||||||
self.setProjectChanged(True)
|
self.currWCount = theCount
|
||||||
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getSessionWordCount(self):
|
def getSessionWordCount(self):
|
||||||
|
|||||||
+41
-2
@@ -14,19 +14,30 @@ import logging
|
|||||||
import configparser
|
import configparser
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path
|
from os import path, listdir
|
||||||
|
|
||||||
|
from nw.enum import nwAlert
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Theme:
|
class Theme:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, theParent):
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
|
self.theParent = theParent
|
||||||
self.cssName = "styles.css"
|
self.cssName = "styles.css"
|
||||||
self.confName = "theme.conf"
|
self.confName = "theme.conf"
|
||||||
|
self.themeList = []
|
||||||
|
|
||||||
# Loaded Theme Settings
|
# Loaded Theme Settings
|
||||||
|
|
||||||
|
## Main
|
||||||
|
self.themeName = "No Name"
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
self.colText = [0,0,0]
|
||||||
|
self.colLink = [0,0,0]
|
||||||
self.colHead = [0,0,0]
|
self.colHead = [0,0,0]
|
||||||
self.colHeadH = [0,0,0]
|
self.colHeadH = [0,0,0]
|
||||||
self.colEmph = [0,0,0]
|
self.colEmph = [0,0,0]
|
||||||
@@ -83,6 +94,11 @@ class Theme:
|
|||||||
logger.error("Could not load theme config file")
|
logger.error("Could not load theme config file")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
## Main
|
||||||
|
cnfSec = "Main"
|
||||||
|
if confParser.has_section(cnfSec):
|
||||||
|
self.themeName = confParser.get(cnfSec,"name")
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
cnfSec = "Syntax"
|
cnfSec = "Syntax"
|
||||||
if confParser.has_section(cnfSec):
|
if confParser.has_section(cnfSec):
|
||||||
@@ -103,6 +119,29 @@ class Theme:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def listThemes(self):
|
||||||
|
|
||||||
|
if len(self.themeList) > 0:
|
||||||
|
return self.themeList
|
||||||
|
|
||||||
|
confParser = configparser.ConfigParser()
|
||||||
|
for themeDir in listdir(self.mainConf.themeRoot):
|
||||||
|
themeConf = path.join(self.mainConf.themeRoot, themeDir, self.confName)
|
||||||
|
logger.verbose("Checking theme config for '%s'" % themeDir)
|
||||||
|
try:
|
||||||
|
confParser.read_file(open(themeConf))
|
||||||
|
except Exception as e:
|
||||||
|
self.theParent.makeAlert(["Could not load theme config file",str(e)],nwAlert.ERROR)
|
||||||
|
return []
|
||||||
|
themeName = ""
|
||||||
|
if confParser.has_section("Main"):
|
||||||
|
themeName = confParser.get("Main","name")
|
||||||
|
logger.verbose("Theme name is '%s'" % themeName)
|
||||||
|
if themeName != "":
|
||||||
|
self.themeList.append((themeDir, themeName))
|
||||||
|
|
||||||
|
return self.themeList
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Default Theme: Dark
|
||||||
|
*/
|
||||||
|
|
||||||
* {
|
* {
|
||||||
background-color: #999999;
|
background-color: #999999;
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
[Main]
|
||||||
|
name = Default Dark
|
||||||
|
|
||||||
[Syntax]
|
[Syntax]
|
||||||
text = 199, 207, 208
|
text = 199, 207, 208
|
||||||
link = 184, 200, 0
|
link = 184, 200, 0
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Default Theme: Light
|
||||||
|
*/
|
||||||
|
|
||||||
|
QTreeView, QHeaderView {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
[Main]
|
||||||
|
name = Default Light
|
||||||
|
|
||||||
|
[Syntax]
|
||||||
|
text = 0, 0, 0
|
||||||
|
link = 0, 0, 0
|
||||||
|
headertext = 0, 0, 0
|
||||||
|
headertag = 0, 0, 0
|
||||||
|
emphasis = 0, 0, 0
|
||||||
|
straightquotes = 0, 0, 0
|
||||||
|
doublequotes = 0, 0, 0
|
||||||
|
singlequotes = 0, 0, 0
|
||||||
|
hidden = 50, 50, 50
|
||||||
|
keyword = 0, 0, 0
|
||||||
|
value = 0, 0, 0
|
||||||
|
spellcheckline = 0, 0, 0
|
||||||
|
tagerror = 0, 0, 0
|
||||||
|
replacetag = 0, 0, 0
|
||||||
Reference in New Issue
Block a user