@@ -48,9 +48,10 @@ addition to the word count.
|
|||||||
Project Tree Drag and Drop
|
Project Tree Drag and Drop
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The project tree allows dragging and drop to a certain extent, but it does not allow bulk actions.
|
The project tree allows dragging and drop to a certain extent. This feature is primarily intended
|
||||||
This is deliberate to avoid accidentally messing up your project. The project tree has no undo
|
for rearranging the order of your files within each root folder, and has only limited support for
|
||||||
function.
|
moving files elsewhere in the project tree. In general, bulk actions are not allowed. This is
|
||||||
|
deliberate to avoid accidentally messing up your project. The project tree has no undo function.
|
||||||
|
|
||||||
Document files and their folders can be rearranged freely within their root folders. Novel files
|
Document files and their folders can be rearranged freely within their root folders. Novel files
|
||||||
cannot be moved out of the :guilabel:`Novel` folder, except to :guilabel:`Trash` and the
|
cannot be moved out of the :guilabel:`Novel` folder, except to :guilabel:`Trash` and the
|
||||||
@@ -59,9 +60,9 @@ cannot be moved out of the :guilabel:`Novel` folder, except to :guilabel:`Trash`
|
|||||||
Folders cannot be moved at all outside their root tree. Neither can a folder containing files be
|
Folders cannot be moved at all outside their root tree. Neither can a folder containing files be
|
||||||
deleted. You must first delete the files.
|
deleted. You must first delete the files.
|
||||||
|
|
||||||
Root folders in the project tree cannot be dragged and dropped. However, if you want to reorder
|
Root folders in the project tree cannot be dragged and dropped at all. However, if you want to
|
||||||
them, you can move them up or down with respect to eachother from the :guilabel:`Tools` menu, or by
|
reorder them, you can move them up or down with respect to eachother from the :guilabel:`Tools`
|
||||||
pressing :kbd:`Ctrl`:kbd:`Shift` and the :kbd:`Up` or :kbd:`Down` key.
|
menu, or by pressing :kbd:`Ctrl`:kbd:`Shift` and the :kbd:`Up` or :kbd:`Down` key.
|
||||||
|
|
||||||
|
|
||||||
.. _a_ui_edit:
|
.. _a_ui_edit:
|
||||||
|
|||||||
@@ -90,10 +90,8 @@ trash folder can then be deleted permanently, either individually, or by emptyin
|
|||||||
menu. Files in this folder are removed from the project index and cannot be referenced.
|
menu. Files in this folder are removed from the project index and cannot be referenced.
|
||||||
|
|
||||||
Folders and root folders can only be deleted when they are empty. Recursive deletion is not
|
Folders and root folders can only be deleted when they are empty. Recursive deletion is not
|
||||||
supported.
|
supported. A document file or a folder can be deleted from the :guilabel:`project` menu, or by
|
||||||
|
pressing :kbd:`Ctrl`:kbd:`Del`.
|
||||||
A document file or a folder can be deleted from the :guilabel:`project` menu, or by pressing
|
|
||||||
:kbd:`Ctrl`:kbd:`Del`.
|
|
||||||
|
|
||||||
|
|
||||||
.. _a_proj_roots_out:
|
.. _a_proj_roots_out:
|
||||||
@@ -103,13 +101,13 @@ Archived Documents (Outtakes)
|
|||||||
|
|
||||||
If you don't want to delete a file, or put it in the :guilabel:`Trash` folder where it may be
|
If you don't want to delete a file, or put it in the :guilabel:`Trash` folder where it may be
|
||||||
deleted, but still want it out of your main project tree, you can create an :guilabel:`Outtakes`
|
deleted, but still want it out of your main project tree, you can create an :guilabel:`Outtakes`
|
||||||
root folder from the :guilabel:`project` menu. This folder is similar to the :guilabel:`Trash`
|
root folder from the :guilabel:`Project` menu. You are not allowed to move folders to this root
|
||||||
folder in that it doesn't allow subfolders and creating new files.
|
folder, only files. If you need folders in it to organise your files, you can of course create new
|
||||||
|
ones there.
|
||||||
|
|
||||||
You can drag any file to this folder and preserve its settings. The file will always be excluded
|
You can drag any file to this folder and preserve its settings. The file will always be excluded
|
||||||
from the :guilabel:`Build Novel Project` builds, even with the setting to ignore the excluded files
|
from the :guilabel:`Build Novel Project` builds. The file is also removed from the project index, so
|
||||||
option. The file is also removed from the project index, so the tags and references defined in it
|
the tags and references defined in it will not show up anywhere else.
|
||||||
will not show up anywhere else.
|
|
||||||
|
|
||||||
|
|
||||||
.. _a_proj_roots_orph:
|
.. _a_proj_roots_orph:
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ class nwConst():
|
|||||||
fStampFmt = "%Y-%m-%d %H.%M.%S" # FileName safe format
|
fStampFmt = "%Y-%m-%d %H.%M.%S" # FileName safe format
|
||||||
dStampFmt = "%Y-%m-%d" # Date only format
|
dStampFmt = "%Y-%m-%d" # Date only format
|
||||||
|
|
||||||
|
maxDepth = 30 # Maximum folder depth of a project
|
||||||
|
|
||||||
# END Class nwConst
|
# END Class nwConst
|
||||||
|
|
||||||
class nwRegEx():
|
class nwRegEx():
|
||||||
|
|||||||
+2
-2
@@ -33,7 +33,7 @@ from os import path, rename, unlink
|
|||||||
from nw.core.item import NWItem
|
from nw.core.item import NWItem
|
||||||
from nw.constants import nwAlert
|
from nw.constants import nwAlert
|
||||||
from nw.common import isHandle
|
from nw.common import isHandle
|
||||||
from nw.constants import nwItemLayout, nwItemClass
|
from nw.constants import nwItemLayout, nwItemClass, nwConst
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ class NWDoc():
|
|||||||
|
|
||||||
# Scan for handles
|
# Scan for handles
|
||||||
thePath = []
|
thePath = []
|
||||||
for n in range(200):
|
for n in range(nwConst.maxDepth + 5):
|
||||||
if len(theMeta) < 14:
|
if len(theMeta) < 14:
|
||||||
break
|
break
|
||||||
if theMeta[13] == ":":
|
if theMeta[13] == ":":
|
||||||
|
|||||||
+19
-16
@@ -176,7 +176,7 @@ class NWIndex():
|
|||||||
if "textCounts" in theData.keys():
|
if "textCounts" in theData.keys():
|
||||||
self.textCounts = theData["textCounts"]
|
self.textCounts = theData["textCounts"]
|
||||||
|
|
||||||
nowTime = time()
|
nowTime = round(time())
|
||||||
self.timeNovel = nowTime
|
self.timeNovel = nowTime
|
||||||
self.timeNote = nowTime
|
self.timeNote = nowTime
|
||||||
self.timeIndex = nowTime
|
self.timeIndex = nowTime
|
||||||
@@ -268,21 +268,28 @@ class NWIndex():
|
|||||||
"""
|
"""
|
||||||
theItem = self.theProject.projTree[tHandle]
|
theItem = self.theProject.projTree[tHandle]
|
||||||
theRoot = self.theProject.projTree.getRootItem(tHandle)
|
theRoot = self.theProject.projTree.getRootItem(tHandle)
|
||||||
|
|
||||||
if theItem is None:
|
if theItem is None:
|
||||||
logger.error("Not indexing unknown item %s" % tHandle)
|
logger.error("Not indexing unknown item %s" % tHandle)
|
||||||
return False
|
return False
|
||||||
if theItem.itemType != nwItemType.FILE:
|
if theItem.itemType != nwItemType.FILE:
|
||||||
logger.error("Not indexing non-file item %s" % tHandle)
|
logger.error("Not indexing non-file item %s" % tHandle)
|
||||||
return False
|
return False
|
||||||
if theItem.parHandle == self.theProject.projTree.trashRoot():
|
|
||||||
logger.error("Not indexing trash item %s" % tHandle)
|
|
||||||
return False
|
|
||||||
if theItem.itemLayout == nwItemLayout.NO_LAYOUT:
|
if theItem.itemLayout == nwItemLayout.NO_LAYOUT:
|
||||||
logger.error("Not indexing no-layout item %s" % tHandle)
|
logger.error("Not indexing no-layout item %s" % tHandle)
|
||||||
return False
|
return False
|
||||||
if theRoot is None:
|
if theRoot is None:
|
||||||
logger.error("Not indexing homeless item %s" % tHandle)
|
logger.error("Not indexing homeless item %s" % tHandle)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Run word counter for the whole text
|
||||||
|
cC, wC, pC = countWords(theText)
|
||||||
|
self.textCounts[tHandle] = [cC, wC, pC]
|
||||||
|
|
||||||
|
# If the file is archived or trashed, we don't index the file itself
|
||||||
|
if theItem.parHandle == self.theProject.projTree.trashRoot():
|
||||||
|
logger.error("Not indexing trash item %s" % tHandle)
|
||||||
|
return False
|
||||||
if theRoot.itemClass == nwItemClass.ARCHIVE:
|
if theRoot.itemClass == nwItemClass.ARCHIVE:
|
||||||
logger.error("Not indexing archived item %s" % tHandle)
|
logger.error("Not indexing archived item %s" % tHandle)
|
||||||
return False
|
return False
|
||||||
@@ -297,7 +304,7 @@ class NWIndex():
|
|||||||
self.refIndex[tHandle] = {}
|
self.refIndex[tHandle] = {}
|
||||||
self.refIndex[tHandle]["T000000"] = {
|
self.refIndex[tHandle]["T000000"] = {
|
||||||
"tags" : [],
|
"tags" : [],
|
||||||
"updated" : time(),
|
"updated" : round(time()),
|
||||||
}
|
}
|
||||||
if itemLayout == nwItemLayout.NOTE:
|
if itemLayout == nwItemLayout.NOTE:
|
||||||
self.noteIndex[tHandle] = {}
|
self.noteIndex[tHandle] = {}
|
||||||
@@ -351,12 +358,8 @@ class NWIndex():
|
|||||||
lastText = "\n".join(theLines[nTitle-1:nLine-1])
|
lastText = "\n".join(theLines[nTitle-1:nLine-1])
|
||||||
self._indexWordCounts(tHandle, isNovel, lastText, nTitle)
|
self._indexWordCounts(tHandle, isNovel, lastText, nTitle)
|
||||||
|
|
||||||
# Run word counter for whole text
|
|
||||||
cC, wC, pC = countWords(theText)
|
|
||||||
self.textCounts[tHandle] = [cC, wC, pC]
|
|
||||||
|
|
||||||
# Update timestamps for index changes
|
# Update timestamps for index changes
|
||||||
nowTime = time()
|
nowTime = round(time())
|
||||||
self.timeIndex = nowTime
|
self.timeIndex = nowTime
|
||||||
if isNovel:
|
if isNovel:
|
||||||
self.timeNovel = nowTime
|
self.timeNovel = nowTime
|
||||||
@@ -391,7 +394,7 @@ class NWIndex():
|
|||||||
sTitle = "T%06d" % nLine
|
sTitle = "T%06d" % nLine
|
||||||
self.refIndex[tHandle][sTitle] = {
|
self.refIndex[tHandle][sTitle] = {
|
||||||
"tags" : [],
|
"tags" : [],
|
||||||
"updated" : time(),
|
"updated" : round(time()),
|
||||||
}
|
}
|
||||||
theData = {
|
theData = {
|
||||||
"level" : hDepth,
|
"level" : hDepth,
|
||||||
@@ -401,7 +404,7 @@ class NWIndex():
|
|||||||
"cCount" : 0,
|
"cCount" : 0,
|
||||||
"wCount" : 0,
|
"wCount" : 0,
|
||||||
"pCount" : 0,
|
"pCount" : 0,
|
||||||
"updated" : time(),
|
"updated" : round(time()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if hText != "":
|
if hText != "":
|
||||||
@@ -425,14 +428,14 @@ class NWIndex():
|
|||||||
self.novelIndex[tHandle][sTitle]["cCount"] = cC
|
self.novelIndex[tHandle][sTitle]["cCount"] = cC
|
||||||
self.novelIndex[tHandle][sTitle]["wCount"] = wC
|
self.novelIndex[tHandle][sTitle]["wCount"] = wC
|
||||||
self.novelIndex[tHandle][sTitle]["pCount"] = pC
|
self.novelIndex[tHandle][sTitle]["pCount"] = pC
|
||||||
self.novelIndex[tHandle][sTitle]["updated"] = time()
|
self.novelIndex[tHandle][sTitle]["updated"] = round(time())
|
||||||
else:
|
else:
|
||||||
if tHandle in self.noteIndex:
|
if tHandle in self.noteIndex:
|
||||||
if sTitle in self.noteIndex[tHandle]:
|
if sTitle in self.noteIndex[tHandle]:
|
||||||
self.noteIndex[tHandle][sTitle]["cCount"] = cC
|
self.noteIndex[tHandle][sTitle]["cCount"] = cC
|
||||||
self.noteIndex[tHandle][sTitle]["wCount"] = wC
|
self.noteIndex[tHandle][sTitle]["wCount"] = wC
|
||||||
self.noteIndex[tHandle][sTitle]["pCount"] = pC
|
self.noteIndex[tHandle][sTitle]["pCount"] = pC
|
||||||
self.noteIndex[tHandle][sTitle]["updated"] = time()
|
self.noteIndex[tHandle][sTitle]["updated"] = round(time())
|
||||||
return
|
return
|
||||||
|
|
||||||
def _indexSynopsis(self, tHandle, isNovel, theText, nTitle):
|
def _indexSynopsis(self, tHandle, isNovel, theText, nTitle):
|
||||||
@@ -443,12 +446,12 @@ class NWIndex():
|
|||||||
if tHandle in self.novelIndex:
|
if tHandle in self.novelIndex:
|
||||||
if sTitle in self.novelIndex[tHandle]:
|
if sTitle in self.novelIndex[tHandle]:
|
||||||
self.novelIndex[tHandle][sTitle]["synopsis"] = theText
|
self.novelIndex[tHandle][sTitle]["synopsis"] = theText
|
||||||
self.novelIndex[tHandle][sTitle]["updated"] = time()
|
self.novelIndex[tHandle][sTitle]["updated"] = round(time())
|
||||||
else:
|
else:
|
||||||
if tHandle in self.noteIndex:
|
if tHandle in self.noteIndex:
|
||||||
if sTitle in self.noteIndex[tHandle]:
|
if sTitle in self.noteIndex[tHandle]:
|
||||||
self.noteIndex[tHandle][sTitle]["synopsis"] = theText
|
self.noteIndex[tHandle][sTitle]["synopsis"] = theText
|
||||||
self.noteIndex[tHandle][sTitle]["updated"] = time()
|
self.noteIndex[tHandle][sTitle]["updated"] = round(time())
|
||||||
return
|
return
|
||||||
|
|
||||||
def _indexNoteRef(self, tHandle, aLine, nLine, nTitle):
|
def _indexNoteRef(self, tHandle, aLine, nLine, nTitle):
|
||||||
|
|||||||
+5
-5
@@ -35,7 +35,7 @@ from time import time
|
|||||||
|
|
||||||
from nw.core.item import NWItem
|
from nw.core.item import NWItem
|
||||||
from nw.common import checkString
|
from nw.common import checkString
|
||||||
from nw.constants import nwFiles, nwItemType, nwItemClass, nwItemLayout
|
from nw.constants import nwFiles, nwItemType, nwItemClass, nwItemLayout, nwConst
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -251,11 +251,11 @@ class NWTree():
|
|||||||
def getRootItem(self, tHandle):
|
def getRootItem(self, tHandle):
|
||||||
"""Iterate upwards in the tree until we find the item with
|
"""Iterate upwards in the tree until we find the item with
|
||||||
parent None, the root item. We do this with a for loop with a
|
parent None, the root item. We do this with a for loop with a
|
||||||
maximum depth of 200 to make infinite loops impossible.
|
maximum depth to make infinite loops impossible.
|
||||||
"""
|
"""
|
||||||
tItem = self.__getitem__(tHandle)
|
tItem = self.__getitem__(tHandle)
|
||||||
if tItem is not None:
|
if tItem is not None:
|
||||||
for i in range(200):
|
for i in range(nwConst.maxDepth + 1):
|
||||||
if tItem.parHandle is None:
|
if tItem.parHandle is None:
|
||||||
return tItem
|
return tItem
|
||||||
else:
|
else:
|
||||||
@@ -266,14 +266,14 @@ class NWTree():
|
|||||||
def getItemPath(self, tHandle):
|
def getItemPath(self, tHandle):
|
||||||
"""Iterate upwards in the tree until we find the item with
|
"""Iterate upwards in the tree until we find the item with
|
||||||
parent None, the root item, and return the list of handles.
|
parent None, the root item, and return the list of handles.
|
||||||
We do this with a for loop with a maximum depth of 200 to make
|
We do this with a for loop with a maximum depth to make
|
||||||
infinite loops impossible.
|
infinite loops impossible.
|
||||||
"""
|
"""
|
||||||
tTree = []
|
tTree = []
|
||||||
tItem = self.__getitem__(tHandle)
|
tItem = self.__getitem__(tHandle)
|
||||||
if tItem is not None:
|
if tItem is not None:
|
||||||
tTree.append(tHandle)
|
tTree.append(tHandle)
|
||||||
for i in range(200):
|
for i in range(nwConst.maxDepth + 1):
|
||||||
if tItem.parHandle is None:
|
if tItem.parHandle is None:
|
||||||
return tTree
|
return tTree
|
||||||
else:
|
else:
|
||||||
|
|||||||
+43
-21
@@ -38,7 +38,7 @@ from PyQt5.QtWidgets import (
|
|||||||
|
|
||||||
from nw.core import NWDoc
|
from nw.core import NWDoc
|
||||||
from nw.constants import (
|
from nw.constants import (
|
||||||
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwConst
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -59,6 +59,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
self.theTheme = theParent.theTheme
|
self.theTheme = theParent.theTheme
|
||||||
self.theProject = theParent.theProject
|
self.theProject = theParent.theProject
|
||||||
|
self.theIndex = theParent.theIndex
|
||||||
|
|
||||||
# Tree Settings
|
# Tree Settings
|
||||||
self.theMap = None
|
self.theMap = None
|
||||||
@@ -145,6 +146,9 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
if not self.theParent.hasProject:
|
if not self.theParent.hasProject:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# The item needs to be assigned an item class, so one must be
|
||||||
|
# provided, or it must be possible to extract it from the parent
|
||||||
|
# item of the new item.
|
||||||
if itemClass is None and pHandle is not None:
|
if itemClass is None and pHandle is not None:
|
||||||
pItem = self.theProject.projTree[pHandle]
|
pItem = self.theProject.projTree[pHandle]
|
||||||
if pItem is not None:
|
if pItem is not None:
|
||||||
@@ -167,6 +171,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.makeAlert("Failed to add new item.", nwAlert.BUG)
|
self.makeAlert("Failed to add new item.", nwAlert.BUG)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Everything is fine, we have what we need, so we proceed
|
||||||
logger.verbose("Adding new item of type %s and class %s to handle %s" % (
|
logger.verbose("Adding new item of type %s and class %s to handle %s" % (
|
||||||
itemType.name, itemClass.name, str(pHandle))
|
itemType.name, itemClass.name, str(pHandle))
|
||||||
)
|
)
|
||||||
@@ -182,7 +187,9 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
# If still nothing, give up
|
# If still nothing, give up
|
||||||
if pHandle is None:
|
if pHandle is None:
|
||||||
logger.error("Did not find anywhere to add the item!")
|
self.makeAlert(
|
||||||
|
"Did not find anywhere to add the file or folder!", nwAlert.ERROR
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Now check if the selected item is a file, in which case
|
# Now check if the selected item is a file, in which case
|
||||||
@@ -207,19 +214,23 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if pItem.itemClass == nwItemClass.ARCHIVE:
|
parTree = self.theProject.projTree.getItemPath(pHandle)
|
||||||
self.makeAlert(
|
|
||||||
"Cannot add new files or folders to the %s folder." % (
|
|
||||||
nwLabels.CLASS_NAME[nwItemClass.ARCHIVE]
|
|
||||||
), nwAlert.ERROR
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
# If we're still here, add the file or folder
|
# If we're still here, add the file or folder
|
||||||
if itemType == nwItemType.FILE:
|
if itemType == nwItemType.FILE:
|
||||||
tHandle = self.theProject.newFile("New File", itemClass, pHandle)
|
tHandle = self.theProject.newFile("New File", itemClass, pHandle)
|
||||||
|
|
||||||
elif itemType == nwItemType.FOLDER:
|
elif itemType == nwItemType.FOLDER:
|
||||||
|
if len(parTree) >= nwConst.maxDepth - 1:
|
||||||
|
# Folders cannot be deeper than maxDepth - 1, leaving room
|
||||||
|
# for one more level of files.
|
||||||
|
self.makeAlert((
|
||||||
|
"Cannot add new folder to this item. "
|
||||||
|
"Maximum folder depth has been reached."
|
||||||
|
), nwAlert.ERROR)
|
||||||
|
return False
|
||||||
tHandle = self.theProject.newFolder("New Folder", itemClass, pHandle)
|
tHandle = self.theProject.newFolder("New Folder", itemClass, pHandle)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error("Failed to add new item")
|
logger.error("Failed to add new item")
|
||||||
return False
|
return False
|
||||||
@@ -332,7 +343,9 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
logger.debug("Emptying Trash folder")
|
logger.debug("Emptying Trash folder")
|
||||||
if trashHandle is None:
|
if trashHandle is None:
|
||||||
self.makeAlert("There is no Trash folder.", nwAlert.INFO)
|
self.makeAlert(
|
||||||
|
"There is currently no Trash folder in this project.", nwAlert.INFO
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
theTrash = self.getTreeFromHandle(trashHandle)
|
theTrash = self.getTreeFromHandle(trashHandle)
|
||||||
@@ -341,13 +354,13 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
|
|
||||||
nTrash = len(theTrash)
|
nTrash = len(theTrash)
|
||||||
if nTrash == 0:
|
if nTrash == 0:
|
||||||
self.makeAlert("The Trash folder is empty.", nwAlert.INFO)
|
self.makeAlert("The Trash folder is already empty.", nwAlert.INFO)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(
|
msgRes = msgBox.question(
|
||||||
self, "Empty Trash", "Permanently delete %d file%s from Trash?" % (
|
self, "Empty Trash", "Permanently delete %d file%s from Trash?" % (
|
||||||
nTrash, "s"*int(nTrash > 1)
|
nTrash, "s" if nTrash > 1 else ""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
@@ -420,7 +433,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
theDoc = NWDoc(self.theProject, self.theParent)
|
theDoc = NWDoc(self.theProject, self.theParent)
|
||||||
theDoc.deleteDocument(tHandle)
|
theDoc.deleteDocument(tHandle)
|
||||||
del self.theProject.projTree[tHandle]
|
del self.theProject.projTree[tHandle]
|
||||||
self.theParent.theIndex.deleteHandle(tHandle)
|
self.theIndex.deleteHandle(tHandle)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# The file is not already in the trash folder, so we
|
# The file is not already in the trash folder, so we
|
||||||
@@ -448,7 +461,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.propagateCount(tHandle, wCount)
|
self.propagateCount(tHandle, wCount)
|
||||||
|
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
self.theParent.theIndex.deleteHandle(tHandle)
|
self.theIndex.deleteHandle(tHandle)
|
||||||
|
|
||||||
elif nwItemS.itemType == nwItemType.FOLDER:
|
elif nwItemS.itemType == nwItemType.FOLDER:
|
||||||
logger.debug("User requested folder %s deleted" % tHandle)
|
logger.debug("User requested folder %s deleted" % tHandle)
|
||||||
@@ -461,7 +474,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
trItemP.takeChild(tIndex)
|
trItemP.takeChild(tIndex)
|
||||||
del self.theProject.projTree[tHandle]
|
del self.theProject.projTree[tHandle]
|
||||||
else:
|
else:
|
||||||
self.makeAlert("Cannot delete folder. It is not empty.", nwAlert.ERROR)
|
self.makeAlert((
|
||||||
|
"Cannot delete folder. It is not empty. "
|
||||||
|
"Recursive deletion is not supported. "
|
||||||
|
"Please delete the content first."
|
||||||
|
), nwAlert.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
elif nwItemS.itemType == nwItemType.ROOT:
|
elif nwItemS.itemType == nwItemType.ROOT:
|
||||||
@@ -473,7 +490,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.theParent.mainMenu.setAvailableRoot()
|
self.theParent.mainMenu.setAvailableRoot()
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
else:
|
else:
|
||||||
self.makeAlert("Cannot delete root folder. It is not empty.", nwAlert.ERROR)
|
self.makeAlert((
|
||||||
|
"Cannot delete root folder. It is not empty. "
|
||||||
|
"Recursive deletion is not supported. "
|
||||||
|
"Please delete the content first."
|
||||||
|
), nwAlert.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -532,7 +553,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
pCount += int(pItem.child(i).text(self.C_COUNT))
|
pCount += int(pItem.child(i).text(self.C_COUNT))
|
||||||
pHandle = pItem.data(self.C_NAME, Qt.UserRole)
|
pHandle = pItem.data(self.C_NAME, Qt.UserRole)
|
||||||
|
|
||||||
if not nDepth > 200 and pHandle != "":
|
if not nDepth > nwConst.maxDepth + 1 and pHandle != "":
|
||||||
self.propagateCount(pHandle, pCount, nDepth+1)
|
self.propagateCount(pHandle, pCount, nDepth+1)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -710,11 +731,12 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
self.propagateCount(sHandle, wCount)
|
self.propagateCount(sHandle, wCount)
|
||||||
|
|
||||||
# The items dropped into archive or trash should be removed
|
# The items dropped into archive or trash should be removed
|
||||||
# from the project index
|
# from the project index, for all other items, we rescan the
|
||||||
|
# file to ensure the index is up to date.
|
||||||
if onFree:
|
if onFree:
|
||||||
self.theParent.theIndex.deleteHandle(sHandle)
|
self.theIndex.deleteHandle(sHandle)
|
||||||
else:
|
else:
|
||||||
self.theParent.theIndex.reIndexHandle(sHandle)
|
self.theIndex.reIndexHandle(sHandle)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.debug("Drag'n'drop of item %s not accepted" % sHandle)
|
logger.debug("Drag'n'drop of item %s not accepted" % sHandle)
|
||||||
@@ -964,7 +986,7 @@ class GuiProjectTreeMenu(QMenu):
|
|||||||
showEdit = not isTrash and not isOrph
|
showEdit = not isTrash and not isOrph
|
||||||
showExport = isFile and not inTrash and not isOrph
|
showExport = isFile and not inTrash and not isOrph
|
||||||
showNewFile = not isTrash and not inTrash and not isOrph and not isArch
|
showNewFile = not isTrash and not inTrash and not isOrph and not isArch
|
||||||
showNewFolder = not isTrash and not inTrash and not isOrph and not isArch
|
showNewFolder = not isTrash and not inTrash and not isOrph
|
||||||
showDelete = not isTrash
|
showDelete = not isTrash
|
||||||
showEmpty = isTrash
|
showEmpty = isTrash
|
||||||
|
|
||||||
|
|||||||
+18
-11
@@ -1,13 +1,13 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.12.1" hexVersion="0x001201f0" fileVersion="1.2" timeStamp="2020-08-16 17:50:53">
|
<novelWriterXML appVersion="0.12.1" hexVersion="0x001201f0" fileVersion="1.2" timeStamp="2020-08-16 21:12:32">
|
||||||
<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>713</saveCount>
|
<saveCount>723</saveCount>
|
||||||
<autoCount>138</autoCount>
|
<autoCount>140</autoCount>
|
||||||
<editTime>35134</editTime>
|
<editTime>35485</editTime>
|
||||||
</project>
|
</project>
|
||||||
<settings>
|
<settings>
|
||||||
<doBackup>False</doBackup>
|
<doBackup>False</doBackup>
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
<autoOutline>True</autoOutline>
|
<autoOutline>True</autoOutline>
|
||||||
<lastEdited>636b6aa9b697b</lastEdited>
|
<lastEdited>636b6aa9b697b</lastEdited>
|
||||||
<lastViewed>636b6aa9b697b</lastViewed>
|
<lastViewed>636b6aa9b697b</lastViewed>
|
||||||
<lastWordCount>1071</lastWordCount>
|
<lastWordCount>1077</lastWordCount>
|
||||||
<novelWordCount>695</novelWordCount>
|
<novelWordCount>701</novelWordCount>
|
||||||
<notesWordCount>376</notesWordCount>
|
<notesWordCount>376</notesWordCount>
|
||||||
<autoReplace>
|
<autoReplace>
|
||||||
<entry key="A">B</entry>
|
<entry key="A">B</entry>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<entry blue="175" green="0" red="117">Main</entry>
|
<entry blue="175" green="0" red="117">Main</entry>
|
||||||
</importance>
|
</importance>
|
||||||
</settings>
|
</settings>
|
||||||
<content count="24">
|
<content count="25">
|
||||||
<item handle="7031beac91f75" order="0" parent="None">
|
<item handle="7031beac91f75" order="0" parent="None">
|
||||||
<name>Novel</name>
|
<name>Novel</name>
|
||||||
<type>ROOT</type>
|
<type>ROOT</type>
|
||||||
@@ -269,7 +269,14 @@
|
|||||||
<status>None</status>
|
<status>None</status>
|
||||||
<expanded>True</expanded>
|
<expanded>True</expanded>
|
||||||
</item>
|
</item>
|
||||||
<item handle="8a5deb88c0e97" order="0" parent="6827118336ac1">
|
<item handle="ae9bf3c3ea159" order="0" parent="6827118336ac1">
|
||||||
|
<name>Scenes</name>
|
||||||
|
<type>FOLDER</type>
|
||||||
|
<class>ARCHIVE</class>
|
||||||
|
<status>None</status>
|
||||||
|
<expanded>True</expanded>
|
||||||
|
</item>
|
||||||
|
<item handle="8a5deb88c0e97" order="0" parent="ae9bf3c3ea159">
|
||||||
<name>Old File</name>
|
<name>Old File</name>
|
||||||
<type>FILE</type>
|
<type>FILE</type>
|
||||||
<class>NOVEL</class>
|
<class>NOVEL</class>
|
||||||
@@ -295,9 +302,9 @@
|
|||||||
<status>New</status>
|
<status>New</status>
|
||||||
<exported>True</exported>
|
<exported>True</exported>
|
||||||
<layout>SCENE</layout>
|
<layout>SCENE</layout>
|
||||||
<charCount>0</charCount>
|
<charCount>30</charCount>
|
||||||
<wordCount>0</wordCount>
|
<wordCount>6</wordCount>
|
||||||
<paraCount>0</paraCount>
|
<paraCount>1</paraCount>
|
||||||
<cursorPos>36</cursorPos>
|
<cursorPos>36</cursorPos>
|
||||||
</item>
|
</item>
|
||||||
</content>
|
</content>
|
||||||
|
|||||||
Reference in New Issue
Block a user