@@ -24,7 +24,8 @@ Tags in Notes
|
||||
Each new heading in a note can have a tag associated with it. The format of a tag is
|
||||
``@tag: tagname``, where tagname is a unique identifier. Tags can then be referenced in the novel
|
||||
documents, or cross-referenced in other notes, and will show up in the outline view and in the
|
||||
back-reference panel when a document is being viewed.
|
||||
back-reference panel when a document is being viewed. See :ref:`a_struct_tags` for how to reference
|
||||
notes.
|
||||
|
||||
The syntax highlighter will alert the user that the keyword is correctly used and that the tag is
|
||||
allowed, that is, the tag is unique. Duplicate tags should be detected as long as the index is up
|
||||
|
||||
@@ -86,10 +86,11 @@ more details.
|
||||
Tag References
|
||||
==============
|
||||
|
||||
Each text partition indicated by a heading of any level, can contain references to tags set in the
|
||||
supporting notes of the project. The references are gathered by the indexer and used to generate
|
||||
an outline view on the :guilabel:`Outline` tab of how the different parts of the novel are
|
||||
connected.
|
||||
Each text partition, indicated by a heading of any level, can contain references to tags set in the
|
||||
supporting notes of the project. The references are gathered by the indexer and used to generate an
|
||||
outline view on the :guilabel:`Outline` tab of how the different parts of the novel are connected.
|
||||
This section covers how to set references to tags. See :ref:`a_notes_tags` for how to define tags
|
||||
the references can point to.
|
||||
|
||||
References and tags are also clickable in the document editor and viewer, making it easy to
|
||||
navigate between reference notes while writing. Clicked links are always opened in the view panel.
|
||||
|
||||
@@ -210,7 +210,6 @@ class nwQuotes():
|
||||
"""Allowed quotation marks.
|
||||
Source: https://en.wikipedia.org/wiki/Quotation_mark
|
||||
"""
|
||||
|
||||
SYMBOLS = {
|
||||
"\u0027" : "Straight single quotation mark",
|
||||
"\u0022" : "Straight double quotation mark",
|
||||
@@ -241,7 +240,6 @@ class nwQuotes():
|
||||
class nwUnicode:
|
||||
"""Supported unicode character constants and their HTML equivalents.
|
||||
"""
|
||||
|
||||
# Unicode Constants
|
||||
# =================
|
||||
|
||||
|
||||
+2
-3
@@ -416,9 +416,7 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
self.theIndex.scanText(tHandle, docText)
|
||||
if self._updateHeaders(checkLevel=True):
|
||||
if self.theParent.projTabs.currentIndex() == self.theParent.idxNovelView:
|
||||
logger.verbose("Document headers have changed, updating novel tree")
|
||||
self.theParent.novelView.refreshTree()
|
||||
self.theParent.requestNovelTreeRefresh()
|
||||
else:
|
||||
self.theParent.novelView.updateWordCounts(tHandle)
|
||||
|
||||
@@ -1990,6 +1988,7 @@ class GuiDocEditSearch(QFrame):
|
||||
if theText is not None:
|
||||
self.searchBox.setText(theText)
|
||||
self.searchBox.setFocus()
|
||||
self.searchBox.selectAll()
|
||||
if self.isRegEx:
|
||||
self._alertSearchValid(True)
|
||||
logger.verbose("Setting search text to '%s'" % theText)
|
||||
|
||||
+41
-38
@@ -227,55 +227,58 @@ class GuiItemDetails(QWidget):
|
||||
def updateViewBox(self, tHandle):
|
||||
"""Populate the details box from a given handle.
|
||||
"""
|
||||
self.theHandle = tHandle
|
||||
nwItem = self.theProject.projTree[tHandle]
|
||||
if tHandle is None:
|
||||
self.clearDetails()
|
||||
return
|
||||
|
||||
nwItem = self.theProject.projTree[tHandle]
|
||||
if nwItem is None:
|
||||
self.clearDetails()
|
||||
return
|
||||
|
||||
self.theHandle = tHandle
|
||||
theLabel = nwItem.itemName
|
||||
if len(theLabel) > 100:
|
||||
theLabel = theLabel[:96].rstrip()+" ..."
|
||||
|
||||
itStatus = nwItem.itemStatus
|
||||
if nwItem.itemClass == nwItemClass.NOVEL:
|
||||
itStatus = self.theProject.statusItems.checkEntry(itStatus) # Make sure it's valid
|
||||
flagIcon = self.theParent.statusIcons[itStatus]
|
||||
else:
|
||||
theLabel = nwItem.itemName
|
||||
if len(theLabel) > 100:
|
||||
theLabel = theLabel[:96].rstrip()+" ..."
|
||||
itStatus = self.theProject.importItems.checkEntry(itStatus) # Make sure it's valid
|
||||
flagIcon = self.theParent.importIcons[itStatus]
|
||||
|
||||
itStatus = nwItem.itemStatus
|
||||
if nwItem.itemClass == nwItemClass.NOVEL:
|
||||
itStatus = self.theProject.statusItems.checkEntry(itStatus) # Make sure it's valid
|
||||
flagIcon = self.theParent.statusIcons[itStatus]
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
if nwItem.isExported:
|
||||
self.labelFlag.setPixmap(self.expCheck)
|
||||
else:
|
||||
itStatus = self.theProject.importItems.checkEntry(itStatus) # Make sure it's valid
|
||||
flagIcon = self.theParent.importIcons[itStatus]
|
||||
self.labelFlag.setPixmap(self.expCross)
|
||||
else:
|
||||
self.labelFlag.setPixmap(QPixmap(1, 1))
|
||||
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
if nwItem.isExported:
|
||||
self.labelFlag.setPixmap(self.expCheck)
|
||||
else:
|
||||
self.labelFlag.setPixmap(self.expCross)
|
||||
else:
|
||||
self.labelFlag.setPixmap(QPixmap(1, 1))
|
||||
iPx = int(round(0.8*self.theTheme.baseIconSize))
|
||||
self.statusFlag.setPixmap(flagIcon.pixmap(iPx, iPx))
|
||||
self.classFlag.setText(nwLabels.CLASS_FLAG[nwItem.itemClass])
|
||||
|
||||
iPx = int(round(0.8*self.theTheme.baseIconSize))
|
||||
self.statusFlag.setPixmap(flagIcon.pixmap(iPx, iPx))
|
||||
self.classFlag.setText(nwLabels.CLASS_FLAG[nwItem.itemClass])
|
||||
if nwItem.itemLayout == nwItemLayout.NO_LAYOUT:
|
||||
self.layoutFlag.setText("-")
|
||||
else:
|
||||
self.layoutFlag.setText(nwLabels.LAYOUT_FLAG[nwItem.itemLayout])
|
||||
|
||||
if nwItem.itemLayout == nwItemLayout.NO_LAYOUT:
|
||||
self.layoutFlag.setText("-")
|
||||
else:
|
||||
self.layoutFlag.setText(nwLabels.LAYOUT_FLAG[nwItem.itemLayout])
|
||||
self.labelData.setText(theLabel)
|
||||
self.statusData.setText(nwItem.itemStatus)
|
||||
self.classData.setText(nwLabels.CLASS_NAME[nwItem.itemClass])
|
||||
self.layoutData.setText(nwLabels.LAYOUT_NAME[nwItem.itemLayout])
|
||||
|
||||
self.labelData.setText(theLabel)
|
||||
self.statusData.setText(nwItem.itemStatus)
|
||||
self.classData.setText(nwLabels.CLASS_NAME[nwItem.itemClass])
|
||||
self.layoutData.setText(nwLabels.LAYOUT_NAME[nwItem.itemLayout])
|
||||
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
self.cCountData.setText(f"{nwItem.charCount:n}")
|
||||
self.wCountData.setText(f"{nwItem.wordCount:n}")
|
||||
self.pCountData.setText(f"{nwItem.paraCount:n}")
|
||||
else:
|
||||
self.cCountData.setText("–")
|
||||
self.wCountData.setText("–")
|
||||
self.pCountData.setText("–")
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
self.cCountData.setText(f"{nwItem.charCount:n}")
|
||||
self.wCountData.setText(f"{nwItem.wordCount:n}")
|
||||
self.pCountData.setText(f"{nwItem.paraCount:n}")
|
||||
else:
|
||||
self.cCountData.setText("–")
|
||||
self.wCountData.setText("–")
|
||||
self.pCountData.setText("–")
|
||||
|
||||
return
|
||||
|
||||
|
||||
+2
-1
@@ -131,10 +131,11 @@ class GuiNovelTree(QTreeWidget):
|
||||
def refreshTree(self, overRide=False):
|
||||
"""Called whenever the Novel tab is activated.
|
||||
"""
|
||||
logger.verbose("Requesting refresh of the novel tree")
|
||||
treeChanged = self.theParent.treeView.changedSince(self._lastBuild)
|
||||
indexChanged = self.theIndex.novelChangedSince(self._lastBuild)
|
||||
if not (treeChanged or indexChanged):
|
||||
logger.verbose("No changes made to the novel")
|
||||
logger.verbose("No changes have been made to the novel index")
|
||||
return
|
||||
|
||||
selItem = self.selectedItems()
|
||||
|
||||
+10
-6
@@ -129,6 +129,9 @@ class GuiProjectLoad(QDialog):
|
||||
self.newButton = self.buttonBox.addButton("New", QDialogButtonBox.ActionRole)
|
||||
self.newButton.clicked.connect(self._doNewProject)
|
||||
|
||||
self.delButton = self.buttonBox.addButton("Remove", QDialogButtonBox.ActionRole)
|
||||
self.delButton.clicked.connect(self._doDeleteRecent)
|
||||
|
||||
self.outerBox.addLayout(self.innerBox)
|
||||
self.outerBox.addWidget(self.buttonBox)
|
||||
self.setLayout(self.outerBox)
|
||||
@@ -138,7 +141,7 @@ class GuiProjectLoad(QDialog):
|
||||
|
||||
keyDelete = QShortcut(self.listBox)
|
||||
keyDelete.setKey(QKeySequence(Qt.Key_Delete))
|
||||
keyDelete.activated.connect(self._keyPressDelete)
|
||||
keyDelete.activated.connect(self._doDeleteRecent)
|
||||
|
||||
logger.debug("GuiProjectLoad initialisation complete")
|
||||
|
||||
@@ -212,15 +215,16 @@ class GuiProjectLoad(QDialog):
|
||||
self.accept()
|
||||
return
|
||||
|
||||
def _keyPressDelete(self):
|
||||
def _doDeleteRecent(self):
|
||||
"""Remove an entry from the recent projects list.
|
||||
"""
|
||||
selList = self.listBox.selectedItems()
|
||||
if selList:
|
||||
msgYes = self.theParent.askQuestion(
|
||||
"Remove Entry",
|
||||
"Remove the selected entry from the recent projects list?"
|
||||
)
|
||||
projName = selList[0].text(self.C_NAME)
|
||||
msgYes = self.theParent.askQuestion("Remove Entry", (
|
||||
"Remove '%s' from the recent projects list? "
|
||||
"The project files will not be deleted."
|
||||
) % projName)
|
||||
if msgYes:
|
||||
self.mainConf.removeFromRecentCache(
|
||||
selList[0].data(self.C_NAME, Qt.UserRole)
|
||||
|
||||
@@ -817,6 +817,14 @@ class GuiMain(QMainWindow):
|
||||
self.novelView.refreshTree()
|
||||
return
|
||||
|
||||
def requestNovelTreeRefresh(self):
|
||||
"""Update the novel tree, but only if it is visible.
|
||||
"""
|
||||
if self.projTabs.currentIndex() == self.idxNovelView and self.hasProject:
|
||||
self.novelView.refreshTree()
|
||||
return True
|
||||
return False
|
||||
|
||||
def rebuildIndex(self, beQuiet=False):
|
||||
"""Rebuild the entire index.
|
||||
"""
|
||||
|
||||
@@ -102,7 +102,7 @@ def testGuiLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.show()
|
||||
nwLoad._keyPressDelete()
|
||||
nwLoad._doDeleteRecent()
|
||||
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
|
||||
|
||||
getFile = os.path.join(nwMinimal, "nwProject.nwx")
|
||||
|
||||
Reference in New Issue
Block a user