Merge branch 'master' of github.com:vkbo/novelWriter

This commit is contained in:
Veronica K. B. Olsen
2019-06-15 23:33:39 +02:00
30 changed files with 680 additions and 295 deletions
+12 -5
View File
@@ -14,9 +14,11 @@ import logging
import configparser import configparser
import nw import nw
from os import path, mkdir, getcwd from os import path, mkdir, getcwd
from appdirs import user_config_dir from appdirs import user_config_dir
from datetime import datetime from datetime import datetime
from nw.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -43,6 +45,7 @@ class Config:
self.homePath = None self.homePath = None
self.appPath = None self.appPath = None
self.appRoot = None self.appRoot = None
self.appIcon = None
self.guiPath = None self.guiPath = None
self.themeRoot = None self.themeRoot = None
self.themePath = None self.themePath = None
@@ -51,7 +54,8 @@ class Config:
self.confChanged = False self.confChanged = False
## General ## General
self.guiTheme = "default_dark" self.guiTheme = "default"
self.guiSyntax = "default_light"
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]
@@ -110,6 +114,7 @@ class Config:
self.guiPath = path.join(self.appPath,"gui") self.guiPath = path.join(self.appPath,"gui")
self.themeRoot = path.join(self.appPath,"themes") self.themeRoot = path.join(self.appPath,"themes")
self.themePath = path.join(self.themeRoot) self.themePath = path.join(self.themeRoot)
self.appIcon = path.join(self.appRoot, nwFiles.APP_ICON)
# 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.
@@ -144,7 +149,8 @@ class Config:
## Main ## Main
cnfSec = "Main" cnfSec = "Main"
self.guiTheme = self._parseLine(cnfParse, cnfSec, "theme", self.CNF_STR, self.guiTheme) self.guiTheme = self._parseLine(cnfParse, cnfSec, "theme", self.CNF_STR, self.guiTheme)
self.guiSyntax = self._parseLine(cnfParse, cnfSec, "syntax", self.CNF_STR, self.guiSyntax)
## Sizes ## Sizes
cnfSec = "Sizes" cnfSec = "Sizes"
@@ -197,6 +203,7 @@ class Config:
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec,"timestamp", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) cnfParse.set(cnfSec,"timestamp", datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
cnfParse.set(cnfSec,"theme", str(self.guiTheme)) cnfParse.set(cnfSec,"theme", str(self.guiTheme))
cnfParse.set(cnfSec,"syntax", str(self.guiSyntax))
## Sizes ## Sizes
cnfSec = "Sizes" cnfSec = "Sizes"
-38
View File
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg1014"
version="1.1"
viewBox="0 0 40 40"
height="40mm"
width="40mm">
<defs
id="defs1008" />
<metadata
id="metadata1011">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-257)"
id="layer1">
<rect
y="257"
x="-1.7763568e-15"
height="40"
width="40"
id="rect1580"
style="fill:#646464;fill-opacity:0.39351851;stroke:none;stroke-width:0.18425357;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="280px"
height="279.416px"
viewBox="340 140 280 279.416"
enable-background="new 340 140 280 279.416"
xml:space="preserve"
sodipodi:docname="gear.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1013"
id="namedview5"
showgrid="false"
inkscape:zoom="0.84461882"
inkscape:cx="22.787362"
inkscape:cy="139.70799"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<path
d="M620,305.666v-51.333l-31.5-5.25c-2.333-8.75-5.833-16.917-9.917-23.917L597.25,199.5l-36.167-36.75l-26.25,18.083 c-7.583-4.083-15.75-7.583-23.916-9.917L505.667,140h-51.334l-5.25,31.5c-8.75,2.333-16.333,5.833-23.916,9.916L399.5,163.333 L362.75,199.5l18.667,25.666c-4.083,7.584-7.583,15.75-9.917,24.5l-31.5,4.667v51.333l31.5,5.25 c2.333,8.75,5.833,16.334,9.917,23.917l-18.667,26.25l36.167,36.167l26.25-18.667c7.583,4.083,15.75,7.583,24.5,9.917l5.25,30.916 h51.333l5.25-31.5c8.167-2.333,16.333-5.833,23.917-9.916l26.25,18.666l36.166-36.166l-18.666-26.25 c4.083-7.584,7.583-15.167,9.916-23.917L620,305.666z M480,333.666c-29.75,0-53.667-23.916-53.667-53.666s24.5-53.667,53.667-53.667 S533.667,250.25,533.667,280S509.75,333.666,480,333.666z"
id="path2"
style="fill:#000000;fill-opacity:0.35408559" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

-60
View File
@@ -1,60 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg1014"
version="1.1"
viewBox="0 0 40 40"
height="40mm"
width="40mm">
<defs
id="defs1008">
<linearGradient
id="linearGradient1586">
<stop
id="stop1582"
offset="0"
style="stop-color:#646464;stop-opacity:0" />
<stop
id="stop1584"
offset="1"
style="stop-color:#646464;stop-opacity:1" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0.90450234,0,0,0.53447864,-9.5726494,251.5932)"
gradientUnits="userSpaceOnUse"
y2="47.535713"
x2="54.938839"
y1="47.535713"
x1="10.451041"
id="linearGradient1588"
xlink:href="#linearGradient1586" />
</defs>
<metadata
id="metadata1011">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-257)"
id="layer1">
<rect
y="257"
x="-1.7763568e-15"
height="40"
width="40"
id="rect1580"
style="fill:url(#linearGradient1588);fill-opacity:1;stroke:none;stroke-width:0.18425357;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

