Merge branch 'main' into release_1.0rc1

This commit is contained in:
Veronica K. B. Olsen
2020-11-08 18:11:50 +01:00
11 changed files with 186 additions and 203 deletions
-1
View File
@@ -59,7 +59,6 @@ class nwFiles():
PROJ_DICT = "wordlist.txt"
PROJ_LOCK = "nwProject.lock"
TOC_TXT = "ToC.txt"
TOC_JSON = "ToC.json"
SESS_STATS = "sessionStats.log"
INDEX_FILE = "tagsIndex.json"
OPTS_FILE = "guiOptions.json"
+6 -1
View File
@@ -743,7 +743,7 @@ class NWProject():
"""Close the current project and clear all meta data.
"""
self.optState.saveSettings()
self.projTree.writeToCFiles()
self.projTree.writeToCFile()
self._appendSessionStats()
self._clearLockFile()
self.clearProject()
@@ -781,6 +781,10 @@ class NWProject():
def zipIt(self, doNotify):
"""Create a zip file of the entire project.
"""
if not self.theParent.hasProject:
logger.error("No project open")
return False
logger.info("Backing up project")
self.theParent.setStatus("Backing up project ...")
@@ -1476,6 +1480,7 @@ class NWProject():
os.path.join(self.projMeta, "timelineOptions.json"),
os.path.join(self.projMeta, "docMergeOptions.json"),
os.path.join(self.projMeta, "sessionLogOptions.json"),
os.path.join(self.projPath, "ToC.json"),
]
for rmFile in rmList:
+27 -32
View File
@@ -26,7 +26,6 @@
"""
import logging
import json
import os
from lxml import etree
@@ -139,46 +138,42 @@ class NWTree():
return True
def writeToCFiles(self):
"""Write the convenience table of contents files in the root of
the project directory. These files are there to assist the user
if they wish to browse the stored files.
def writeToCFile(self):
"""Write the convenience table of contents file in the root of
the project directory.
"""
tocText = os.path.join(self.theProject.projPath, nwFiles.TOC_TXT)
tocJson = os.path.join(self.theProject.projPath, nwFiles.TOC_JSON)
tocList = []
tocLen = 0
for tHandle in self._treeOrder:
tItem = self.__getitem__(tHandle)
if tItem is None:
continue
tFile = tHandle+".nwd"
if os.path.isfile(os.path.join(self.theProject.projContent, tFile)):
tocLine = "%-25s %-9s %-10s %s" % (
os.path.join("content", tFile),
tItem.itemClass.name,
tItem.itemLayout.name,
tItem.itemName,
)
tocList.append(tocLine)
tocLen = max(tocLen, len(tocLine))
jsonData = []
try:
# Dump the text
tocText = os.path.join(self.theProject.projPath, nwFiles.TOC_TXT)
with open(tocText, mode="w", encoding="utf8") as outFile:
outFile.write("\n")
outFile.write(" Table of Contents\n")
outFile.write("===================\n")
outFile.write("Table of Contents\n")
outFile.write("=================\n")
outFile.write("\n")
outFile.write(" %-25s %-9s %s\n" % ("File Name", "Class", "Document Label"))
outFile.write("-"*80+"\n")
for tHandle in sorted(self._treeOrder):
tItem = self.__getitem__(tHandle)
if tItem is None:
continue
tFile = tHandle+".nwd"
if os.path.isfile(os.path.join(self.theProject.projContent, tFile)):
outFile.write(" %-25s %-9s %s\n" % (
os.path.join("content", tFile),
tItem.itemClass.name,
tItem.itemName,
))
jsonData.append([
os.path.join("content", tFile),
tItem.itemClass.name,
tItem.itemName,
])
outFile.write("%-25s %-9s %-10s %s\n" % (
"File Name", "Class", "Layout", "Document Label"
))
outFile.write("-"*tocLen + "\n")
outFile.write("\n".join(tocList))
outFile.write("\n")
# Dump the JSON
with open(tocJson, mode="w+", encoding="utf8") as outFile:
json.dump(jsonData, outFile, indent=2)
except Exception as e:
logger.error(str(e))
+23 -12
View File
@@ -620,9 +620,10 @@ class GuiDocEditor(QTextEdit):
this class when calling these actions from other classes.
"""
logger.verbose("Requesting action: %s" % theAction.name)
if not self.theParent.hasProject:
logger.error("No project open")
if self.theHandle is None:
logger.error("No document open")
return False
self._allowAutoReplace(False)
if theAction == nwDocAction.UNDO:
self.undo()
@@ -678,7 +679,9 @@ class GuiDocEditor(QTextEdit):
logger.debug("Unknown or unsupported document action %s" % str(theAction))
self._allowAutoReplace(True)
return False
self._allowAutoReplace(True)
return True
def isEmpty(self):
@@ -690,21 +693,29 @@ class GuiDocEditor(QTextEdit):
"""Tell the user where on the file system the file in the editor
is saved.
"""
if self.theHandle is not None:
msgBox = QMessageBox()
msgBox.information(self, "File Location", (
"File details for the currently open file<br>"
"Handle: {handle:s}<br>"
"Location: {fileLoc:s}"
).format(
handle = self.theHandle,
fileLoc = str(self.nwDocument.getFileLocation())
))
if self.theHandle is None:
logger.error("No document open")
return False
msgBox = QMessageBox()
msgBox.information(self, "File Location", (
"File details for the currently open file<br>"
"Handle: {handle:s}<br>"
"Location: {fileLoc:s}"
).format(
handle = self.theHandle,
fileLoc = str(self.nwDocument.getFileLocation())
))
return
def insertText(self, theInsert):
"""Insert a specific type of text at the cursor position.
"""
if self.theHandle is None:
logger.error("No document open")
return False
if isinstance(theInsert, str):
theText = theInsert
elif isinstance(theInsert, nwDocInsert):
+13
View File
@@ -163,6 +163,7 @@ class GuiProjectTree(QTreeWidget):
nHandle = None
if not self.theParent.hasProject:
logger.error("No project open")
return False
# The item needs to be assigned an item class, so one must be
@@ -281,6 +282,10 @@ class GuiProjectTree(QTreeWidget):
"""Move an item up or down in the tree, but only if the treeView
has focus. This also applies when the menu is used.
"""
if not self.theParent.hasProject:
logger.error("No project open")
return False
hasFocus = qApp.focusWidget() == self or not self.mainConf.showGUI
if hasFocus and self.theParent.hasProject:
@@ -364,6 +369,10 @@ class GuiProjectTree(QTreeWidget):
function only asks for confirmation once, and calls the regular
deleteItem function for each document in the Trash folder.
"""
if not self.theParent.hasProject:
logger.error("No project open")
return False
trashHandle = self.theProject.projTree.trashRoot()
logger.debug("Emptying Trash folder")
@@ -409,6 +418,10 @@ class GuiProjectTree(QTreeWidget):
delete the files on disk. Folders are deleted if they're empty only,
and the deletion is always permanent.
"""
if not self.theParent.hasProject:
logger.error("No project open")
return False
if tHandle is None:
tHandle = self.getSelectedHandle()
+93 -45
View File
@@ -316,7 +316,8 @@ class GuiMain(QMainWindow):
if not isYes:
msgBox = QMessageBox()
msgRes = msgBox.question(
self, "Close Project", "Save changes and close the current project?"
self, "Close Project",
"Close the current project?<br>Changes are saved automatically."
)
if msgRes != QMessageBox.Yes:
return False
@@ -442,6 +443,7 @@ class GuiMain(QMainWindow):
"""Save the current project.
"""
if not self.hasProject:
logger.error("No project open")
return False
# If the project is new, it may not have a path, so we need one
@@ -465,27 +467,33 @@ class GuiMain(QMainWindow):
def closeDocument(self):
"""Close the document and clear the editor and title field.
"""
if self.hasProject:
self.docEditor.saveCursorPosition()
if self.docEditor.docChanged:
self.saveDocument()
self.docEditor.clearEditor()
if not self.hasProject:
logger.error("No project open")
return False
self.docEditor.saveCursorPosition()
if self.docEditor.docChanged:
self.saveDocument()
self.docEditor.clearEditor()
return True
def openDocument(self, tHandle, tLine=None, changeFocus=True, doScroll=False):
"""Open a specific document, optionally at a given line.
"""
if self.hasProject:
self.closeDocument()
self.tabWidget.setCurrentWidget(self.splitDocs)
if self.docEditor.loadText(tHandle, tLine):
if changeFocus:
self.docEditor.setFocus()
self.theProject.setLastEdited(tHandle)
self.treeView.setSelectedHandle(tHandle, doScroll=doScroll)
else:
return False
if not self.hasProject:
logger.error("No project open")
return False
self.closeDocument()
self.tabWidget.setCurrentWidget(self.splitDocs)
if self.docEditor.loadText(tHandle, tLine):
if changeFocus:
self.docEditor.setFocus()
self.theProject.setLastEdited(tHandle)
self.treeView.setSelectedHandle(tHandle, doScroll=doScroll)
else:
return False
return True
@@ -493,43 +501,54 @@ class GuiMain(QMainWindow):
"""Opens the next document in the project tree, following the
document with the given handle. Stops when reaching the end.
"""
if self.hasProject:
self.treeView.flushTreeOrder()
nHandle = None # The next handle after tHandle
fHandle = None # The first file handle we encounter
foundIt = False # We've found tHandle, pick the next we see
for tItem in self.theProject.projTree:
if tItem is None:
continue
if tItem.itemType != nwItemType.FILE:
continue
if fHandle is None:
fHandle = tItem.itemHandle
if tItem.itemHandle == tHandle:
foundIt = True
elif foundIt:
nHandle = tItem.itemHandle
break
if not self.hasProject:
logger.error("No project open")
return False
if nHandle is not None:
self.openDocument(nHandle, tLine=0, doScroll=True)
return True
elif wrapAround:
self.openDocument(fHandle, tLine=0, doScroll=True)
return False
self.treeView.flushTreeOrder()
nHandle = None # The next handle after tHandle
fHandle = None # The first file handle we encounter
foundIt = False # We've found tHandle, pick the next we see
for tItem in self.theProject.projTree:
if tItem is None:
continue
if tItem.itemType != nwItemType.FILE:
continue
if fHandle is None:
fHandle = tItem.itemHandle
if tItem.itemHandle == tHandle:
foundIt = True
elif foundIt:
nHandle = tItem.itemHandle
break
if nHandle is not None:
self.openDocument(nHandle, tLine=0, doScroll=True)
return True
elif wrapAround:
self.openDocument(fHandle, tLine=0, doScroll=True)
return False
return False
def saveDocument(self):
"""Save the current documents.
"""
if self.hasProject:
self.docEditor.saveText()
if not self.hasProject:
logger.error("No project open")
return False
self.docEditor.saveText()
return True
def viewDocument(self, tHandle=None, tAnchor=None):
"""Load a document for viewing in the view panel.
"""
if not self.hasProject:
logger.error("No project open")
return False
if tHandle is None:
logger.debug("Viewing document, but no handle provided")
@@ -573,8 +592,11 @@ class GuiMain(QMainWindow):
"""Import the text contained in an out-of-project text file, and
insert the text into the currently open document.
"""
lastPath = self.mainConf.lastPath
if not self.hasProject:
logger.error("No project open")
return False
lastPath = self.mainConf.lastPath
extFilter = [
"Text files (*.txt)",
"Markdown files (*.md)",
@@ -627,16 +649,26 @@ class GuiMain(QMainWindow):
def mergeDocuments(self):
"""Merge multiple documents to one single new document.
"""
if not self.hasProject:
logger.error("No project open")
return False
dlgMerge = GuiDocMerge(self, self.theProject)
dlgMerge.exec_()
return
return True
def splitDocument(self):
"""Split a single document into multiple documents.
"""
if not self.hasProject:
logger.error("No project open")
return False
dlgSplit = GuiDocSplit(self, self.theProject)
dlgSplit.exec_()
return
return True
def passDocumentAction(self, theAction):
"""Pass on document action theAction to the document viewer if
@@ -655,6 +687,10 @@ class GuiMain(QMainWindow):
def openSelectedItem(self):
"""Open the selected documents.
"""
if not self.hasProject:
logger.error("No project open")
return False
tHandle = self.treeView.getSelectedHandle()
if tHandle is None:
logger.warning("No item selected")
@@ -673,6 +709,10 @@ class GuiMain(QMainWindow):
def editItem(self, tHandle=None):
"""Open the edit item dialog.
"""
if not self.hasProject:
logger.error("No project open")
return False
if tHandle is None:
tHandle = self.treeView.getSelectedHandle()
if tHandle is None:
@@ -703,6 +743,7 @@ class GuiMain(QMainWindow):
"""Rebuild the entire index.
"""
if not self.hasProject:
logger.error("No project open")
return False
logger.debug("Rebuilding index ...")
@@ -748,9 +789,14 @@ class GuiMain(QMainWindow):
def rebuildOutline(self):
"""Force a rebuild of the Outline view.
"""
if not self.hasProject:
logger.error("No project open")
return False
logger.verbose("Forcing a rebuild of the Project Outline")
self.tabWidget.setCurrentWidget(self.splitOutline)
self.projView.refreshTree(overRide=True)
return True
##
@@ -943,7 +989,8 @@ class GuiMain(QMainWindow):
if self.hasProject:
msgBox = QMessageBox()
msgRes = msgBox.question(
self, "Exit", "Do you want to save changes and exit?"
self, "Exit",
"Do you want to exit novelWriter?<br>Changes are saved automatically."
)
if msgRes != QMessageBox.Yes:
return False
@@ -1008,6 +1055,7 @@ class GuiMain(QMainWindow):
"""
if self.docEditor.theHandle is None:
logger.error("No document open, so not activating Focus Mode")
self.mainMenu.aFocusMode.setChecked(self.isFocusMode)
return False
self.isFocusMode = not self.isFocusMode