Add the core code for the DocSplitter tool

This commit is contained in:
Veronica Berglyd Olsen
2022-10-12 23:39:56 +02:00
parent baafd5f83c
commit 31a5761ba0
4 changed files with 135 additions and 9 deletions
+2 -1
View File
@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from novelwriter.core.doctools import DocMerger from novelwriter.core.doctools import DocMerger, DocSplitter
from novelwriter.core.document import NWDoc from novelwriter.core.document import NWDoc
from novelwriter.core.index import countWords from novelwriter.core.index import countWords
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
@@ -30,6 +30,7 @@ from novelwriter.core.tomd import ToMarkdown
__all__ = [ __all__ = [
"DocMerger", "DocMerger",
"DocSplitter",
"countWords", "countWords",
"NWDoc", "NWDoc",
"NWProject", "NWProject",
+89 -1
View File
@@ -4,7 +4,8 @@ novelWriter Project Document Tools
A collection of tools to create and manipulate documents A collection of tools to create and manipulate documents
File History: File History:
Created: 2022-10-02 [2.0b1] Created: 2022-10-02 [2.0b1] DocMerger
Created: 2022-10-11 [2.0b1] DocSplitter
This file is a part of novelWriter This file is a part of novelWriter
Copyright 20182022, Veronica Berglyd Olsen Copyright 20182022, Veronica Berglyd Olsen
@@ -117,3 +118,90 @@ class DocMerger:
return status return status
# END Class DocMerger # END Class DocMerger
class DocSplitter:
def __init__(self, theProject, sHandle):
self.theProject = theProject
self._error = ""
self._parHandle = None
self._srcHandle = None
self._srcItem = None
self._rawData = []
srcItem = self.theProject.tree[sHandle]
if srcItem is not None and srcItem.isFileType():
self._srcHandle = sHandle
self._srcItem = srcItem
return
##
# Methods
##
def getError(self):
"""Return any collected errors.
"""
return self._error
def setParentItem(self, pHandle):
"""Set the item that will be the top level parent item for the
new documents.
"""
self._parHandle = pHandle
return
def newParentFolder(self, pHandle, folderLabel):
"""Create a new folder that will be the top level parent item
for the new documents.
"""
if self._srcItem is None:
return None
newHandle = self.theProject.newFolder(folderLabel, pHandle)
newItem = self.theProject.tree[self._parHandle]
newItem.setStatus(self._srcItem.itemStatus)
newItem.setImport(self._srcItem.itemImport)
self._parHandle = newHandle
return newHandle
def splitDocument(self, splitData, splitText):
"""Loop through the split data record and perform the split job.
"""
self._rawData = []
buffer = splitText.copy()
for lineNo, hLevel, hLabel in reversed(splitData):
chunk = buffer[lineNo:]
buffer = buffer[:lineNo]
self._rawData.insert(0, (chunk, hLevel, hLabel))
return True
def writeDocuments(self):
"""An iterator that will write each document in the buffer, and
return its new handle, parent handle, and sibling handle.
"""
nearHandle = self._parHandle
for docText, hLevel, docLabel in self._rawData:
newHandle = self.theProject.newFile(docLabel, self._parHandle)
outDoc = NWDoc(self.theProject, newHandle)
status = outDoc.writeDocument("\n".join(docText))
if not status:
self._error = outDoc.getError()
yield newHandle, self._parHandle, nearHandle
nearHandle = newHandle
return
# END Class DocSplitter
+31 -6
View File
@@ -41,6 +41,10 @@ logger = logging.getLogger(__name__)
class GuiDocSplit(QDialog): class GuiDocSplit(QDialog):
LINE_ROLE = Qt.UserRole
LEVEL_ROLE = Qt.UserRole + 1
LABEL_ROLE = Qt.UserRole + 2
def __init__(self, mainGui, sHandle): def __init__(self, mainGui, sHandle):
super().__init__(parent=mainGui) super().__init__(parent=mainGui)
@@ -141,7 +145,9 @@ class GuiDocSplit(QDialog):
headerList = [] headerList = []
for i in range(self.listBox.count()): for i in range(self.listBox.count()):
item = self.listBox.item(i) item = self.listBox.item(i)
headerList.append((item.text(), item.data(Qt.UserRole))) headerList.append(
(item.data(self.LINE_ROLE), item.data(self.LEVEL_ROLE), item.data(self.LABEL_ROLE))
)
spLevel = self.splitLevel.currentData() spLevel = self.splitLevel.currentData()
intoFolder = self.folderSwitch.isChecked() intoFolder = self.folderSwitch.isChecked()
@@ -157,7 +163,7 @@ class GuiDocSplit(QDialog):
pOptions.setValue("GuiDocSplit", "intoFolder", intoFolder) pOptions.setValue("GuiDocSplit", "intoFolder", intoFolder)
pOptions.setValue("GuiDocSplit", "docHierarchy", docHierarchy) pOptions.setValue("GuiDocSplit", "docHierarchy", docHierarchy)
return self._data return self._data, self._text
## ##
# Slots # Slots
@@ -193,19 +199,38 @@ class GuiDocSplit(QDialog):
for lineNo, aLine in enumerate(self._text): for lineNo, aLine in enumerate(self._text):
onLine = -1 onLine = -1
if aLine.startswith(("# ", "#! ")) and spLevel >= 1: hLevel = 0
if aLine.startswith("# ") and spLevel >= 1:
onLine = lineNo onLine = lineNo
elif aLine.startswith(("## ", "##! ")) and spLevel >= 2: hLevel = 1
hLabel = aLine[2:].strip()
elif aLine.startswith("## ") and spLevel >= 2:
onLine = lineNo onLine = lineNo
hLevel = 2
hLabel = aLine[3:].strip()
elif aLine.startswith("### ") and spLevel >= 3: elif aLine.startswith("### ") and spLevel >= 3:
onLine = lineNo onLine = lineNo
hLevel = 3
hLabel = aLine[4:].strip()
elif aLine.startswith("#### ") and spLevel >= 4: elif aLine.startswith("#### ") and spLevel >= 4:
onLine = lineNo onLine = lineNo
hLevel = 4
hLabel = aLine[5:].strip()
elif aLine.startswith("#! ") and spLevel >= 1:
onLine = lineNo
hLevel = 1
hLabel = aLine[3:].strip()
elif aLine.startswith("##! ") and spLevel >= 2:
onLine = lineNo
hLevel = 2
hLabel = aLine[4:].strip()
if onLine >= 0: if onLine >= 0 and hLevel > 0:
newItem = QListWidgetItem() newItem = QListWidgetItem()
newItem.setText(aLine.strip()) newItem.setText(aLine.strip())
newItem.setData(Qt.UserRole, onLine) newItem.setData(self.LINE_ROLE, onLine)
newItem.setData(self.LEVEL_ROLE, hLevel)
newItem.setData(self.LABEL_ROLE, hLabel)
self.listBox.addItem(newItem) self.listBox.addItem(newItem)
return True return True
+13 -1
View File
@@ -40,6 +40,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter.core import DocMerger from novelwriter.core import DocMerger
from novelwriter.core.doctools import DocSplitter
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.dialogs import GuiDocMerge, GuiDocSplit, GuiEditLabel from novelwriter.dialogs import GuiDocMerge, GuiDocSplit, GuiEditLabel
from novelwriter.constants import nwHeaders, trConst, nwLabels from novelwriter.constants import nwHeaders, trConst, nwLabels
@@ -1475,7 +1476,18 @@ class GuiProjectTree(QTreeWidget):
if dlgSplit.result() == QDialog.Accepted: if dlgSplit.result() == QDialog.Accepted:
print(dlgSplit.getData()) splitData, splitText = dlgSplit.getData()
print(splitData)
headerList = splitData.get("headerList", [])
docSplit = DocSplitter(self.theProject, tHandle)
docSplit.setParentItem(tItem.itemParent)
docSplit.splitDocument(headerList, splitText)
for dHandle, _, nHandle in docSplit.writeDocuments():
self.mainGui.projView.revealNewTreeItem(dHandle, nHandle)
self._alertTreeChange(dHandle, flush=False)
else: else:
logger.info("Action cancelled by user") logger.info("Action cancelled by user")