Merge branch 'main' into doc_meta

This commit is contained in:
Veronica K. B. Olsen
2020-10-24 18:32:49 +02:00
27 changed files with 118 additions and 94 deletions
+15 -4
View File
@@ -152,13 +152,13 @@ def formatInt(theInt):
theVal /= 1000.0
if theVal < 1000.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:
return "%4.1f%s%s" % (theVal, nwUnicode.U_THNSP, pF)
return f"{theVal:4.1f}{nwUnicode.U_THNSP}{pF}"
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):
"""Take a number (on the format returned by time.time()) and convert
@@ -169,6 +169,17 @@ def formatTimeStamp(theTime, fileSafe=False):
else:
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):
""" Splits a version string on the form aa.bb.cc into major, minor
and patch, and computes an integer value aabbcc.
+2 -2
View File
@@ -3,7 +3,7 @@
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:
Created: 2018-09-22 [0.0.1]
@@ -911,7 +911,7 @@ class Config:
def _packList(self, inData):
"""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):
"""Parse a line and return the correct datatype.
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter Project Document
================================
Class holding a document
Class holding a single novelWriter document
File History:
Created: 2018-09-29 [0.0.1]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter Project Index
=============================
Class holding the index of tags
Class holding the project index of tags, headers and references
File History:
Created: 2019-05-27 [0.1.4]
+30 -20
View File
@@ -29,7 +29,7 @@ import logging
from lxml import etree
from nw.common import checkInt
from nw.common import checkInt, isHandle
from nw.constants import nwItemType, nwItemClass, nwItemLayout
logger = logging.getLogger(__name__)
@@ -104,27 +104,37 @@ class NWItem():
if "parent" in xItem.attrib:
self.itemParent = xItem.attrib["parent"]
setMap = {
"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,
}
retStatus = True
for xValue in xItem:
if xValue.tag in setMap:
setMap[xValue.tag](xValue.text)
if xValue.tag == "name":
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:
logger.error("Unknown tag '%s'" % xValue.tag)
retStatus = False
return True
return retStatus
@staticmethod
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.
"""
if isinstance(theHandle, str):
if len(theHandle) == 13:
if isHandle(theHandle):
self.itemHandle = theHandle
else:
self.itemHandle = None
@@ -167,7 +177,7 @@ class NWItem():
if theParent is None:
self.itemParent = None
elif isinstance(theParent, str):
if len(theParent) == 13:
if isHandle(theParent):
self.itemParent = theParent
else:
self.itemParent = None
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter Spell Check Classes
===================================
Wrapper class for spell checking
Wrapper class for spell checking tools
File History:
Created: 2019-06-11 [0.1.5]
+1 -1
View File
@@ -3,7 +3,7 @@
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:
Created: 2019-05-19 [0.1.3]
+1 -1
View File
@@ -3,7 +3,7 @@
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:
Created: 2019-05-05 [0.0.1]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter Project Tree Class
==================================
Class holding the data of the project tree
Class holding the project's tree of project items
File History:
Created: 2020-05-07 [0.4.5]
+6 -7
View File
@@ -55,14 +55,14 @@ class GuiAbout(QDialog):
self.innerBox = QHBoxLayout()
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.setMinimumHeight(self.mainConf.pxInt(600))
nPx = self.mainConf.pxInt(96)
self.nwIcon = QLabel()
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.lblDate = QLabel(datetime.strptime(nw.__date__, "%Y-%m-%d").strftime("%x"))
@@ -115,17 +115,17 @@ class GuiAbout(QDialog):
"""
listPrefix = "&nbsp;&nbsp;&bull;&nbsp;&nbsp;"
aboutMsg = (
"<h2>About {name:s}</h2>"
"<h2>About novelWriter</h2>"
"<p>{copyright:s}.</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 "
"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 "
"published by the Free Software Foundation, either version 3 of "
"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 "
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</p>"
"<p>See the License tab for the full text, or visit the GNU website "
@@ -134,7 +134,6 @@ class GuiAbout(QDialog):
"<h3>Credits</h3>"
"<p>{credits:s}</p>"
).format(
name = self.mainConf.appName,
copyright = nw.__copyright__,
website = nw.__url__,
domain = nw.__domain__,
+8 -8
View File
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
"""novelWriter GUI Build Novel
"""novelWriter GUI Build Novel Project
novelWriter GUI Build Novel
===============================
Class holding the build novel window
novelWriter GUI Build Novel Project
=======================================
Class holding the build novel project dialog
File History:
Created: 2020-05-09 [0.5]
@@ -391,11 +391,11 @@ class GuiBuildNovel(QDialog):
self.savePDF.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
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.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.saveMenu.addAction(self.saveNWD)
@@ -408,11 +408,11 @@ class GuiBuildNovel(QDialog):
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
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.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.saveMenu.addAction(self.saveJsonM)
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Document Editor
===================================
Class holding the document editor
Class holding the main document editor
File History:
Created: 2018-09-29 [0.0.1] GuiDocEditor
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Document Highlighter
========================================
Syntax highlighting for MarkDown
Subclass for the main editor syntax highlighting
File History:
Created: 2019-04-06 [0.0.1]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Doc Merge
=============================
Tool for merging multiple documents to one
Tool for merging multiple documents to one document
File History:
Created: 2020-01-23 [0.4.3]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Document Viewer
===================================
Class holding the document html viewer
Class holding the main document viewer
File History:
Created: 2019-05-10 [0.0.1] GuiDocViewer
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Document Details
====================================
Class holding the left side document details panel
Class holding the project tree item details panel
File History:
Created: 2019-04-24 [0.0.1]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Item Editor
===============================
Class holding the item editor
Class holding the item editor dialog
File History:
Created: 2019-04-27 [0.0.1]
+5 -5
View File
@@ -3,10 +3,10 @@
novelWriter GUI Main Menu
=============================
Class holding the main window
Class holding the main window menu
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
Copyright 20182020, Veronica Berglyd Olsen
@@ -274,7 +274,7 @@ class GuiMainMenu(QMenuBar):
# Project > Exit
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.setMenuRole(QAction.QuitRole)
self.aExitNW.triggered.connect(lambda: self.theParent.closeMain())
@@ -857,8 +857,8 @@ class GuiMainMenu(QMenuBar):
self.helpMenu = self.addMenu("&Help")
# Help > About
self.aAboutNW = QAction("About %s" % self.mainConf.appName, self)
self.aAboutNW.setStatusTip("About %s" % self.mainConf.appName)
self.aAboutNW = QAction("About novelWriter", self)
self.aAboutNW.setStatusTip("About novelWriter")
self.aAboutNW.setMenuRole(QAction.AboutRole)
self.aAboutNW.triggered.connect(lambda: self.theParent.showAboutNWDialog())
self.helpMenu.addAction(self.aAboutNW)
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Project Outline Details
===========================================
Class holding the project outline details view
Class holding the project outline details panel
File History:
Created: 2020-06-02 [0.7.0]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Open Project
================================
The open project dialog
Class holding the load/browse/new project dialog
File History:
Created: 2020-02-26 [0.4.5]
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI project Tree
================================
Class holding the left side project tree view
Class holding the project tree view
File History:
Created: 2018-09-29 [0.0.1] GuiProjectTree
+2 -4
View File
@@ -35,6 +35,7 @@ from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
from nw.core import NWSpellCheck
from nw.common import formatTime
logger = logging.getLogger(__name__)
@@ -206,10 +207,7 @@ class GuiMainStatus(QStatusBar):
if self.refTime is None:
self.timeText.setText("00:00:00")
else:
tS = int(time() - self.refTime)
self.timeText.setText(
f"{tS//3600:02d}:{tS%3600//60:02d}:{tS%60:02d}"
)
self.timeText.setText(formatTime(round(time() - self.refTime)))
return
# END Class GuiMainStatus
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter Theme and Icons Classs
======================================
This class reads and stores the themes and the icons
Class managing and caching themes and icons
File History:
Created: 2019-05-18 [0.1.3] GuiTheme
+12 -24
View File
@@ -3,7 +3,7 @@
novelWriter GUI Writing Statistics
======================================
Class showing the word count and session statistics
Class holding the word count and session statistics dialog
File History:
Created: 2019-10-20 [0.3]
@@ -39,6 +39,7 @@ from PyQt5.QtWidgets import (
QLabel, QGroupBox, QMenu, QAction, QFileDialog, QSpinBox, QHBoxLayout
)
from nw.common import formatTime
from nw.constants import nwConst, nwFiles, nwAlert
from nw.gui.custom import QSwitch
@@ -123,11 +124,11 @@ class GuiWritingStats(QDialog):
self.infoForm = QGridLayout(self)
self.infoBox.setLayout(self.infoForm)
self.labelTotal = QLabel(self._formatTime(0))
self.labelTotal = QLabel(formatTime(0))
self.labelTotal.setFont(self.theTheme.guiFontFixed)
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.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
@@ -367,32 +368,28 @@ class GuiWritingStats(QDialog):
elif dataFmt == self.FMT_CSV:
outFile.write(
"\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n" % (
"Date", "Length (sec)", "Words Changed", "Novel Words", "Note Words"
)
'"Date","Length (sec)","Words Changed","Novel Words","Note Words"\n'
)
for _, sD, tT, wD, wA, wB in self.filterData:
outFile.write(
"\"%s\",%d,%d,%d,%d\n" % (sD, tT, wD, wA, wB)
)
outFile.write(f'"{sD}",{tT:.0f},{wD},{wA},{wB}\n')
wSuccess = True
else:
errMsg = "Unknown format"
except Exception as e:
errMsg = str(e)
errMsg = str(e).replace("\n", "<br>")
# Report to user
if wSuccess:
self.theParent.makeAlert(
"%s file successfully written to:<br> %s" % (
"%s file successfully written to:<br>%s" % (
textFmt, savePath
), nwAlert.INFO
)
else:
self.theParent.makeAlert(
"Failed to write %s file. %s" % (
"Failed to write %s file.<br>%s" % (
textFmt, errMsg
), nwAlert.ERROR
)
@@ -455,7 +452,7 @@ class GuiWritingStats(QDialog):
return False
ttWords = ttNovel + ttNotes
self.labelTotal.setText(self._formatTime(ttTime))
self.labelTotal.setText(formatTime(round(ttTime)))
self.novelWords.setText(f"{ttNovel:n}")
self.notesWords.setText(f"{ttNotes:n}")
self.totalWords.setText(f"{ttWords:n}")
@@ -544,7 +541,7 @@ class GuiWritingStats(QDialog):
newItem = QTreeWidgetItem()
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}")
if nWords > 0 and listMax > 0:
@@ -567,17 +564,8 @@ class GuiWritingStats(QDialog):
self.listBox.addTopLevelItem(newItem)
self.timeFilter += sDiff
self.labelFilter.setText(self._formatTime(self.timeFilter))
self.labelFilter.setText(formatTime(round(self.timeFilter)))
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
+1 -1
View File
@@ -3,7 +3,7 @@
novelWriter GUI Main Window
===============================
Class holding the main window
Class holding the main application window
File History:
Created: 2018-09-22 [0.0.1]
+20 -2
View File
@@ -7,7 +7,7 @@ import pytest
from nw.common import (
checkString, checkBool, checkInt, colRange, formatInt, transferCase,
fuzzyTime, checkHandle, formatTimeStamp
fuzzyTime, checkHandle, formatTimeStamp, formatTime
)
from nwtools import cmpList
@@ -78,11 +78,29 @@ def testColRange():
)
@pytest.mark.core
def testFormatTime():
def testFormatTimeStamp():
tTime = time.mktime(time.gmtime(0))
assert formatTimeStamp(tTime, False) == "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
def testFormatInt():
assert formatInt(1000) == "1000"
+1 -1
View File
@@ -252,7 +252,7 @@ def testItemXMLPackUnpack(nwDummy):
xDummy = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
xParam = etree.SubElement(xDummy, "invalid")
xParam.text = "stuff"
assert theItem.unpackXML(xDummy) # Passes, but not saved
assert not theItem.unpackXML(xDummy)
# Pack Valid Item
xDummy = etree.SubElement(nwXML, "group")