Merge branch 'main' into doc_meta
This commit is contained in:
+15
-4
@@ -152,13 +152,13 @@ def formatInt(theInt):
|
|||||||
theVal /= 1000.0
|
theVal /= 1000.0
|
||||||
if theVal < 1000.0:
|
if theVal < 1000.0:
|
||||||
if theVal < 10.0:
|
if theVal < 10.0:
|
||||||
return "%4.2f%s%s" % (theVal, nwUnicode.U_THNSP, pF)
|
return f"{theVal:4.2f}{nwUnicode.U_THNSP}{pF}"
|
||||||
elif theVal < 100.0:
|
elif theVal < 100.0:
|
||||||
return "%4.1f%s%s" % (theVal, nwUnicode.U_THNSP, pF)
|
return f"{theVal:4.1f}{nwUnicode.U_THNSP}{pF}"
|
||||||
else:
|
else:
|
||||||
return "%3.0f%s%s" % (theVal, nwUnicode.U_THNSP, pF)
|
return f"{theVal:3.0f}{nwUnicode.U_THNSP}{pF}"
|
||||||
|
|
||||||
return "%d" % theInt
|
return str(theInt)
|
||||||
|
|
||||||
def formatTimeStamp(theTime, fileSafe=False):
|
def formatTimeStamp(theTime, fileSafe=False):
|
||||||
"""Take a number (on the format returned by time.time()) and convert
|
"""Take a number (on the format returned by time.time()) and convert
|
||||||
@@ -169,6 +169,17 @@ def formatTimeStamp(theTime, fileSafe=False):
|
|||||||
else:
|
else:
|
||||||
return datetime.fromtimestamp(theTime).strftime(nwConst.tStampFmt)
|
return datetime.fromtimestamp(theTime).strftime(nwConst.tStampFmt)
|
||||||
|
|
||||||
|
def formatTime(tS):
|
||||||
|
"""Format a time in seconds in HH:MM:SS format or d-HH:MM:SS format
|
||||||
|
if a full day or longer.
|
||||||
|
"""
|
||||||
|
if isinstance(tS, int):
|
||||||
|
if tS >= 86400:
|
||||||
|
return f"{tS//86400:d}-{tS%86400//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
|
||||||
|
else:
|
||||||
|
return f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
|
||||||
|
return "ERROR"
|
||||||
|
|
||||||
def splitVersionNumber(vString):
|
def splitVersionNumber(vString):
|
||||||
""" Splits a version string on the form aa.bb.cc into major, minor
|
""" Splits a version string on the form aa.bb.cc into major, minor
|
||||||
and patch, and computes an integer value aabbcc.
|
and patch, and computes an integer value aabbcc.
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Config Class
|
novelWriter – Config Class
|
||||||
============================
|
============================
|
||||||
This class reads and store the main preferences of the application
|
Class reading and holding the preferences of the application
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-22 [0.0.1]
|
Created: 2018-09-22 [0.0.1]
|
||||||
@@ -911,7 +911,7 @@ class Config:
|
|||||||
def _packList(self, inData):
|
def _packList(self, inData):
|
||||||
"""Pack a list of items into a comma separated string.
|
"""Pack a list of items into a comma separated string.
|
||||||
"""
|
"""
|
||||||
return ", ".join(str(inVal) for inVal in inData)
|
return ", ".join([str(inVal) for inVal in inData])
|
||||||
|
|
||||||
def _parseLine(self, cnfParse, cnfSec, cnfName, cnfType, cnfDefault):
|
def _parseLine(self, cnfParse, cnfSec, cnfName, cnfType, cnfDefault):
|
||||||
"""Parse a line and return the correct datatype.
|
"""Parse a line and return the correct datatype.
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Project Document
|
novelWriter – Project Document
|
||||||
================================
|
================================
|
||||||
Class holding a document
|
Class holding a single novelWriter document
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-29 [0.0.1]
|
Created: 2018-09-29 [0.0.1]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Project Index
|
novelWriter – Project Index
|
||||||
=============================
|
=============================
|
||||||
Class holding the index of tags
|
Class holding the project index of tags, headers and references
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-27 [0.1.4]
|
Created: 2019-05-27 [0.1.4]
|
||||||
|
|||||||
+30
-20
@@ -29,7 +29,7 @@ import logging
|
|||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from nw.common import checkInt
|
from nw.common import checkInt, isHandle
|
||||||
from nw.constants import nwItemType, nwItemClass, nwItemLayout
|
from nw.constants import nwItemType, nwItemClass, nwItemLayout
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -104,27 +104,37 @@ class NWItem():
|
|||||||
if "parent" in xItem.attrib:
|
if "parent" in xItem.attrib:
|
||||||
self.itemParent = xItem.attrib["parent"]
|
self.itemParent = xItem.attrib["parent"]
|
||||||
|
|
||||||
setMap = {
|
retStatus = True
|
||||||
"name" : self.setName,
|
|
||||||
"order" : self.setOrder,
|
|
||||||
"type" : self.setType,
|
|
||||||
"class" : self.setClass,
|
|
||||||
"layout" : self.setLayout,
|
|
||||||
"status" : self.setStatus,
|
|
||||||
"expanded" : self.setExpanded,
|
|
||||||
"exported" : self.setExported,
|
|
||||||
"charCount" : self.setCharCount,
|
|
||||||
"wordCount" : self.setWordCount,
|
|
||||||
"paraCount" : self.setParaCount,
|
|
||||||
"cursorPos" : self.setCursorPos,
|
|
||||||
}
|
|
||||||
for xValue in xItem:
|
for xValue in xItem:
|
||||||
if xValue.tag in setMap:
|
if xValue.tag == "name":
|
||||||
setMap[xValue.tag](xValue.text)
|
self.setName(xValue.text)
|
||||||
|
elif xValue.tag == "order":
|
||||||
|
self.setOrder(xValue.text)
|
||||||
|
elif xValue.tag == "type":
|
||||||
|
self.setType(xValue.text)
|
||||||
|
elif xValue.tag == "class":
|
||||||
|
self.setClass(xValue.text)
|
||||||
|
elif xValue.tag == "layout":
|
||||||
|
self.setLayout(xValue.text)
|
||||||
|
elif xValue.tag == "status":
|
||||||
|
self.setStatus(xValue.text)
|
||||||
|
elif xValue.tag == "expanded":
|
||||||
|
self.setExpanded(xValue.text)
|
||||||
|
elif xValue.tag == "exported":
|
||||||
|
self.setExported(xValue.text)
|
||||||
|
elif xValue.tag == "charCount":
|
||||||
|
self.setCharCount(xValue.text)
|
||||||
|
elif xValue.tag == "wordCount":
|
||||||
|
self.setWordCount(xValue.text)
|
||||||
|
elif xValue.tag == "paraCount":
|
||||||
|
self.setParaCount(xValue.text)
|
||||||
|
elif xValue.tag == "cursorPos":
|
||||||
|
self.setCursorPos(xValue.text)
|
||||||
else:
|
else:
|
||||||
logger.error("Unknown tag '%s'" % xValue.tag)
|
logger.error("Unknown tag '%s'" % xValue.tag)
|
||||||
|
retStatus = False
|
||||||
|
|
||||||
return True
|
return retStatus
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _subPack(xParent, name, attrib=None, text=None, none=True):
|
def _subPack(xParent, name, attrib=None, text=None, none=True):
|
||||||
@@ -153,7 +163,7 @@ class NWItem():
|
|||||||
"""Set the item handle, and ensure it is valid.
|
"""Set the item handle, and ensure it is valid.
|
||||||
"""
|
"""
|
||||||
if isinstance(theHandle, str):
|
if isinstance(theHandle, str):
|
||||||
if len(theHandle) == 13:
|
if isHandle(theHandle):
|
||||||
self.itemHandle = theHandle
|
self.itemHandle = theHandle
|
||||||
else:
|
else:
|
||||||
self.itemHandle = None
|
self.itemHandle = None
|
||||||
@@ -167,7 +177,7 @@ class NWItem():
|
|||||||
if theParent is None:
|
if theParent is None:
|
||||||
self.itemParent = None
|
self.itemParent = None
|
||||||
elif isinstance(theParent, str):
|
elif isinstance(theParent, str):
|
||||||
if len(theParent) == 13:
|
if isHandle(theParent):
|
||||||
self.itemParent = theParent
|
self.itemParent = theParent
|
||||||
else:
|
else:
|
||||||
self.itemParent = None
|
self.itemParent = None
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Spell Check Classes
|
novelWriter – Spell Check Classes
|
||||||
===================================
|
===================================
|
||||||
Wrapper class for spell checking
|
Wrapper class for spell checking tools
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-06-11 [0.1.5]
|
Created: 2019-06-11 [0.1.5]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Project Item Status Class
|
novelWriter – Project Item Status Class
|
||||||
=========================================
|
=========================================
|
||||||
Class holding the status elements of a project item
|
Class holding the status/importance elements of a project item
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-19 [0.1.3]
|
Created: 2019-05-19 [0.1.3]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Text Tokenizer
|
novelWriter – Text Tokenizer
|
||||||
==============================
|
==============================
|
||||||
Splits a piece of nW markdown text into its elements
|
Splits a piece of novelWriter markdown text into its elements
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-05 [0.0.1]
|
Created: 2019-05-05 [0.0.1]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Project Tree Class
|
novelWriter – Project Tree Class
|
||||||
==================================
|
==================================
|
||||||
Class holding the data of the project tree
|
Class holding the project's tree of project items
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2020-05-07 [0.4.5]
|
Created: 2020-05-07 [0.4.5]
|
||||||
|
|||||||
+6
-7
@@ -55,14 +55,14 @@ class GuiAbout(QDialog):
|
|||||||
self.innerBox = QHBoxLayout()
|
self.innerBox = QHBoxLayout()
|
||||||
self.innerBox.setSpacing(self.mainConf.pxInt(16))
|
self.innerBox.setSpacing(self.mainConf.pxInt(16))
|
||||||
|
|
||||||
self.setWindowTitle("About %s" % self.mainConf.appName)
|
self.setWindowTitle("About novelWriter")
|
||||||
self.setMinimumWidth(self.mainConf.pxInt(650))
|
self.setMinimumWidth(self.mainConf.pxInt(650))
|
||||||
self.setMinimumHeight(self.mainConf.pxInt(600))
|
self.setMinimumHeight(self.mainConf.pxInt(600))
|
||||||
|
|
||||||
nPx = self.mainConf.pxInt(96)
|
nPx = self.mainConf.pxInt(96)
|
||||||
self.nwIcon = QLabel()
|
self.nwIcon = QLabel()
|
||||||
self.nwIcon.setPixmap(self.theParent.theTheme.getPixmap("novelwriter", (nPx, nPx)))
|
self.nwIcon.setPixmap(self.theParent.theTheme.getPixmap("novelwriter", (nPx, nPx)))
|
||||||
self.lblName = QLabel("<b>%s</b>" % self.mainConf.appName)
|
self.lblName = QLabel("<b>novelWriter</b>")
|
||||||
self.lblVers = QLabel("v%s" % nw.__version__)
|
self.lblVers = QLabel("v%s" % nw.__version__)
|
||||||
self.lblDate = QLabel(datetime.strptime(nw.__date__, "%Y-%m-%d").strftime("%x"))
|
self.lblDate = QLabel(datetime.strptime(nw.__date__, "%Y-%m-%d").strftime("%x"))
|
||||||
|
|
||||||
@@ -115,17 +115,17 @@ class GuiAbout(QDialog):
|
|||||||
"""
|
"""
|
||||||
listPrefix = " • "
|
listPrefix = " • "
|
||||||
aboutMsg = (
|
aboutMsg = (
|
||||||
"<h2>About {name:s}</h2>"
|
"<h2>About novelWriter</h2>"
|
||||||
"<p>{copyright:s}.</p>"
|
"<p>{copyright:s}.</p>"
|
||||||
"<p>Website: <a href='{website:s}'>{domain:s}</a></p>"
|
"<p>Website: <a href='{website:s}'>{domain:s}</a></p>"
|
||||||
"<p>{name:s} is a markdown-like text editor designed for "
|
"<p>novelWriter is a markdown-like text editor designed for "
|
||||||
"organising and writing novels. It is written in Python 3 with a "
|
"organising and writing novels. It is written in Python 3 with a "
|
||||||
"Qt5 GUI, using PyQt5.</p>"
|
"Qt5 GUI, using PyQt5.</p>"
|
||||||
"<p>{name:s} is free software: you can redistribute it and/or "
|
"<p>novelWriter is free software: you can redistribute it and/or "
|
||||||
"modify it under the terms of the GNU General Public License as "
|
"modify it under the terms of the GNU General Public License as "
|
||||||
"published by the Free Software Foundation, either version 3 of "
|
"published by the Free Software Foundation, either version 3 of "
|
||||||
"the License, or (at your option) any later version.</p>"
|
"the License, or (at your option) any later version.</p>"
|
||||||
"<p>{name:s} is distributed in the hope that it will be useful, "
|
"<p>novelWriter is distributed in the hope that it will be useful, "
|
||||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of "
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of "
|
||||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</p>"
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</p>"
|
||||||
"<p>See the License tab for the full text, or visit the GNU website "
|
"<p>See the License tab for the full text, or visit the GNU website "
|
||||||
@@ -134,7 +134,6 @@ class GuiAbout(QDialog):
|
|||||||
"<h3>Credits</h3>"
|
"<h3>Credits</h3>"
|
||||||
"<p>{credits:s}</p>"
|
"<p>{credits:s}</p>"
|
||||||
).format(
|
).format(
|
||||||
name = self.mainConf.appName,
|
|
||||||
copyright = nw.__copyright__,
|
copyright = nw.__copyright__,
|
||||||
website = nw.__url__,
|
website = nw.__url__,
|
||||||
domain = nw.__domain__,
|
domain = nw.__domain__,
|
||||||
|
|||||||
+8
-8
@@ -1,9 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""novelWriter GUI Build Novel
|
"""novelWriter GUI Build Novel Project
|
||||||
|
|
||||||
novelWriter – GUI Build Novel
|
novelWriter – GUI Build Novel Project
|
||||||
===============================
|
=======================================
|
||||||
Class holding the build novel window
|
Class holding the build novel project dialog
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2020-05-09 [0.5]
|
Created: 2020-05-09 [0.5]
|
||||||
@@ -391,11 +391,11 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.savePDF.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
|
self.savePDF.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
|
||||||
self.saveMenu.addAction(self.savePDF)
|
self.saveMenu.addAction(self.savePDF)
|
||||||
|
|
||||||
self.saveHTM = QAction("%s HTML (.htm)" % self.mainConf.appName, self)
|
self.saveHTM = QAction("novelWriter HTML (.htm)", self)
|
||||||
self.saveHTM.triggered.connect(lambda: self._saveDocument(self.FMT_HTM))
|
self.saveHTM.triggered.connect(lambda: self._saveDocument(self.FMT_HTM))
|
||||||
self.saveMenu.addAction(self.saveHTM)
|
self.saveMenu.addAction(self.saveHTM)
|
||||||
|
|
||||||
self.saveNWD = QAction("%s Markdown (.nwd)" % self.mainConf.appName, self)
|
self.saveNWD = QAction("novelWriter Markdown (.nwd)", self)
|
||||||
self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD))
|
self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD))
|
||||||
self.saveMenu.addAction(self.saveNWD)
|
self.saveMenu.addAction(self.saveNWD)
|
||||||
|
|
||||||
@@ -408,11 +408,11 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
|
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
|
||||||
self.saveMenu.addAction(self.saveTXT)
|
self.saveMenu.addAction(self.saveTXT)
|
||||||
|
|
||||||
self.saveJsonH = QAction("JSON + %s HTML (.json)" % self.mainConf.appName, self)
|
self.saveJsonH = QAction("JSON + novelWriter HTML (.json)", self)
|
||||||
self.saveJsonH.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_H))
|
self.saveJsonH.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_H))
|
||||||
self.saveMenu.addAction(self.saveJsonH)
|
self.saveMenu.addAction(self.saveJsonH)
|
||||||
|
|
||||||
self.saveJsonM = QAction("JSON + %s Markdown (.json)" % self.mainConf.appName, self)
|
self.saveJsonM = QAction("JSON + novelWriters Markdown (.json)", self)
|
||||||
self.saveJsonM.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_M))
|
self.saveJsonM.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_M))
|
||||||
self.saveMenu.addAction(self.saveJsonM)
|
self.saveMenu.addAction(self.saveJsonM)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Document Editor
|
novelWriter – GUI Document Editor
|
||||||
===================================
|
===================================
|
||||||
Class holding the document editor
|
Class holding the main document editor
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-29 [0.0.1] GuiDocEditor
|
Created: 2018-09-29 [0.0.1] GuiDocEditor
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Document Highlighter
|
novelWriter – GUI Document Highlighter
|
||||||
========================================
|
========================================
|
||||||
Syntax highlighting for MarkDown
|
Subclass for the main editor syntax highlighting
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-04-06 [0.0.1]
|
Created: 2019-04-06 [0.0.1]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Doc Merge
|
novelWriter – GUI Doc Merge
|
||||||
=============================
|
=============================
|
||||||
Tool for merging multiple documents to one
|
Tool for merging multiple documents to one document
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2020-01-23 [0.4.3]
|
Created: 2020-01-23 [0.4.3]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Document Viewer
|
novelWriter – GUI Document Viewer
|
||||||
===================================
|
===================================
|
||||||
Class holding the document html viewer
|
Class holding the main document viewer
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-10 [0.0.1] GuiDocViewer
|
Created: 2019-05-10 [0.0.1] GuiDocViewer
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Document Details
|
novelWriter – GUI Document Details
|
||||||
====================================
|
====================================
|
||||||
Class holding the left side document details panel
|
Class holding the project tree item details panel
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-04-24 [0.0.1]
|
Created: 2019-04-24 [0.0.1]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Item Editor
|
novelWriter – GUI Item Editor
|
||||||
===============================
|
===============================
|
||||||
Class holding the item editor
|
Class holding the item editor dialog
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-04-27 [0.0.1]
|
Created: 2019-04-27 [0.0.1]
|
||||||
|
|||||||
+5
-5
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
novelWriter – GUI Main Menu
|
novelWriter – GUI Main Menu
|
||||||
=============================
|
=============================
|
||||||
Class holding the main window
|
Class holding the main window menu
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-04-27 [0.0.1] (Split from winmain)
|
Created: 2019-04-27 [0.0.1]
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2020, Veronica Berglyd Olsen
|
Copyright 2018–2020, Veronica Berglyd Olsen
|
||||||
@@ -274,7 +274,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
|
|
||||||
# Project > Exit
|
# Project > Exit
|
||||||
self.aExitNW = QAction("Exit", self)
|
self.aExitNW = QAction("Exit", self)
|
||||||
self.aExitNW.setStatusTip("Exit %s" % self.mainConf.appName)
|
self.aExitNW.setStatusTip("Exit novelWriter")
|
||||||
self.aExitNW.setShortcut("Ctrl+Q")
|
self.aExitNW.setShortcut("Ctrl+Q")
|
||||||
self.aExitNW.setMenuRole(QAction.QuitRole)
|
self.aExitNW.setMenuRole(QAction.QuitRole)
|
||||||
self.aExitNW.triggered.connect(lambda: self.theParent.closeMain())
|
self.aExitNW.triggered.connect(lambda: self.theParent.closeMain())
|
||||||
@@ -857,8 +857,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.helpMenu = self.addMenu("&Help")
|
self.helpMenu = self.addMenu("&Help")
|
||||||
|
|
||||||
# Help > About
|
# Help > About
|
||||||
self.aAboutNW = QAction("About %s" % self.mainConf.appName, self)
|
self.aAboutNW = QAction("About novelWriter", self)
|
||||||
self.aAboutNW.setStatusTip("About %s" % self.mainConf.appName)
|
self.aAboutNW.setStatusTip("About novelWriter")
|
||||||
self.aAboutNW.setMenuRole(QAction.AboutRole)
|
self.aAboutNW.setMenuRole(QAction.AboutRole)
|
||||||
self.aAboutNW.triggered.connect(lambda: self.theParent.showAboutNWDialog())
|
self.aAboutNW.triggered.connect(lambda: self.theParent.showAboutNWDialog())
|
||||||
self.helpMenu.addAction(self.aAboutNW)
|
self.helpMenu.addAction(self.aAboutNW)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Project Outline Details
|
novelWriter – GUI Project Outline Details
|
||||||
===========================================
|
===========================================
|
||||||
Class holding the project outline details view
|
Class holding the project outline details panel
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2020-06-02 [0.7.0]
|
Created: 2020-06-02 [0.7.0]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Open Project
|
novelWriter – GUI Open Project
|
||||||
================================
|
================================
|
||||||
The open project dialog
|
Class holding the load/browse/new project dialog
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2020-02-26 [0.4.5]
|
Created: 2020-02-26 [0.4.5]
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI project Tree
|
novelWriter – GUI project Tree
|
||||||
================================
|
================================
|
||||||
Class holding the left side project tree view
|
Class holding the project tree view
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
||||||
|
|||||||
+2
-4
@@ -35,6 +35,7 @@ from PyQt5.QtGui import QColor, QPainter
|
|||||||
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
||||||
|
|
||||||
from nw.core import NWSpellCheck
|
from nw.core import NWSpellCheck
|
||||||
|
from nw.common import formatTime
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -206,10 +207,7 @@ class GuiMainStatus(QStatusBar):
|
|||||||
if self.refTime is None:
|
if self.refTime is None:
|
||||||
self.timeText.setText("00:00:00")
|
self.timeText.setText("00:00:00")
|
||||||
else:
|
else:
|
||||||
tS = int(time() - self.refTime)
|
self.timeText.setText(formatTime(round(time() - self.refTime)))
|
||||||
self.timeText.setText(
|
|
||||||
f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiMainStatus
|
# END Class GuiMainStatus
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – Theme and Icons Classs
|
novelWriter – Theme and Icons Classs
|
||||||
======================================
|
======================================
|
||||||
This class reads and stores the themes and the icons
|
Class managing and caching themes and icons
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-05-18 [0.1.3] GuiTheme
|
Created: 2019-05-18 [0.1.3] GuiTheme
|
||||||
|
|||||||
+12
-24
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Writing Statistics
|
novelWriter – GUI Writing Statistics
|
||||||
======================================
|
======================================
|
||||||
Class showing the word count and session statistics
|
Class holding the word count and session statistics dialog
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-10-20 [0.3]
|
Created: 2019-10-20 [0.3]
|
||||||
@@ -39,6 +39,7 @@ from PyQt5.QtWidgets import (
|
|||||||
QLabel, QGroupBox, QMenu, QAction, QFileDialog, QSpinBox, QHBoxLayout
|
QLabel, QGroupBox, QMenu, QAction, QFileDialog, QSpinBox, QHBoxLayout
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from nw.common import formatTime
|
||||||
from nw.constants import nwConst, nwFiles, nwAlert
|
from nw.constants import nwConst, nwFiles, nwAlert
|
||||||
from nw.gui.custom import QSwitch
|
from nw.gui.custom import QSwitch
|
||||||
|
|
||||||
@@ -123,11 +124,11 @@ class GuiWritingStats(QDialog):
|
|||||||
self.infoForm = QGridLayout(self)
|
self.infoForm = QGridLayout(self)
|
||||||
self.infoBox.setLayout(self.infoForm)
|
self.infoBox.setLayout(self.infoForm)
|
||||||
|
|
||||||
self.labelTotal = QLabel(self._formatTime(0))
|
self.labelTotal = QLabel(formatTime(0))
|
||||||
self.labelTotal.setFont(self.theTheme.guiFontFixed)
|
self.labelTotal.setFont(self.theTheme.guiFontFixed)
|
||||||
self.labelTotal.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
|
self.labelTotal.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
|
||||||
|
|
||||||
self.labelFilter = QLabel(self._formatTime(0))
|
self.labelFilter = QLabel(formatTime(0))
|
||||||
self.labelFilter.setFont(self.theTheme.guiFontFixed)
|
self.labelFilter.setFont(self.theTheme.guiFontFixed)
|
||||||
self.labelFilter.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
|
self.labelFilter.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
|
||||||
|
|
||||||
@@ -367,32 +368,28 @@ class GuiWritingStats(QDialog):
|
|||||||
|
|
||||||
elif dataFmt == self.FMT_CSV:
|
elif dataFmt == self.FMT_CSV:
|
||||||
outFile.write(
|
outFile.write(
|
||||||
"\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n" % (
|
'"Date","Length (sec)","Words Changed","Novel Words","Note Words"\n'
|
||||||
"Date", "Length (sec)", "Words Changed", "Novel Words", "Note Words"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
for _, sD, tT, wD, wA, wB in self.filterData:
|
for _, sD, tT, wD, wA, wB in self.filterData:
|
||||||
outFile.write(
|
outFile.write(f'"{sD}",{tT:.0f},{wD},{wA},{wB}\n')
|
||||||
"\"%s\",%d,%d,%d,%d\n" % (sD, tT, wD, wA, wB)
|
|
||||||
)
|
|
||||||
wSuccess = True
|
wSuccess = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
errMsg = "Unknown format"
|
errMsg = "Unknown format"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errMsg = str(e)
|
errMsg = str(e).replace("\n", "<br>")
|
||||||
|
|
||||||
# Report to user
|
# Report to user
|
||||||
if wSuccess:
|
if wSuccess:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
"%s file successfully written to:<br> %s" % (
|
"%s file successfully written to:<br>%s" % (
|
||||||
textFmt, savePath
|
textFmt, savePath
|
||||||
), nwAlert.INFO
|
), nwAlert.INFO
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.theParent.makeAlert(
|
self.theParent.makeAlert(
|
||||||
"Failed to write %s file. %s" % (
|
"Failed to write %s file.<br>%s" % (
|
||||||
textFmt, errMsg
|
textFmt, errMsg
|
||||||
), nwAlert.ERROR
|
), nwAlert.ERROR
|
||||||
)
|
)
|
||||||
@@ -455,7 +452,7 @@ class GuiWritingStats(QDialog):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
ttWords = ttNovel + ttNotes
|
ttWords = ttNovel + ttNotes
|
||||||
self.labelTotal.setText(self._formatTime(ttTime))
|
self.labelTotal.setText(formatTime(round(ttTime)))
|
||||||
self.novelWords.setText(f"{ttNovel:n}")
|
self.novelWords.setText(f"{ttNovel:n}")
|
||||||
self.notesWords.setText(f"{ttNotes:n}")
|
self.notesWords.setText(f"{ttNotes:n}")
|
||||||
self.totalWords.setText(f"{ttWords:n}")
|
self.totalWords.setText(f"{ttWords:n}")
|
||||||
@@ -544,7 +541,7 @@ class GuiWritingStats(QDialog):
|
|||||||
|
|
||||||
newItem = QTreeWidgetItem()
|
newItem = QTreeWidgetItem()
|
||||||
newItem.setText(self.C_TIME, sStart)
|
newItem.setText(self.C_TIME, sStart)
|
||||||
newItem.setText(self.C_LENGTH, self._formatTime(sDiff))
|
newItem.setText(self.C_LENGTH, formatTime(round(sDiff)))
|
||||||
newItem.setText(self.C_COUNT, f"{nWords:n}")
|
newItem.setText(self.C_COUNT, f"{nWords:n}")
|
||||||
|
|
||||||
if nWords > 0 and listMax > 0:
|
if nWords > 0 and listMax > 0:
|
||||||
@@ -567,17 +564,8 @@ class GuiWritingStats(QDialog):
|
|||||||
self.listBox.addTopLevelItem(newItem)
|
self.listBox.addTopLevelItem(newItem)
|
||||||
self.timeFilter += sDiff
|
self.timeFilter += sDiff
|
||||||
|
|
||||||
self.labelFilter.setText(self._formatTime(self.timeFilter))
|
self.labelFilter.setText(formatTime(round(self.timeFilter)))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _formatTime(self, tS):
|
|
||||||
"""Format the time spent in 00:00:00 format.
|
|
||||||
"""
|
|
||||||
tM = int(tS/60)
|
|
||||||
tH = int(tM/60)
|
|
||||||
tM = tM - tH*60
|
|
||||||
tS = tS - tM*60 - tH*3600
|
|
||||||
return "%02d:%02d:%02d" % (tH, tM, tS)
|
|
||||||
|
|
||||||
# END Class GuiWritingStats
|
# END Class GuiWritingStats
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
novelWriter – GUI Main Window
|
novelWriter – GUI Main Window
|
||||||
===============================
|
===============================
|
||||||
Class holding the main window
|
Class holding the main application window
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-22 [0.0.1]
|
Created: 2018-09-22 [0.0.1]
|
||||||
|
|||||||
+20
-2
@@ -7,7 +7,7 @@ import pytest
|
|||||||
|
|
||||||
from nw.common import (
|
from nw.common import (
|
||||||
checkString, checkBool, checkInt, colRange, formatInt, transferCase,
|
checkString, checkBool, checkInt, colRange, formatInt, transferCase,
|
||||||
fuzzyTime, checkHandle, formatTimeStamp
|
fuzzyTime, checkHandle, formatTimeStamp, formatTime
|
||||||
)
|
)
|
||||||
from nwtools import cmpList
|
from nwtools import cmpList
|
||||||
|
|
||||||
@@ -78,11 +78,29 @@ def testColRange():
|
|||||||
)
|
)
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testFormatTime():
|
def testFormatTimeStamp():
|
||||||
tTime = time.mktime(time.gmtime(0))
|
tTime = time.mktime(time.gmtime(0))
|
||||||
assert formatTimeStamp(tTime, False) == "1970-01-01 00:00:00"
|
assert formatTimeStamp(tTime, False) == "1970-01-01 00:00:00"
|
||||||
assert formatTimeStamp(tTime, True) == "1970-01-01 00.00.00"
|
assert formatTimeStamp(tTime, True) == "1970-01-01 00.00.00"
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testFormatTime():
|
||||||
|
assert formatTime("1") == "ERROR"
|
||||||
|
assert formatTime(1.0) == "ERROR"
|
||||||
|
assert formatTime(1) == "00:00:01"
|
||||||
|
assert formatTime(59) == "00:00:59"
|
||||||
|
assert formatTime(60) == "00:01:00"
|
||||||
|
assert formatTime(180) == "00:03:00"
|
||||||
|
assert formatTime(194) == "00:03:14"
|
||||||
|
assert formatTime(3540) == "00:59:00"
|
||||||
|
assert formatTime(3599) == "00:59:59"
|
||||||
|
assert formatTime(3600) == "01:00:00"
|
||||||
|
assert formatTime(11640) == "03:14:00"
|
||||||
|
assert formatTime(11655) == "03:14:15"
|
||||||
|
assert formatTime(86399) == "23:59:59"
|
||||||
|
assert formatTime(86400) == "1-00:00:00"
|
||||||
|
assert formatTime(360000) == "4-04:00:00"
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testFormatInt():
|
def testFormatInt():
|
||||||
assert formatInt(1000) == "1000"
|
assert formatInt(1000) == "1000"
|
||||||
|
|||||||
+1
-1
@@ -252,7 +252,7 @@ def testItemXMLPackUnpack(nwDummy):
|
|||||||
xDummy = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
|
xDummy = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
|
||||||
xParam = etree.SubElement(xDummy, "invalid")
|
xParam = etree.SubElement(xDummy, "invalid")
|
||||||
xParam.text = "stuff"
|
xParam.text = "stuff"
|
||||||
assert theItem.unpackXML(xDummy) # Passes, but not saved
|
assert not theItem.unpackXML(xDummy)
|
||||||
|
|
||||||
# Pack Valid Item
|
# Pack Valid Item
|
||||||
xDummy = etree.SubElement(nwXML, "group")
|
xDummy = etree.SubElement(nwXML, "group")
|
||||||
|
|||||||
Reference in New Issue
Block a user