+93
-101
@@ -25,6 +25,11 @@ class Config:
|
|||||||
WIN_WIDTH = 0
|
WIN_WIDTH = 0
|
||||||
WIN_HEIGHT = 1
|
WIN_HEIGHT = 1
|
||||||
|
|
||||||
|
CNF_STR = 0
|
||||||
|
CNF_INT = 1
|
||||||
|
CNF_BOOL = 2
|
||||||
|
CNF_LIST = 3
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# Set Application Variables
|
# Set Application Variables
|
||||||
@@ -38,6 +43,7 @@ class Config:
|
|||||||
self.confFile = None
|
self.confFile = None
|
||||||
self.homePath = None
|
self.homePath = None
|
||||||
self.appPath = None
|
self.appPath = None
|
||||||
|
self.appRoot = None
|
||||||
self.guiPath = None
|
self.guiPath = None
|
||||||
self.themePath = None
|
self.themePath = None
|
||||||
|
|
||||||
@@ -60,6 +66,7 @@ class Config:
|
|||||||
self.textWidth = 600
|
self.textWidth = 600
|
||||||
self.textMargin = [40, 40]
|
self.textMargin = [40, 40]
|
||||||
self.textSize = 13
|
self.textSize = 13
|
||||||
|
self.tabWidth = 40
|
||||||
self.doJustify = True
|
self.doJustify = True
|
||||||
self.autoSelect = True
|
self.autoSelect = True
|
||||||
self.doReplace = True
|
self.doReplace = True
|
||||||
@@ -95,6 +102,7 @@ class Config:
|
|||||||
self.confFile = self.appHandle+".conf"
|
self.confFile = self.appHandle+".conf"
|
||||||
self.homePath = path.expanduser("~")
|
self.homePath = path.expanduser("~")
|
||||||
self.appPath = path.dirname(__file__)
|
self.appPath = path.dirname(__file__)
|
||||||
|
self.appRoot = path.join(self.appPath,path.pardir)
|
||||||
self.guiPath = path.join(self.appPath,"gui")
|
self.guiPath = path.join(self.appPath,"gui")
|
||||||
self.themePath = path.join(self.appPath,"themes")
|
self.themePath = path.join(self.appPath,"themes")
|
||||||
|
|
||||||
@@ -117,140 +125,105 @@ class Config:
|
|||||||
def loadConfig(self):
|
def loadConfig(self):
|
||||||
|
|
||||||
logger.debug("Loading config file")
|
logger.debug("Loading config file")
|
||||||
confParser = configparser.ConfigParser()
|
cnfParse = configparser.ConfigParser()
|
||||||
try:
|
try:
|
||||||
confParser.read_file(open(path.join(self.confPath,self.confFile)))
|
cnfParse.read_file(open(path.join(self.confPath,self.confFile)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Could not load config file")
|
logger.error("Could not load config file")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Get options
|
|
||||||
|
|
||||||
## Main
|
## Main
|
||||||
cnfSec = "Main"
|
cnfSec = "Main"
|
||||||
if confParser.has_section(cnfSec):
|
self.guiTheme = self._parseLine(cnfParse, cnfSec, "theme", self.CNF_STR, self.guiTheme)
|
||||||
if confParser.has_option(cnfSec,"theme"):
|
|
||||||
self.guiTheme = confParser.get(cnfSec,"theme")
|
|
||||||
|
|
||||||
## Sizes
|
## Sizes
|
||||||
cnfSec = "Sizes"
|
cnfSec = "Sizes"
|
||||||
if confParser.has_section(cnfSec):
|
self.winGeometry = self._parseLine(cnfParse, cnfSec, "geometry", self.CNF_LIST, self.winGeometry)
|
||||||
if confParser.has_option(cnfSec,"geometry"):
|
self.treeColWidth = self._parseLine(cnfParse, cnfSec, "treecols", self.CNF_LIST, self.treeColWidth)
|
||||||
self.winGeometry = self.unpackList(
|
self.mainPanePos = self._parseLine(cnfParse, cnfSec, "mainpane", self.CNF_LIST, self.mainPanePos)
|
||||||
confParser.get(cnfSec,"geometry"), 2, self.winGeometry
|
self.docPanePos = self._parseLine(cnfParse, cnfSec, "docpane", self.CNF_LIST, self.docPanePos)
|
||||||
)
|
|
||||||
if confParser.has_option(cnfSec,"treecols"):
|
|
||||||
self.treeColWidth = self.unpackList(
|
|
||||||
confParser.get(cnfSec,"treecols"), 3, self.treeColWidth
|
|
||||||
)
|
|
||||||
if confParser.has_option(cnfSec,"mainpane"):
|
|
||||||
self.mainPanePos = self.unpackList(
|
|
||||||
confParser.get(cnfSec,"mainpane"), 2, self.mainPanePos
|
|
||||||
)
|
|
||||||
if confParser.has_option(cnfSec,"docpane"):
|
|
||||||
self.docPanePos = self.unpackList(
|
|
||||||
confParser.get(cnfSec,"docpane"), 2, self.docPanePos
|
|
||||||
)
|
|
||||||
|
|
||||||
## Project
|
## Project
|
||||||
cnfSec = "Project"
|
cnfSec = "Project"
|
||||||
if confParser.has_section(cnfSec):
|
self.autoSaveProj = self._parseLine(cnfParse, cnfSec, "autosaveproject", self.CNF_INT, self.autoSaveProj)
|
||||||
if confParser.has_option(cnfSec,"autosaveproject"):
|
self.autoSaveDoc = self._parseLine(cnfParse, cnfSec, "autosavedoc", self.CNF_INT, self.autoSaveDoc)
|
||||||
self.autoSaveProj = confParser.getint(cnfSec,"autosaveproject")
|
|
||||||
if confParser.has_option(cnfSec,"autosavedoc"):
|
|
||||||
self.autoSaveDoc = confParser.getint(cnfSec,"autosavedoc")
|
|
||||||
|
|
||||||
## Editor
|
## Editor
|
||||||
cnfSec = "Editor"
|
cnfSec = "Editor"
|
||||||
if confParser.has_section(cnfSec):
|
self.textFixedW = self._parseLine(cnfParse, cnfSec, "fixedwidth", self.CNF_BOOL, self.textFixedW)
|
||||||
if confParser.has_option(cnfSec,"fixedwidth"):
|
self.textWidth = self._parseLine(cnfParse, cnfSec, "width", self.CNF_INT, self.textWidth)
|
||||||
self.textFixedW = confParser.getboolean(cnfSec,"fixedwidth")
|
self.textMargin = self._parseLine(cnfParse, cnfSec, "margins", self.CNF_LIST, self.textMargin)
|
||||||
if confParser.has_option(cnfSec,"width"):
|
self.textSize = self._parseLine(cnfParse, cnfSec, "textsize", self.CNF_INT, self.textSize)
|
||||||
self.textWidth = confParser.getint(cnfSec,"width")
|
self.tabWidth = self._parseLine(cnfParse, cnfSec, "tabwidth", self.CNF_INT, self.tabWidth)
|
||||||
if confParser.has_option(cnfSec,"margins"):
|
self.doJustify = self._parseLine(cnfParse, cnfSec, "justify", self.CNF_BOOL, self.doJustify)
|
||||||
self.textMargin = self.unpackList(
|
self.autoSelect = self._parseLine(cnfParse, cnfSec, "autoselect", self.CNF_BOOL, self.autoSelect)
|
||||||
confParser.get(cnfSec,"margins"), 2, self.textMargin
|
self.doReplace = self._parseLine(cnfParse, cnfSec, "autoreplace", self.CNF_BOOL, self.doReplace)
|
||||||
)
|
self.doReplaceSQuote = self._parseLine(cnfParse, cnfSec, "repsquotes", self.CNF_BOOL, self.doReplaceSQuote)
|
||||||
if confParser.has_option(cnfSec,"textsize"):
|
self.doReplaceDQuote = self._parseLine(cnfParse, cnfSec, "repdquotes", self.CNF_BOOL, self.doReplaceDQuote)
|
||||||
self.textSize = confParser.getint(cnfSec,"textsize")
|
self.doReplaceDash = self._parseLine(cnfParse, cnfSec, "repdash", self.CNF_BOOL, self.doReplaceDash)
|
||||||
if confParser.has_option(cnfSec,"justify"):
|
self.doReplaceDots = self._parseLine(cnfParse, cnfSec, "repdots", self.CNF_BOOL, self.doReplaceDots)
|
||||||
self.doJustify = confParser.getboolean(cnfSec,"justify")
|
self.spellLanguage = self._parseLine(cnfParse, cnfSec, "spellcheck", self.CNF_STR, self.spellLanguage)
|
||||||
if confParser.has_option(cnfSec,"autoselect"):
|
|
||||||
self.autoSelect = confParser.getboolean(cnfSec,"autoselect")
|
|
||||||
if confParser.has_option(cnfSec,"autoreplace"):
|
|
||||||
self.doReplace = confParser.getboolean(cnfSec,"autoreplace")
|
|
||||||
if confParser.has_option(cnfSec,"repsquotes"):
|
|
||||||
self.doReplaceSQuote = confParser.getboolean(cnfSec,"repsquotes")
|
|
||||||
if confParser.has_option(cnfSec,"repdquotes"):
|
|
||||||
self.doReplaceDQuote = confParser.getboolean(cnfSec,"repdquotes")
|
|
||||||
if confParser.has_option(cnfSec,"repdash"):
|
|
||||||
self.doReplaceDash = confParser.getboolean(cnfSec,"repdash")
|
|
||||||
if confParser.has_option(cnfSec,"repdots"):
|
|
||||||
self.doReplaceDots = confParser.getboolean(cnfSec,"repdots")
|
|
||||||
if confParser.has_option(cnfSec,"spellcheck"):
|
|
||||||
self.spellLanguage = confParser.get(cnfSec,"spellcheck")
|
|
||||||
|
|
||||||
## Path
|
## Path
|
||||||
cnfSec = "Path"
|
cnfSec = "Path"
|
||||||
if confParser.has_section(cnfSec):
|
for i in range(10):
|
||||||
for i in range(10):
|
self.recentList[i] = self._parseLine(cnfParse, cnfSec, "recent%d" % i,self.CNF_STR, self.recentList[i])
|
||||||
if confParser.has_option(cnfSec,"recent%d" % i):
|
|
||||||
self.recentList[i] = confParser.get(cnfSec,"recent%d" % i)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def saveConfig(self):
|
def saveConfig(self):
|
||||||
|
|
||||||
logger.debug("Saving config file")
|
logger.debug("Saving config file")
|
||||||
confParser = configparser.ConfigParser()
|
cnfParse = configparser.ConfigParser()
|
||||||
|
|
||||||
# Set options
|
# Set options
|
||||||
|
|
||||||
## Main
|
## Main
|
||||||
cnfSec = "Main"
|
cnfSec = "Main"
|
||||||
confParser.add_section(cnfSec)
|
cnfParse.add_section(cnfSec)
|
||||||
confParser.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"))
|
||||||
confParser.set(cnfSec,"theme", str(self.guiTheme))
|
cnfParse.set(cnfSec,"theme", str(self.guiTheme))
|
||||||
|
|
||||||
## Sizes
|
## Sizes
|
||||||
cnfSec = "Sizes"
|
cnfSec = "Sizes"
|
||||||
confParser.add_section(cnfSec)
|
cnfParse.add_section(cnfSec)
|
||||||
confParser.set(cnfSec,"geometry", self.packList(self.winGeometry))
|
cnfParse.set(cnfSec,"geometry", self._packList(self.winGeometry))
|
||||||
confParser.set(cnfSec,"treecols", self.packList(self.treeColWidth))
|
cnfParse.set(cnfSec,"treecols", self._packList(self.treeColWidth))
|
||||||
confParser.set(cnfSec,"mainpane", self.packList(self.mainPanePos))
|
cnfParse.set(cnfSec,"mainpane", self._packList(self.mainPanePos))
|
||||||
confParser.set(cnfSec,"docpane", self.packList(self.docPanePos))
|
cnfParse.set(cnfSec,"docpane", self._packList(self.docPanePos))
|
||||||
|
|
||||||
## Project
|
## Project
|
||||||
cnfSec = "Project"
|
cnfSec = "Project"
|
||||||
confParser.add_section(cnfSec)
|
cnfParse.add_section(cnfSec)
|
||||||
confParser.set(cnfSec,"autosaveproject", str(self.autoSaveProj))
|
cnfParse.set(cnfSec,"autosaveproject", str(self.autoSaveProj))
|
||||||
confParser.set(cnfSec,"autosavedoc", str(self.autoSaveDoc))
|
cnfParse.set(cnfSec,"autosavedoc", str(self.autoSaveDoc))
|
||||||
|
|
||||||
## Editor
|
## Editor
|
||||||
cnfSec = "Editor"
|
cnfSec = "Editor"
|
||||||
confParser.add_section(cnfSec)
|
cnfParse.add_section(cnfSec)
|
||||||
confParser.set(cnfSec,"fixedwidth", str(self.textFixedW))
|
cnfParse.set(cnfSec,"fixedwidth", str(self.textFixedW))
|
||||||
confParser.set(cnfSec,"width", str(self.textWidth))
|
cnfParse.set(cnfSec,"width", str(self.textWidth))
|
||||||
confParser.set(cnfSec,"margins", self.packList(self.textMargin))
|
cnfParse.set(cnfSec,"margins", self._packList(self.textMargin))
|
||||||
confParser.set(cnfSec,"textsize", str(self.textSize))
|
cnfParse.set(cnfSec,"textsize", str(self.textSize))
|
||||||
confParser.set(cnfSec,"justify", str(self.doJustify))
|
cnfParse.set(cnfSec,"tabwidth", str(self.tabWidth))
|
||||||
confParser.set(cnfSec,"autoselect", str(self.autoSelect))
|
cnfParse.set(cnfSec,"justify", str(self.doJustify))
|
||||||
confParser.set(cnfSec,"autoreplace",str(self.doReplace))
|
cnfParse.set(cnfSec,"autoselect", str(self.autoSelect))
|
||||||
confParser.set(cnfSec,"repsquotes", str(self.doReplaceSQuote))
|
cnfParse.set(cnfSec,"autoreplace",str(self.doReplace))
|
||||||
confParser.set(cnfSec,"repdquotes", str(self.doReplaceDQuote))
|
cnfParse.set(cnfSec,"repsquotes", str(self.doReplaceSQuote))
|
||||||
confParser.set(cnfSec,"repdash", str(self.doReplaceDash))
|
cnfParse.set(cnfSec,"repdquotes", str(self.doReplaceDQuote))
|
||||||
confParser.set(cnfSec,"repdots", str(self.doReplaceDots))
|
cnfParse.set(cnfSec,"repdash", str(self.doReplaceDash))
|
||||||
confParser.set(cnfSec,"spellcheck", str(self.spellLanguage))
|
cnfParse.set(cnfSec,"repdots", str(self.doReplaceDots))
|
||||||
|
cnfParse.set(cnfSec,"spellcheck", str(self.spellLanguage))
|
||||||
|
|
||||||
## Path
|
## Path
|
||||||
cnfSec = "Path"
|
cnfSec = "Path"
|
||||||
confParser.add_section(cnfSec)
|
cnfParse.add_section(cnfSec)
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
confParser.set(cnfSec,"recent%d" % i, str(self.recentList[i]))
|
cnfParse.set(cnfSec,"recent%d" % i, str(self.recentList[i]))
|
||||||
|
|
||||||
# Write config file
|
# Write config file
|
||||||
try:
|
try:
|
||||||
confParser.write(open(path.join(self.confPath,self.confFile),"w"))
|
cnfParse.write(open(path.join(self.confPath,self.confFile),"w"))
|
||||||
self.confChanged = False
|
self.confChanged = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Could not save config file")
|
logger.error("Could not save config file")
|
||||||
@@ -258,19 +231,6 @@ class Config:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unpackList(self, inStr, listLen, listDefault, castTo=int):
|
|
||||||
inData = inStr.split(",")
|
|
||||||
outData = []
|
|
||||||
for i in range(listLen):
|
|
||||||
try:
|
|
||||||
outData.append(castTo(inData[i]))
|
|
||||||
except:
|
|
||||||
outData.append(listDefault[i])
|
|
||||||
return outData
|
|
||||||
|
|
||||||
def packList(self, inData):
|
|
||||||
return ", ".join(str(inVal) for inVal in inData)
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
@@ -316,4 +276,36 @@ class Config:
|
|||||||
self.confChanged = True
|
self.confChanged = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
def _unpackList(self, inStr, listLen, listDefault, castTo=int):
|
||||||
|
inData = inStr.split(",")
|
||||||
|
outData = []
|
||||||
|
for i in range(listLen):
|
||||||
|
try:
|
||||||
|
outData.append(castTo(inData[i]))
|
||||||
|
except:
|
||||||
|
outData.append(listDefault[i])
|
||||||
|
return outData
|
||||||
|
|
||||||
|
def _packList(self, inData):
|
||||||
|
return ", ".join(str(inVal) for inVal in inData)
|
||||||
|
|
||||||
|
def _parseLine(self, cnfParse, cnfSec, cnfName, cnfType, cnfDefault):
|
||||||
|
if cnfParse.has_section(cnfSec):
|
||||||
|
if cnfParse.has_option(cnfSec, cnfName):
|
||||||
|
if cnfType == self.CNF_STR:
|
||||||
|
return cnfParse.get(cnfSec, cnfName)
|
||||||
|
elif cnfType == self.CNF_INT:
|
||||||
|
return cnfParse.getint(cnfSec, cnfName)
|
||||||
|
elif cnfType == self.CNF_BOOL:
|
||||||
|
return cnfParse.getboolean(cnfSec, cnfName)
|
||||||
|
elif cnfType == self.CNF_LIST:
|
||||||
|
return self._unpackList(
|
||||||
|
cnfParse.get(cnfSec, cnfName), len(cnfDefault), cnfDefault
|
||||||
|
)
|
||||||
|
return cnfDefault
|
||||||
|
|
||||||
# End Class Config
|
# End Class Config
|
||||||
|
|||||||
+10
-2
@@ -12,6 +12,15 @@
|
|||||||
|
|
||||||
from nw.enum import nwItemClass, nwItemLayout
|
from nw.enum import nwItemClass, nwItemLayout
|
||||||
|
|
||||||
|
class nwFiles():
|
||||||
|
|
||||||
|
APP_ICON = "novelWriter.svg"
|
||||||
|
PROJ_FILE = "nwProject.nwx"
|
||||||
|
PROJ_DICT = "wordlist.txt"
|
||||||
|
SESS_INFO = "sessionInfo.log"
|
||||||
|
|
||||||
|
# END Class nwFiles
|
||||||
|
|
||||||
class nwLabels():
|
class nwLabels():
|
||||||
|
|
||||||
CLASS_NAME = {
|
CLASS_NAME = {
|
||||||
@@ -59,5 +68,4 @@ class nwLabels():
|
|||||||
nwItemLayout.NOTE : "Nt",
|
nwItemLayout.NOTE : "Nt",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# END Class nwLabels
|
||||||
# END nwLabels
|
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""novelWriter GUI About View
|
|
||||||
|
|
||||||
novelWriter – GUI About View
|
|
||||||
==============================
|
|
||||||
Class holding the tab viewing the about information
|
|
||||||
|
|
||||||
File History:
|
|
||||||
Created: 2018-10-02 [0.0.1]
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import nw
|
|
||||||
|
|
||||||
from os import path
|
|
||||||
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QLabel
|
|
||||||
from PyQt5.QtSvg import QSvgWidget
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
|
||||||
from PyQt5.QtGui import QFont
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class GuiAboutView(QWidget):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
QWidget.__init__(self)
|
|
||||||
|
|
||||||
logger.debug("Initialising AboutView ...")
|
|
||||||
self.mainConf = nw.CONFIG
|
|
||||||
self.innerBox = QHBoxLayout()
|
|
||||||
self.outerBox = QVBoxLayout()
|
|
||||||
|
|
||||||
logoPath = path.abspath(path.join(self.mainConf.appPath,"..","novelWriter.svg"))
|
|
||||||
logger.verbose("Loading image: %s" % logoPath)
|
|
||||||
nwLogo = QSvgWidget(logoPath)
|
|
||||||
nwLogo.setFixedSize(QSize(300,300))
|
|
||||||
|
|
||||||
nwName = QLabel()
|
|
||||||
nwName.setText(nw.__package__)
|
|
||||||
nwName.setAlignment(Qt.AlignCenter)
|
|
||||||
fnName = QFont()
|
|
||||||
fnName.setPointSize(22)
|
|
||||||
fnName.setBold(True)
|
|
||||||
nwName.setFont(fnName)
|
|
||||||
|
|
||||||
nwVersion = QLabel()
|
|
||||||
nwVersion.setText("Version %s" % nw.__version__)
|
|
||||||
nwVersion.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
nwCredits = QLabel()
|
|
||||||
nwCredits.setText("Created By: %s" % ",".join(nw.__credits__))
|
|
||||||
nwCredits.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
nwWebsite = QLabel()
|
|
||||||
nwWebsite.setText("<a href='%s'>%s</a>" % (nw.__website__,nw.__website__))
|
|
||||||
nwWebsite.setOpenExternalLinks(True)
|
|
||||||
nwWebsite.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
self.outerBox.addStretch(1)
|
|
||||||
self.innerBox.addStretch(1)
|
|
||||||
self.innerBox.addWidget(nwLogo)
|
|
||||||
self.innerBox.addStretch(1)
|
|
||||||
self.outerBox.addLayout(self.innerBox)
|
|
||||||
self.outerBox.addWidget(nwName)
|
|
||||||
self.outerBox.addWidget(nwVersion)
|
|
||||||
self.outerBox.addWidget(nwCredits)
|
|
||||||
self.outerBox.addWidget(nwWebsite)
|
|
||||||
self.outerBox.addStretch(1)
|
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
|
||||||
|
|
||||||
logger.debug("AboutView initialisation complete")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class GuiAboutView
|
|
||||||
+6
-1
@@ -104,8 +104,12 @@ 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)
|
||||||
|
theOpt = QTextOption()
|
||||||
|
if self.mainConf.tabWidth is not None:
|
||||||
|
theOpt.setTabStopDistance(self.mainConf.tabWidth)
|
||||||
if self.mainConf.doJustify:
|
if self.mainConf.doJustify:
|
||||||
self.theDoc.setDefaultTextOption(QTextOption(Qt.AlignJustify))
|
theOpt.setAlignment(Qt.AlignJustify)
|
||||||
|
self.theDoc.setDefaultTextOption(theOpt)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -376,6 +380,7 @@ class GuiDocEditor(QTextEdit):
|
|||||||
self.paraCount = self.wCounter.paraCount
|
self.paraCount = self.wCounter.paraCount
|
||||||
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount)
|
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount)
|
||||||
self.theParent.treeView.propagateCount(tHandle, self.wordCount)
|
self.theParent.treeView.propagateCount(tHandle, self.wordCount)
|
||||||
|
self.theParent.treeView.projectWordCount()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -194,13 +194,14 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
self.setCurrentBlockState(0)
|
self.setCurrentBlockState(0)
|
||||||
|
|
||||||
if self.theDict is None or not self.spellCheck:
|
if self.theDict is None or not self.spellCheck or theText.startswith("@"):
|
||||||
return
|
return
|
||||||
|
|
||||||
rxSpell = self.spellRx.globalMatch(theText.replace("_"," "), 0)
|
rxSpell = self.spellRx.globalMatch(theText.replace("_"," "), 0)
|
||||||
while rxSpell.hasNext():
|
while rxSpell.hasNext():
|
||||||
rxMatch = rxSpell.next()
|
rxMatch = rxSpell.next()
|
||||||
if not self.theDict.check(rxMatch.captured(0)):
|
if not self.theDict.check(rxMatch.captured(0)):
|
||||||
|
if rxMatch.captured(0) == rxMatch.captured(0).upper(): continue
|
||||||
xPos = rxMatch.capturedStart(0)
|
xPos = rxMatch.capturedStart(0)
|
||||||
xLen = rxMatch.capturedLength(0)
|
xLen = rxMatch.capturedLength(0)
|
||||||
spFmt = self.format(xPos)
|
spFmt = self.format(xPos)
|
||||||
|
|||||||
+13
-1
@@ -50,7 +50,7 @@ class GuiDocTree(QTreeWidget):
|
|||||||
self.setExpandsOnDoubleClick(True)
|
self.setExpandsOnDoubleClick(True)
|
||||||
self.setIndentation(13)
|
self.setIndentation(13)
|
||||||
self.setColumnCount(4)
|
self.setColumnCount(4)
|
||||||
self.setHeaderLabels(["Name","Count","Flags","Handle"])
|
self.setHeaderLabels(["Name","Words","Flags","Handle"])
|
||||||
if not self.debugGUI:
|
if not self.debugGUI:
|
||||||
self.hideColumn(self.C_HANDLE)
|
self.hideColumn(self.C_HANDLE)
|
||||||
|
|
||||||
@@ -286,6 +286,18 @@ class GuiDocTree(QTreeWidget):
|
|||||||
self.propagateCount(pHandle, pCount, nDepth+1)
|
self.propagateCount(pHandle, pCount, nDepth+1)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def projectWordCount(self):
|
||||||
|
nWords = 0
|
||||||
|
for n in range(self.topLevelItemCount()):
|
||||||
|
tItem = self.topLevelItem(n)
|
||||||
|
if tItem == self.orphRoot:
|
||||||
|
continue
|
||||||
|
nWords += int(tItem.text(self.C_COUNT))
|
||||||
|
self.theProject.setProjectWordCount(nWords)
|
||||||
|
sWords = self.theProject.getSessionWordCount()
|
||||||
|
self.theParent.statusBar.setStats(nWords,sWords)
|
||||||
|
return
|
||||||
|
|
||||||
def buildTree(self):
|
def buildTree(self):
|
||||||
self.clear()
|
self.clear()
|
||||||
for nwItem in self.theProject.getProjectItems():
|
for nwItem in self.theProject.getProjectItems():
|
||||||
|
|||||||
@@ -253,6 +253,13 @@ class GuiMainMenu(QMenuBar):
|
|||||||
menuItem.triggered.connect(self.theParent.saveDocument)
|
menuItem.triggered.connect(self.theParent.saveDocument)
|
||||||
self.docuMenu.addAction(menuItem)
|
self.docuMenu.addAction(menuItem)
|
||||||
|
|
||||||
|
# Document > Close
|
||||||
|
menuItem = QAction(QIcon.fromTheme("document-revert"), "Close Document", self)
|
||||||
|
menuItem.setStatusTip("Close Current Document")
|
||||||
|
menuItem.setShortcut("Ctrl+W")
|
||||||
|
menuItem.triggered.connect(self.theParent.closeDocEditor)
|
||||||
|
self.docuMenu.addAction(menuItem)
|
||||||
|
|
||||||
# Document > Separator
|
# Document > Separator
|
||||||
self.docuMenu.addSeparator()
|
self.docuMenu.addSeparator()
|
||||||
|
|
||||||
|
|||||||
+83
-20
@@ -13,6 +13,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
from PyQt5.QtCore import Qt, QTimer
|
||||||
|
from PyQt5.QtGui import QIcon, QColor, QPixmap
|
||||||
from PyQt5.QtWidgets import QStatusBar, QLabel, QFrame
|
from PyQt5.QtWidgets import QStatusBar, QLabel, QFrame
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -25,36 +28,74 @@ class GuiMainStatus(QStatusBar):
|
|||||||
logger.debug("Initialising GuiMainStatus ...")
|
logger.debug("Initialising GuiMainStatus ...")
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
|
self.refTime = None
|
||||||
|
|
||||||
|
self.iconGrey = QPixmap(16,16)
|
||||||
|
self.iconGrey.fill(QColor(120,120,120))
|
||||||
|
self.iconYellow = QPixmap(16,16)
|
||||||
|
self.iconYellow.fill(QColor(120,120, 40))
|
||||||
|
self.iconGreen = QPixmap(16,16)
|
||||||
|
self.iconGreen.fill(QColor( 40,120, 0))
|
||||||
|
|
||||||
|
self.boxStats = QLabel()
|
||||||
|
self.boxStats.setToolTip("Project Word Count | Session Word Count")
|
||||||
|
|
||||||
|
self.boxTime = QLabel("")
|
||||||
|
self.boxTime.setToolTip("Session Time")
|
||||||
|
self.boxTime.setAlignment(Qt.AlignRight)
|
||||||
|
self.boxTime.setMinimumWidth(80)
|
||||||
|
|
||||||
self.boxCounts = QLabel()
|
self.boxCounts = QLabel()
|
||||||
self.boxCounts.setToolTip("Character, Word, Paragraph Count")
|
self.boxCounts.setToolTip("Document Character | Word | Paragraph Count")
|
||||||
self.boxCounts.setFrameStyle(QFrame.Panel | QFrame.Sunken);
|
|
||||||
self.addPermanentWidget(self.boxCounts)
|
|
||||||
|
|
||||||
self.projChanged = QLabel("P")
|
self.projChanged = QLabel("")
|
||||||
|
self.projChanged.setFixedHeight(16)
|
||||||
|
self.projChanged.setFixedWidth(16)
|
||||||
self.projChanged.setToolTip("Project Changes Saved")
|
self.projChanged.setToolTip("Project Changes Saved")
|
||||||
self.projChanged.setFrameStyle(QFrame.Panel | QFrame.Sunken);
|
|
||||||
self.addPermanentWidget(self.projChanged)
|
|
||||||
|
|
||||||
self.docChanged = QLabel("D")
|
self.docChanged = QLabel("")
|
||||||
|
self.docChanged.setFixedHeight(16)
|
||||||
|
self.docChanged.setFixedWidth(16)
|
||||||
self.docChanged.setToolTip("Document Changes Saved")
|
self.docChanged.setToolTip("Document Changes Saved")
|
||||||
self.docChanged.setFrameStyle(QFrame.Panel | QFrame.Sunken);
|
|
||||||
self.addPermanentWidget(self.docChanged)
|
|
||||||
|
|
||||||
self.boxDocHandle = QLabel()
|
self.boxDocHandle = QLabel()
|
||||||
self.boxDocHandle.setFrameStyle(QFrame.Panel | QFrame.Sunken);
|
self.boxDocHandle.setFrameStyle(QFrame.Panel | QFrame.Sunken);
|
||||||
|
|
||||||
|
# Add Them
|
||||||
|
self.addPermanentWidget(self.docChanged)
|
||||||
|
self.addPermanentWidget(self.boxCounts)
|
||||||
|
self.addPermanentWidget(QLabel(" "))
|
||||||
|
self.addPermanentWidget(self.projChanged)
|
||||||
|
self.addPermanentWidget(self.boxStats)
|
||||||
|
self.addPermanentWidget(self.boxTime)
|
||||||
if self.mainConf.debugGUI:
|
if self.mainConf.debugGUI:
|
||||||
self.addPermanentWidget(self.boxDocHandle)
|
self.addPermanentWidget(self.boxDocHandle)
|
||||||
|
|
||||||
|
self.setSizeGripEnabled(True)
|
||||||
|
|
||||||
|
self.sessionTimer = QTimer()
|
||||||
|
self.sessionTimer.setInterval(1000)
|
||||||
|
self.sessionTimer.timeout.connect(self._updateTime)
|
||||||
|
self.sessionTimer.start()
|
||||||
|
|
||||||
logger.debug("GuiMainStatus initialisation complete")
|
logger.debug("GuiMainStatus initialisation complete")
|
||||||
|
|
||||||
|
self.clearStatus()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def clearStatus(self):
|
||||||
|
self.setRefTime(None)
|
||||||
|
self.setStats(0,0)
|
||||||
self.setCounts(0,0,0)
|
self.setCounts(0,0,0)
|
||||||
self.setDocHandleCount(None)
|
self.setDocHandleCount(None)
|
||||||
self.setProjectStatus(None)
|
self.setProjectStatus(None)
|
||||||
self.setDocumentStatus(None)
|
self.setDocumentStatus(None)
|
||||||
|
self._updateTime()
|
||||||
|
return True
|
||||||
|
|
||||||
self.setSizeGripEnabled(True)
|
def setRefTime(self, theTime):
|
||||||
|
self.refTime = theTime
|
||||||
return
|
return
|
||||||
|
|
||||||
def setStatus(self, theMessage, timeOut=10.0):
|
def setStatus(self, theMessage, timeOut=10.0):
|
||||||
@@ -63,28 +104,32 @@ class GuiMainStatus(QStatusBar):
|
|||||||
|
|
||||||
def setProjectStatus(self, isChanged):
|
def setProjectStatus(self, isChanged):
|
||||||
if isChanged is None:
|
if isChanged is None:
|
||||||
self.projChanged.setStyleSheet("QLabel {background-color: rgba(120,120,120,1.0);}")
|
self.projChanged.setPixmap(self.iconGrey)
|
||||||
elif isChanged == True:
|
elif isChanged == True:
|
||||||
self.projChanged.setStyleSheet("QLabel {background-color: rgba(120,120,40,1.0);}")
|
self.projChanged.setPixmap(self.iconYellow)
|
||||||
elif isChanged == False:
|
elif isChanged == False:
|
||||||
self.projChanged.setStyleSheet("QLabel {background-color: rgba(40,120,0,1.0);}")
|
self.projChanged.setPixmap(self.iconGreen)
|
||||||
else:
|
else:
|
||||||
self.projChanged.setStyleSheet("QLabel {background-color: rgba(120,120,120,1.0);}")
|
self.projChanged.setPixmap(self.iconGrey)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setDocumentStatus(self, isChanged):
|
def setDocumentStatus(self, isChanged):
|
||||||
if isChanged is None:
|
if isChanged is None:
|
||||||
self.docChanged.setStyleSheet("QLabel {background-color: rgba(120,120,120,1.0);}")
|
self.docChanged.setPixmap(self.iconGrey)
|
||||||
elif isChanged == True:
|
elif isChanged == True:
|
||||||
self.docChanged.setStyleSheet("QLabel {background-color: rgba(120,120,40,1.0);}")
|
self.docChanged.setPixmap(self.iconYellow)
|
||||||
elif isChanged == False:
|
elif isChanged == False:
|
||||||
self.docChanged.setStyleSheet("QLabel {background-color: rgba(40,120,0,1.0);}")
|
self.docChanged.setPixmap(self.iconGreen)
|
||||||
else:
|
else:
|
||||||
self.docChanged.setStyleSheet("QLabel {background-color: rgba(120,120,120,1.0);}")
|
self.docChanged.setPixmap(self.iconGrey)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setStats(self, pWC, sWC):
|
||||||
|
self.boxStats.setText("<b>Project:</b> {:d} : {:d}".format(pWC,sWC))
|
||||||
return
|
return
|
||||||
|
|
||||||
def setCounts(self, cC, wC, pC):
|
def setCounts(self, cC, wC, pC):
|
||||||
self.boxCounts.setText("<b>C:</b> {:n} <b>W:</b> {:n} <b>P:</b> {:n}".format(cC,wC,pC))
|
self.boxCounts.setText("<b>Document:</b> {:d} : {:d} : {:d}".format(cC,wC,pC))
|
||||||
return
|
return
|
||||||
|
|
||||||
def setDocHandleCount(self, theHandle):
|
def setDocHandleCount(self, theHandle):
|
||||||
@@ -94,4 +139,22 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self.boxDocHandle.setText("%13s" % theHandle)
|
self.boxDocHandle.setText("%13s" % theHandle)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
def _updateTime(self):
|
||||||
|
if self.refTime is None:
|
||||||
|
theTime = "00:00:00"
|
||||||
|
else:
|
||||||
|
# This is much faster than using datetime format
|
||||||
|
tS = int(time() - self.refTime)
|
||||||
|
tM = int(tS/60)
|
||||||
|
tH = int(tM/60)
|
||||||
|
tM = tM - tH*60
|
||||||
|
tS = tS - tM*60 - tH*3600
|
||||||
|
theTime = "%02d:%02d:%02d" % (tH,tM,tS)
|
||||||
|
self.boxTime.setText(theTime)
|
||||||
|
return
|
||||||
|
|
||||||
# END Class GuiMainStatus
|
# END Class GuiMainStatus
|
||||||
|
|||||||
+84
-74
@@ -36,6 +36,7 @@ from nw.project.item import NWItem
|
|||||||
from nw.convert.tokenizer import Tokenizer
|
from nw.convert.tokenizer import Tokenizer
|
||||||
from nw.convert.tohtml import ToHtml
|
from nw.convert.tohtml import ToHtml
|
||||||
from nw.enum import nwItemType, nwAlert
|
from nw.enum import nwItemType, nwAlert
|
||||||
|
from nw.constants import nwFiles
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -53,7 +54,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.appPath,"..","novelWriter.svg")))
|
self.setWindowIcon(QIcon(path.join(self.mainConf.appRoot, nwFiles.APP_ICON)))
|
||||||
self.theTheme.loadTheme()
|
self.theTheme.loadTheme()
|
||||||
|
|
||||||
# Main GUI Elements
|
# Main GUI Elements
|
||||||
@@ -139,43 +140,11 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def makeAlert(self, theMessage, theLevel=nwAlert.INFO):
|
|
||||||
"""Alert both the user and the logger at the same time. Message can be either a string or an
|
|
||||||
array of strings. Severity level is 0 = info, 1 = warning, and 2 = error.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if isinstance(theMessage, list):
|
|
||||||
popMsg = "<br>".join(theMessage)
|
|
||||||
logMsg = theMessage
|
|
||||||
else:
|
|
||||||
popMsg = theMessage
|
|
||||||
logMsg = [theMessage]
|
|
||||||
|
|
||||||
msgBox = QMessageBox()
|
|
||||||
if theLevel == nwAlert.INFO:
|
|
||||||
for msgLine in logMsg:
|
|
||||||
logger.info(msgLine)
|
|
||||||
msgBox.information(self, "Information", popMsg)
|
|
||||||
elif theLevel == nwAlert.WARN:
|
|
||||||
for msgLine in logMsg:
|
|
||||||
logger.warning(msgLine)
|
|
||||||
msgBox.warning(self, "Warning", popMsg)
|
|
||||||
elif theLevel == nwAlert.ERROR:
|
|
||||||
for msgLine in logMsg:
|
|
||||||
logger.error(msgLine)
|
|
||||||
msgBox.critical(self, "Error", popMsg)
|
|
||||||
elif theLevel == nwAlert.BUG:
|
|
||||||
for msgLine in logMsg:
|
|
||||||
logger.error(msgLine)
|
|
||||||
popMsg += "<br>This is a bug!"
|
|
||||||
msgBox.critical(self, "Internal Error", popMsg)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def clearGUI(self):
|
def clearGUI(self):
|
||||||
self.treeView.clearTree()
|
self.treeView.clearTree()
|
||||||
self.docEditor.clearEditor()
|
self.docEditor.clearEditor()
|
||||||
self.closeDocViewer()
|
self.closeDocViewer()
|
||||||
|
self.statusBar.clearStatus()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -211,19 +180,22 @@ class GuiMain(QMainWindow):
|
|||||||
self.rebuildTree()
|
self.rebuildTree()
|
||||||
self.saveProject()
|
self.saveProject()
|
||||||
self.hasProject = True
|
self.hasProject = True
|
||||||
|
self.statusBar.setRefTime(self.theProject.projOpened)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def closeProject(self, isYes=False):
|
def closeProject(self, isYes=False):
|
||||||
|
"""Closes the project if one is open.
|
||||||
|
isYes is passed on from the close application event so the user doesn't get prompted twice.
|
||||||
|
"""
|
||||||
if not self.hasProject:
|
if not self.hasProject:
|
||||||
|
# There is no project loaded, everything OK
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if not isYes:
|
if self.mainConf.showGUI and not isYes:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Close Project",
|
self, "Close Project", "Save changes and close current project?"
|
||||||
"Close current project?<br>Unsaved changes will be saved."
|
|
||||||
)
|
)
|
||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
return False
|
return False
|
||||||
@@ -235,29 +207,38 @@ class GuiMain(QMainWindow):
|
|||||||
saveOK = True
|
saveOK = True
|
||||||
|
|
||||||
if saveOK:
|
if saveOK:
|
||||||
self.theProject.clearProject()
|
self.theProject.closeProject()
|
||||||
self.clearGUI()
|
self.clearGUI()
|
||||||
self.hasProject = False
|
self.hasProject = False
|
||||||
|
|
||||||
return saveOK
|
return saveOK
|
||||||
|
|
||||||
def openProject(self, projFile=None):
|
def openProject(self, projFile=None):
|
||||||
|
"""Open a project.
|
||||||
|
projFile is passed from the open recent projects menu, so can be set. If not, we pop the dialog.
|
||||||
|
"""
|
||||||
if projFile is None:
|
if projFile is None:
|
||||||
projFile = self.openProjectDialog()
|
projFile = self.openProjectDialog()
|
||||||
if projFile is None:
|
if projFile is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Make sure any open project is cleared out first before we load another one
|
||||||
if not self.closeProject():
|
if not self.closeProject():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.theProject.openProject(projFile)
|
# Try to open the project
|
||||||
|
if not self.theProject.openProject(projFile):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Update GUI
|
||||||
self._setWindowTitle(self.theProject.projName)
|
self._setWindowTitle(self.theProject.projName)
|
||||||
self.rebuildTree()
|
self.rebuildTree()
|
||||||
self.docEditor.setPwl(path.join(self.theProject.projMeta,"wordlist.txt"))
|
self.docEditor.setPwl(path.join(self.theProject.projMeta, nwFiles.PROJ_DICT))
|
||||||
self.docEditor.setSpellCheck(self.theProject.spellCheck)
|
self.docEditor.setSpellCheck(self.theProject.spellCheck)
|
||||||
|
self.statusBar.setRefTime(self.theProject.projOpened)
|
||||||
self.mainMenu.updateMenu()
|
self.mainMenu.updateMenu()
|
||||||
|
|
||||||
|
# Restore previously open documents, if any
|
||||||
if self.theProject.lastEdited is not None:
|
if self.theProject.lastEdited is not None:
|
||||||
self.openDocument(self.theProject.lastEdited)
|
self.openDocument(self.theProject.lastEdited)
|
||||||
if self.theProject.lastViewed is not None:
|
if self.theProject.lastViewed is not None:
|
||||||
@@ -268,7 +249,9 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def saveProject(self):
|
def saveProject(self):
|
||||||
|
"""Save the current project.
|
||||||
|
"""
|
||||||
|
# If the project is new, it may not have a path, so we need one
|
||||||
if self.theProject.projPath is None:
|
if self.theProject.projPath is None:
|
||||||
projPath = self.saveProjectDialog()
|
projPath = self.saveProjectDialog()
|
||||||
self.theProject.setProjectPath(projPath)
|
self.theProject.setProjectPath(projPath)
|
||||||
@@ -286,13 +269,14 @@ class GuiMain(QMainWindow):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def closeDocument(self):
|
def closeDocument(self):
|
||||||
self.saveDocument()
|
if self.docEditor.docChanged:
|
||||||
|
self.saveDocument()
|
||||||
self.theDocument.clearDocument()
|
self.theDocument.clearDocument()
|
||||||
|
self.docEditor.clearEditor()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def openDocument(self, tHandle):
|
def openDocument(self, tHandle):
|
||||||
if self.docEditor.docChanged:
|
self.closeDocument()
|
||||||
self.saveDocument()
|
|
||||||
self.docEditor.setText(self.theDocument.openDocument(tHandle))
|
self.docEditor.setText(self.theDocument.openDocument(tHandle))
|
||||||
self.docEditor.setReadOnly(False)
|
self.docEditor.setReadOnly(False)
|
||||||
self.docEditor.setCursorPosition(self.theDocument.theItem.cursorPos)
|
self.docEditor.setCursorPosition(self.theDocument.theItem.cursorPos)
|
||||||
@@ -303,13 +287,13 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
def saveDocument(self):
|
def saveDocument(self):
|
||||||
if self.theDocument.theItem is not None:
|
if self.theDocument.theItem is not None:
|
||||||
docHtml = self.docEditor.getText()
|
docText = self.docEditor.getText()
|
||||||
cursPos = self.docEditor.getCursorPosition()
|
cursPos = self.docEditor.getCursorPosition()
|
||||||
self.theDocument.theItem.setCharCount(self.docEditor.charCount)
|
self.theDocument.theItem.setCharCount(self.docEditor.charCount)
|
||||||
self.theDocument.theItem.setWordCount(self.docEditor.wordCount)
|
self.theDocument.theItem.setWordCount(self.docEditor.wordCount)
|
||||||
self.theDocument.theItem.setParaCount(self.docEditor.paraCount)
|
self.theDocument.theItem.setParaCount(self.docEditor.paraCount)
|
||||||
self.theDocument.theItem.setCursorPos(cursPos)
|
self.theDocument.theItem.setCursorPos(cursPos)
|
||||||
self.theDocument.saveDocument(docHtml)
|
self.theDocument.saveDocument(docText)
|
||||||
self.docEditor.setDocumentChanged(False)
|
self.docEditor.setDocumentChanged(False)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -393,7 +377,9 @@ class GuiMain(QMainWindow):
|
|||||||
dlgOpt = QFileDialog.Options()
|
dlgOpt = QFileDialog.Options()
|
||||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||||
projFile, _ = QFileDialog.getOpenFileName(
|
projFile, _ = QFileDialog.getOpenFileName(
|
||||||
self,"Open novelWriter Project","","novelWriter Project File (nwProject.nwx);;All Files (*)",options=dlgOpt
|
self, "Open novelWriter Project", "",
|
||||||
|
"novelWriter Project File (%s);;All Files (*)" % nwFiles.PROJ_FILE,
|
||||||
|
options=dlgOpt
|
||||||
)
|
)
|
||||||
if projFile:
|
if projFile:
|
||||||
return projFile
|
return projFile
|
||||||
@@ -427,26 +413,56 @@ class GuiMain(QMainWindow):
|
|||||||
self._setWindowTitle(self.theProject.projName)
|
self._setWindowTitle(self.theProject.projName)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def makeAlert(self, theMessage, theLevel=nwAlert.INFO):
|
||||||
|
"""Alert both the user and the logger at the same time. Message can be either a string or an
|
||||||
|
array of strings. Severity level is 0 = info, 1 = warning, and 2 = error.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(theMessage, list):
|
||||||
|
popMsg = "<br>".join(theMessage)
|
||||||
|
logMsg = theMessage
|
||||||
|
else:
|
||||||
|
popMsg = theMessage
|
||||||
|
logMsg = [theMessage]
|
||||||
|
|
||||||
|
msgBox = QMessageBox()
|
||||||
|
if theLevel == nwAlert.INFO:
|
||||||
|
for msgLine in logMsg:
|
||||||
|
logger.info(msgLine)
|
||||||
|
msgBox.information(self, "Information", popMsg)
|
||||||
|
elif theLevel == nwAlert.WARN:
|
||||||
|
for msgLine in logMsg:
|
||||||
|
logger.warning(msgLine)
|
||||||
|
msgBox.warning(self, "Warning", popMsg)
|
||||||
|
elif theLevel == nwAlert.ERROR:
|
||||||
|
for msgLine in logMsg:
|
||||||
|
logger.error(msgLine)
|
||||||
|
msgBox.critical(self, "Error", popMsg)
|
||||||
|
elif theLevel == nwAlert.BUG:
|
||||||
|
for msgLine in logMsg:
|
||||||
|
logger.error(msgLine)
|
||||||
|
popMsg += "<br>This is a bug!"
|
||||||
|
msgBox.critical(self, "Internal Error", popMsg)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Main Window Actions
|
# Main Window Actions
|
||||||
##
|
##
|
||||||
|
|
||||||
def closeMain(self, isYes=False):
|
def closeMain(self):
|
||||||
|
|
||||||
if not isYes:
|
if self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Exit",
|
self, "Exit", "Do you want to save changes and exit?"
|
||||||
"Do you want to exit %s?" % nw.__package__
|
|
||||||
)
|
)
|
||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info("Exiting %s" % nw.__package__)
|
logger.info("Exiting %s" % nw.__package__)
|
||||||
if self._takeDocumentAction():
|
self.closeProject(True)
|
||||||
self.saveDocument()
|
|
||||||
if self._takeProjectAction():
|
|
||||||
self.saveProject()
|
|
||||||
self.mainConf.setWinSize(self.width(), self.height())
|
self.mainConf.setWinSize(self.width(), self.height())
|
||||||
self.mainConf.setTreeColWidths(self.treeView.getColumnSizes())
|
self.mainConf.setTreeColWidths(self.treeView.getColumnSizes())
|
||||||
self.mainConf.setMainPanePos(self.splitMain.sizes())
|
self.mainConf.setMainPanePos(self.splitMain.sizes())
|
||||||
@@ -466,6 +482,11 @@ class GuiMain(QMainWindow):
|
|||||||
self.docViewer.setFocus()
|
self.docViewer.setFocus()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def closeDocEditor(self):
|
||||||
|
self.closeDocument()
|
||||||
|
self.theProject.setLastEdited(None)
|
||||||
|
return
|
||||||
|
|
||||||
def closeDocViewer(self):
|
def closeDocViewer(self):
|
||||||
self.docViewer.clearViewer()
|
self.docViewer.clearViewer()
|
||||||
self.theProject.setLastViewed(None)
|
self.theProject.setLastViewed(None)
|
||||||
@@ -488,31 +509,17 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _autoSaveProject(self):
|
def _autoSaveProject(self):
|
||||||
if self._takeProjectAction():
|
if self.hasProject and self.theProject.projChanged and self.theProject.projPath is not None:
|
||||||
logger.debug("Autosaving project")
|
logger.debug("Autosaving project")
|
||||||
self.saveProject()
|
self.saveProject()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _autoSaveDocument(self):
|
def _autoSaveDocument(self):
|
||||||
if self._takeDocumentAction():
|
if self.hasProject and self.docEditor.docChanged and self.theDocument.theItem is not None:
|
||||||
logger.debug("Autosaving document")
|
logger.debug("Autosaving document")
|
||||||
self.saveDocument()
|
self.saveDocument()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _takeProjectAction(self):
|
|
||||||
if self.theProject.projPath is None:
|
|
||||||
return False
|
|
||||||
if not self.theProject.projChanged:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _takeDocumentAction(self):
|
|
||||||
if self.theDocument.theItem is None:
|
|
||||||
return False
|
|
||||||
if not self.docEditor.docChanged:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _makeStatusIcons(self):
|
def _makeStatusIcons(self):
|
||||||
self.statusIcons = {}
|
self.statusIcons = {}
|
||||||
for sLabel, sCol, _ in self.theProject.statusItems:
|
for sLabel, sCol, _ in self.theProject.statusItems:
|
||||||
@@ -541,7 +548,10 @@ class GuiMain(QMainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def closeEvent(self, theEvent):
|
def closeEvent(self, theEvent):
|
||||||
self.closeMain()
|
if self.closeMain():
|
||||||
|
theEvent.accept()
|
||||||
|
else:
|
||||||
|
theEvent.ignore()
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
+53
-9
@@ -19,10 +19,11 @@ from hashlib import sha256
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
|
|
||||||
from nw.common import checkString, checkBool
|
|
||||||
from nw.project.item import NWItem
|
from nw.project.item import NWItem
|
||||||
from nw.project.status import NWStatus
|
from nw.project.status import NWStatus
|
||||||
|
from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||||
|
from nw.common import checkString, checkBool, checkInt
|
||||||
|
from nw.constants import nwFiles
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ class NWProject():
|
|||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
self.mainConf = self.theParent.mainConf
|
self.mainConf = self.theParent.mainConf
|
||||||
self.projChanged = None
|
self.projChanged = None
|
||||||
|
self.projOpened = None
|
||||||
|
|
||||||
# Debug
|
# Debug
|
||||||
self.handleSeed = None
|
self.handleSeed = None
|
||||||
@@ -59,6 +61,8 @@ class NWProject():
|
|||||||
self.importItems = None
|
self.importItems = None
|
||||||
self.lastEdited = None
|
self.lastEdited = None
|
||||||
self.lastViewed = None
|
self.lastViewed = None
|
||||||
|
self.lastWCount = 0
|
||||||
|
self.currWCount = 0
|
||||||
|
|
||||||
# Set Defaults
|
# Set Defaults
|
||||||
self.clearProject()
|
self.clearProject()
|
||||||
@@ -119,19 +123,20 @@ class NWProject():
|
|||||||
##
|
##
|
||||||
|
|
||||||
def newProject(self):
|
def newProject(self):
|
||||||
|
|
||||||
hNovel = self.newRoot("Novel", nwItemClass.NOVEL)
|
hNovel = self.newRoot("Novel", nwItemClass.NOVEL)
|
||||||
hChars = self.newRoot("Characters", nwItemClass.CHARACTER)
|
hChars = self.newRoot("Characters", nwItemClass.CHARACTER)
|
||||||
hWorld = self.newRoot("Plot", nwItemClass.PLOT)
|
hWorld = self.newRoot("Plot", nwItemClass.PLOT)
|
||||||
hWorld = self.newRoot("World", nwItemClass.WORLD)
|
hWorld = self.newRoot("World", nwItemClass.WORLD)
|
||||||
hChapt = self.newFolder("New Chapter", nwItemClass.NOVEL, hNovel)
|
hChapt = self.newFolder("New Chapter", nwItemClass.NOVEL, hNovel)
|
||||||
hScene = self.newFile("New Scene", nwItemClass.NOVEL, hChapt)
|
hScene = self.newFile("New Scene", nwItemClass.NOVEL, hChapt)
|
||||||
|
self.projOpened = time()
|
||||||
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def clearProject(self):
|
def clearProject(self):
|
||||||
|
|
||||||
self.projChanged = None
|
self.projChanged = None
|
||||||
|
self.projOpened = None
|
||||||
|
|
||||||
# Project Settings
|
# Project Settings
|
||||||
self.projTree = {}
|
self.projTree = {}
|
||||||
@@ -141,7 +146,7 @@ class NWProject():
|
|||||||
self.projPath = None
|
self.projPath = None
|
||||||
self.projMeta = None
|
self.projMeta = None
|
||||||
self.projCache = None
|
self.projCache = None
|
||||||
self.projFile = "nwProject.nwx"
|
self.projFile = nwFiles.PROJ_FILE
|
||||||
self.projName = ""
|
self.projName = ""
|
||||||
self.bookTitle = ""
|
self.bookTitle = ""
|
||||||
self.bookAuthors = []
|
self.bookAuthors = []
|
||||||
@@ -156,13 +161,17 @@ class NWProject():
|
|||||||
self.importItems.addEntry("Minor", (200, 50, 0))
|
self.importItems.addEntry("Minor", (200, 50, 0))
|
||||||
self.importItems.addEntry("Major", (200,150, 0))
|
self.importItems.addEntry("Major", (200,150, 0))
|
||||||
self.importItems.addEntry("Main", ( 50,200, 0))
|
self.importItems.addEntry("Main", ( 50,200, 0))
|
||||||
|
self.lastEdited = None
|
||||||
|
self.lastViewed = None
|
||||||
|
self.lastWCount = 0
|
||||||
|
self.currWCount = 0
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def openProject(self, fileName):
|
def openProject(self, fileName):
|
||||||
|
|
||||||
if not path.isfile(fileName):
|
if not path.isfile(fileName):
|
||||||
fileName = path.join(fileName, "nwProject.nwx")
|
fileName = path.join(fileName, nwFiles.PROJ_FILE)
|
||||||
if not path.isfile(fileName):
|
if not path.isfile(fileName):
|
||||||
self.makeAlert("File not found: %s" % fileName, nwAlert.ERROR)
|
self.makeAlert("File not found: %s" % fileName, nwAlert.ERROR)
|
||||||
return False
|
return False
|
||||||
@@ -215,6 +224,8 @@ class NWProject():
|
|||||||
self.lastEdited = checkString(xItem.text,None,True)
|
self.lastEdited = checkString(xItem.text,None,True)
|
||||||
if xItem.tag == "lastViewed":
|
if xItem.tag == "lastViewed":
|
||||||
self.lastViewed = checkString(xItem.text,None,True)
|
self.lastViewed = checkString(xItem.text,None,True)
|
||||||
|
if xItem.tag == "lastWordCount":
|
||||||
|
self.lastWCount = checkInt(xItem.text,0,False)
|
||||||
if xItem.tag == "status":
|
if xItem.tag == "status":
|
||||||
self.statusItems.unpackEntries(xItem)
|
self.statusItems.unpackEntries(xItem)
|
||||||
if xItem.tag == "importance":
|
if xItem.tag == "importance":
|
||||||
@@ -242,6 +253,7 @@ class NWProject():
|
|||||||
|
|
||||||
self._scanProjectFolder()
|
self._scanProjectFolder()
|
||||||
self.setProjectChanged(False)
|
self.setProjectChanged(False)
|
||||||
|
self.projOpened = time()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -276,9 +288,10 @@ class NWProject():
|
|||||||
|
|
||||||
# Save Project Settings
|
# Save Project Settings
|
||||||
xSettings = etree.SubElement(nwXML,"settings")
|
xSettings = etree.SubElement(nwXML,"settings")
|
||||||
self._saveProjectValue(xSettings,"spellCheck",self.spellCheck)
|
self._saveProjectValue(xSettings,"spellCheck", self.spellCheck)
|
||||||
self._saveProjectValue(xSettings,"lastEdited",self.lastEdited)
|
self._saveProjectValue(xSettings,"lastEdited", self.lastEdited)
|
||||||
self._saveProjectValue(xSettings,"lastViewed",self.lastViewed)
|
self._saveProjectValue(xSettings,"lastViewed", self.lastViewed)
|
||||||
|
self._saveProjectValue(xSettings,"lastWordCount",self.currWCount)
|
||||||
|
|
||||||
xStatus = etree.SubElement(xSettings,"status")
|
xStatus = etree.SubElement(xSettings,"status")
|
||||||
self.statusItems.packEntries(xStatus)
|
self.statusItems.packEntries(xStatus)
|
||||||
@@ -311,6 +324,11 @@ class NWProject():
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def closeProject(self):
|
||||||
|
self._appendSessionStats()
|
||||||
|
self.clearProject()
|
||||||
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Set Functions
|
# Set Functions
|
||||||
##
|
##
|
||||||
@@ -365,6 +383,14 @@ class NWProject():
|
|||||||
self.setProjectChanged(True)
|
self.setProjectChanged(True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def setProjectWordCount(self, theCount):
|
||||||
|
self.currWCount = theCount
|
||||||
|
self.setProjectChanged(True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def getSessionWordCount(self):
|
||||||
|
return self.currWCount - self.lastWCount
|
||||||
|
|
||||||
def setStatusColours(self, newCols):
|
def setStatusColours(self, newCols):
|
||||||
replaceMap = self.statusItems.setNewEntries(newCols)
|
replaceMap = self.statusItems.setNewEntries(newCols)
|
||||||
if self.projTree is not None:
|
if self.projTree is not None:
|
||||||
@@ -576,6 +602,24 @@ class NWProject():
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _appendSessionStats(self):
|
||||||
|
|
||||||
|
if self.projMeta is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
with open(path.join(self.projMeta, nwFiles.SESS_INFO), mode="a+") as outFile:
|
||||||
|
print((
|
||||||
|
"Start: {opened:s} "
|
||||||
|
"End: {closed:s} "
|
||||||
|
"Words: {words:8d}"
|
||||||
|
).format(
|
||||||
|
opened = datetime.fromtimestamp(self.projOpened).strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
closed = datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
words = self.getSessionWordCount(),
|
||||||
|
), file=outFile)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def _makeHandle(self, addSeed=""):
|
def _makeHandle(self, addSeed=""):
|
||||||
if self.handleSeed is None:
|
if self.handleSeed is None:
|
||||||
newSeed = str(time()) + addSeed
|
newSeed = str(time()) + addSeed
|
||||||
|
|||||||
@@ -13,8 +13,12 @@ Some text here would look good as well, and maybe some "dialogue"?
|
|||||||
|
|
||||||
So, this is some __text__ that we’ve been adding to this document. It is utterly meaningless text, _but_ since this is just dummy text, that doesn’t really matter. The text is perfectly happy to live in this document regardless.
|
So, this is some __text__ that we’ve been adding to this document. It is utterly meaningless text, _but_ since this is just dummy text, that doesn’t really matter. The text is perfectly happy to live in this document regardless.
|
||||||
|
|
||||||
This paragraph is also meaningless. At least a bit. It’s also very short.
|
This paragraph is also meaningless. At least a bit. It’s also very short. But we could make it less meaningless if we wanted to … but we won’t, will we.
|
||||||
|
|
||||||
This one is a bit longer. “It also has some dialogue in it” she said, before she moved on to check if the spellchecker worked. It did. “Cool,” she concluded.
|
This one is a bit longer. “It also has some dialogue in it” she said, before she moved on to check if the spellchecker worked. It did. “Cool,” she concluded.
|
||||||
|
|
||||||
|
|
||||||
|
@ToDo: Stuff that will be done at some point
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
Start: 2019-05-26 14:28:28 End: 2019-05-26 14:28:38 Words: -23
|
||||||
|
Start: 2019-05-26 14:31:12 End: 2019-05-26 14:31:34 Words: 12
|
||||||
|
Start: 2019-05-26 14:33:27 End: 2019-05-26 14:33:31 Words: 0
|
||||||
|
Start: 2019-05-26 14:40:29 End: 2019-05-26 14:40:32 Words: 0
|
||||||
|
Start: 2019-05-26 14:40:43 End: 2019-05-26 14:40:46 Words: 0
|
||||||
|
Start: 2019-05-26 14:48:40 End: 2019-05-26 14:48:50 Words: 0
|
||||||
|
Start: 2019-05-26 14:50:18 End: 2019-05-26 14:50:21 Words: 0
|
||||||
|
Start: 2019-05-26 14:50:29 End: 2019-05-26 14:50:47 Words: 3
|
||||||
|
Start: 2019-05-26 15:10:52 End: 2019-05-26 15:11:09 Words: 0
|
||||||
|
Start: 2019-05-26 15:28:56 End: 2019-05-26 15:29:08 Words: 0
|
||||||
|
Start: 2019-05-26 15:37:34 End: 2019-05-26 15:37:43 Words: -538
|
||||||
|
Start: 2019-05-26 15:37:47 End: 2019-05-26 15:38:07 Words: 538
|
||||||
|
Start: 2019-05-26 15:38:11 End: 2019-05-26 15:43:07 Words: 2
|
||||||
|
Start: 2019-05-26 15:49:18 End: 2019-05-26 15:49:47 Words: 0
|
||||||
|
Start: 2019-05-26 15:52:39 End: 2019-05-26 15:52:56 Words: 0
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-24 00:28:28">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-26 15:52:53">
|
||||||
<project>
|
<project>
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
@@ -9,7 +9,8 @@
|
|||||||
<settings>
|
<settings>
|
||||||
<spellCheck>True</spellCheck>
|
<spellCheck>True</spellCheck>
|
||||||
<lastEdited>636b6aa9b697b</lastEdited>
|
<lastEdited>636b6aa9b697b</lastEdited>
|
||||||
<lastViewed>636b6aa9b697b</lastViewed>
|
<lastViewed>None</lastViewed>
|
||||||
|
<lastWordCount>540</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Notes</entry>
|
<entry blue="0" green="50" red="200">Notes</entry>
|
||||||
@@ -72,10 +73,10 @@
|
|||||||
<status>Notes</status>
|
<status>Notes</status>
|
||||||
<expanded>False</expanded>
|
<expanded>False</expanded>
|
||||||
<layout>SCENE</layout>
|
<layout>SCENE</layout>
|
||||||
<charCount>577</charCount>
|
<charCount>656</charCount>
|
||||||
<wordCount>104</wordCount>
|
<wordCount>121</wordCount>
|
||||||
<paraCount>5</paraCount>
|
<paraCount>5</paraCount>
|
||||||
<cursorPos>603</cursorPos>
|
<cursorPos>573</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>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-23 23:02:29">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-25 23:29:02">
|
||||||
<project>
|
<project>
|
||||||
<name></name>
|
<name></name>
|
||||||
<title></title>
|
<title></title>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<spellCheck>False</spellCheck>
|
<spellCheck>False</spellCheck>
|
||||||
<lastEdited>None</lastEdited>
|
<lastEdited>None</lastEdited>
|
||||||
<lastViewed>None</lastViewed>
|
<lastViewed>None</lastViewed>
|
||||||
|
<lastWordCount>0</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Note</entry>
|
<entry blue="0" green="50" red="200">Note</entry>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-22 21:14:26">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-25 23:29:32">
|
||||||
<project>
|
<project>
|
||||||
<name></name>
|
<name></name>
|
||||||
<title></title>
|
<title></title>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<spellCheck>True</spellCheck>
|
<spellCheck>True</spellCheck>
|
||||||
<lastEdited>31489056e0916</lastEdited>
|
<lastEdited>31489056e0916</lastEdited>
|
||||||
<lastViewed>31489056e0916</lastViewed>
|
<lastViewed>31489056e0916</lastViewed>
|
||||||
|
<lastWordCount>69</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Note</entry>
|
<entry blue="0" green="50" red="200">Note</entry>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-22 21:35:39">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-25 23:31:12">
|
||||||
<project>
|
<project>
|
||||||
<name>Project Name</name>
|
<name>Project Name</name>
|
||||||
<title>Project Title</title>
|
<title>Project Title</title>
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<spellCheck>False</spellCheck>
|
<spellCheck>False</spellCheck>
|
||||||
<lastEdited>None</lastEdited>
|
<lastEdited>None</lastEdited>
|
||||||
<lastViewed>None</lastViewed>
|
<lastViewed>None</lastViewed>
|
||||||
|
<lastWordCount>0</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Note</entry>
|
<entry blue="0" green="50" red="200">Note</entry>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-22 21:16:34">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-25 23:31:45">
|
||||||
<project>
|
<project>
|
||||||
<name></name>
|
<name></name>
|
||||||
<title></title>
|
<title></title>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<spellCheck>False</spellCheck>
|
<spellCheck>False</spellCheck>
|
||||||
<lastEdited>None</lastEdited>
|
<lastEdited>None</lastEdited>
|
||||||
<lastViewed>None</lastViewed>
|
<lastViewed>None</lastViewed>
|
||||||
|
<lastWordCount>0</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Note</entry>
|
<entry blue="0" green="50" red="200">Note</entry>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Main]
|
[Main]
|
||||||
timestamp = 2019-05-18 15:06:44
|
timestamp = 2019-05-25 23:33:23
|
||||||
theme = default
|
theme = default
|
||||||
|
|
||||||
[Sizes]
|
[Sizes]
|
||||||
@@ -17,6 +17,7 @@ fixedwidth = True
|
|||||||
width = 600
|
width = 600
|
||||||
margins = 40, 40
|
margins = 40, 40
|
||||||
textsize = 13
|
textsize = 13
|
||||||
|
tabwidth = 40
|
||||||
justify = True
|
justify = True
|
||||||
autoselect = True
|
autoselect = True
|
||||||
autoreplace = True
|
autoreplace = True
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-22 20:48:51">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-25 23:25:27">
|
||||||
<project>
|
<project>
|
||||||
<name></name>
|
<name></name>
|
||||||
<title></title>
|
<title></title>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<spellCheck>False</spellCheck>
|
<spellCheck>False</spellCheck>
|
||||||
<lastEdited>None</lastEdited>
|
<lastEdited>None</lastEdited>
|
||||||
<lastViewed>None</lastViewed>
|
<lastViewed>None</lastViewed>
|
||||||
|
<lastWordCount>0</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Note</entry>
|
<entry blue="0" green="50" red="200">Note</entry>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.1.3" fileVersion="1.0" timeStamp="2019-05-22 20:52:32">
|
<novelWriterXML appVersion="0.1.4" fileVersion="1.0" timeStamp="2019-05-25 23:26:15">
|
||||||
<project>
|
<project>
|
||||||
<name></name>
|
<name></name>
|
||||||
<title></title>
|
<title></title>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<spellCheck>False</spellCheck>
|
<spellCheck>False</spellCheck>
|
||||||
<lastEdited>None</lastEdited>
|
<lastEdited>None</lastEdited>
|
||||||
<lastViewed>None</lastViewed>
|
<lastViewed>None</lastViewed>
|
||||||
|
<lastWordCount>0</lastWordCount>
|
||||||
<status>
|
<status>
|
||||||
<entry blue="100" green="100" red="100">New</entry>
|
<entry blue="100" green="100" red="100">New</entry>
|
||||||
<entry blue="0" green="50" red="200">Note</entry>
|
<entry blue="0" green="50" red="200">Note</entry>
|
||||||
|
|||||||
+4
-4
@@ -27,7 +27,7 @@ def testMainWindows(qtbot, nwTempGUI, nwRef):
|
|||||||
nwGUI.theProject.handleSeed = 42
|
nwGUI.theProject.handleSeed = 42
|
||||||
assert nwGUI.newProject(nwTempGUI, True)
|
assert nwGUI.newProject(nwTempGUI, True)
|
||||||
assert nwGUI.saveProject()
|
assert nwGUI.saveProject()
|
||||||
assert nwGUI.closeProject(True)
|
assert nwGUI.closeProject()
|
||||||
|
|
||||||
assert len(nwGUI.theProject.projTree) == 0
|
assert len(nwGUI.theProject.projTree) == 0
|
||||||
assert len(nwGUI.theProject.treeOrder) == 0
|
assert len(nwGUI.theProject.treeOrder) == 0
|
||||||
@@ -155,7 +155,7 @@ def testMainWindows(qtbot, nwTempGUI, nwRef):
|
|||||||
sceneFile = path.join(nwTempGUI,"data_3","1489056e0916_main.nwd")
|
sceneFile = path.join(nwTempGUI,"data_3","1489056e0916_main.nwd")
|
||||||
assert cmpFiles(sceneFile, path.join(nwRef,"gui","1_1489056e0916_main.nwd"))
|
assert cmpFiles(sceneFile, path.join(nwRef,"gui","1_1489056e0916_main.nwd"))
|
||||||
|
|
||||||
nwGUI.closeMain(True)
|
nwGUI.closeMain()
|
||||||
# qtbot.stopForInteraction()
|
# qtbot.stopForInteraction()
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
@@ -217,7 +217,7 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef):
|
|||||||
projFile = path.join(nwTempGUI,"nwProject.nwx")
|
projFile = path.join(nwTempGUI,"nwProject.nwx")
|
||||||
assert cmpFiles(projFile, path.join(nwRef,"gui","2_nwProject.nwx"), [2])
|
assert cmpFiles(projFile, path.join(nwRef,"gui","2_nwProject.nwx"), [2])
|
||||||
|
|
||||||
nwGUI.closeMain(True)
|
nwGUI.closeMain()
|
||||||
# qtbot.stopForInteraction()
|
# qtbot.stopForInteraction()
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
@@ -263,5 +263,5 @@ def testItemEditor(qtbot, nwTempGUI, nwRef):
|
|||||||
projFile = path.join(nwTempGUI,"nwProject.nwx")
|
projFile = path.join(nwTempGUI,"nwProject.nwx")
|
||||||
assert cmpFiles(projFile, path.join(nwRef,"gui","3_nwProject.nwx"), [2])
|
assert cmpFiles(projFile, path.join(nwRef,"gui","3_nwProject.nwx"), [2])
|
||||||
|
|
||||||
nwGUI.closeMain(True)
|
nwGUI.closeMain()
|
||||||
# qtbot.stopForInteraction()
|
# qtbot.stopForInteraction()
|
||||||
|
|||||||
Reference in New Issue
Block a user