=@LpU+njEDU%w8f9;952w=!
zfZOe+rlyAa`g(?jhH$xDG&eW1v$Mn0)D+=x*brvY&9YfrTU+hz?R`+GbSssx5Q0b~
z^4r+h*hF58lgZ?>?d|QX!{KNwRcVEw!nuo!i^EhZ_1y6N3$d4|d1`T3+5i9m07*qo
IM6N<$f(rfLQUCw|
literal 0
HcmV?d00001
diff --git a/setup/icons/24x24/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-24.png
similarity index 100%
rename from setup/icons/24x24/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-24.png
diff --git a/setup/icons/256x256/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-256.png
similarity index 100%
rename from setup/icons/256x256/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-256.png
diff --git a/setup/icons/32x32/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-32.png
similarity index 100%
rename from setup/icons/32x32/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-32.png
diff --git a/setup/icons/32x32@2x/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-32@2.png
similarity index 100%
rename from setup/icons/32x32@2x/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-32@2.png
diff --git a/setup/icons/48x48/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-48.png
similarity index 100%
rename from setup/icons/48x48/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-48.png
diff --git a/setup/icons/512x512/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-512.png
similarity index 100%
rename from setup/icons/512x512/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-512.png
diff --git a/setup/icons/64x64/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-64.png
similarity index 100%
rename from setup/icons/64x64/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-64.png
diff --git a/setup/icons/96x96/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-96.png
similarity index 100%
rename from setup/icons/96x96/x-novelwriter-project.png
rename to setup/icons/scaled/mime-novelwriter-96.png
From 92610ca88a6c624d954c30f4084a55faa3702c54 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Thu, 22 Oct 2020 22:33:32 +0200
Subject: [PATCH 091/104] Move the import of setuptools to where it's used
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index da2a6c34..e515e9c0 100755
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,6 @@ import os
import sys
import shutil
import subprocess
-import setuptools
# =============================================================================================== #
# Qt Assistant Documentation Builder
@@ -327,6 +326,7 @@ if __name__ == "__main__":
sys.exit(0)
# Run the standard setup
+ import setuptools
setuptools.setup()
# END Main
From 56cbf86df42efcecef0bc0183fb05f10886f4617 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Thu, 22 Oct 2020 22:34:31 +0200
Subject: [PATCH 092/104] Flake8 tag
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index e515e9c0..49cd049d 100755
--- a/setup.py
+++ b/setup.py
@@ -326,7 +326,7 @@ if __name__ == "__main__":
sys.exit(0)
# Run the standard setup
- import setuptools
+ import setuptools # noqa: F401
setuptools.setup()
# END Main
From 299b8cde1ba82db36408e22524742adbc8c7577c Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Thu, 22 Oct 2020 22:40:54 +0200
Subject: [PATCH 093/104] Update readmes with the XDG changes
---
README.md | 4 +++-
setup/README.md | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 9efa0b24..54348b1f 100644
--- a/README.md
+++ b/README.md
@@ -104,8 +104,10 @@ If you want to run directly from the source, the application can be started with
You can also create a launcher for running directly from source with:
```bash
-sudo python3 setup.py launcher
+python3 setup.py xdg-install
```
+This will install the launcher and icons for the current user.
+To install them system-wide, run the above command with `sudo` or as root.
For more install options, see [Build and Install novelWriter](setup/README.md).
diff --git a/setup/README.md b/setup/README.md
index 81479cf7..252f70cd 100644
--- a/setup/README.md
+++ b/setup/README.md
@@ -13,8 +13,9 @@ The `setup.py` is a standard Python setup script with a couple of additional opt
* `sample`: Will create a `sample.zip` file in the `nw/assets` folder.
This is the file the New Project Wizard uses to generate an example project.
If novelWriter is run from source, this file is not needed.
-* `launcher`: Will try to copy the novelWriter icons and create a novelWriter.desktop file to launch
+* `xdg-install`: Will install novelWriter icons, mimetype, and desktop and menu launcher on Linux desktops.
the application. This should work on standard Linux desktops.
+ By default, this is installed for the current user. Run with `sudo` to install system-wide.
To install novelWriter as a local Python package, run:
```bash
From bfcbf66044805b70a0f8c9d609ede51fe802f5a9 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Thu, 22 Oct 2020 23:00:06 +0200
Subject: [PATCH 094/104] Some minor tweaks of the xdg install
---
setup.py | 16 +++++++---------
setup/novelwriter.desktop | 2 +-
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/setup.py b/setup.py
index 49cd049d..1eae8bf7 100755
--- a/setup.py
+++ b/setup.py
@@ -193,13 +193,11 @@ def xdgInstall():
# ===========================
desktopData = ""
- with open(os.path.join("setup", "novelwriter.desktop"), mode="r") as inFile:
+ with open("./setup/novelwriter.desktop", mode="r") as inFile:
desktopData = inFile.read()
desktopData = desktopData.replace(r"%%exec%%", useExec)
-
- desktopFile = os.path.join(os.getcwd(), "novelwriter.desktop")
- with open(desktopFile, mode="w+") as outFile:
+ with open("./novelwriter.desktop", mode="w+") as outFile:
outFile.write(desktopData)
exCode = subprocess.call(
@@ -225,7 +223,7 @@ def xdgInstall():
exCode = subprocess.call([
"xdg-mime", "install",
- "setup/mime/x-novelwriter-project.xml"
+ "./setup/mime/x-novelwriter-project.xml"
])
if exCode == 0:
print("Installed mimetype")
@@ -237,7 +235,7 @@ def xdgInstall():
# Install Icons
# =============
- sizeArr = ["16", "22", "24", "32", "48", "96", "128", "256", "512"]
+ sizeArr = ["16", "22", "24", "32", "48", "64", "96", "128", "256", "512"]
# App Icon
for aSize in sizeArr:
@@ -246,7 +244,7 @@ def xdgInstall():
"--novendor", "--noupdate",
"--context", "apps",
"--size", aSize,
- f"setup/icons/scaled/icon-novelwriter-{aSize}.png",
+ f"./setup/icons/scaled/icon-novelwriter-{aSize}.png",
"novelwriter"
])
if exCode == 0:
@@ -261,7 +259,7 @@ def xdgInstall():
"--noupdate",
"--context", "mimetypes",
"--size", aSize,
- f"setup/icons/scaled/mime-novelwriter-{aSize}.png",
+ f"./setup/icons/scaled/mime-novelwriter-{aSize}.png",
"application-x-novelwriter-project"
])
if exCode == 0:
@@ -274,7 +272,7 @@ def xdgInstall():
if exCode == 0:
print("Updated icon cache")
else:
- print("Error {exCode}: Could not update icon cache")
+ print(f"Error {exCode}: Could not update icon cache")
print("")
print("Done!")
diff --git a/setup/novelwriter.desktop b/setup/novelwriter.desktop
index 69550600..37236fab 100644
--- a/setup/novelwriter.desktop
+++ b/setup/novelwriter.desktop
@@ -2,7 +2,7 @@
Type=Application
Encoding=UTF-8
Name=novelWriter
-Comment=Multi-document markdown editor for novels
+Comment=Multi-document markdown-like editor for novels
Exec=%%exec%% %f
Icon=novelwriter
Categories=Qt;Office;WordProcessor;
From 170c2dc19c63f6ce5b3a59432660a5625ff5bee3 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 23 Oct 2020 20:26:29 +0200
Subject: [PATCH 095/104] Added a new formatTime function to common, and
replaced similar functions in other classes
---
nw/common.py | 10 ++++++++++
nw/gui/statusbar.py | 6 ++----
nw/gui/writingstats.py | 38 +++++++++++---------------------------
tests/test_common.py | 22 ++++++++++++++++++++--
4 files changed, 43 insertions(+), 33 deletions(-)
diff --git a/nw/common.py b/nw/common.py
index 17a8a337..021fa162 100644
--- a/nw/common.py
+++ b/nw/common.py
@@ -169,6 +169,16 @@ def formatTimeStamp(theTime, fileSafe=False):
else:
return datetime.fromtimestamp(theTime).strftime(nwConst.tStampFmt)
+def formatTime(tS):
+ """Format the time spent in 00:00:00 format.
+ """
+ if isinstance(tS, int):
+ if tS >= 86400:
+ return f"{tS//86400:d}-{tS//3600%24: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.
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index 0b95ef16..ace755ae 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -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
diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py
index fa03a278..170d8cf8 100644
--- a/nw/gui/writingstats.py
+++ b/nw/gui/writingstats.py
@@ -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,34 +368,26 @@ 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", "
")
# Report to user
if wSuccess:
self.theParent.makeAlert(
- "%s file successfully written to:
%s" % (
- textFmt, savePath
- ), nwAlert.INFO
+ f"{textFmt} file successfully written to:
{savePath}", nwAlert.INFO
)
else:
self.theParent.makeAlert(
- "Failed to write %s file. %s" % (
- textFmt, errMsg
- ), nwAlert.ERROR
+ f"Failed to write {textFmt} file.
{errMsg}", nwAlert.ERROR
)
return True
@@ -455,7 +448,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 +537,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 +560,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
diff --git a/tests/test_common.py b/tests/test_common.py
index 4dc9cfcf..2a24f31f 100644
--- a/tests/test_common.py
+++ b/tests/test_common.py
@@ -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"
From 8db7c17798691e6b23380c60da02ade2407f351c Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 23 Oct 2020 20:56:44 +0200
Subject: [PATCH 096/104] Drop using formatting a few places where it isn't
necessary
---
nw/gui/about.py | 13 ++++++-------
nw/gui/build.py | 8 ++++----
nw/gui/mainmenu.py | 6 +++---
nw/gui/writingstats.py | 8 ++++++--
4 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/nw/gui/about.py b/nw/gui/about.py
index 248cf7d1..7f00cf11 100644
--- a/nw/gui/about.py
+++ b/nw/gui/about.py
@@ -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("%s" % self.mainConf.appName)
+ self.lblName = QLabel("novelWriter")
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 = " • "
aboutMsg = (
- "About {name:s}
"
+ "About novelWriter
"
"{copyright:s}.
"
"Website: {domain:s}
"
- "{name:s} is a markdown-like text editor designed for "
+ "
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.
"
- "{name:s} is free software: you can redistribute it and/or "
+ "
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.
"
- "{name:s} is distributed in the hope that it will be useful, "
+ "
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.
"
"See the License tab for the full text, or visit the GNU website "
@@ -134,7 +134,6 @@ class GuiAbout(QDialog):
"
Credits
"
"{credits:s}
"
).format(
- name = self.mainConf.appName,
copyright = nw.__copyright__,
website = nw.__url__,
domain = nw.__domain__,
diff --git a/nw/gui/build.py b/nw/gui/build.py
index 45a1a073..9b8b42ac 100644
--- a/nw/gui/build.py
+++ b/nw/gui/build.py
@@ -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)
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 6bb7edf1..7fcd2a89 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -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)
diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py
index 170d8cf8..c394c43d 100644
--- a/nw/gui/writingstats.py
+++ b/nw/gui/writingstats.py
@@ -383,11 +383,15 @@ class GuiWritingStats(QDialog):
# Report to user
if wSuccess:
self.theParent.makeAlert(
- f"{textFmt} file successfully written to:
{savePath}", nwAlert.INFO
+ "%s file successfully written to:
%s" % (
+ textFmt, savePath
+ ), nwAlert.INFO
)
else:
self.theParent.makeAlert(
- f"Failed to write {textFmt} file.
{errMsg}", nwAlert.ERROR
+ "Failed to write %s file.
%s" % (
+ textFmt, errMsg
+ ), nwAlert.ERROR
)
return True
From c0ad631039662c587ba57e030ec99b6a8108386c Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Fri, 23 Oct 2020 21:05:41 +0200
Subject: [PATCH 097/104] Updated source file descriptions
---
nw/config.py | 2 +-
nw/core/document.py | 2 +-
nw/core/index.py | 2 +-
nw/core/spellcheck.py | 2 +-
nw/core/status.py | 2 +-
nw/core/tokenizer.py | 2 +-
nw/core/tree.py | 2 +-
nw/gui/build.py | 8 ++++----
nw/gui/doceditor.py | 2 +-
nw/gui/dochighlight.py | 2 +-
nw/gui/docmerge.py | 2 +-
nw/gui/docviewer.py | 2 +-
nw/gui/itemdetails.py | 2 +-
nw/gui/itemeditor.py | 2 +-
nw/gui/mainmenu.py | 4 ++--
nw/gui/outlinedetails.py | 2 +-
nw/gui/projload.py | 2 +-
nw/gui/projtree.py | 2 +-
nw/gui/theme.py | 2 +-
nw/gui/writingstats.py | 2 +-
nw/guimain.py | 2 +-
21 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/nw/config.py b/nw/config.py
index bc777812..0aa6cf50 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -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]
diff --git a/nw/core/document.py b/nw/core/document.py
index 1452e9dd..b1056a6b 100644
--- a/nw/core/document.py
+++ b/nw/core/document.py
@@ -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]
diff --git a/nw/core/index.py b/nw/core/index.py
index 97ad7ba4..29f80ea9 100644
--- a/nw/core/index.py
+++ b/nw/core/index.py
@@ -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]
diff --git a/nw/core/spellcheck.py b/nw/core/spellcheck.py
index e3093070..7223c616 100644
--- a/nw/core/spellcheck.py
+++ b/nw/core/spellcheck.py
@@ -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]
diff --git a/nw/core/status.py b/nw/core/status.py
index a2e5b92a..7a1c7127 100644
--- a/nw/core/status.py
+++ b/nw/core/status.py
@@ -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]
diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py
index 5087c67c..c7b23208 100644
--- a/nw/core/tokenizer.py
+++ b/nw/core/tokenizer.py
@@ -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]
diff --git a/nw/core/tree.py b/nw/core/tree.py
index f33b0d59..fc908745 100644
--- a/nw/core/tree.py
+++ b/nw/core/tree.py
@@ -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]
diff --git a/nw/gui/build.py b/nw/gui/build.py
index 9b8b42ac..4a8f8aad 100644
--- a/nw/gui/build.py
+++ b/nw/gui/build.py
@@ -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]
diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py
index 9a2cb683..a24a1f4e 100644
--- a/nw/gui/doceditor.py
+++ b/nw/gui/doceditor.py
@@ -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
diff --git a/nw/gui/dochighlight.py b/nw/gui/dochighlight.py
index cc11ef86..309b74a8 100644
--- a/nw/gui/dochighlight.py
+++ b/nw/gui/dochighlight.py
@@ -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]
diff --git a/nw/gui/docmerge.py b/nw/gui/docmerge.py
index d7d128fe..f2a49e19 100644
--- a/nw/gui/docmerge.py
+++ b/nw/gui/docmerge.py
@@ -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]
diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py
index 0c9a8086..636c4637 100644
--- a/nw/gui/docviewer.py
+++ b/nw/gui/docviewer.py
@@ -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
diff --git a/nw/gui/itemdetails.py b/nw/gui/itemdetails.py
index 6d5cbcb5..da1a8f4a 100644
--- a/nw/gui/itemdetails.py
+++ b/nw/gui/itemdetails.py
@@ -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]
diff --git a/nw/gui/itemeditor.py b/nw/gui/itemeditor.py
index 95a68c82..a56a93bf 100644
--- a/nw/gui/itemeditor.py
+++ b/nw/gui/itemeditor.py
@@ -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]
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index 7fcd2a89..706b5bba 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -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 2018–2020, Veronica Berglyd Olsen
diff --git a/nw/gui/outlinedetails.py b/nw/gui/outlinedetails.py
index 18f2b90f..d19bf2e9 100644
--- a/nw/gui/outlinedetails.py
+++ b/nw/gui/outlinedetails.py
@@ -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]
diff --git a/nw/gui/projload.py b/nw/gui/projload.py
index 29c9c9ab..35621032 100644
--- a/nw/gui/projload.py
+++ b/nw/gui/projload.py
@@ -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]
diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py
index 77fdf610..89e41374 100644
--- a/nw/gui/projtree.py
+++ b/nw/gui/projtree.py
@@ -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
diff --git a/nw/gui/theme.py b/nw/gui/theme.py
index 9d907a67..2b5f31f5 100644
--- a/nw/gui/theme.py
+++ b/nw/gui/theme.py
@@ -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
diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py
index c394c43d..fb10f7a4 100644
--- a/nw/gui/writingstats.py
+++ b/nw/gui/writingstats.py
@@ -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]
diff --git a/nw/guimain.py b/nw/guimain.py
index 6742a0d9..9b1a8a42 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -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]
From 3b14aacc0fee6b2d064f436a7b70ec5ea731177e Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 24 Oct 2020 12:06:42 +0200
Subject: [PATCH 098/104] Fix icon link
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 54348b1f..72ae5824 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
[](https://pypi.org/project/novelWriter)
[](https://pypi.org/project/novelWriter)
-
+
novelWriter is a Markdown-like text editor designed for writing novels and larger projects of many
smaller plain text documents. It uses its own flavour of Markdown that supports a meta data syntax
From 8d31428a9d14473cfdc0b5d0d789d25c70ca61be Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 24 Oct 2020 17:54:02 +0200
Subject: [PATCH 099/104] Improve a few functions in common and item
---
nw/common.py | 13 ++++++------
nw/config.py | 2 +-
nw/core/item.py | 50 +++++++++++++++++++++++++++-------------------
tests/test_item.py | 2 +-
4 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/nw/common.py b/nw/common.py
index 021fa162..d5563d16 100644
--- a/nw/common.py
+++ b/nw/common.py
@@ -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
@@ -170,11 +170,12 @@ def formatTimeStamp(theTime, fileSafe=False):
return datetime.fromtimestamp(theTime).strftime(nwConst.tStampFmt)
def formatTime(tS):
- """Format the time spent in 00:00:00 format.
+ """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//3600%24:02d}:{tS%3600//60:02d}:{tS%60:02d}"
+ 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"
diff --git a/nw/config.py b/nw/config.py
index 0aa6cf50..a82c133b 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -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.
diff --git a/nw/core/item.py b/nw/core/item.py
index 944b5f0c..6793af39 100644
--- a/nw/core/item.py
+++ b/nw/core/item.py
@@ -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
diff --git a/tests/test_item.py b/tests/test_item.py
index 936ba185..95aa8470 100644
--- a/tests/test_item.py
+++ b/tests/test_item.py
@@ -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")
From f13bd877022350d597a9e508b6d5c89b5e50cab6 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 24 Oct 2020 18:31:18 +0200
Subject: [PATCH 100/104] Allow more than one meta data line in documents, and
split the current line into three
---
nw/core/document.py | 99 +++++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 48 deletions(-)
diff --git a/nw/core/document.py b/nw/core/document.py
index 1452e9dd..6b9361d0 100644
--- a/nw/core/document.py
+++ b/nw/core/document.py
@@ -30,7 +30,7 @@ import os
from nw.constants import nwAlert
from nw.common import isHandle
-from nw.constants import nwItemLayout, nwItemClass, nwConst
+from nw.constants import nwItemLayout, nwItemClass
logger = logging.getLogger(__name__)
@@ -45,7 +45,7 @@ class NWDoc():
self._theItem = None # The currently open item
self._docHandle = None # The handle of the currently open item
self._fileLoc = None # The file location of the currently open item
- self._docMeta = "" # The meta string of the currently open item
+ self._docMeta = {} # The meta data of the currently open item
# Internal Mapping
self.makeAlert = self.theParent.makeAlert
@@ -62,7 +62,7 @@ class NWDoc():
self._theItem = None
self._docHandle = None
self._fileLoc = None
- self._docMeta = ""
+ self._docMeta = {}
return
def openDocument(self, tHandle, showStatus=True, isOrphan=False):
@@ -94,16 +94,21 @@ class NWDoc():
self._fileLoc = docPath
theText = ""
- self._docMeta = ""
+ self._docMeta = {}
if os.path.isfile(docPath):
try:
with open(docPath, mode="r", encoding="utf8") as inFile:
- fstLine = inFile.readline()
- if fstLine.startswith("%%~ "):
- # This is the meta line
- self._docMeta = fstLine[4:].strip()
- else:
- theText = fstLine
+
+ # Check the first <= 10 lines for metadata
+ for i in range(10):
+ inLine = inFile.readline()
+ if inLine.startswith(r"%%~"):
+ self._parseMeta(inLine)
+ else:
+ theText = inLine
+ break
+
+ # Load the rest of the file
theText += inFile.read()
except Exception as e:
@@ -119,8 +124,6 @@ class NWDoc():
logger.debug("The requested document does not exist.")
return ""
- logger.verbose("DocMeta: '%s'" % self._docMeta)
-
if showStatus and not isOrphan:
self.theParent.setStatus("Opened Document: %s" % self._theItem.itemName)
@@ -145,14 +148,10 @@ class NWDoc():
if self._theItem is None:
docMeta = ""
else:
- itemPath = self.theProject.projTree.getItemPath(self._docHandle)
docMeta = (
- "%%~ {handlepath:s}:{itemclass:s}:{itemlayout:s}:{itemname:s}\n"
- ).format(
- handlepath = ":".join(itemPath),
- itemclass = self._theItem.itemClass.name,
- itemlayout = self._theItem.itemLayout.name,
- itemname = self._theItem.itemName,
+ f"%%~name: {self._theItem.itemName:s}\n"
+ f"%%~path: {self._theItem.itemParent:s}/{self._theItem.itemHandle:s}\n"
+ f"%%~kind: {self._theItem.itemClass.name:s}/{self._theItem.itemLayout.name:s}\n"
)
try:
@@ -215,39 +214,43 @@ class NWDoc():
"""Parses the document meta tag and returns the path and name as
a list and a string.
"""
- if len(self._docMeta) < 14:
- # Not enough information
- return "", [], None, None
+ theName = self._docMeta.get("name", "")
+ theParent = self._docMeta.get("parent", None)
+ theClass = self._docMeta.get("class", None)
+ theLayout = self._docMeta.get("layout", None)
- theMeta = self._docMeta
+ return theName, theParent, theClass, theLayout
- # Scan for handles
- thePath = []
- for n in range(nwConst.maxDepth + 5):
- if len(theMeta) < 14:
- break
- if theMeta[13] == ":":
- theHandle = theMeta[:13]
- if isHandle(theHandle):
- thePath.append(theHandle)
- theMeta = theMeta[14:]
- else:
- break
- else:
- break
+ ##
+ # Internal Functions
+ ##
- theClass = nwItemClass.NO_CLASS
- for aClass in nwItemClass:
- if theMeta.startswith(aClass.name):
- theClass = aClass
- theMeta = theMeta[len(aClass.name)+1:]
+ def _parseMeta(self, metaLine):
+ """Parse a line from the document statting with the characters
+ %%~ that may contain meta data.
+ """
+ if metaLine.startswith("%%~name:"):
+ self._docMeta["name"] = metaLine[9:].strip()
- theLayout = nwItemLayout.NO_LAYOUT
- for aLayout in nwItemLayout:
- if theMeta.startswith(aLayout.name):
- theLayout = aLayout
- theMeta = theMeta[len(aLayout.name)+1:]
+ elif metaLine.startswith("%%~path:"):
+ metaVal = metaLine[9:].strip()
+ metaBits = metaVal.split("/")
+ if len(metaBits) == 2:
+ if isHandle(metaBits[0]):
+ self._docMeta["parent"] = metaBits[0]
+ if isHandle(metaBits[1]):
+ self._docMeta["handle"] = metaBits[1]
- return theMeta, thePath, theClass, theLayout
+ elif metaLine.startswith("%%~kind:"):
+ metaVal = metaLine[9:].strip()
+ metaBits = metaVal.split("/")
+ if len(metaBits) == 2:
+ if metaBits[0] in nwItemClass.__members__:
+ self._docMeta["class"] = nwItemClass[metaBits[0]]
+ if metaBits[1] in nwItemLayout.__members__:
+ self._docMeta["layout"] = nwItemLayout[metaBits[1]]
+
+ # print(self._docMeta)
+ return
# END Class NWDoc
From 538009eff65182077edae572e7e83a5af6161a8d Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Sat, 24 Oct 2020 18:56:01 +0200
Subject: [PATCH 101/104] Updated tests
---
nw/core/document.py | 6 +++---
sample/content/636b6aa9b697b.nwd | 5 ++++-
tests/lipsum/content/04468803b92e1.nwd | 4 +++-
tests/lipsum/content/2426c6f0ca922.nwd | 4 +++-
tests/lipsum/content/441420a886d82.nwd | 4 +++-
tests/lipsum/content/47666c91c7ccf.nwd | 4 +++-
tests/lipsum/content/4c4f28287af27.nwd | 4 +++-
tests/lipsum/content/7a992350f3eb6.nwd | 4 +++-
tests/lipsum/content/846352075de7d.nwd | 4 +++-
tests/lipsum/content/88243afbe5ed8.nwd | 4 +++-
tests/lipsum/content/88d59a277361b.nwd | 4 +++-
tests/lipsum/content/8c58a65414c23.nwd | 4 +++-
tests/lipsum/content/db7e733775d4d.nwd | 4 +++-
tests/lipsum/content/eb103bc70c90c.nwd | 4 +++-
tests/lipsum/content/f8c0562e50f1b.nwd | 4 +++-
tests/lipsum/content/f96ec11c6a3da.nwd | 4 +++-
tests/lipsum/content/fb609cd8319dc.nwd | 4 +++-
tests/lipsum/nwProject.nwx | 8 ++++----
tests/minimal/content/8c659a11cd429.nwd | 4 +++-
tests/minimal/content/a35baf2e93843.nwd | 4 +++-
tests/minimal/content/f5ab3e30151e1.nwd | 4 +++-
tests/minimal/nwProject.nwx | 13 +++++++------
tests/reference/gui/1_031b4af5197ec.nwd | 4 +++-
tests/reference/gui/1_0e17daca5f3e1.nwd | 4 +++-
tests/reference/gui/1_1a6562590ef19.nwd | 4 +++-
tests/reference/gui/1_41cfc0d1f2d12.nwd | 4 +++-
tests/reference/gui/4_73475cb40a568.nwd | 4 +++-
tests/reference/gui/5_031b4af5197ec.nwd | 4 +++-
tests/reference/gui/5_25fc0e7096fc6.nwd | 4 +++-
tests/reference/gui/5_2858dcd1057d3.nwd | 4 +++-
tests/reference/gui/5_2fca346db6561.nwd | 4 +++-
tests/reference/gui/5_31489056e0916.nwd | 4 +++-
tests/reference/gui/5_41cfc0d1f2d12.nwd | 4 +++-
tests/reference/gui/5_98010bd9270f9.nwd | 4 +++-
tests/test_dialogs.py | 4 ++--
tests/test_gui.py | 10 ----------
tests/test_project.py | 21 ++++++++++-----------
37 files changed, 120 insertions(+), 67 deletions(-)
diff --git a/nw/core/document.py b/nw/core/document.py
index d1b4196a..2cbb16bd 100644
--- a/nw/core/document.py
+++ b/nw/core/document.py
@@ -230,10 +230,10 @@ class NWDoc():
%%~ that may contain meta data.
"""
if metaLine.startswith("%%~name:"):
- self._docMeta["name"] = metaLine[9:].strip()
+ self._docMeta["name"] = metaLine[8:].strip()
elif metaLine.startswith("%%~path:"):
- metaVal = metaLine[9:].strip()
+ metaVal = metaLine[8:].strip()
metaBits = metaVal.split("/")
if len(metaBits) == 2:
if isHandle(metaBits[0]):
@@ -242,7 +242,7 @@ class NWDoc():
self._docMeta["handle"] = metaBits[1]
elif metaLine.startswith("%%~kind:"):
- metaVal = metaLine[9:].strip()
+ metaVal = metaLine[8:].strip()
metaBits = metaVal.split("/")
if len(metaBits) == 2:
if metaBits[0] in nwItemClass.__members__:
diff --git a/sample/content/636b6aa9b697b.nwd b/sample/content/636b6aa9b697b.nwd
index 5936fbd3..eb0545cf 100644
--- a/sample/content/636b6aa9b697b.nwd
+++ b/sample/content/636b6aa9b697b.nwd
@@ -1,4 +1,7 @@
-%%~ 636b6aa9b697b:e7ded148d6e4a:7031beac91f75:NOVEL:SCENE:Making a Scene
+%%~name: Making a Scene
+%%~path: e7ded148d6e4a/636b6aa9b697b
+%%~kind: NOVEL/SCENE
+%%~
### Making a Scene
@pov: Jane
diff --git a/tests/lipsum/content/04468803b92e1.nwd b/tests/lipsum/content/04468803b92e1.nwd
index af7504dc..6d706890 100644
--- a/tests/lipsum/content/04468803b92e1.nwd
+++ b/tests/lipsum/content/04468803b92e1.nwd
@@ -1,4 +1,6 @@
-%%~ 04468803b92e1:60bdf227455cc:WORLD:NOTE:Ancient Europe
+%%~name: Ancient Europe
+%%~path: 60bdf227455cc/04468803b92e1
+%%~kind: WORLD/NOTE
# Ancient Europe
@tag: Europe
diff --git a/tests/lipsum/content/2426c6f0ca922.nwd b/tests/lipsum/content/2426c6f0ca922.nwd
index 98ea99c3..ad926141 100644
--- a/tests/lipsum/content/2426c6f0ca922.nwd
+++ b/tests/lipsum/content/2426c6f0ca922.nwd
@@ -1,4 +1,6 @@
-%%~ 2426c6f0ca922:6c6afb1247750:PLOT:NOTE:Main
+%%~name: Main
+%%~path: 6c6afb1247750/2426c6f0ca922
+%%~kind: PLOT/NOTE
# Main Plot
@tag: Main
diff --git a/tests/lipsum/content/441420a886d82.nwd b/tests/lipsum/content/441420a886d82.nwd
index 820862ba..26237180 100644
--- a/tests/lipsum/content/441420a886d82.nwd
+++ b/tests/lipsum/content/441420a886d82.nwd
@@ -1,4 +1,6 @@
-%%~ 441420a886d82:6bd935d2490cd:b3643d0f92e32:NOVEL:CHAPTER:Chapter Two
+%%~name: Chapter Two
+%%~path: 6bd935d2490cd/441420a886d82
+%%~kind: NOVEL/CHAPTER
## Chapter Two
@pov: Bod
diff --git a/tests/lipsum/content/47666c91c7ccf.nwd b/tests/lipsum/content/47666c91c7ccf.nwd
index 027b20e5..7ea17223 100644
--- a/tests/lipsum/content/47666c91c7ccf.nwd
+++ b/tests/lipsum/content/47666c91c7ccf.nwd
@@ -1,4 +1,6 @@
-%%~ 47666c91c7ccf:6bd935d2490cd:b3643d0f92e32:NOVEL:SCENE:Scene Five
+%%~name: Scene Five
+%%~path: 6bd935d2490cd/47666c91c7ccf
+%%~kind: NOVEL/SCENE
### Scene Five
@pov: Bod
diff --git a/tests/lipsum/content/4c4f28287af27.nwd b/tests/lipsum/content/4c4f28287af27.nwd
index 50f646b5..d845442f 100644
--- a/tests/lipsum/content/4c4f28287af27.nwd
+++ b/tests/lipsum/content/4c4f28287af27.nwd
@@ -1,4 +1,6 @@
-%%~ 4c4f28287af27:67a8707f2f249:CHARACTER:NOTE:Mr. Nobody
+%%~name: Mr. Nobody
+%%~path: 67a8707f2f249/4c4f28287af27
+%%~kind: CHARACTER/NOTE
# Nobody Owens
@tag: Bod
diff --git a/tests/lipsum/content/7a992350f3eb6.nwd b/tests/lipsum/content/7a992350f3eb6.nwd
index ab7eb619..6982e548 100644
--- a/tests/lipsum/content/7a992350f3eb6.nwd
+++ b/tests/lipsum/content/7a992350f3eb6.nwd
@@ -1,4 +1,6 @@
-%%~ 7a992350f3eb6:b3643d0f92e32:NOVEL:TITLE:Lorem Ipusm
+%%~name: Lorem Ipsum
+%%~path: b3643d0f92e32/7a992350f3eb6
+%%~kind: NOVEL/TITLE
# Lorem Ipsum
**By lipsum.com**
diff --git a/tests/lipsum/content/846352075de7d.nwd b/tests/lipsum/content/846352075de7d.nwd
index 6a608f16..d362ccc6 100644
--- a/tests/lipsum/content/846352075de7d.nwd
+++ b/tests/lipsum/content/846352075de7d.nwd
@@ -1,4 +1,6 @@
-%%~ 846352075de7d:b3643d0f92e32:NOVEL:BOOK:Interlude
+%%~name: Interlude
+%%~path: b3643d0f92e32/846352075de7d
+%%~kind: NOVEL/BOOK
## Why do we use it?
% Exctracted from the lipsum.com website.
diff --git a/tests/lipsum/content/88243afbe5ed8.nwd b/tests/lipsum/content/88243afbe5ed8.nwd
index eba37bae..426ffeba 100644
--- a/tests/lipsum/content/88243afbe5ed8.nwd
+++ b/tests/lipsum/content/88243afbe5ed8.nwd
@@ -1,4 +1,6 @@
-%%~ 88243afbe5ed8:45e6b01ca35c1:b3643d0f92e32:NOVEL:SCENE:Scene One
+%%~name: Scene One
+%%~path: 45e6b01ca35c1/88243afbe5ed8
+%%~kind: NOVEL/SCENE
### Scene One
@pov: Bod
diff --git a/tests/lipsum/content/88d59a277361b.nwd b/tests/lipsum/content/88d59a277361b.nwd
index f6ac2810..4d55bfda 100644
--- a/tests/lipsum/content/88d59a277361b.nwd
+++ b/tests/lipsum/content/88d59a277361b.nwd
@@ -1,4 +1,6 @@
-%%~ 88d59a277361b:b3643d0f92e32:NOVEL:UNNUMBERED:Prologue
+%%~name: Prologue
+%%~path: b3643d0f92e32/88d59a277361b
+%%~kind: NOVEL/UNNUMBERED
## Prologue
% Synopsis:Explanation from the lipsum.com website.
diff --git a/tests/lipsum/content/8c58a65414c23.nwd b/tests/lipsum/content/8c58a65414c23.nwd
index 408a3bec..28e54bef 100644
--- a/tests/lipsum/content/8c58a65414c23.nwd
+++ b/tests/lipsum/content/8c58a65414c23.nwd
@@ -1,4 +1,6 @@
-%%~ 8c58a65414c23:b3643d0f92e32:NOVEL:PAGE:Front Matter
+%%~name: Front Matter
+%%~path: b3643d0f92e32/8c58a65414c23
+%%~kind: NOVEL/PAGE
% Exctracted from the lipsum.com website.
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
diff --git a/tests/lipsum/content/db7e733775d4d.nwd b/tests/lipsum/content/db7e733775d4d.nwd
index 7f4de78f..d677152f 100644
--- a/tests/lipsum/content/db7e733775d4d.nwd
+++ b/tests/lipsum/content/db7e733775d4d.nwd
@@ -1,4 +1,6 @@
-%%~ db7e733775d4d:b3643d0f92e32:NOVEL:PARTITION:Act One
+%%~name: Act One
+%%~path: b3643d0f92e32/db7e733775d4d
+%%~kind: NOVEL/PARTITION
# Act One
“Fusce maximus felis libero”
\ No newline at end of file
diff --git a/tests/lipsum/content/eb103bc70c90c.nwd b/tests/lipsum/content/eb103bc70c90c.nwd
index db11bbf0..65ce7e49 100644
--- a/tests/lipsum/content/eb103bc70c90c.nwd
+++ b/tests/lipsum/content/eb103bc70c90c.nwd
@@ -1,4 +1,6 @@
-%%~ eb103bc70c90c:6bd935d2490cd:b3643d0f92e32:NOVEL:SCENE:Scene Three
+%%~name: Scene Three
+%%~path: 6bd935d2490cd/eb103bc70c90c
+%%~kind: NOVEL/SCENE
### Scene Three
@pov: Bod
diff --git a/tests/lipsum/content/f8c0562e50f1b.nwd b/tests/lipsum/content/f8c0562e50f1b.nwd
index 15a33bc8..f8218e1f 100644
--- a/tests/lipsum/content/f8c0562e50f1b.nwd
+++ b/tests/lipsum/content/f8c0562e50f1b.nwd
@@ -1,4 +1,6 @@
-%%~ f8c0562e50f1b:6bd935d2490cd:b3643d0f92e32:NOVEL:SCENE:Scene Four
+%%~name: Scene Four
+%%~path: 6bd935d2490cd/f8c0562e50f1b
+%%~kind: NOVEL/SCENE
### Scene Four
@pov: Bod
diff --git a/tests/lipsum/content/f96ec11c6a3da.nwd b/tests/lipsum/content/f96ec11c6a3da.nwd
index b95163d5..60853dc2 100644
--- a/tests/lipsum/content/f96ec11c6a3da.nwd
+++ b/tests/lipsum/content/f96ec11c6a3da.nwd
@@ -1,4 +1,6 @@
-%%~ f96ec11c6a3da:45e6b01ca35c1:b3643d0f92e32:NOVEL:SCENE:Scene Two
+%%~name: Scene Two
+%%~path: 45e6b01ca35c1/f96ec11c6a3da
+%%~kind: NOVEL/SCENE
### Scene Two
@pov: Bod
diff --git a/tests/lipsum/content/fb609cd8319dc.nwd b/tests/lipsum/content/fb609cd8319dc.nwd
index fa9626f2..ff48ad12 100644
--- a/tests/lipsum/content/fb609cd8319dc.nwd
+++ b/tests/lipsum/content/fb609cd8319dc.nwd
@@ -1,4 +1,6 @@
-%%~ fb609cd8319dc:45e6b01ca35c1:b3643d0f92e32:NOVEL:CHAPTER:Chapter One
+%%~name: Chapter One
+%%~path: 45e6b01ca35c1/fb609cd8319dc
+%%~kind: NOVEL/CHAPTER
## Chapter One
@pov: Bod
diff --git a/tests/lipsum/nwProject.nwx b/tests/lipsum/nwProject.nwx
index 680059d5..5dec55bb 100644
--- a/tests/lipsum/nwProject.nwx
+++ b/tests/lipsum/nwProject.nwx
@@ -1,19 +1,19 @@
-
+
Lorem Ipsum
Lorem Ipsum
lipsum.com
- 9
+ 10
22
- 1552
+ 1571
False
False
None
True
- 846352075de7d
+ 04468803b92e1
None
3847
3109
diff --git a/tests/minimal/content/8c659a11cd429.nwd b/tests/minimal/content/8c659a11cd429.nwd
index 5ecf5c59..bdb8079f 100644
--- a/tests/minimal/content/8c659a11cd429.nwd
+++ b/tests/minimal/content/8c659a11cd429.nwd
@@ -1,3 +1,5 @@
-%%~ 8c659a11cd429:a6d311a93600a:a508bb932959c:NOVEL:SCENE:New Scene
+%%~name: New Scene
+%%~path: a6d311a93600a/8c659a11cd429
+%%~kind: NOVEL/SCENE
### New Scene
diff --git a/tests/minimal/content/a35baf2e93843.nwd b/tests/minimal/content/a35baf2e93843.nwd
index a7745e3b..a1120152 100644
--- a/tests/minimal/content/a35baf2e93843.nwd
+++ b/tests/minimal/content/a35baf2e93843.nwd
@@ -1,4 +1,6 @@
-%%~ a35baf2e93843:a508bb932959c:NOVEL:TITLE:Title Page
+%%~name: Title Page
+%%~path: a508bb932959c/a35baf2e93843
+%%~kind: NOVEL/TITLE
# Minimal
By Jane Doe, John Doh
diff --git a/tests/minimal/content/f5ab3e30151e1.nwd b/tests/minimal/content/f5ab3e30151e1.nwd
index ba1c9faa..f08335a0 100644
--- a/tests/minimal/content/f5ab3e30151e1.nwd
+++ b/tests/minimal/content/f5ab3e30151e1.nwd
@@ -1,3 +1,5 @@
-%%~ f5ab3e30151e1:a6d311a93600a:a508bb932959c:NOVEL:CHAPTER:New Chapter
+%%~name: New Chapter
+%%~path: a6d311a93600a/f5ab3e30151e1
+%%~kind: NOVEL/CHAPTER
## New Chapter
diff --git a/tests/minimal/nwProject.nwx b/tests/minimal/nwProject.nwx
index af99a8ce..d45f9bfa 100644
--- a/tests/minimal/nwProject.nwx
+++ b/tests/minimal/nwProject.nwx
@@ -1,17 +1,18 @@
-
+
Test Minimal
Minimal
Jane Doe
John Doh
- 1
+ 3
1
- 8
+ 33
True
False
+ None
True
None
None
@@ -57,7 +58,7 @@
28
6
1
- 0
+ 33