+20 -7
View File
@@ -15,7 +15,7 @@ import nw
from os import path from os import path
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush, QStandardItemModel, QFont from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush, QStandardItemModel, QFont
from PyQt5.QtSvg import QSvgWidget from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
@@ -43,9 +43,9 @@ class GuiConfigEditor(QDialog):
self.setWindowTitle("Preferences") 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","gear.svg"))
self.svgGradient = QSvgWidget(self.gradPath) self.svgGradient = QSvgWidget(path.join(self.gradPath))
self.svgGradient.setFixedWidth(80) self.svgGradient.setFixedSize(QSize(64,64))
self.theProject.countStatus() self.theProject.countStatus()
self.tabMain = GuiConfigEditGeneral(self.theParent) self.tabMain = GuiConfigEditGeneral(self.theParent)
@@ -56,7 +56,7 @@ class GuiConfigEditor(QDialog):
self.tabWidget.addTab(self.tabEditor, "Editor") self.tabWidget.addTab(self.tabEditor, "Editor")
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.outerBox.addWidget(self.svgGradient) self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox) self.outerBox.addLayout(self.innerBox)
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
@@ -129,8 +129,19 @@ class GuiConfigEditGeneral(QWidget):
if themeIdx != -1: if themeIdx != -1:
self.guiLookTheme.setCurrentIndex(themeIdx) self.guiLookTheme.setCurrentIndex(themeIdx)
self.guiLookForm.addWidget(QLabel("Theme"), 0, 0) self.guiLookSyntax = QComboBox()
self.guiLookForm.addWidget(self.guiLookTheme, 0, 1) self.guiLookSyntax.setMinimumWidth(200)
self.theSyntaxes = self.theParent.theTheme.listSyntax()
for syntaxFile, syntaxName in self.theSyntaxes:
self.guiLookSyntax.addItem(syntaxName, syntaxFile)
syntaxIdx = self.guiLookSyntax.findData(self.mainConf.guiSyntax)
if syntaxIdx != -1:
self.guiLookSyntax.setCurrentIndex(syntaxIdx)
self.guiLookForm.addWidget(QLabel("Theme"), 0, 0)
self.guiLookForm.addWidget(self.guiLookTheme, 0, 1)
self.guiLookForm.addWidget(QLabel("Syntax"), 1, 0)
self.guiLookForm.addWidget(self.guiLookSyntax, 1, 1)
# Spell Checking # Spell Checking
self.spellLang = QGroupBox("Spell Checker", self) self.spellLang = QGroupBox("Spell Checker", self)
@@ -188,6 +199,7 @@ class GuiConfigEditGeneral(QWidget):
needsRestart = False needsRestart = False
guiTheme = self.guiLookTheme.currentData() guiTheme = self.guiLookTheme.currentData()
guiSyntax = self.guiLookSyntax.currentData()
spellLanguage = self.spellLangList.currentData() spellLanguage = self.spellLangList.currentData()
autoSaveDoc = self.autoSaveDoc.value() autoSaveDoc = self.autoSaveDoc.value()
autoSaveProj = self.autoSaveProj.value() autoSaveProj = self.autoSaveProj.value()
@@ -196,6 +208,7 @@ class GuiConfigEditGeneral(QWidget):
needsRestart |= self.mainConf.guiTheme != guiTheme needsRestart |= self.mainConf.guiTheme != guiTheme
self.mainConf.guiTheme = guiTheme self.mainConf.guiTheme = guiTheme
self.mainConf.guiSyntax = guiSyntax
self.mainConf.spellLanguage = spellLanguage self.mainConf.spellLanguage = spellLanguage
self.mainConf.autoSaveDoc = autoSaveDoc self.mainConf.autoSaveDoc = autoSaveDoc
self.mainConf.autoSaveProj = autoSaveProj self.mainConf.autoSaveProj = autoSaveProj
+22 -18
View File
@@ -17,7 +17,7 @@ from time import time
from PyQt5.QtCore import Qt, QTimer, QSizeF from PyQt5.QtCore import Qt, QTimer, QSizeF
from PyQt5.QtWidgets import QTextEdit, QAction, QMenu, QShortcut from PyQt5.QtWidgets import QTextEdit, QAction, QMenu, QShortcut
from PyQt5.QtGui import QTextCursor, QTextOption, QIcon, QKeySequence, QFont from PyQt5.QtGui import QTextCursor, QTextOption, QIcon, QKeySequence, QFont, QColor, QPalette
from nw.project.document import NWDoc from nw.project.document import NWDoc
from nw.gui.dochighlight import GuiDocHighlighter from nw.gui.dochighlight import GuiDocHighlighter
@@ -37,8 +37,9 @@ class GuiDocEditor(QTextEdit):
# Class Variables # Class Variables
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.theParent = theParent
self.theTheme = theParent.theTheme
self.docChanged = False self.docChanged = False
self.spellCheck = False self.spellCheck = False
self.nwDocument = NWDoc(self.theProject, self.theParent) self.nwDocument = NWDoc(self.theProject, self.theParent)
@@ -58,6 +59,7 @@ class GuiDocEditor(QTextEdit):
# Core Elements # Core Elements
self.qDocument = self.document() self.qDocument = self.document()
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.qDocument.contentsChange.connect(self._docChange) self.qDocument.contentsChange.connect(self._docChange)
if self.mainConf.spellTool == "enchant": if self.mainConf.spellTool == "enchant":
from nw.tools.spellenchant import NWSpellEnchant from nw.tools.spellenchant import NWSpellEnchant
@@ -89,7 +91,6 @@ class GuiDocEditor(QTextEdit):
self.wCounter = WordCounter(self) self.wCounter = WordCounter(self)
self.wCounter.finished.connect(self._updateCounts) self.wCounter.finished.connect(self._updateCounts)
self.clearEditor()
self.initEditor() self.initEditor()
logger.debug("DocEditor initialisation complete") logger.debug("DocEditor initialisation complete")
@@ -132,9 +133,13 @@ class GuiDocEditor(QTextEdit):
theFont.setPointSize(self.mainConf.textSize) theFont.setPointSize(self.mainConf.textSize)
self.setFont(theFont) self.setFont(theFont)
# Set text fixed width, or alternatively, just margins docPalette = self.palette()
docPalette.setColor(QPalette.Base, QColor(*self.theTheme.colBack))
docPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
self.setPalette(docPalette)
# Set default text margins
self.qDocument.setDocumentMargin(self.mainConf.textMargin) self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.changeWidth()
# Also set the document text options for the document text flow # Also set the document text options for the document text flow
theOpt = QTextOption() theOpt = QTextOption()
@@ -144,12 +149,14 @@ class GuiDocEditor(QTextEdit):
theOpt.setAlignment(Qt.AlignJustify) theOpt.setAlignment(Qt.AlignJustify)
self.qDocument.setDefaultTextOption(theOpt) self.qDocument.setDefaultTextOption(theOpt)
self.hLight.initHighlighter()
# If we have a document open, we should reload it in case the font changed # If we have a document open, we should reload it in case the font changed
if self.theHandle is not None: if self.theHandle is not None:
tHandle = self.theHandle tHandle = self.theHandle
self.hLight.initHighlighter()
self.clearEditor() self.clearEditor()
self.loadText(tHandle) self.loadText(tHandle)
self.changeWidth()
return True return True
@@ -220,18 +227,14 @@ class GuiDocEditor(QTextEdit):
def setSpellCheck(self, theMode): def setSpellCheck(self, theMode):
self.spellCheck = theMode self.spellCheck = theMode
self.hLight.setSpellCheck(theMode) self.hLight.setSpellCheck(theMode)
self.rehighlightDocument() self.hLight.rehighlight()
return True return True
def updateSpellCheck(self): def updateSpellCheck(self):
if self.spellCheck: if self.spellCheck:
self.rehighlightDocument() self.hLight.rehighlight()
return True return True
def rehighlightDocument(self):
self.hLight.rehighlight()
return
## ##
# General Class Methods # General Class Methods
## ##
@@ -251,11 +254,11 @@ class GuiDocEditor(QTextEdit):
tM = int((wW - sW - tW)/2) tM = int((wW - sW - tW)/2)
if tM < 0: if tM < 0:
tM = 0 tM = 0
# print(wW, tW, dW, sW, tM) docFormat = self.qDocument.rootFrame().frameFormat()
self.setViewportMargins(tM,0,tM,0) docFormat.setLeftMargin(tM)
self.qDocument.setTextWidth(tW) docFormat.setRightMargin(tM)
else: self.qDocument.rootFrame().setFrameFormat(docFormat)
self.setViewportMargins(0,0,0,0)
return return
def docAction(self, theAction): def docAction(self, theAction):
@@ -359,7 +362,8 @@ class GuiDocEditor(QTextEdit):
def _docChange(self, thePos, charsRemoved, charsAdded): def _docChange(self, thePos, charsRemoved, charsAdded):
self.lastEdit = time() self.lastEdit = time()
self.setDocumentChanged(True) if not self.docChanged:
self.setDocumentChanged(True)
if not self.wcTimer.isActive(): if not self.wcTimer.isActive():
self.wcTimer.start() self.wcTimer.start()
if self.mainConf.doReplace and not self.hasSelection: if self.mainConf.doReplace and not self.hasSelection:
+28 -12
View File
@@ -36,18 +36,18 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.hRules = [] self.hRules = []
self.hStyles = {} self.hStyles = {}
self.colHead = QColor(*self.theTheme.colHead) self.colHead = QColor(0,0,0)
self.colHeadH = QColor(*self.theTheme.colHeadH) self.colHeadH = QColor(0,0,0)
self.colEmph = QColor(*self.theTheme.colEmph) self.colEmph = QColor(0,0,0)
self.colDialN = QColor(*self.theTheme.colDialN) self.colDialN = QColor(0,0,0)
self.colDialD = QColor(*self.theTheme.colDialD) self.colDialD = QColor(0,0,0)
self.colDialS = QColor(*self.theTheme.colDialS) self.colDialS = QColor(0,0,0)
self.colComm = QColor(*self.theTheme.colComm) self.colComm = QColor(0,0,0)
self.colKey = QColor(*self.theTheme.colKey) self.colKey = QColor(0,0,0)
self.colVal = QColor(*self.theTheme.colVal) self.colVal = QColor(0,0,0)
self.colSpell = QColor(*self.theTheme.colSpell) self.colSpell = QColor(0,0,0)
self.colTagErr = QColor(*self.theTheme.colTagErr) self.colTagErr = QColor(0,0,0)
self.colRepTag = QColor(*self.theTheme.colRepTag) self.colRepTag = QColor(0,0,0)
self.initHighlighter() self.initHighlighter()
@@ -57,6 +57,21 @@ class GuiDocHighlighter(QSyntaxHighlighter):
def initHighlighter(self): def initHighlighter(self):
logger.debug("Setting up highlighting rules")
self.colHead = QColor(*self.theTheme.colHead)
self.colHeadH = QColor(*self.theTheme.colHeadH)
self.colEmph = QColor(*self.theTheme.colEmph)
self.colDialN = QColor(*self.theTheme.colDialN)
self.colDialD = QColor(*self.theTheme.colDialD)
self.colDialS = QColor(*self.theTheme.colDialS)
self.colComm = QColor(*self.theTheme.colComm)
self.colKey = QColor(*self.theTheme.colKey)
self.colVal = QColor(*self.theTheme.colVal)
self.colSpell = QColor(*self.theTheme.colSpell)
self.colTagErr = QColor(*self.theTheme.colTagErr)
self.colRepTag = QColor(*self.theTheme.colRepTag)
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),
@@ -80,6 +95,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
} }
# Headers # Headers
self.hRules = []
self.hRules.append(( self.hRules.append((
r"^(#{1}) (.*)[^\n]", { r"^(#{1}) (.*)[^\n]", {
0 : self.hStyles["header1"], 0 : self.hStyles["header1"],
+1 -1
View File
@@ -360,7 +360,7 @@ class GuiDocTree(QTreeWidget):
newItem.setText(self.C_FLAGS, "") newItem.setText(self.C_FLAGS, "")
newItem.setText(self.C_HANDLE, tHandle) newItem.setText(self.C_HANDLE, tHandle)
newItem.setForeground(self.C_COUNT,QColor(0,105,135)) # newItem.setForeground(self.C_COUNT,QColor(*self.theParent.theTheme.treeWCount))
newItem.setTextAlignment(self.C_COUNT,Qt.AlignRight) newItem.setTextAlignment(self.C_COUNT,Qt.AlignRight)
newItem.setFont(self.C_FLAGS,self.fontFlags) newItem.setFont(self.C_FLAGS,self.fontFlags)
+65 -49
View File
@@ -15,7 +15,7 @@ import nw
from PyQt5.QtCore import Qt, QUrl from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtWidgets import QTextBrowser from PyQt5.QtWidgets import QTextBrowser
from PyQt5.QtGui import QTextOption, QFont from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor
from nw.convert.tokenizer import Tokenizer from nw.convert.tokenizer import Tokenizer
from nw.convert.tohtml import ToHtml from nw.convert.tohtml import ToHtml
@@ -37,57 +37,14 @@ class GuiDocViewer(QTextBrowser):
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theHandle = None self.theHandle = None
self.theQDoc = self.document() self.qDocument = self.document()
self.theQDoc.setDefaultStyleSheet((
"body {{"
" font-size: {textSize}pt;"
" color: rgb({tColR},{tColG},{tColB});"
"}}\n"
"h1, h2, h3, h4 {{"
" color: rgb({hColR},{hColG},{hColB});"
"}}\n"
"a {{"
" color: rgb({aColR},{aColG},{aColB});"
"}}\n"
"pre {{"
" color: rgb({cColR},{cColG},{cColB});"
" font-size: {preSize}pt;"
"}}\n"
"mark {{"
" color: rgb({eColR},{eColG},{eColB});"
"}}\n"
"table {{"
" margin: 10px 0px;"
"}}\n"
"td {{"
" padding: 0px 4px;"
"}}\n"
).format(
textSize = self.mainConf.textSize,
preSize = self.mainConf.textSize*0.9,
tColR = self.theTheme.colText[0],
tColG = self.theTheme.colText[1],
tColB = self.theTheme.colText[2],
hColR = self.theTheme.colHead[0],
hColG = self.theTheme.colHead[1],
hColB = self.theTheme.colHead[2],
cColR = self.theTheme.colComm[0],
cColG = self.theTheme.colComm[1],
cColB = self.theTheme.colComm[2],
eColR = self.theTheme.colEmph[0],
eColG = self.theTheme.colEmph[1],
eColB = self.theTheme.colEmph[2],
aColR = self.theTheme.colLink[0],
aColG = self.theTheme.colLink[1],
aColB = self.theTheme.colLink[2],
))
self.setMinimumWidth(300) self.setMinimumWidth(300)
self.initViewer() self.initViewer()
theOpt = QTextOption() theOpt = QTextOption()
if self.mainConf.doJustify: if self.mainConf.doJustify:
theOpt.setAlignment(Qt.AlignJustify) theOpt.setAlignment(Qt.AlignJustify)
self.theQDoc.setDefaultTextOption(theOpt) self.qDocument.setDefaultTextOption(theOpt)
logger.debug("DocViewer initialisation complete") logger.debug("DocViewer initialisation complete")
@@ -102,20 +59,27 @@ class GuiDocViewer(QTextBrowser):
"""Set editor settings from main config. """Set editor settings from main config.
""" """
self._makeStyleSheet()
# Set Font # Set Font
theFont = QFont() theFont = QFont()
if self.mainConf.textFont is None: if self.mainConf.textFont is None:
# If none is defined, set the default back to config # If none is defined, set the default back to config
self.mainConf.textFont = self.theQDoc.defaultFont().family() self.mainConf.textFont = self.qDocument.defaultFont().family()
theFont.setFamily(self.mainConf.textFont) theFont.setFamily(self.mainConf.textFont)
theFont.setPointSize(self.mainConf.textSize) theFont.setPointSize(self.mainConf.textSize)
self.setFont(theFont) self.setFont(theFont)
self.theQDoc.setDocumentMargin(self.mainConf.textMargin) docPalette = self.palette()
docPalette.setColor(QPalette.Base, QColor(*self.theTheme.colBack))
docPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
self.setPalette(docPalette)
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
theOpt = QTextOption() theOpt = QTextOption()
if self.mainConf.doJustify: if self.mainConf.doJustify:
theOpt.setAlignment(Qt.AlignJustify) theOpt.setAlignment(Qt.AlignJustify)
self.theQDoc.setDefaultTextOption(theOpt) self.qDocument.setDefaultTextOption(theOpt)
# If we have a document open, we should reload it in case the font changed # If we have a document open, we should reload it in case the font changed
if self.theHandle is not None: if self.theHandle is not None:
@@ -162,4 +126,56 @@ class GuiDocViewer(QTextBrowser):
return True return True
##
# Internal Functions
##
def _makeStyleSheet(self):
self.qDocument.setDefaultStyleSheet((
"body {{"
" font-size: {textSize}pt;"
" color: rgb({tColR},{tColG},{tColB});"
"}}\n"
"h1, h2, h3, h4 {{"
" color: rgb({hColR},{hColG},{hColB});"
"}}\n"
"a {{"
" color: rgb({aColR},{aColG},{aColB});"
"}}\n"
"pre {{"
" color: rgb({cColR},{cColG},{cColB});"
" font-size: {preSize}pt;"
"}}\n"
"mark {{"
" color: rgb({eColR},{eColG},{eColB});"
"}}\n"
"table {{"
" margin: 10px 0px;"
"}}\n"
"td {{"
" padding: 0px 4px;"
"}}\n"
).format(
textSize = self.mainConf.textSize,
preSize = self.mainConf.textSize*0.9,
tColR = self.theTheme.colText[0],
tColG = self.theTheme.colText[1],
tColB = self.theTheme.colText[2],
hColR = self.theTheme.colHead[0],
hColG = self.theTheme.colHead[1],
hColB = self.theTheme.colHead[2],
cColR = self.theTheme.colComm[0],
cColG = self.theTheme.colComm[1],
cColB = self.theTheme.colComm[2],
eColR = self.theTheme.colEmph[0],
eColG = self.theTheme.colEmph[1],
eColB = self.theTheme.colEmph[2],
aColR = self.theTheme.colLink[0],
aColG = self.theTheme.colLink[1],
aColB = self.theTheme.colLink[2],
))
return True
# END Class GuiDocViewer # END Class GuiDocViewer
+5 -3
View File
@@ -15,6 +15,7 @@ import nw
from os import path from os import path
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit, QPushButton, QComboBox from PyQt5.QtWidgets import QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit, QPushButton, QComboBox
from PyQt5.QtSvg import QSvgWidget from PyQt5.QtSvg import QSvgWidget
@@ -40,11 +41,12 @@ class GuiItemEditor(QDialog):
self.setWindowTitle("Item Settings") self.setWindowTitle("Item Settings")
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","block.svg")) self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","gear.svg"))
self.svgGradient = QSvgWidget(self.gradPath) self.svgGradient = QSvgWidget(self.gradPath)
self.svgGradient.setFixedWidth(80) self.svgGradient.setFixedSize(QSize(64,64))
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.outerBox.addWidget(self.svgGradient) self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox) self.outerBox.addLayout(self.innerBox)
self.mainGroup = QGroupBox("Item Settings") self.mainGroup = QGroupBox("Item Settings")
+19 -4
View File
@@ -104,8 +104,8 @@ class GuiMainMenu(QMenuBar):
return True return True
def _showAbout(self): def _showAbout(self):
msgBox = QMessageBox() listPrefix = "&nbsp;&nbsp;&bull;&nbsp;&nbsp;"
msgBox.about(self.theParent, "About %s" % nw.__package__, ( aboutMsg = (
"<h3>About {name:s}</h3>" "<h3>About {name:s}</h3>"
"<p>Version: {version:s}<br>Release Date: {date:s}</p>" "<p>Version: {version:s}<br>Release Date: {date:s}</p>"
"<p>{name:s} is a markdown-like text editor designed for organising and writing novels. " "<p>{name:s} is a markdown-like text editor designed for organising and writing novels. "
@@ -121,8 +121,23 @@ class GuiMainMenu(QMenuBar):
date = nw.__date__, date = nw.__date__,
copyright = nw.__copyright__, copyright = nw.__copyright__,
website = nw.__url__, website = nw.__url__,
credits = "".join(["&nbsp;&nbsp;&bull;&nbsp;&nbsp;%s<br/>" % x for x in nw.__credits__]), credits = "<br/>".join(["%s%s" % (listPrefix, x) for x in nw.__credits__]),
)) )
theTheme = self.theParent.theTheme
if theTheme.themeCredit != "" or theTheme.syntaxCredit != "":
aboutMsg += "<h4>GUI Theme and Syntax Highlighting</h4>"
aboutMsg += "<p>"
if theTheme.themeCredit != "":
aboutMsg += "%s%s by %s<br/>" % (
listPrefix, theTheme.themeName, theTheme.themeCredit
)
if theTheme.syntaxCredit != "":
aboutMsg += "%s%s by %s<br/>" % (
listPrefix, theTheme.syntaxName, theTheme.syntaxCredit
)
aboutMsg += "</p>"
msgBox = QMessageBox()
msgBox.about(self.theParent, "About %s" % nw.__package__, aboutMsg)
return True return True
def _showAboutQt(self): def _showAboutQt(self):
+6 -6
View File
@@ -15,7 +15,7 @@ import nw
from os import path from os import path
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush, QStandardItemModel 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 (
@@ -37,14 +37,15 @@ class GuiProjectEditor(QDialog):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.outerBox = QHBoxLayout() self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout() self.innerBox = QVBoxLayout()
self.setWindowTitle("Project Settings") self.setWindowTitle("Project Settings")
self.setLayout(self.outerBox)
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","block.svg")) self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","gear.svg"))
self.svgGradient = QSvgWidget(self.gradPath) self.svgGradient = QSvgWidget(self.gradPath)
self.svgGradient.setFixedWidth(80) self.svgGradient.setFixedSize(QSize(64,64))
self.theProject.countStatus() self.theProject.countStatus()
self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) self.tabMain = GuiProjectEditMain(self.theParent, self.theProject)
@@ -58,8 +59,7 @@ class GuiProjectEditor(QDialog):
self.tabWidget.addTab(self.tabImport, "Importance") self.tabWidget.addTab(self.tabImport, "Importance")
self.tabWidget.addTab(self.tabReplace,"Auto-Replace") self.tabWidget.addTab(self.tabReplace,"Auto-Replace")
self.setLayout(self.outerBox) self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
self.outerBox.addWidget(self.svgGradient)
self.outerBox.addLayout(self.innerBox) self.outerBox.addLayout(self.innerBox)
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
+7 -5
View File
@@ -27,15 +27,17 @@ class GuiMainStatus(QStatusBar):
logger.debug("Initialising GuiMainStatus ...") logger.debug("Initialising GuiMainStatus ...")
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.refTime = None self.theParent = theParent
self.refTime = None
self.iconGrey = QPixmap(16,16) self.iconGrey = QPixmap(16,16)
self.iconGrey.fill(QColor(120,120,120))
self.iconYellow = QPixmap(16,16) self.iconYellow = QPixmap(16,16)
self.iconYellow.fill(QColor(120,120, 40))
self.iconGreen = QPixmap(16,16) self.iconGreen = QPixmap(16,16)
self.iconGreen.fill(QColor( 40,120, 0))
self.iconGrey.fill(QColor(*self.theParent.theTheme.statNone))
self.iconYellow.fill(QColor(*self.theParent.theTheme.statUnsaved))
self.iconGreen.fill(QColor(*self.theParent.theTheme.statSaved))
self.boxStats = QLabel() self.boxStats = QLabel()
self.boxStats.setToolTip("Project Word Count | Session Word Count") self.boxStats.setToolTip("Project Word Count | Session Word Count")
+4 -5
View File
@@ -48,6 +48,7 @@ class GuiMain(QMainWindow):
def __init__(self): def __init__(self):
QWidget.__init__(self) QWidget.__init__(self)
logger.info("Starting %s" % nw.__package__)
logger.debug("Initialising GUI ...") logger.debug("Initialising GUI ...")
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theTheme = Theme(self) self.theTheme = Theme(self)
@@ -57,8 +58,7 @@ class GuiMain(QMainWindow):
self.resize(*self.mainConf.winGeometry) self.resize(*self.mainConf.winGeometry)
self._setWindowTitle() self._setWindowTitle()
self.setWindowIcon(QIcon(path.join(self.mainConf.appRoot, nwFiles.APP_ICON))) self.setWindowIcon(QIcon(path.join(self.mainConf.appIcon)))
self.theTheme.loadTheme()
# Main GUI Elements # Main GUI Elements
self.statusBar = GuiMainStatus(self) self.statusBar = GuiMainStatus(self)
@@ -114,9 +114,6 @@ class GuiMain(QMainWindow):
self.setStatusBar(self.statusBar) self.setStatusBar(self.statusBar)
self.statusBar.showMessage("Ready") self.statusBar.showMessage("Ready")
# Load Theme StyleSheet
self.setStyleSheet(self.theTheme.cssData)
# Set Up Autosaving Project Timer # Set Up Autosaving Project Timer
self.asProjTimer = QTimer() self.asProjTimer = QTimer()
self.asProjTimer.timeout.connect(self._autoSaveProject) self.asProjTimer.timeout.connect(self._autoSaveProject)
@@ -138,6 +135,7 @@ class GuiMain(QMainWindow):
self.initMain() self.initMain()
self.asProjTimer.start() self.asProjTimer.start()
self.asDocTimer.start() self.asDocTimer.start()
self.statusBar.clearStatus()
logger.debug("GUI initialisation complete") logger.debug("GUI initialisation complete")
@@ -467,6 +465,7 @@ class GuiMain(QMainWindow):
if dlgConf.exec_() == QDialog.Accepted: if dlgConf.exec_() == QDialog.Accepted:
logger.debug("Applying new preferences") logger.debug("Applying new preferences")
self.initMain() self.initMain()
self.theTheme.updateTheme()
self.docEditor.initEditor() self.docEditor.initEditor()
self.docViewer.initViewer() self.docViewer.initViewer()
return True return True
+175 -38
View File
@@ -16,6 +16,9 @@ import nw
from os import path, listdir from os import path, listdir
from PyQt5.QtWidgets import qApp
from PyQt5.QtGui import QPalette, QColor
from nw.enum import nwAlert from nw.enum import nwAlert
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -24,39 +27,60 @@ class Theme:
def __init__(self, theParent): def __init__(self, theParent):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theParent = theParent self.theParent = theParent
self.cssName = "styles.css" self.guiPalette = QPalette()
self.confName = "theme.conf" self.guiPath = "gui"
self.themeList = [] self.syntaxPath = "syntax"
self.cssName = "style.qss"
self.confName = "theme.conf"
self.themeList = []
self.syntaxList = []
# Loaded Theme Settings # Loaded Theme Settings
## Main ## Theme
self.themeName = "No Name" self.themeName = ""
self.themeAuthor = ""
self.themeCredit = ""
self.themeUrl = ""
## Syntax ## GUI
self.colText = [0,0,0] self.treeWCount = [ 0, 0, 0]
self.colLink = [0,0,0] self.statNone = [120,120,120]
self.colHead = [0,0,0] self.statUnsaved = [120,120, 40]
self.colHeadH = [0,0,0] self.statSaved = [ 40,120, 0]
self.colEmph = [0,0,0]
self.colDialN = [0,0,0] # Loaded Syntax Settings
self.colDialD = [0,0,0]
self.colDialS = [0,0,0] ## Main
self.colComm = [0,0,0] self.syntaxName = ""
self.colKey = [0,0,0] self.syntaxAuthor = ""
self.colVal = [0,0,0] self.syntaxCredit = ""
self.colSpell = [0,0,0] self.syntaxUrl = ""
self.colTagErr = [0,0,0]
self.colRepTag = [0,0,0] ## Colours
self.colBack = [255,255,255]
self.colText = [ 0, 0, 0]
self.colLink = [ 0, 0, 0]
self.colHead = [ 0, 0, 0]
self.colHeadH = [ 0, 0, 0]
self.colEmph = [ 0, 0, 0]
self.colDialN = [ 0, 0, 0]
self.colDialD = [ 0, 0, 0]
self.colDialS = [ 0, 0, 0]
self.colComm = [ 0, 0, 0]
self.colKey = [ 0, 0, 0]
self.colVal = [ 0, 0, 0]
self.colSpell = [ 0, 0, 0]
self.colTagErr = [ 0, 0, 0]
self.colRepTag = [ 0, 0, 0]
# Changeable Settings # Changeable Settings
self.guiTheme = None self.guiTheme = None
self.themePath = None self.guiSyntax = None
self.confFile = None self.themeRoot = None
self.cssFile = None self.cssFile = None
self.cssData = ""
self.updateTheme() self.updateTheme()
@@ -67,10 +91,18 @@ class Theme:
## ##
def updateTheme(self): def updateTheme(self):
self.guiTheme = self.mainConf.guiTheme
self.themePath = path.join(self.mainConf.themePath, self.guiTheme) self.guiTheme = self.mainConf.guiTheme
self.confFile = path.join(self.themePath,self.confName) self.guiSyntax = self.mainConf.guiSyntax
self.cssFile = path.join(self.themePath,self.cssName) self.themeRoot = self.mainConf.themeRoot
self.themePath = path.join(self.mainConf.themeRoot, self.guiPath, self.guiTheme)
self.syntaxFile = path.join(self.themeRoot,self.syntaxPath,self.guiSyntax+".conf")
self.confFile = path.join(self.themePath,self.confName)
self.cssFile = path.join(self.themePath,self.cssName)
self.loadTheme()
self.loadSyntax()
return True return True
def loadTheme(self): def loadTheme(self):
@@ -78,30 +110,82 @@ class Theme:
logger.debug("Loading theme files") logger.debug("Loading theme files")
# CSS File # CSS File
cssData = ""
try: try:
if path.isfile(self.cssFile): if path.isfile(self.cssFile):
with open(self.cssFile,mode="r") as inFile: with open(self.cssFile,mode="r") as inFile:
self.cssData = inFile.read() cssData = inFile.read()
except Exception as e: except Exception as e:
logger.error("Could not load theme css file") logger.error("Could not load theme css file")
return False return False
# Color Config # Config File
confParser = configparser.ConfigParser() confParser = configparser.ConfigParser()
try: try:
confParser.read_file(open(self.confFile)) confParser.read_file(open(self.confFile))
except Exception as e: except Exception as e:
logger.error("Could not load theme config file") logger.error("Could not load theme settings from: %s" % self.confFile)
return False return False
## Main ## Main
cnfSec = "Main" cnfSec = "Main"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.themeName = confParser.get(cnfSec,"name") self.themeName = self._parseLine(confParser,cnfSec,"name", "")
self.themeAuthor = self._parseLine(confParser,cnfSec,"author","")
self.themeCredit = self._parseLine(confParser,cnfSec,"credit","")
self.themeUrl = self._parseLine(confParser,cnfSec,"url", "")
## Palette
cnfSec = "Palette"
if confParser.has_section(cnfSec):
self._setPalette(confParser,cnfSec,"window", QPalette.Window)
self._setPalette(confParser,cnfSec,"windowtext", QPalette.WindowText)
self._setPalette(confParser,cnfSec,"base", QPalette.Base)
self._setPalette(confParser,cnfSec,"alternatebase",QPalette.AlternateBase)
self._setPalette(confParser,cnfSec,"text", QPalette.Text)
self._setPalette(confParser,cnfSec,"tooltipbase", QPalette.ToolTipBase)
self._setPalette(confParser,cnfSec,"tooltiptext", QPalette.ToolTipText)
self._setPalette(confParser,cnfSec,"button", QPalette.Button)
self._setPalette(confParser,cnfSec,"buttontext", QPalette.ButtonText)
self._setPalette(confParser,cnfSec,"brighttext", QPalette.BrightText)
## GUI
cnfSec = "GUI"
if confParser.has_section(cnfSec):
self.treeWCount = self._loadColour(confParser,cnfSec,"treewordcount")
self.statNone = self._loadColour(confParser,cnfSec,"statusnone")
self.statUnsaved = self._loadColour(confParser,cnfSec,"statusunsaved")
self.statSaved = self._loadColour(confParser,cnfSec,"statussaved")
# Apply Styles
qApp.setStyleSheet(cssData)
qApp.setPalette(self.guiPalette)
logger.info("Loaded theme '%s'" % self.guiTheme)
return True
def loadSyntax(self):
confParser = configparser.ConfigParser()
try:
confParser.read_file(open(self.syntaxFile))
except Exception as e:
logger.error("Could not load syntax colours from: %s" % self.syntaxFile)
return False
## Main
cnfSec = "Main"
if confParser.has_section(cnfSec):
self.syntaxName = self._parseLine(confParser,cnfSec,"name","")
self.syntaxAuthor = self._parseLine(confParser,cnfSec,"author","")
self.syntaxCredit = self._parseLine(confParser,cnfSec,"credit","")
self.syntaxUrl = self._parseLine(confParser,cnfSec,"url", "")
## Syntax ## Syntax
cnfSec = "Syntax" cnfSec = "Syntax"
if confParser.has_section(cnfSec): if confParser.has_section(cnfSec):
self.colBack = self._loadColour(confParser,cnfSec,"background")
self.colText = self._loadColour(confParser,cnfSec,"text") self.colText = self._loadColour(confParser,cnfSec,"text")
self.colLink = self._loadColour(confParser,cnfSec,"link") self.colLink = self._loadColour(confParser,cnfSec,"link")
self.colHead = self._loadColour(confParser,cnfSec,"headertext") self.colHead = self._loadColour(confParser,cnfSec,"headertext")
@@ -117,6 +201,8 @@ class Theme:
self.colTagErr = self._loadColour(confParser,cnfSec,"tagerror") self.colTagErr = self._loadColour(confParser,cnfSec,"tagerror")
self.colRepTag = self._loadColour(confParser,cnfSec,"replacetag") self.colRepTag = self._loadColour(confParser,cnfSec,"replacetag")
logger.info("Loaded syntax theme '%s'" % self.guiSyntax)
return True return True
def listThemes(self): def listThemes(self):
@@ -125,14 +211,14 @@ class Theme:
return self.themeList return self.themeList
confParser = configparser.ConfigParser() confParser = configparser.ConfigParser()
for themeDir in listdir(self.mainConf.themeRoot): for themeDir in listdir(path.join(self.mainConf.themeRoot, self.guiPath)):
themeConf = path.join(self.mainConf.themeRoot, themeDir, self.confName) themeConf = path.join(self.mainConf.themeRoot, self.guiPath, themeDir, self.confName)
logger.verbose("Checking theme config for '%s'" % themeDir) logger.verbose("Checking theme config for '%s'" % themeDir)
try: try:
confParser.read_file(open(themeConf)) confParser.read_file(open(themeConf))
except Exception as e: except Exception as e:
self.theParent.makeAlert(["Could not load theme config file",str(e)],nwAlert.ERROR) self.theParent.makeAlert(["Could not load theme config file",str(e)],nwAlert.ERROR)
return [] continue
themeName = "" themeName = ""
if confParser.has_section("Main"): if confParser.has_section("Main"):
themeName = confParser.get("Main","name") themeName = confParser.get("Main","name")
@@ -140,8 +226,38 @@ class Theme:
if themeName != "": if themeName != "":
self.themeList.append((themeDir, themeName)) self.themeList.append((themeDir, themeName))
self.themeList = sorted(self.themeList, key=lambda x: x[1])
return self.themeList return self.themeList
def listSyntax(self):
if len(self.syntaxList) > 0:
return self.syntaxList
confParser = configparser.ConfigParser()
syntaxDir = path.join(self.mainConf.themeRoot, self.syntaxPath)
for syntaxFile in listdir(syntaxDir):
syntaxPath = path.join(syntaxDir, syntaxFile)
if not path.isfile(syntaxPath):
continue
logger.verbose("Checking theme syntax for '%s'" % syntaxFile)
try:
confParser.read_file(open(syntaxPath))
except Exception as e:
self.theParent.makeAlert(["Could not load syntax file",str(e)],nwAlert.ERROR)
return []
syntaxName = ""
if confParser.has_section("Main"):
syntaxName = confParser.get("Main","name")
if len(syntaxFile) > 5 and syntaxName != "":
self.syntaxList.append((syntaxFile[:-5], syntaxName))
logger.verbose("Syntax name is '%s'" % syntaxName)
self.syntaxList = sorted(self.syntaxList, key=lambda x: x[1])
return self.syntaxList
## ##
# Internal Functions # Internal Functions
## ##
@@ -162,4 +278,25 @@ class Theme:
outData = [0,0,0] outData = [0,0,0]
return outData return outData
def _setPalette(self, confParser, cnfSec, cnfName, paletteVal):
if confParser.has_option(cnfSec,cnfName):
inData = confParser.get(cnfSec,cnfName).split(",")
readCol = []
try:
readCol.append(int(inData[0]))
readCol.append(int(inData[1]))
readCol.append(int(inData[2]))
except:
logger.error("Could not load theme colours for '%s' from config file" % cnfName)
return
if len(readCol) == 3:
self.guiPalette.setColor(paletteVal, QColor(*readCol))
return
def _parseLine(self, confParser, cnfSec, cnfName, cnfDefault):
if confParser.has_section(cnfSec):
if confParser.has_option(cnfSec, cnfName):
return confParser.get(cnfSec, cnfName)
return cnfDefault
# End Class Theme # End Class Theme
-21
View File
@@ -1,21 +0,0 @@
/**
* Default Theme: Dark
*/
* {
background-color: #999999;
}
QTextEdit {
background-color: #141414;
color: #c7cfd0;
}
QTextBrowser {
background-color: #141414;
color: #c7cfd0;
}
QTreeView, QHeaderView {
font-size: 13px;
}
-18
View File
@@ -1,18 +0,0 @@
[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
+2
View File
@@ -0,0 +1,2 @@
[Main]
name = Default System Theme
+7
View File
@@ -0,0 +1,7 @@
/**
* Default Theme: Dark
*/
QTreeView, QHeaderView {
font-size: 13px;
}
+23
View File
@@ -0,0 +1,23 @@
[Main]
name = Default Dark Theme
author = Veronica Berglyd Olsen
credit = Veronica Berglyd Olsen
url = https://github.com/vkbo/novelWriter
[Palette]
window = 54, 54, 54
windowtext = 174, 174, 174
base = 62, 62, 62
alternatebase = 67, 67, 67
text = 174, 174, 174
tooltipbase = 255, 255, 192
tooltiptext = 21, 21, 13
button = 62, 62, 62
buttontext = 174, 174, 174
brighttext = 174, 174, 174
[GUI]
treewordcount = 197, 200, 198
statusnone = 150, 152, 150
statussaved = 39, 135, 78
statusunsaved = 138, 32, 32
@@ -2,6 +2,7 @@
name = Default Dark name = Default Dark
[Syntax] [Syntax]
background = 54, 54, 54
text = 199, 207, 208 text = 199, 207, 208
link = 184, 200, 0 link = 184, 200, 0
headertext = 0, 155, 200 headertext = 0, 155, 200
+19
View File
@@ -0,0 +1,19 @@
[Main]
name = Default Light
[Syntax]
background = 255, 255, 255
text = 0, 0, 0
link = 0, 0, 200
headertext = 0, 100, 00
headertag = 50, 100, 50
emphasis = 150, 110, 30
straightquotes = 200, 0, 0
doublequotes = 0, 0, 200
singlequotes = 0, 0, 200
hidden = 100, 100, 100
keyword = 200, 50, 50
value = 50, 150, 50
spellcheckline = 200, 0, 0
tagerror = 0, 150, 0
replacetag = 0, 150, 0
+42
View File
@@ -0,0 +1,42 @@
##
# Theme: Tomorrow
# Source: https://github.com/chriskempson/tomorrow-theme
# Credit: Chris Kempson
##
# Colours:
# Background = 2d2d2d : 45, 45, 45
# Current Line = 393939 : 57, 57, 57
# Selection = 515151 : 81, 81, 81
# Foreground = cccccc : 204, 204, 204
# Comment = 999999 : 153, 153, 153
# Red = f2777a : 242, 119, 122
# Orange = f99157 : 249, 145, 57
# Yellow = ffcc66 : 255, 204, 102
# Green = 99cc99 : 153, 204, 153
# Aqua = 66cccc : 102, 204, 204
# Blue = 6699cc : 102, 153, 204
# Purple = cc99cc : 204, 153, 204
##
[Main]
name = Tomorrow
author = Veronica Berglyd Olsen
credit = Chris Kempson
url = https://github.com/chriskempson/tomorrow-theme
[Syntax]
background = 45, 45, 45
text = 204, 204, 204
link = 102, 153, 204
headertext = 102, 153, 204
headertag = 102, 153, 204
emphasis = 249, 145, 57
straightquotes = 242, 119, 122
doublequotes = 153, 204, 153
singlequotes = 255, 204, 102
hidden = 153, 153, 153
keyword = 242, 119, 122
value = 204, 153, 204
spellcheckline = 242, 119, 122
tagerror = 153, 204, 153
replacetag = 102, 204, 204
+42
View File
@@ -0,0 +1,42 @@
##
# Theme: Tomorrow Night
# Source: https://github.com/chriskempson/tomorrow-theme
# Credit: Chris Kempson
##
# Colours:
# Background = 1d1f21 : 29, 31, 33
# Current Line = 282a2e : 40, 42, 46
# Selection = 373b41 : 55, 59. 65
# Foreground = c5c8c6 : 197, 200, 198
# Comment = 969896 : 150, 152, 150
# Red = cc6666 : 204, 102, 102
# Orange = de935f : 222, 147, 95
# Yellow = f0c674 : 240, 198, 116
# Green = b5bd68 : 181, 189, 104
# Aqua = 8abeb7 : 138, 190, 183
# Blue = 81a2be : 129, 162, 190
# Purple = b294bb : 178, 148, 187
##
[Main]
name = Tomorrow Night
author = Veronica Berglyd Olsen
credit = Chris Kempson
url = https://github.com/chriskempson/tomorrow-theme
[Syntax]
background = 29, 31, 33
text = 197, 200, 198
link = 129, 162, 190
headertext = 129, 162, 190
headertag = 129, 162, 190
emphasis = 222, 147, 95
straightquotes = 204, 102, 102
doublequotes = 181, 189, 104
singlequotes = 240, 198, 116
hidden = 150, 152, 150
keyword = 204, 102, 102
value = 178, 148, 187
spellcheckline = 204, 102, 102
tagerror = 181, 189, 104
replacetag = 138, 190, 183
+42
View File
@@ -0,0 +1,42 @@
##
# Theme: Tomorrow Night Blue
# Source: https://github.com/chriskempson/tomorrow-theme
# Credit: Chris Kempson
##
# Colours:
# Background = 002451 : 0, 36, 81
# Current Line = 00346e : 0, 52, 110
# Selection = 003f8e : 0, 63, 142
# Foreground = ffffff : 255, 255, 255
# Comment = 7285b7 : 114, 133, 183
# Red = ff9da4 : 255, 157, 164
# Orange = ffc58f : 255, 197, 143
# Yellow = ffeead : 255, 238, 173
# Green = d1f1a9 : 209, 241, 169
# Aqua = 99ffff : 153, 255, 255
# Blue = bbdaff : 187, 218, 255
# Purple = ebbbff : 235, 187, 255
##
[Main]
name = Tomorrow Night Blue
author = Veronica Berglyd Olsen
credit = Chris Kempson
url = https://github.com/chriskempson/tomorrow-theme
[Syntax]
background = 0, 36, 81
text = 255, 255, 255
link = 187, 218, 255
headertext = 187, 218, 255
headertag = 187, 218, 255
emphasis = 255, 197, 143
straightquotes = 255, 157, 164
doublequotes = 209, 241, 169
singlequotes = 255, 238, 173
hidden = 114, 133, 183
keyword = 255, 157, 164
value = 235, 187, 255
spellcheckline = 255, 157, 164
tagerror = 209, 241, 169
replacetag = 153, 255, 255
@@ -0,0 +1,42 @@
##
# Theme: Tomorrow Night Bright
# Source: https://github.com/chriskempson/tomorrow-theme
# Credit: Chris Kempson
##
# Colours:
# Background = 000000 : 0, 0, 0
# Current Line = 2a2a2a : 42, 42, 42
# Selection = 424242 : 66, 66, 66
# Foreground = eaeaea : 234, 234, 234
# Comment = 969896 : 150, 152, 150
# Red = d54e53 : 213, 78, 83
# Orange = e78c45 : 231, 140, 69
# Yellow = e7c547 : 231, 197, 71
# Green = b9ca4a : 185, 202, 74
# Aqua = 70c0b1 : 112, 192, 177
# Blue = 7aa6da : 122, 166, 218
# Purple = c397d8 : 195, 151, 216
##
[Main]
name = Tomorrow Night Bright
author = Veronica Berglyd Olsen
credit = Chris Kempson
url = https://github.com/chriskempson/tomorrow-theme
[Syntax]
background = 0, 0, 0
text = 234, 234, 234
link = 122, 166, 218
headertext = 122, 166, 218
headertag = 122, 166, 218
emphasis = 231, 140, 69
straightquotes = 213, 78, 83
doublequotes = 185, 202, 74
singlequotes = 231, 197, 71
hidden = 150, 152, 150
keyword = 213, 78, 83
value = 195, 151, 216
spellcheckline = 213, 78, 83
tagerror = 185, 202, 74
replacetag = 112, 192, 177
@@ -0,0 +1,42 @@
##
# Theme: Tomorrow Night Eighties
# Source: https://github.com/chriskempson/tomorrow-theme
# Credit: Chris Kempson
##
# Colours:
# Background = 2d2d2d : 45, 45, 45
# Current Line = 393939 : 57, 57, 57
# Selection = 515151 : 81, 81, 81
# Foreground = cccccc : 204, 204, 204
# Comment = 999999 : 153, 153, 153
# Red = f2777a : 242, 119, 122
# Orange = f99157 : 249, 145, 57
# Yellow = ffcc66 : 255, 204, 102
# Green = 99cc99 : 153, 204, 153
# Aqua = 66cccc : 102, 204, 204
# Blue = 6699cc : 102, 153, 204
# Purple = cc99cc : 204, 153, 204
##
[Main]
name = Tomorrow Night Eighties
author = Veronica Berglyd Olsen
credit = Chris Kempson
url = https://github.com/chriskempson/tomorrow-theme
[Syntax]
background = 45, 45, 45
text = 204, 204, 204
link = 102, 153, 204
headertext = 102, 153, 204
headertag = 102, 153, 204
emphasis = 249, 145, 57
straightquotes = 242, 119, 122
doublequotes = 153, 204, 153
singlequotes = 255, 204, 102
hidden = 153, 153, 153
keyword = 242, 119, 122
value = 204, 153, 204
spellcheckline = 242, 119, 122
tagerror = 153, 204, 153
replacetag = 102, 204, 204
+3 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.1.5" fileVersion="1.0" timeStamp="2019-06-12 20:54:46"> <novelWriterXML appVersion="0.1.5" fileVersion="1.0" timeStamp="2019-06-15 22:17:54">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
@@ -9,7 +9,7 @@
<settings> <settings>
<spellCheck>True</spellCheck> <spellCheck>True</spellCheck>
<lastEdited>636b6aa9b697b</lastEdited> <lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>bc0cbd2a407f3</lastViewed> <lastViewed>636b6aa9b697b</lastViewed>
<lastWordCount>581</lastWordCount> <lastWordCount>581</lastWordCount>
<autoReplace> <autoReplace>
<A>B</A> <A>B</A>
@@ -80,7 +80,7 @@
<charCount>736</charCount> <charCount>736</charCount>
<wordCount>137</wordCount> <wordCount>137</wordCount>
<paraCount>6</paraCount> <paraCount>6</paraCount>
<cursorPos>424</cursorPos> <cursorPos>69</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>
+3 -2
View File
@@ -1,6 +1,7 @@
[Main] [Main]
timestamp = 2019-06-15 12:26:17 timestamp = 2019-06-15 23:10:43
theme = default_dark theme = default
syntax = default_light
[Sizes] [Sizes]
geometry = 1100, 650 geometry = 1100, 650