Merge pull request #30 from vkbo/config_gui

Config GUI
This commit is contained in:
Veronica K. Berglyd Olsen
2019-06-11 20:58:20 +02:00
committed by GitHub
16 changed files with 759 additions and 61 deletions
+39 -31
View File
@@ -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]
@@ -63,10 +64,11 @@ class Config:
self.autoSaveDoc = 30 self.autoSaveDoc = 30
## Text Editor ## Text Editor
self.textFont = None
self.textSize = 12
self.textFixedW = True self.textFixedW = True
self.textWidth = 600 self.textWidth = 600
self.textMargin = [40, 40] self.textMargin = [40, 40]
self.textSize = 13
self.tabWidth = 40 self.tabWidth = 40
self.doJustify = True self.doJustify = True
self.autoSelect = True self.autoSelect = True
@@ -77,9 +79,8 @@ class Config:
self.doReplaceDots = True self.doReplaceDots = True
self.wordCountTimer = 5.0 self.wordCountTimer = 5.0
self.fmtDoubleQuotes = ["",""]
self.fmtSingleQuotes = ["",""] self.fmtSingleQuotes = ["",""]
self.fmtApostrophe = "" self.fmtDoubleQuotes = ["",""]
self.spellLanguage = "en_GB" self.spellLanguage = "en_GB"
@@ -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.
@@ -153,19 +155,22 @@ class Config:
## Editor ## Editor
cnfSec = "Editor" cnfSec = "Editor"
self.textFixedW = self._parseLine(cnfParse, cnfSec, "fixedwidth", self.CNF_BOOL, self.textFixedW) self.textFont = self._parseLine(cnfParse, cnfSec, "textfont", self.CNF_STR, self.textFont)
self.textWidth = self._parseLine(cnfParse, cnfSec, "width", self.CNF_INT, self.textWidth) self.textSize = self._parseLine(cnfParse, cnfSec, "textsize", self.CNF_INT, self.textSize)
self.textMargin = self._parseLine(cnfParse, cnfSec, "margins", self.CNF_LIST, self.textMargin) self.textFixedW = self._parseLine(cnfParse, cnfSec, "fixedwidth", self.CNF_BOOL, self.textFixedW)
self.textSize = self._parseLine(cnfParse, cnfSec, "textsize", self.CNF_INT, self.textSize) self.textWidth = self._parseLine(cnfParse, cnfSec, "width", self.CNF_INT, self.textWidth)
self.tabWidth = self._parseLine(cnfParse, cnfSec, "tabwidth", self.CNF_INT, self.tabWidth) self.textMargin = self._parseLine(cnfParse, cnfSec, "margins", self.CNF_LIST, self.textMargin)
self.doJustify = self._parseLine(cnfParse, cnfSec, "justify", self.CNF_BOOL, self.doJustify) self.tabWidth = self._parseLine(cnfParse, cnfSec, "tabwidth", self.CNF_INT, self.tabWidth)
self.autoSelect = self._parseLine(cnfParse, cnfSec, "autoselect", self.CNF_BOOL, self.autoSelect) self.doJustify = self._parseLine(cnfParse, cnfSec, "justify", self.CNF_BOOL, self.doJustify)
self.doReplace = self._parseLine(cnfParse, cnfSec, "autoreplace", self.CNF_BOOL, self.doReplace) self.autoSelect = self._parseLine(cnfParse, cnfSec, "autoselect", self.CNF_BOOL, self.autoSelect)
self.doReplaceSQuote = self._parseLine(cnfParse, cnfSec, "repsquotes", self.CNF_BOOL, self.doReplaceSQuote) self.doReplace = self._parseLine(cnfParse, cnfSec, "autoreplace", self.CNF_BOOL, self.doReplace)
self.doReplaceDQuote = self._parseLine(cnfParse, cnfSec, "repdquotes", self.CNF_BOOL, self.doReplaceDQuote) self.doReplaceSQuote = self._parseLine(cnfParse, cnfSec, "repsquotes", self.CNF_BOOL, self.doReplaceSQuote)
self.doReplaceDash = self._parseLine(cnfParse, cnfSec, "repdash", self.CNF_BOOL, self.doReplaceDash) self.doReplaceDQuote = self._parseLine(cnfParse, cnfSec, "repdquotes", self.CNF_BOOL, self.doReplaceDQuote)
self.doReplaceDots = self._parseLine(cnfParse, cnfSec, "repdots", self.CNF_BOOL, self.doReplaceDots) self.doReplaceDash = self._parseLine(cnfParse, cnfSec, "repdash", self.CNF_BOOL, self.doReplaceDash)
self.spellLanguage = self._parseLine(cnfParse, cnfSec, "spellcheck", self.CNF_STR, self.spellLanguage) self.doReplaceDots = self._parseLine(cnfParse, cnfSec, "repdots", self.CNF_BOOL, self.doReplaceDots)
self.fmtSingleQuotes = self._parseLine(cnfParse, cnfSec, "fmtsinglequote", self.CNF_LIST, self.fmtSingleQuotes)
self.fmtDoubleQuotes = self._parseLine(cnfParse, cnfSec, "fmtdoublequote", self.CNF_LIST, self.fmtDoubleQuotes)
self.spellLanguage = self._parseLine(cnfParse, cnfSec, "spellcheck", self.CNF_STR, self.spellLanguage)
## Path ## Path
cnfSec = "Path" cnfSec = "Path"
@@ -205,19 +210,22 @@ class Config:
## Editor ## Editor
cnfSec = "Editor" cnfSec = "Editor"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec,"fixedwidth", str(self.textFixedW)) cnfParse.set(cnfSec,"textfont", str(self.textFont))
cnfParse.set(cnfSec,"width", str(self.textWidth)) cnfParse.set(cnfSec,"textsize", str(self.textSize))
cnfParse.set(cnfSec,"margins", self._packList(self.textMargin)) cnfParse.set(cnfSec,"fixedwidth", str(self.textFixedW))
cnfParse.set(cnfSec,"textsize", str(self.textSize)) cnfParse.set(cnfSec,"width", str(self.textWidth))
cnfParse.set(cnfSec,"tabwidth", str(self.tabWidth)) cnfParse.set(cnfSec,"margins", self._packList(self.textMargin))
cnfParse.set(cnfSec,"justify", str(self.doJustify)) cnfParse.set(cnfSec,"tabwidth", str(self.tabWidth))
cnfParse.set(cnfSec,"autoselect", str(self.autoSelect)) cnfParse.set(cnfSec,"justify", str(self.doJustify))
cnfParse.set(cnfSec,"autoreplace",str(self.doReplace)) cnfParse.set(cnfSec,"autoselect", str(self.autoSelect))
cnfParse.set(cnfSec,"repsquotes", str(self.doReplaceSQuote)) cnfParse.set(cnfSec,"autoreplace", str(self.doReplace))
cnfParse.set(cnfSec,"repdquotes", str(self.doReplaceDQuote)) cnfParse.set(cnfSec,"repsquotes", str(self.doReplaceSQuote))
cnfParse.set(cnfSec,"repdash", str(self.doReplaceDash)) cnfParse.set(cnfSec,"repdquotes", str(self.doReplaceDQuote))
cnfParse.set(cnfSec,"repdots", str(self.doReplaceDots)) cnfParse.set(cnfSec,"repdash", str(self.doReplaceDash))
cnfParse.set(cnfSec,"spellcheck", str(self.spellLanguage)) cnfParse.set(cnfSec,"repdots", str(self.doReplaceDots))
cnfParse.set(cnfSec,"fmtsinglequote",self._packList(self.fmtSingleQuotes))
cnfParse.set(cnfSec,"fmtdoublequote",self._packList(self.fmtDoubleQuotes))
cnfParse.set(cnfSec,"spellcheck", str(self.spellLanguage))
## Path ## Path
cnfSec = "Path" cnfSec = "Path"
+50
View File
@@ -70,3 +70,53 @@ class nwLabels():
} }
# END Class nwLabels # END Class nwLabels
class nwQuotes():
"""Allowed quotation marks.
Source: https://en.wikipedia.org/wiki/Quotation_mark
"""
SYMBOLS = [
"\u0022", # Quotation mark
"\u0027", # Apostrophe
"\u00ab", # Left-pointing double angle quotation mark
"\u00bb", # Right-pointing double angle quotation mark
"\u2018", # Left single quotation mark
"\u2019", # Right single quotation mark
"\u201a", # Single low-9 quotation mark
"\u201b", # Single high-reversed-9 quotation mark
"\u201c", # Left double quotation mark
"\u201d", # Right double quotation mark
"\u201e", # Double low-9 quotation mark
"\u201f", # Double high-reversed-9 quotation mark
"\u2039", # Single left-pointing angle quotation mark
"\u203a", # Single right-pointing angle quotation mark
"\u2e42", # Double low-reversed-9 quotation mark
"\u300c", # Left corner bracket
"\u300d", # Right corner bracket
"\u300e", # Left white corner bracket
"\u300f", # Right white corner bracket
]
HTML = {
"\u0022" : """,
"\u0027" : "'",
"\u00ab" : "«",
"\u00bb" : "»",
"\u2018" : "‘",
"\u2019" : "’",
"\u201a" : "‚",
"\u201b" : "‛",
"\u201c" : "“",
"\u201d" : "”",
"\u201e" : "„",
"\u201f" : "‟",
"\u2039" : "‹",
"\u203a" : "›",
"\u2e42" : "⹂",
"\u300c" : "「",
"\u300d" : "」",
"\u300e" : "『",
"\u300f" : "』",
}
# END Class nwQuotes
+492
View File
@@ -0,0 +1,492 @@
# -*- coding: utf-8 -*-
"""novelWriter GUI Config Editor
novelWriter GUI Config Editor
=================================
Class holding the config dialog
File History:
Created: 2019-06-10 [0.1.5]
"""
import logging
import enchant
import nw
from os import path
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush, QStandardItemModel, QFont
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel,
QWidget, QTabWidget, QDialogButtonBox, QSpinBox, QGroupBox, QComboBox, QMessageBox,
QCheckBox, QGridLayout, QFontComboBox
)
from nw.enum import nwAlert
from nw.constants import nwQuotes
logger = logging.getLogger(__name__)
class GuiConfigEditor(QDialog):
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
logger.debug("Initialising ConfigEditor ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setWindowTitle("Preferences")
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","block.svg"))
self.svgGradient = QSvgWidget(self.gradPath)
self.svgGradient.setFixedWidth(80)
self.theProject.countStatus()
self.tabMain = GuiConfigEditGeneral(self.theParent)
self.tabEditor = GuiConfigEditEditor(self.theParent)
self.tabWidget = QTabWidget()
self.tabWidget.addTab(self.tabMain, "General")
self.tabWidget.addTab(self.tabEditor, "Editor")
self.setLayout(self.outerBox)
self.outerBox.addWidget(self.svgGradient)
self.outerBox.addLayout(self.innerBox)
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose)
self.innerBox.addWidget(self.tabWidget)
self.innerBox.addWidget(self.buttonBox)
self.show()
logger.debug("ProjectEditor ConfigEditor complete")
return
def _doSave(self):
logger.verbose("ConfigEditor save button clicked")
validEntries = True
needsRestart = False
retA, retB = self.tabMain.saveValues()
validEntries &= retA
needsRestart |= retB
retA, retB = self.tabEditor.saveValues()
validEntries &= retA
needsRestart |= retB
if needsRestart:
msgBox = QMessageBox()
msgBox.information(
self, "Preferences",
"Some changes will not be applied until<br>%s has been restarted." % nw.__package__
)
if validEntries:
self.accept()
return
def _doClose(self):
logger.verbose("ConfigEditor close button clicked")
self.close()
return
# END Class GuiConfigEditor
class GuiConfigEditGeneral(QWidget):
def __init__(self, theParent):
QWidget.__init__(self, theParent)
self.mainConf = nw.CONFIG
self.theParent = theParent
self.outerBox = QGridLayout()
# User Interface
self.guiLook = QGroupBox("User Interface", self)
self.guiLookForm = QGridLayout(self)
self.guiLook.setLayout(self.guiLookForm)
self.guiLookTheme = QComboBox()
self.guiLookTheme.setMinimumWidth(200)
self.theThemes = self.theParent.theTheme.listThemes()
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.addWidget(QLabel("Theme"), 0, 0)
self.guiLookForm.addWidget(self.guiLookTheme, 0, 1)
# Spell Checking
self.spellLang = QGroupBox("Spell Checker", self)
self.spellLangForm = QGridLayout(self)
self.spellLang.setLayout(self.spellLangForm)
self.spellLangList = QComboBox(self)
for spTag, spProvider in enchant.list_dicts():
self.spellLangList.addItem("%s [%s]" % (spTag, spProvider.name), spTag)
spellIdx = self.spellLangList.findData(self.mainConf.spellLanguage)
if spellIdx != -1:
self.spellLangList.setCurrentIndex(spellIdx)
self.spellLangForm.addWidget(QLabel("Language"), 0, 0)
self.spellLangForm.addWidget(self.spellLangList, 0, 1)
self.spellLangForm.setColumnStretch(1, 1)
# AutoSave
self.autoSave = QGroupBox("Auto-Save", self)
self.autoSaveForm = QGridLayout(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.autoSaveProj = QSpinBox(self)
self.autoSaveProj.setMinimum(5)
self.autoSaveProj.setMaximum(600)
self.autoSaveProj.setSingleStep(1)
self.autoSaveProj.setValue(self.mainConf.autoSaveProj)
self.autoSaveForm.addWidget(QLabel("Document"), 0, 0)
self.autoSaveForm.addWidget(self.autoSaveDoc, 0, 1)
self.autoSaveForm.addWidget(QLabel("seconds"), 0, 2)
self.autoSaveForm.addWidget(QLabel("Project"), 1, 0)
self.autoSaveForm.addWidget(self.autoSaveProj, 1, 1)
self.autoSaveForm.addWidget(QLabel("seconds"), 1, 2)
# Assemble
self.outerBox.addWidget(self.guiLook, 0, 0)
self.outerBox.addWidget(self.spellLang, 1, 0)
self.outerBox.addWidget(self.autoSave, 2, 0)
self.outerBox.setColumnStretch(2, 1)
self.outerBox.setRowStretch(3, 1)
self.setLayout(self.outerBox)
return
def saveValues(self):
validEntries = True
needsRestart = False
guiTheme = self.guiLookTheme.currentData()
spellLanguage = self.spellLangList.currentData()
autoSaveDoc = self.autoSaveDoc.value()
autoSaveProj = self.autoSaveProj.value()
# Check if restart is needed
needsRestart |= self.mainConf.guiTheme != guiTheme
self.mainConf.guiTheme = guiTheme
self.mainConf.spellLanguage = spellLanguage
self.mainConf.autoSaveDoc = autoSaveDoc
self.mainConf.autoSaveProj = autoSaveProj
self.mainConf.confChanged = True
return validEntries, needsRestart
# END Class GuiConfigEditGeneral
class GuiConfigEditEditor(QWidget):
def __init__(self, theParent):
QWidget.__init__(self, theParent)
self.mainConf = nw.CONFIG
self.theParent = theParent
self.outerBox = QGridLayout()
# Text Style
self.textStyle = QGroupBox("Text Style", self)
self.textStyleForm = QGridLayout(self)
self.textStyle.setLayout(self.textStyleForm)
self.textStyleFont = QFontComboBox()
self.textStyleFont.setMaximumWidth(250)
self.textStyleFont.setCurrentFont(QFont(self.mainConf.textFont))
self.textStyleSize = QSpinBox(self)
self.textStyleSize.setMinimum(5)
self.textStyleSize.setMaximum(120)
self.textStyleSize.setSingleStep(1)
self.textStyleSize.setValue(self.mainConf.textSize)
self.textStyleForm.addWidget(QLabel("Font Family"), 0, 0)
self.textStyleForm.addWidget(self.textStyleFont, 0, 1)
self.textStyleForm.addWidget(QLabel("Size"), 0, 2)
self.textStyleForm.addWidget(self.textStyleSize, 0, 3)
self.textStyleForm.setColumnStretch(4, 1)
# Text Flow
self.textFlow = QGroupBox("Text Flow", self)
self.textFlowForm = QGridLayout(self)
self.textFlow.setLayout(self.textFlowForm)
self.textFlowFixed = QCheckBox(self)
self.textFlowFixed.setToolTip("Make text in editor fixed width and scale margins instead.")
if self.mainConf.textFixedW:
self.textFlowFixed.setCheckState(Qt.Checked)
else:
self.textFlowFixed.setCheckState(Qt.Unchecked)
self.textFlowWidth = QSpinBox(self)
self.textFlowWidth.setMinimum(300)
self.textFlowWidth.setMaximum(10000)
self.textFlowWidth.setSingleStep(10)
self.textFlowWidth.setValue(self.mainConf.textWidth)
self.textFlowJustify = QCheckBox(self)
self.textFlowJustify.setToolTip("Justify text in main document editor.")
if self.mainConf.doJustify:
self.textFlowJustify.setCheckState(Qt.Checked)
else:
self.textFlowJustify.setCheckState(Qt.Unchecked)
self.testFlowAutoSelect = QCheckBox(self)
self.testFlowAutoSelect.setToolTip("Auto-select word under cursor when applying formatting.")
if self.mainConf.autoSelect:
self.testFlowAutoSelect.setCheckState(Qt.Checked)
else:
self.testFlowAutoSelect.setCheckState(Qt.Unchecked)
self.textFlowForm.addWidget(QLabel("Fixed Width"), 0, 0)
self.textFlowForm.addWidget(self.textFlowFixed, 0, 1)
self.textFlowForm.addWidget(self.textFlowWidth, 0, 2)
self.textFlowForm.addWidget(QLabel("px"), 0, 3)
self.textFlowForm.addWidget(QLabel("Justify Text"), 1, 0)
self.textFlowForm.addWidget(self.textFlowJustify, 1, 1)
self.textFlowForm.addWidget(QLabel("Auto-Select Text"), 2, 0)
self.textFlowForm.addWidget(self.testFlowAutoSelect, 2, 1)
self.textFlowForm.setColumnStretch(4, 1)
# Text Margins
self.textMargin = QGroupBox("Margins", self)
self.textMarginForm = QGridLayout(self)
self.textMargin.setLayout(self.textMarginForm)
self.textMarginHor = QSpinBox(self)
self.textMarginHor.setMinimum(0)
self.textMarginHor.setMaximum(2000)
self.textMarginHor.setSingleStep(1)
self.textMarginHor.setValue(self.mainConf.textMargin[0])
self.textMarginVer = QSpinBox(self)
self.textMarginVer.setMinimum(0)
self.textMarginVer.setMaximum(2000)
self.textMarginVer.setSingleStep(1)
self.textMarginVer.setValue(self.mainConf.textMargin[1])
self.textMarginTab = QSpinBox(self)
self.textMarginTab.setMinimum(0)
self.textMarginTab.setMaximum(200)
self.textMarginTab.setSingleStep(1)
self.textMarginTab.setValue(self.mainConf.tabWidth)
self.textMarginForm.addWidget(QLabel("Horizontal"), 0, 0)
self.textMarginForm.addWidget(self.textMarginHor, 0, 1)
self.textMarginForm.addWidget(QLabel("px"), 0, 2)
self.textMarginForm.addWidget(QLabel("Vertical"), 1, 0)
self.textMarginForm.addWidget(self.textMarginVer, 1, 1)
self.textMarginForm.addWidget(QLabel("px"), 1, 2)
self.textMarginForm.addWidget(QLabel("Tab Width"), 2, 0)
self.textMarginForm.addWidget(self.textMarginTab, 2, 1)
self.textMarginForm.addWidget(QLabel("px"), 2, 2)
self.textMarginForm.setColumnStretch(4, 1)
# Auto-Replace
self.autoReplace = QGroupBox("Auto-Replace", self)
self.autoReplaceForm = QGridLayout(self)
self.autoReplace.setLayout(self.autoReplaceForm)
self.autoReplaceMain = QCheckBox(self)
self.autoReplaceMain.setToolTip("Auto-replace text as you type.")
if self.mainConf.doReplace:
self.autoReplaceMain.setCheckState(Qt.Checked)
else:
self.autoReplaceMain.setCheckState(Qt.Unchecked)
self.autoReplaceSQ = QCheckBox(self)
self.autoReplaceSQ.setToolTip("Auto-replace single quotes.")
if self.mainConf.doReplaceSQuote:
self.autoReplaceSQ.setCheckState(Qt.Checked)
else:
self.autoReplaceSQ.setCheckState(Qt.Unchecked)
self.autoReplaceSStyleO = QLineEdit()
self.autoReplaceSStyleO.setMaxLength(1)
self.autoReplaceSStyleO.setFixedWidth(30)
self.autoReplaceSStyleO.setAlignment(Qt.AlignCenter)
self.autoReplaceSStyleO.setText(self.mainConf.fmtSingleQuotes[0])
self.autoReplaceSStyleC = QLineEdit()
self.autoReplaceSStyleC.setMaxLength(1)
self.autoReplaceSStyleC.setFixedWidth(30)
self.autoReplaceSStyleC.setAlignment(Qt.AlignCenter)
self.autoReplaceSStyleC.setText(self.mainConf.fmtSingleQuotes[1])
self.autoReplaceDQ = QCheckBox(self)
self.autoReplaceDQ.setToolTip("Auto-replace double quotes.")
if self.mainConf.doReplaceDQuote:
self.autoReplaceDQ.setCheckState(Qt.Checked)
else:
self.autoReplaceDQ.setCheckState(Qt.Unchecked)
self.autoReplaceDStyleO = QLineEdit()
self.autoReplaceDStyleO.setMaxLength(1)
self.autoReplaceDStyleO.setFixedWidth(30)
self.autoReplaceDStyleO.setAlignment(Qt.AlignCenter)
self.autoReplaceDStyleO.setText(self.mainConf.fmtDoubleQuotes[0])
self.autoReplaceDStyleC = QLineEdit()
self.autoReplaceDStyleC.setMaxLength(1)
self.autoReplaceDStyleC.setFixedWidth(30)
self.autoReplaceDStyleC.setAlignment(Qt.AlignCenter)
self.autoReplaceDStyleC.setText(self.mainConf.fmtDoubleQuotes[1])
self.autoReplaceDash = QCheckBox(self)
self.autoReplaceDash.setToolTip("Auto-replace double and triple hyphens with short and long dash.")
if self.mainConf.doReplaceDash:
self.autoReplaceDash.setCheckState(Qt.Checked)
else:
self.autoReplaceDash.setCheckState(Qt.Unchecked)
self.autoReplaceDots = QCheckBox(self)
self.autoReplaceDots.setToolTip("Auto-replace three dots with ellipsis.")
if self.mainConf.doReplaceDots:
self.autoReplaceDots.setCheckState(Qt.Checked)
else:
self.autoReplaceDots.setCheckState(Qt.Unchecked)
self.autoReplaceForm.addWidget(QLabel("Enable Feature"), 0, 0)
self.autoReplaceForm.addWidget(self.autoReplaceMain, 0, 1)
self.autoReplaceForm.addWidget(QLabel("Single Quotes"), 1, 0)
self.autoReplaceForm.addWidget(self.autoReplaceSQ, 1, 1)
self.autoReplaceForm.addWidget(QLabel("Open"), 1, 2)
self.autoReplaceForm.addWidget(self.autoReplaceSStyleO, 1, 3)
self.autoReplaceForm.addWidget(QLabel("Close"), 1, 4)
self.autoReplaceForm.addWidget(self.autoReplaceSStyleC, 1, 5)
self.autoReplaceForm.addWidget(QLabel("Double Quotes"), 2, 0)
self.autoReplaceForm.addWidget(self.autoReplaceDQ, 2, 1)
self.autoReplaceForm.addWidget(QLabel("Open"), 2, 2)
self.autoReplaceForm.addWidget(self.autoReplaceDStyleO, 2, 3)
self.autoReplaceForm.addWidget(QLabel("Close"), 2, 4)
self.autoReplaceForm.addWidget(self.autoReplaceDStyleC, 2, 5)
self.autoReplaceForm.addWidget(QLabel("Hyphens with Dash"), 3, 0)
self.autoReplaceForm.addWidget(self.autoReplaceDash, 3, 1)
self.autoReplaceForm.addWidget(QLabel("Dots with Ellipsis"), 4, 0)
self.autoReplaceForm.addWidget(self.autoReplaceDots, 4, 1)
self.autoReplaceForm.setColumnStretch(6, 1)
# Assemble
self.outerBox.addWidget(self.textStyle, 0, 0, 1, 2)
self.outerBox.addWidget(self.textFlow, 1, 0)
self.outerBox.addWidget(self.textMargin, 1, 1)
self.outerBox.addWidget(self.autoReplace, 2, 0, 1, 2)
self.outerBox.setColumnStretch(2, 1)
self.setLayout(self.outerBox)
return
def saveValues(self):
validEntries = True
textFont = self.textStyleFont.currentFont().family()
textSize = self.textStyleSize.value()
self.mainConf.textFont = textFont
self.mainConf.textSize = textSize
textWidth = self.textFlowWidth.value()
textFixedW = self.textFlowFixed.isChecked()
doJustify = self.textFlowJustify.isChecked()
autoSelect = self.testFlowAutoSelect.isChecked()
self.mainConf.textWidth = textWidth
self.mainConf.textFixedW = textFixedW
self.mainConf.doJustify = doJustify
self.mainConf.autoSelect = autoSelect
textMarginH = self.textMarginHor.value()
textMarginV = self.textMarginVer.value()
tabWidth = self.textMarginTab.value()
self.mainConf.textMargin[0] = textMarginH
self.mainConf.textMargin[1] = textMarginV
self.mainConf.tabWidth = tabWidth
doReplace = self.autoReplaceMain.isChecked()
doReplaceSQuote = self.autoReplaceSQ.isChecked()
doReplaceDQuote = self.autoReplaceDQ.isChecked()
doReplaceDash = self.autoReplaceDash.isChecked()
doReplaceDots = self.autoReplaceDash.isChecked()
fmtSingleQuotesO = self.autoReplaceSStyleO.text()
fmtSingleQuotesC = self.autoReplaceSStyleC.text()
fmtDoubleQuotesO = self.autoReplaceDStyleO.text()
fmtDoubleQuotesC = self.autoReplaceDStyleC.text()
self.mainConf.doReplace = doReplace
self.mainConf.doReplaceSQuote = doReplaceSQuote
self.mainConf.doReplaceDQuote = doReplaceDQuote
self.mainConf.doReplaceDash = doReplaceDash
self.mainConf.doReplaceDots = doReplaceDots
if self._checkQuoteSymbol(fmtSingleQuotesO):
self.mainConf.fmtSingleQuotes[0] = fmtSingleQuotesO
else:
self.theParent.makeAlert("Invalid quote symbol: %s" % fmtSingleQuotesO, nwAlert.ERROR)
validEntries = False
if self._checkQuoteSymbol(fmtSingleQuotesC):
self.mainConf.fmtSingleQuotes[1] = fmtSingleQuotesC
else:
self.theParent.makeAlert("Invalid quote symbol: %s" % fmtSingleQuotesC, nwAlert.ERROR)
validEntries = False
if self._checkQuoteSymbol(fmtDoubleQuotesO):
self.mainConf.fmtDoubleQuotes[0] = fmtDoubleQuotesO
else:
self.theParent.makeAlert("Invalid quote symbol: %s" % fmtDoubleQuotesO, nwAlert.ERROR)
validEntries = False
if self._checkQuoteSymbol(fmtDoubleQuotesC):
self.mainConf.fmtDoubleQuotes[1] = fmtDoubleQuotesC
else:
self.theParent.makeAlert("Invalid quote symbol: %s" % fmtDoubleQuotesC, nwAlert.ERROR)
validEntries = False
self.mainConf.confChanged = True
return validEntries, False
##
# Internal Functions
##
def _checkQuoteSymbol(self, toCheck):
if len(toCheck) != 1:
return False
if toCheck in nwQuotes.SYMBOLS:
return True
return False
# END Class GuiConfigEditEditor
+25 -2
View File
@@ -18,7 +18,7 @@ from time import time
from PyQt5.QtCore import Qt, QTimer from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QTextEdit, QAction, QMenu, QShortcut from PyQt5.QtWidgets import QTextEdit, QAction, QMenu, QShortcut
from PyQt5.QtGui import QTextCursor, QTextOption, QIcon, QKeySequence from PyQt5.QtGui import QTextCursor, QTextOption, QIcon, QKeySequence, QFont
from nw.project.document import NWDoc from nw.project.document import NWDoc
from nw.gui.dochighlight import GuiDocHighlighter from nw.gui.dochighlight import GuiDocHighlighter
@@ -55,7 +55,6 @@ class GuiDocEditor(QTextEdit):
self.typDQClose = self.mainConf.fmtDoubleQuotes[1] self.typDQClose = self.mainConf.fmtDoubleQuotes[1]
self.typSQOpen = self.mainConf.fmtSingleQuotes[0] self.typSQOpen = self.mainConf.fmtSingleQuotes[0]
self.typSQClose = self.mainConf.fmtSingleQuotes[1] self.typSQClose = self.mainConf.fmtSingleQuotes[1]
self.typApos = self.mainConf.fmtApostrophe
# Core Elements # Core Elements
self.theQDoc = self.document() self.theQDoc = self.document()
@@ -113,7 +112,21 @@ class GuiDocEditor(QTextEdit):
return True return True
def initEditor(self): def initEditor(self):
"""Initialise or re-initialise the editor with the user's settings.
This function is both called when the editor is created, and when the user changes the
main editor preferences.
"""
# Set Font
if self.mainConf.textFont is not None:
self.setFontFamily(self.mainConf.textFont)
else:
# If none is defined, set the default back to config
theFont = self.theQDoc.defaultFont().family()
self.mainConf.textFont = theFont
self.setFontPointSize(self.mainConf.textSize) self.setFontPointSize(self.mainConf.textSize)
# Set text fixed width, or alternatively, just margins
if self.mainConf.textFixedW: if self.mainConf.textFixedW:
self.setLineWrapMode(QTextEdit.FixedPixelWidth) self.setLineWrapMode(QTextEdit.FixedPixelWidth)
self.setLineWrapColumnOrWidth(self.mainConf.textWidth) self.setLineWrapColumnOrWidth(self.mainConf.textWidth)
@@ -121,12 +134,22 @@ class GuiDocEditor(QTextEdit):
mTB = self.mainConf.textMargin[0] mTB = self.mainConf.textMargin[0]
mLR = self.mainConf.textMargin[1] mLR = self.mainConf.textMargin[1]
self.setViewportMargins(mLR,mTB,mLR,mTB) self.setViewportMargins(mLR,mTB,mLR,mTB)
# Also set the document text options for the document text flow
theOpt = QTextOption() theOpt = QTextOption()
if self.mainConf.tabWidth is not None: if self.mainConf.tabWidth is not None:
theOpt.setTabStopDistance(self.mainConf.tabWidth) theOpt.setTabStopDistance(self.mainConf.tabWidth)
if self.mainConf.doJustify: if self.mainConf.doJustify:
theOpt.setAlignment(Qt.AlignJustify) theOpt.setAlignment(Qt.AlignJustify)
self.theQDoc.setDefaultTextOption(theOpt) self.theQDoc.setDefaultTextOption(theOpt)
# If we have a document open, we should reload it in case the font changed
if self.theHandle is not None:
tHandle = self.theHandle
self.hLight.initHighlighter()
self.clearEditor()
self.loadText(tHandle)
return True return True
def loadText(self, tHandle): def loadText(self, tHandle):
+11 -3
View File
@@ -32,7 +32,9 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.theDict = None self.theDict = None
self.theHandle = None self.theHandle = None
self.spellCheck = False self.spellCheck = False
self.spellRx = None
self.hRules = [] self.hRules = []
self.hStyles = {}
self.colHead = QColor(*self.theTheme.colHead) self.colHead = QColor(*self.theTheme.colHead)
self.colHeadH = QColor(*self.theTheme.colHeadH) self.colHeadH = QColor(*self.theTheme.colHeadH)
@@ -47,6 +49,14 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.colTagErr = QColor(*self.theTheme.colTagErr) self.colTagErr = QColor(*self.theTheme.colTagErr)
self.colRepTag = QColor(*self.theTheme.colRepTag) self.colRepTag = QColor(*self.theTheme.colRepTag)
self.initHighlighter()
logger.debug("DocHighlighter initialisation complete")
return
def initHighlighter(self):
self.hStyles = { self.hStyles = {
"header1" : self._makeFormat(self.colHead, "bold",1.8), "header1" : self._makeFormat(self.colHead, "bold",1.8),
"header2" : self._makeFormat(self.colHead, "bold",1.6), "header2" : self._makeFormat(self.colHead, "bold",1.6),
@@ -160,9 +170,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.rules = [(QRegularExpression(a),b) for (a,b) in self.hRules] self.rules = [(QRegularExpression(a),b) for (a,b) in self.hRules]
self.spellRx = QRegularExpression(r"\b[^\s]+\b") self.spellRx = QRegularExpression(r"\b[^\s]+\b")
logger.debug("DocHighlighter initialisation complete") return True
return
## ##
# Setters # Setters
+6 -4
View File
@@ -492,10 +492,12 @@ class GuiMainMenu(QMenuBar):
menuItem.triggered.connect(self.theParent.rebuildIndex) menuItem.triggered.connect(self.theParent.rebuildIndex)
self.toolsMenu.addAction(menuItem) self.toolsMenu.addAction(menuItem)
# # Tools > Settings # Tools > Settings
# menuItem = QAction(QIcon.fromTheme("preferences-system"), "Preferences", self) menuItem = QAction(QIcon.fromTheme("preferences-system"), "Preferences", self)
# menuItem.setStatusTip("Preferences") menuItem.setStatusTip("Preferences")
# self.toolsMenu.addAction(menuItem) menuItem.setShortcut("Ctrl+,")
menuItem.triggered.connect(self.theParent.editConfigDialog)
self.toolsMenu.addAction(menuItem)
return return
+20 -6
View File
@@ -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
@@ -27,6 +27,7 @@ from nw.gui.doceditor import GuiDocEditor
from nw.gui.docviewer import GuiDocViewer from nw.gui.docviewer import GuiDocViewer
from nw.gui.docdetails import GuiDocDetails from nw.gui.docdetails import GuiDocDetails
from nw.gui.mainmenu import GuiMainMenu from nw.gui.mainmenu import GuiMainMenu
from nw.gui.configeditor import GuiConfigEditor
from nw.gui.projecteditor import GuiProjectEditor from nw.gui.projecteditor import GuiProjectEditor
from nw.gui.itemeditor import GuiItemEditor from nw.gui.itemeditor import GuiItemEditor
from nw.gui.statusbar import GuiMainStatus from nw.gui.statusbar import GuiMainStatus
@@ -49,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
@@ -118,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)
@@ -138,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
@@ -149,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
## ##
@@ -454,6 +460,14 @@ class GuiMain(QMainWindow):
return projPath return projPath
return None return None
def editConfigDialog(self):
dlgConf = GuiConfigEditor(self, self.theProject)
if dlgConf.exec_() == QDialog.Accepted:
logger.debug("Applying new preferences")
self.initMain()
self.docEditor.initEditor()
return True
def editProjectDialog(self): def editProjectDialog(self):
if self.hasProject: if self.hasProject:
dlgProj = GuiProjectEditor(self, self.theProject) dlgProj = GuiProjectEditor(self, self.theProject)
+12 -8
View File
@@ -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
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
/**
* Default Theme: Light
*/
QTreeView, QHeaderView {
font-size: 13px;
}
+18
View File
@@ -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
+23
View File
@@ -187,3 +187,26 @@ Start: 2019-06-08 20:30:24 End: 2019-06-08 20:42:10 Words: 9
Start: 2019-06-08 20:42:14 End: 2019-06-08 20:42:37 Words: 0 Start: 2019-06-08 20:42:14 End: 2019-06-08 20:42:37 Words: 0
Start: 2019-06-08 20:42:41 End: 2019-06-08 20:43:25 Words: 0 Start: 2019-06-08 20:42:41 End: 2019-06-08 20:43:25 Words: 0
Start: 2019-06-08 20:43:29 End: 2019-06-08 20:43:42 Words: 0 Start: 2019-06-08 20:43:29 End: 2019-06-08 20:43:42 Words: 0
Start: 2019-06-10 13:26:52 End: 2019-06-10 13:30:22 Words: 0
Start: 2019-06-10 13:30:28 End: 2019-06-10 13:31:44 Words: 0
Start: 2019-06-10 14:17:18 End: 2019-06-10 14:17:48 Words: 0
Start: 2019-06-10 14:20:17 End: 2019-06-10 14:21:11 Words: 0
Start: 2019-06-10 20:41:35 End: 2019-06-10 20:41:48 Words: 0
Start: 2019-06-10 20:42:15 End: 2019-06-10 20:42:27 Words: 0
Start: 2019-06-10 20:42:43 End: 2019-06-10 20:42:47 Words: 0
Start: 2019-06-10 20:45:02 End: 2019-06-10 20:45:07 Words: 0
Start: 2019-06-10 20:45:44 End: 2019-06-10 20:46:03 Words: 0
Start: 2019-06-10 20:46:08 End: 2019-06-10 20:47:15 Words: 0
Start: 2019-06-10 20:47:24 End: 2019-06-10 20:47:28 Words: 0
Start: 2019-06-10 20:47:46 End: 2019-06-10 20:47:59 Words: 0
Start: 2019-06-10 20:48:02 End: 2019-06-10 20:48:08 Words: 0
Start: 2019-06-10 20:57:47 End: 2019-06-10 20:58:01 Words: 0
Start: 2019-06-10 21:29:47 End: 2019-06-10 21:33:22 Words: 0
Start: 2019-06-10 21:33:26 End: 2019-06-10 21:34:59 Words: 0
Start: 2019-06-10 21:39:54 End: 2019-06-10 21:45:25 Words: 0
Start: 2019-06-10 21:45:29 End: 2019-06-10 21:47:40 Words: 0
Start: 2019-06-10 21:48:06 End: 2019-06-10 21:48:47 Words: 0
Start: 2019-06-10 21:48:51 End: 2019-06-10 21:49:07 Words: 0
Start: 2019-06-10 22:17:58 End: 2019-06-10 22:18:44 Words: 0
Start: 2019-06-10 22:46:35 End: 2019-06-10 22:49:34 Words: 0
Start: 2019-06-11 14:44:55 End: 2019-06-11 14:53:47 Words: 0
+2 -2
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-06-08 20:43:42"> <novelWriterXML appVersion="0.1.5" fileVersion="1.0" timeStamp="2019-06-11 14:46:19">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
@@ -80,7 +80,7 @@
<charCount>736</charCount> <charCount>736</charCount>
<wordCount>137</wordCount> <wordCount>137</wordCount>
<paraCount>6</paraCount> <paraCount>6</paraCount>
<cursorPos>725</cursorPos> <cursorPos>738</cursorPos>
</item> </item>
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a"> <item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
<name>New File</name> <name>New File</name>
+6 -3
View File
@@ -1,6 +1,6 @@
[Main] [Main]
timestamp = 2019-05-25 23:33:23 timestamp = 2019-06-11 18:39:59
theme = default theme = default_dark
[Sizes] [Sizes]
geometry = 1100, 650 geometry = 1100, 650
@@ -14,10 +14,11 @@ autosaveproject = 60
autosavedoc = 30 autosavedoc = 30
[Editor] [Editor]
textfont = None
textsize = 12
fixedwidth = True fixedwidth = True
width = 600 width = 600
margins = 40, 40 margins = 40, 40
textsize = 13
tabwidth = 40 tabwidth = 40
justify = True justify = True
autoselect = True autoselect = True
@@ -26,6 +27,8 @@ repsquotes = True
repdquotes = True repdquotes = True
repdash = True repdash = True
repdots = True repdots = True
fmtsinglequote = ,
fmtdoublequote = “, ”
spellcheck = en_GB spellcheck = en_GB
[Path] [Path]