Re-implement the tree context menu
This commit is contained in:
+146
-131
@@ -5,7 +5,6 @@ GUI classes for the main window project tree
|
|||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
||||||
Created: 2020-06-04 [0.7] GuiProjectTreeMenu
|
|
||||||
Created: 2022-06-06 [1.7b1] GuiProjectView
|
Created: 2022-06-06 [1.7b1] GuiProjectView
|
||||||
Created: 2022-06-06 [1.7b1] GuiProjectToolBar
|
Created: 2022-06-06 [1.7b1] GuiProjectToolBar
|
||||||
|
|
||||||
@@ -35,9 +34,9 @@ from time import time
|
|||||||
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtGui import QIcon, QPalette
|
from PyQt5.QtGui import QIcon, QPalette
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractItemView, QAction, QDialog, QFrame, QHBoxLayout, QHeaderView,
|
QAbstractItemView, QDialog, QFrame, QHBoxLayout, QHeaderView, QInputDialog,
|
||||||
QInputDialog, QLabel, QMenu, QShortcut, QSizePolicy, QToolButton,
|
QLabel, QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget,
|
||||||
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
QTreeWidgetItem, QVBoxLayout, QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter.core import NWDoc
|
from novelwriter.core import NWDoc
|
||||||
@@ -211,37 +210,37 @@ class GuiProjectToolBar(QWidget):
|
|||||||
# Add Item Menu
|
# Add Item Menu
|
||||||
self.mAdd = QMenu()
|
self.mAdd = QMenu()
|
||||||
|
|
||||||
self.aAddEmpty = self.mAdd.addAction(self.tr("Plain Document"))
|
self.aAddEmpty = self.mAdd.addAction(trConst(nwLabels.ITEM_DESCRIPTION["document"]))
|
||||||
self.aAddEmpty.setIcon(self.theTheme.getIcon("proj_document"))
|
self.aAddEmpty.setIcon(self.theTheme.getIcon("proj_document"))
|
||||||
self.aAddEmpty.triggered.connect(
|
self.aAddEmpty.triggered.connect(
|
||||||
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=0, isNote=False)
|
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=0, isNote=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.aAddChap = self.mAdd.addAction(self.tr("Chapter Document"))
|
self.aAddChap = self.mAdd.addAction(trConst(nwLabels.ITEM_DESCRIPTION["doc_h2"]))
|
||||||
self.aAddChap.setIcon(self.theTheme.getIcon("proj_chapter"))
|
self.aAddChap.setIcon(self.theTheme.getIcon("proj_chapter"))
|
||||||
self.aAddChap.triggered.connect(
|
self.aAddChap.triggered.connect(
|
||||||
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=2, isNote=False)
|
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=2, isNote=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.aAddScene = self.mAdd.addAction(self.tr("Scene Document"))
|
self.aAddScene = self.mAdd.addAction(trConst(nwLabels.ITEM_DESCRIPTION["doc_h3"]))
|
||||||
self.aAddScene.setIcon(self.theTheme.getIcon("proj_scene"))
|
self.aAddScene.setIcon(self.theTheme.getIcon("proj_scene"))
|
||||||
self.aAddScene.triggered.connect(
|
self.aAddScene.triggered.connect(
|
||||||
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=3, isNote=False)
|
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=3, isNote=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.aAddNote = self.mAdd.addAction(self.tr("Project Note"))
|
self.aAddNote = self.mAdd.addAction(trConst(nwLabels.ITEM_DESCRIPTION["note"]))
|
||||||
self.aAddNote.setIcon(self.theTheme.getIcon("proj_note"))
|
self.aAddNote.setIcon(self.theTheme.getIcon("proj_note"))
|
||||||
self.aAddNote.triggered.connect(
|
self.aAddNote.triggered.connect(
|
||||||
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
|
lambda: self.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.aAddFolder = self.mAdd.addAction(self.tr("Folder"))
|
self.aAddFolder = self.mAdd.addAction(trConst(nwLabels.ITEM_DESCRIPTION["folder"]))
|
||||||
self.aAddFolder.setIcon(self.theTheme.getIcon("proj_folder"))
|
self.aAddFolder.setIcon(self.theTheme.getIcon("proj_folder"))
|
||||||
self.aAddFolder.triggered.connect(
|
self.aAddFolder.triggered.connect(
|
||||||
lambda: self.projTree.newTreeItem(nwItemType.FOLDER)
|
lambda: self.projTree.newTreeItem(nwItemType.FOLDER)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mAddRoot = self.mAdd.addMenu(self.tr("Root Folder"))
|
self.mAddRoot = self.mAdd.addMenu(trConst(nwLabels.ITEM_DESCRIPTION["root"]))
|
||||||
self._addRootFolderEntry(nwItemClass.NOVEL)
|
self._addRootFolderEntry(nwItemClass.NOVEL)
|
||||||
self._addRootFolderEntry(nwItemClass.ARCHIVE)
|
self._addRootFolderEntry(nwItemClass.ARCHIVE)
|
||||||
self.mAddRoot.addSeparator()
|
self.mAddRoot.addSeparator()
|
||||||
@@ -268,6 +267,9 @@ class GuiProjectToolBar(QWidget):
|
|||||||
self.aMoreUndo = self.mMore.addAction(self.tr("Undo Move"))
|
self.aMoreUndo = self.mMore.addAction(self.tr("Undo Move"))
|
||||||
self.aMoreUndo.triggered.connect(lambda: self.projTree.undoLastMove())
|
self.aMoreUndo.triggered.connect(lambda: self.projTree.undoLastMove())
|
||||||
|
|
||||||
|
self.aEmptyTrash = self.mMore.addAction(self.tr("Empty Trash"))
|
||||||
|
self.aEmptyTrash.triggered.connect(lambda: self.projTree.emptyTrash())
|
||||||
|
|
||||||
self.tbMore = QToolButton(self)
|
self.tbMore = QToolButton(self)
|
||||||
self.tbMore.setToolTip(self.tr("More Options"))
|
self.tbMore.setToolTip(self.tr("More Options"))
|
||||||
self.tbMore.setIcon(self.theTheme.getIcon("menu"))
|
self.tbMore.setIcon(self.theTheme.getIcon("menu"))
|
||||||
@@ -335,9 +337,8 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
# Context Menu
|
# Context Menu
|
||||||
self.ctxMenu = GuiProjectTreeMenu(self)
|
|
||||||
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
self.customContextMenuRequested.connect(self._rightClickMenu)
|
self.customContextMenuRequested.connect(self._openContextMenu)
|
||||||
|
|
||||||
# Tree Settings
|
# Tree Settings
|
||||||
iPx = self.theTheme.baseIconSize
|
iPx = self.theTheme.baseIconSize
|
||||||
@@ -972,19 +973,106 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot("QPoint")
|
@pyqtSlot("QPoint")
|
||||||
def _rightClickMenu(self, clickPos):
|
def _openContextMenu(self, clickPos):
|
||||||
"""The user right clicked an element in the project tree, so we
|
"""The user right clicked an element in the project tree, so we
|
||||||
open a context menu in-place.
|
open a context menu in-place.
|
||||||
"""
|
"""
|
||||||
|
tItem = None
|
||||||
selItem = self.itemAt(clickPos)
|
selItem = self.itemAt(clickPos)
|
||||||
if isinstance(selItem, QTreeWidgetItem):
|
if isinstance(selItem, QTreeWidgetItem):
|
||||||
tHandle = selItem.data(self.C_NAME, Qt.UserRole)
|
tHandle = selItem.data(self.C_NAME, Qt.UserRole)
|
||||||
self.setSelectedHandle(tHandle) # Just to be safe
|
|
||||||
tItem = self.theProject.tree[tHandle]
|
tItem = self.theProject.tree[tHandle]
|
||||||
if tItem is not None:
|
|
||||||
if self.ctxMenu.filterActions(tItem):
|
if tItem is None:
|
||||||
# Only open menu if any actions remain after filter
|
logger.debug("No item found")
|
||||||
self.ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
|
|
||||||
|
ctxMenu = QMenu()
|
||||||
|
|
||||||
|
# Trash Folder
|
||||||
|
# ============
|
||||||
|
|
||||||
|
trashHandle = self.theProject.tree.trashRoot()
|
||||||
|
if tItem.itemHandle == trashHandle and trashHandle is not None:
|
||||||
|
# The trash folder only has one option
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Empty Trash"), lambda: self.emptyTrash()
|
||||||
|
)
|
||||||
|
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Document Actions
|
||||||
|
# ================
|
||||||
|
|
||||||
|
isFile = tItem.itemType == nwItemType.FILE
|
||||||
|
if isFile:
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Open Document"),
|
||||||
|
lambda: self.projView.openDocumentRequest.emit(tHandle, nwDocMode.EDIT)
|
||||||
|
)
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("View Document"),
|
||||||
|
lambda: self.projView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW)
|
||||||
|
)
|
||||||
|
ctxMenu.addSeparator()
|
||||||
|
|
||||||
|
# Edit Item Settings
|
||||||
|
# ==================
|
||||||
|
|
||||||
|
if isFile:
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Toggle Exported"), lambda: self._toggleItemExported(tHandle)
|
||||||
|
)
|
||||||
|
|
||||||
|
if tItem.isNovelLike():
|
||||||
|
mStatus = ctxMenu.addMenu(self.tr("Change Status"))
|
||||||
|
for n, (key, entry) in enumerate(self.theProject.statusItems.items()):
|
||||||
|
aStatus = mStatus.addAction(entry["icon"], entry["name"])
|
||||||
|
aStatus.triggered.connect(
|
||||||
|
lambda n, key=key: self._changeItemStatus(tHandle, key)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
mImport = ctxMenu.addMenu(self.tr("Change Importance"))
|
||||||
|
for n, (key, entry) in enumerate(self.theProject.importItems.items()):
|
||||||
|
aImport = mImport.addAction(entry["icon"], entry["name"])
|
||||||
|
aImport.triggered.connect(
|
||||||
|
lambda n, key=key: self._changeItemImport(tHandle, key)
|
||||||
|
)
|
||||||
|
|
||||||
|
if isFile and tItem.documentAllowed():
|
||||||
|
if tItem.itemLayout == nwItemLayout.NOTE:
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Change to {0}").format(
|
||||||
|
trConst(nwLabels.LAYOUT_NAME[nwItemLayout.DOCUMENT])
|
||||||
|
),
|
||||||
|
lambda: self._changeItemLayout(tHandle, nwItemLayout.DOCUMENT)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Change to {0}").format(
|
||||||
|
trConst(nwLabels.LAYOUT_NAME[nwItemLayout.NOTE])
|
||||||
|
),
|
||||||
|
lambda: self._changeItemLayout(tHandle, nwItemLayout.NOTE)
|
||||||
|
)
|
||||||
|
|
||||||
|
ctxMenu.addSeparator()
|
||||||
|
|
||||||
|
# Major Item Actions
|
||||||
|
# ==================
|
||||||
|
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Edit Item Settings"), lambda: self.editTreeItem(tHandle)
|
||||||
|
)
|
||||||
|
|
||||||
|
if tItem.itemClass == nwItemClass.TRASH or tItem.itemType == nwItemType.ROOT:
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Delete Permanently"), lambda: self.deleteItem(tHandle)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
ctxMenu.addAction(
|
||||||
|
self.tr("Move to Trash"), lambda: self.deleteItem(tHandle)
|
||||||
|
)
|
||||||
|
|
||||||
|
ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1121,6 +1209,46 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _toggleItemExported(self, tHandle):
|
||||||
|
"""Toggle the exported status of an item.
|
||||||
|
"""
|
||||||
|
tItem = self.theProject.tree[tHandle]
|
||||||
|
if tItem is not None:
|
||||||
|
tItem.setExported(not tItem.isExported)
|
||||||
|
self.setTreeItemValues(tItem.itemHandle)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _changeItemStatus(self, tHandle, tStatus):
|
||||||
|
"""Set a new status value of an item.
|
||||||
|
"""
|
||||||
|
tItem = self.theProject.tree[tHandle]
|
||||||
|
if tItem is not None:
|
||||||
|
tItem.setStatus(tStatus)
|
||||||
|
self.setTreeItemValues(tItem.itemHandle)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _changeItemImport(self, tHandle, tImport):
|
||||||
|
"""Set a new importance value of an item.
|
||||||
|
"""
|
||||||
|
tItem = self.theProject.tree[tHandle]
|
||||||
|
if tItem is not None:
|
||||||
|
tItem.setImport(tImport)
|
||||||
|
self.setTreeItemValues(tItem.itemHandle)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _changeItemLayout(self, tHandle, itemLayout):
|
||||||
|
"""Set a new item layout value of an item.
|
||||||
|
"""
|
||||||
|
tItem = self.theProject.tree[tHandle]
|
||||||
|
if tItem is not None:
|
||||||
|
if itemLayout == nwItemLayout.DOCUMENT and tItem.documentAllowed():
|
||||||
|
tItem.setLayout(nwItemLayout.DOCUMENT)
|
||||||
|
self.setTreeItemValues(tItem.itemHandle)
|
||||||
|
elif itemLayout == nwItemLayout.NOTE:
|
||||||
|
tItem.setLayout(nwItemLayout.NOTE)
|
||||||
|
self.setTreeItemValues(tItem.itemHandle)
|
||||||
|
return
|
||||||
|
|
||||||
def _scanChildren(self, theList, tItem, tIndex):
|
def _scanChildren(self, theList, tItem, tIndex):
|
||||||
"""This is a recursive function returning all items in a tree
|
"""This is a recursive function returning all items in a tree
|
||||||
starting at a given QTreeWidgetItem.
|
starting at a given QTreeWidgetItem.
|
||||||
@@ -1244,116 +1372,3 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiProjectTree
|
# END Class GuiProjectTree
|
||||||
|
|
||||||
|
|
||||||
class GuiProjectTreeMenu(QMenu):
|
|
||||||
|
|
||||||
def __init__(self, theTree):
|
|
||||||
QMenu.__init__(self, theTree)
|
|
||||||
|
|
||||||
self.theTree = theTree
|
|
||||||
self.theItem = None
|
|
||||||
|
|
||||||
self.editItem = QAction(self.tr("Edit Project Item"), self)
|
|
||||||
self.editItem.triggered.connect(self._doEditItem)
|
|
||||||
self.addAction(self.editItem)
|
|
||||||
|
|
||||||
self.openItem = QAction(self.tr("Open Document"), self)
|
|
||||||
self.openItem.triggered.connect(self._doOpenItem)
|
|
||||||
self.addAction(self.openItem)
|
|
||||||
|
|
||||||
self.viewItem = QAction(self.tr("View Document"), self)
|
|
||||||
self.viewItem.triggered.connect(self._doViewItem)
|
|
||||||
self.addAction(self.viewItem)
|
|
||||||
|
|
||||||
self.toggleExp = QAction(self.tr("Toggle Included Flag"), self)
|
|
||||||
self.toggleExp.triggered.connect(self._doToggleExported)
|
|
||||||
self.addAction(self.toggleExp)
|
|
||||||
|
|
||||||
self.deleteItem = QAction(self.tr("Delete Item"), self)
|
|
||||||
self.deleteItem.triggered.connect(self._doDeleteItem)
|
|
||||||
self.addAction(self.deleteItem)
|
|
||||||
|
|
||||||
self.emptyTrash = QAction(self.tr("Empty Trash"), self)
|
|
||||||
self.emptyTrash.triggered.connect(self._doEmptyTrash)
|
|
||||||
self.addAction(self.emptyTrash)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def filterActions(self, theItem):
|
|
||||||
"""Filter the menu entries available based on the properties of
|
|
||||||
the item the menu was activated on.
|
|
||||||
"""
|
|
||||||
self.theItem = theItem
|
|
||||||
|
|
||||||
if theItem is None:
|
|
||||||
logger.error("Failed to extract information to build tree context menu")
|
|
||||||
return False
|
|
||||||
|
|
||||||
trashHandle = self.theTree.theProject.tree.trashRoot()
|
|
||||||
|
|
||||||
isTrash = theItem.itemHandle == trashHandle and trashHandle is not None
|
|
||||||
isFile = theItem.itemType == nwItemType.FILE
|
|
||||||
|
|
||||||
self.editItem.setVisible(not isTrash)
|
|
||||||
self.openItem.setVisible(isFile)
|
|
||||||
self.viewItem.setVisible(isFile)
|
|
||||||
self.toggleExp.setVisible(isFile)
|
|
||||||
self.deleteItem.setVisible(not isTrash)
|
|
||||||
self.emptyTrash.setVisible(isTrash)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
##
|
|
||||||
# Slots
|
|
||||||
##
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doOpenItem(self):
|
|
||||||
"""Forward the open document call to the main GUI window.
|
|
||||||
"""
|
|
||||||
if self.theItem is not None:
|
|
||||||
self.theTree.theParent.openDocument(self.theItem.itemHandle, doScroll=False)
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doViewItem(self):
|
|
||||||
"""Forward the view document call to the main GUI window.
|
|
||||||
"""
|
|
||||||
if self.theItem is not None:
|
|
||||||
self.theTree.theParent.viewDocument(self.theItem.itemHandle)
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doEditItem(self):
|
|
||||||
"""Forward the edit item call to the main GUI window.
|
|
||||||
"""
|
|
||||||
if self.theItem is not None:
|
|
||||||
self.theTree.theParent.editItem()
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doToggleExported(self):
|
|
||||||
"""Flip the isExported flag of the current item.
|
|
||||||
"""
|
|
||||||
if self.theItem is not None:
|
|
||||||
self.theItem.setExported(not self.theItem.isExported)
|
|
||||||
self.theTree.setTreeItemValues(self.theItem.itemHandle)
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doDeleteItem(self):
|
|
||||||
"""Forward the delete item call to the project tree.
|
|
||||||
"""
|
|
||||||
if self.theItem is not None:
|
|
||||||
self.theTree.deleteItem()
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _doEmptyTrash(self):
|
|
||||||
"""Forward the empty trash call to the project tree.
|
|
||||||
"""
|
|
||||||
self.theTree.emptyTrash()
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class GuiProjectTreeMenu
|
|
||||||
|
|||||||
+12
-12
@@ -1,13 +1,13 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-06-06 22:02:03">
|
<novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-06-11 13:36:01">
|
||||||
<project>
|
<project>
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
<author>Jane Smith</author>
|
<author>Jane Smith</author>
|
||||||
<author>Jay Doh</author>
|
<author>Jay Doh</author>
|
||||||
<saveCount>1342</saveCount>
|
<saveCount>1345</saveCount>
|
||||||
<autoCount>227</autoCount>
|
<autoCount>229</autoCount>
|
||||||
<editTime>68090</editTime>
|
<editTime>68286</editTime>
|
||||||
</project>
|
</project>
|
||||||
<settings>
|
<settings>
|
||||||
<doBackup>False</doBackup>
|
<doBackup>False</doBackup>
|
||||||
@@ -33,13 +33,13 @@
|
|||||||
<section></section>
|
<section></section>
|
||||||
</titleFormat>
|
</titleFormat>
|
||||||
<status>
|
<status>
|
||||||
<entry key="sf12341" count="7" red="100" green="100" blue="100">New</entry>
|
<entry key="sf12341" count="5" red="100" green="100" blue="100">New</entry>
|
||||||
<entry key="sf24ce6" count="1" red="200" green="50" blue="0">Notes</entry>
|
<entry key="sf24ce6" count="2" red="200" green="50" blue="0">Notes</entry>
|
||||||
<entry key="sc24b8f" count="2" red="182" green="60" blue="0">Started</entry>
|
<entry key="sc24b8f" count="2" red="182" green="60" blue="0">Started</entry>
|
||||||
<entry key="s90e6c9" count="6" red="193" green="129" blue="0">1st Draft</entry>
|
<entry key="s90e6c9" count="7" red="193" green="129" blue="0">1st Draft</entry>
|
||||||
<entry key="sd51c5b" count="1" red="193" green="129" blue="0">2nd Draft</entry>
|
<entry key="sd51c5b" count="0" red="193" green="129" blue="0">2nd Draft</entry>
|
||||||
<entry key="s8ae72a" count="0" red="193" green="129" blue="0">3rd Draft</entry>
|
<entry key="s8ae72a" count="0" red="193" green="129" blue="0">3rd Draft</entry>
|
||||||
<entry key="s78ea90" count="0" red="58" green="180" blue="58">Finished</entry>
|
<entry key="s78ea90" count="1" red="58" green="180" blue="58">Finished</entry>
|
||||||
</status>
|
</status>
|
||||||
<importance>
|
<importance>
|
||||||
<entry key="ia857f0" count="5" red="100" green="100" blue="100">None</entry>
|
<entry key="ia857f0" count="5" red="100" green="100" blue="100">None</entry>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
</item>
|
</item>
|
||||||
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" charCount="26" wordCount="6" paraCount="1" cursorPos="36"/>
|
<meta expanded="False" charCount="26" wordCount="6" paraCount="1" cursorPos="36"/>
|
||||||
<name status="sf12341" import="ia857f0" exported="True">Part One</name>
|
<name status="s90e6c9" import="ia857f0" exported="True">Part One</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="True" charCount="95" wordCount="18" paraCount="1" cursorPos="291"/>
|
<meta expanded="True" charCount="95" wordCount="18" paraCount="1" cursorPos="291"/>
|
||||||
@@ -79,11 +79,11 @@
|
|||||||
</item>
|
</item>
|
||||||
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" charCount="617" wordCount="101" paraCount="3" cursorPos="310"/>
|
<meta expanded="False" charCount="617" wordCount="101" paraCount="3" cursorPos="310"/>
|
||||||
<name status="sf12341" import="ia857f0" exported="True">Interlude</name>
|
<name status="s78ea90" import="ia857f0" exported="True">Interlude</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE">
|
<item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE">
|
||||||
<meta expanded="False" charCount="1909" wordCount="346" paraCount="7" cursorPos="0"/>
|
<meta expanded="False" charCount="1909" wordCount="346" paraCount="7" cursorPos="0"/>
|
||||||
<name status="sd51c5b" import="ia857f0" exported="False">A Note on Structure</name>
|
<name status="sf24ce6" import="ia857f0" exported="False">A Note on Structure</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="True" charCount="139" wordCount="28" paraCount="1" cursorPos="343"/>
|
<meta expanded="True" charCount="139" wordCount="28" paraCount="1" cursorPos="343"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user