Merge branch 'master' into project_outline
This commit is contained in:
@@ -60,10 +60,16 @@ These are as following:
|
|||||||
:header: "Shortcut", "Description"
|
:header: "Shortcut", "Description"
|
||||||
:widths: 15, 50
|
:widths: 15, 50
|
||||||
|
|
||||||
|
":kbd:`Alt-1`", "Switch focus to tree view pane."
|
||||||
|
":kbd:`Alt-2`", "Switch focus to document editor pane."
|
||||||
|
":kbd:`Alt-3`", "Switch focus to document viewer pane."
|
||||||
":kbd:`Ctrl-.`", "Correct word under cursor."
|
":kbd:`Ctrl-.`", "Correct word under cursor."
|
||||||
":kbd:`Ctrl-1`", "Switch focus to tree view pane."
|
":kbd:`Ctrl-/`", "Change block format to comment."
|
||||||
":kbd:`Ctrl-2`", "Switch focus to document editor pane."
|
":kbd:`Ctrl-0`", "Remove block formatting for block under cursor."
|
||||||
":kbd:`Ctrl-3`", "Switch focus to document viewer pane."
|
":kbd:`Ctrl-1`", "Change block format to header level 1."
|
||||||
|
":kbd:`Ctrl-2`", "Change block format to header level 2."
|
||||||
|
":kbd:`Ctrl-3`", "Change block format to header level 3."
|
||||||
|
":kbd:`Ctrl-4`", "Change block format to header level 4."
|
||||||
":kbd:`Ctrl-A`", "Select all text in document."
|
":kbd:`Ctrl-A`", "Select all text in document."
|
||||||
":kbd:`Ctrl-B`", "Format selected text, or word under cursor, as bold."
|
":kbd:`Ctrl-B`", "Format selected text, or word under cursor, as bold."
|
||||||
":kbd:`Ctrl-C`", "Copy selected text to clipboard."
|
":kbd:`Ctrl-C`", "Copy selected text to clipboard."
|
||||||
@@ -89,6 +95,7 @@ These are as following:
|
|||||||
":kbd:`Ctrl-Del`", "If in tree view, move a document to trash, or delete a folder."
|
":kbd:`Ctrl-Del`", "If in tree view, move a document to trash, or delete a folder."
|
||||||
":kbd:`Ctrl-Enter`", "Open the tag or reference under the cursor in the view panel."
|
":kbd:`Ctrl-Enter`", "Open the tag or reference under the cursor in the view panel."
|
||||||
":kbd:`Ctrl-Shift-,`", "Change project settings."
|
":kbd:`Ctrl-Shift-,`", "Change project settings."
|
||||||
|
":kbd:`Ctrl-Shift-/`", "Remove block formatting for block under cursor."
|
||||||
":kbd:`Ctrl-Shift-1`", "Replace occurrence of word in current document, and search for next occurrence."
|
":kbd:`Ctrl-Shift-1`", "Replace occurrence of word in current document, and search for next occurrence."
|
||||||
":kbd:`Ctrl-Shift-A`", "Select all text in current paragraph."
|
":kbd:`Ctrl-Shift-A`", "Select all text in current paragraph."
|
||||||
":kbd:`Ctrl-Shift-D`", "Wrap selected text, or word under cursor, in single quotes."
|
":kbd:`Ctrl-Shift-D`", "Wrap selected text, or word under cursor, in single quotes."
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ class nwDocAction(Enum):
|
|||||||
GO_NEXT = 15
|
GO_NEXT = 15
|
||||||
GO_PREV = 16
|
GO_PREV = 16
|
||||||
REPL_NEXT = 17
|
REPL_NEXT = 17
|
||||||
|
BLOCK_H1 = 18
|
||||||
|
BLOCK_H2 = 19
|
||||||
|
BLOCK_H3 = 20
|
||||||
|
BLOCK_H4 = 21
|
||||||
|
BLOCK_COM = 22
|
||||||
|
BLOCK_TXT = 23
|
||||||
|
|
||||||
# END Enum nwDocAction
|
# END Enum nwDocAction
|
||||||
|
|
||||||
|
|||||||
+189
-89
@@ -440,8 +440,20 @@ class GuiDocEditor(QTextEdit):
|
|||||||
self._findPrev()
|
self._findPrev()
|
||||||
elif theAction == nwDocAction.REPL_NEXT:
|
elif theAction == nwDocAction.REPL_NEXT:
|
||||||
self._replaceNext()
|
self._replaceNext()
|
||||||
|
elif theAction == nwDocAction.BLOCK_H1:
|
||||||
|
self._formatBlock(nwDocAction.BLOCK_H1)
|
||||||
|
elif theAction == nwDocAction.BLOCK_H2:
|
||||||
|
self._formatBlock(nwDocAction.BLOCK_H2)
|
||||||
|
elif theAction == nwDocAction.BLOCK_H3:
|
||||||
|
self._formatBlock(nwDocAction.BLOCK_H3)
|
||||||
|
elif theAction == nwDocAction.BLOCK_H4:
|
||||||
|
self._formatBlock(nwDocAction.BLOCK_H4)
|
||||||
|
elif theAction == nwDocAction.BLOCK_COM:
|
||||||
|
self._formatBlock(nwDocAction.BLOCK_COM)
|
||||||
|
elif theAction == nwDocAction.BLOCK_TXT:
|
||||||
|
self._formatBlock(nwDocAction.BLOCK_TXT)
|
||||||
else:
|
else:
|
||||||
logger.error("Unknown or unsupported document action %s" % str(theAction))
|
logger.debug("Unknown or unsupported document action %s" % str(theAction))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -515,59 +527,26 @@ class GuiDocEditor(QTextEdit):
|
|||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Signals and Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
def _followTag(self, theCursor=None):
|
def _docChange(self, thePos, charsRemoved, charsAdded):
|
||||||
"""Activated by Ctrl+Enter. Checks that we're in a block
|
"""Triggered by QTextDocument->contentsChanged. This also
|
||||||
starting with '@'. We then find the word under the cursor and
|
triggers the syntax highlighter.
|
||||||
check that it is after the ':'. If all this is fine, we have a
|
|
||||||
tag and can tell the document viewer to try and find and load
|
|
||||||
the file where the tag is defined.
|
|
||||||
"""
|
"""
|
||||||
|
self.lastEdit = time()
|
||||||
if theCursor is None:
|
if not self.docChanged:
|
||||||
theCursor = self.textCursor()
|
self.setDocumentChanged(True)
|
||||||
|
if not self.wcTimer.isActive():
|
||||||
theBlock = theCursor.block()
|
self.wcTimer.start()
|
||||||
theText = theBlock.text()
|
if self.mainConf.doReplace and not self.hasSelection:
|
||||||
|
self._docAutoReplace(self.qDocument.findBlock(thePos))
|
||||||
if len(theText) == 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if theText.startswith("@"):
|
|
||||||
|
|
||||||
theCursor.select(QTextCursor.WordUnderCursor)
|
|
||||||
theWord = theCursor.selectedText()
|
|
||||||
cPos = theText.find(":")
|
|
||||||
wPos = theCursor.selectionStart() - theBlock.position()
|
|
||||||
if wPos <= cPos:
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.verbose("Attempting to follow tag '%s'" % theWord)
|
|
||||||
self.theParent.docViewer.loadFromTag(theWord)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _insertHardBreak(self):
|
|
||||||
theCursor = self.textCursor()
|
|
||||||
theCursor.beginEditBlock()
|
|
||||||
theCursor.insertText(" \n")
|
|
||||||
theCursor.endEditBlock()
|
|
||||||
return
|
|
||||||
|
|
||||||
def _insertNonBreakingSpace(self):
|
|
||||||
theCursor = self.textCursor()
|
|
||||||
theCursor.beginEditBlock()
|
|
||||||
theCursor.insertText(nwUnicode.U_NBSP)
|
|
||||||
theCursor.endEditBlock()
|
|
||||||
return
|
|
||||||
|
|
||||||
def _openSpellContext(self):
|
|
||||||
self._openContextMenu(self.cursorRect().center())
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _openContextMenu(self, thePos):
|
def _openContextMenu(self, thePos):
|
||||||
|
"""Triggered by right click to open the context menu. Also
|
||||||
|
triggered by the Ctrl+. shortcut.
|
||||||
|
"""
|
||||||
|
|
||||||
if not self.spellCheck:
|
if not self.spellCheck:
|
||||||
return
|
return
|
||||||
@@ -625,17 +604,88 @@ class GuiDocEditor(QTextEdit):
|
|||||||
self.hLight.rehighlightBlock(theCursor.block())
|
self.hLight.rehighlightBlock(theCursor.block())
|
||||||
return
|
return
|
||||||
|
|
||||||
def _docChange(self, thePos, charsRemoved, charsAdded):
|
def _runCounter(self):
|
||||||
"""Triggered by QTextDocument->contentsChanged. This also
|
"""Decide whether to run the word counter, or stop the timer due
|
||||||
triggers the syntax highlighter.
|
to inactivity.
|
||||||
"""
|
"""
|
||||||
self.lastEdit = time()
|
sinceActive = time()-self.lastEdit
|
||||||
if not self.docChanged:
|
if sinceActive > 5*self.wcInterval:
|
||||||
self.setDocumentChanged(True)
|
logger.debug("Stopping word count timer: no activity last %.1f seconds" % sinceActive)
|
||||||
if not self.wcTimer.isActive():
|
self.wcTimer.stop()
|
||||||
self.wcTimer.start()
|
elif self.wCounter.isRunning():
|
||||||
if self.mainConf.doReplace and not self.hasSelection:
|
logger.verbose("Word counter thread is busy")
|
||||||
self._docAutoReplace(self.qDocument.findBlock(thePos))
|
else:
|
||||||
|
logger.verbose("Starting word counter")
|
||||||
|
self.wCounter.start()
|
||||||
|
return
|
||||||
|
|
||||||
|
def _updateCounts(self):
|
||||||
|
"""Slot for the word counter's finished signal
|
||||||
|
"""
|
||||||
|
logger.verbose("Updating word count")
|
||||||
|
|
||||||
|
tHandle = self.nwDocument.docHandle
|
||||||
|
self.charCount = self.wCounter.charCount
|
||||||
|
self.wordCount = self.wCounter.wordCount
|
||||||
|
self.paraCount = self.wCounter.paraCount
|
||||||
|
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount)
|
||||||
|
self.theParent.treeView.propagateCount(tHandle, self.wordCount)
|
||||||
|
self.theParent.treeView.projectWordCount()
|
||||||
|
self._checkDocSize(self.charCount)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
def _followTag(self, theCursor=None):
|
||||||
|
"""Activated by Ctrl+Enter. Checks that we're in a block
|
||||||
|
starting with '@'. We then find the word under the cursor and
|
||||||
|
check that it is after the ':'. If all this is fine, we have a
|
||||||
|
tag and can tell the document viewer to try and find and load
|
||||||
|
the file where the tag is defined.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if theCursor is None:
|
||||||
|
theCursor = self.textCursor()
|
||||||
|
|
||||||
|
theBlock = theCursor.block()
|
||||||
|
theText = theBlock.text()
|
||||||
|
|
||||||
|
if len(theText) == 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if theText.startswith("@"):
|
||||||
|
|
||||||
|
theCursor.select(QTextCursor.WordUnderCursor)
|
||||||
|
theWord = theCursor.selectedText()
|
||||||
|
cPos = theText.find(":")
|
||||||
|
wPos = theCursor.selectionStart() - theBlock.position()
|
||||||
|
if wPos <= cPos:
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.verbose("Attempting to follow tag '%s'" % theWord)
|
||||||
|
self.theParent.docViewer.loadFromTag(theWord)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _insertHardBreak(self):
|
||||||
|
theCursor = self.textCursor()
|
||||||
|
theCursor.beginEditBlock()
|
||||||
|
theCursor.insertText(" \n")
|
||||||
|
theCursor.endEditBlock()
|
||||||
|
return
|
||||||
|
|
||||||
|
def _insertNonBreakingSpace(self):
|
||||||
|
theCursor = self.textCursor()
|
||||||
|
theCursor.beginEditBlock()
|
||||||
|
theCursor.insertText(nwUnicode.U_NBSP)
|
||||||
|
theCursor.endEditBlock()
|
||||||
|
return
|
||||||
|
|
||||||
|
def _openSpellContext(self):
|
||||||
|
self._openContextMenu(self.cursorRect().center())
|
||||||
return
|
return
|
||||||
|
|
||||||
def _docAutoReplace(self, theBlock):
|
def _docAutoReplace(self, theBlock):
|
||||||
@@ -693,37 +743,6 @@ class GuiDocEditor(QTextEdit):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _runCounter(self):
|
|
||||||
"""Decide whether to run the word counter, or stop the timer due
|
|
||||||
to inactivity.
|
|
||||||
"""
|
|
||||||
sinceActive = time()-self.lastEdit
|
|
||||||
if sinceActive > 5*self.wcInterval:
|
|
||||||
logger.debug("Stopping word count timer: no activity last %.1f seconds" % sinceActive)
|
|
||||||
self.wcTimer.stop()
|
|
||||||
elif self.wCounter.isRunning():
|
|
||||||
logger.verbose("Word counter thread is busy")
|
|
||||||
else:
|
|
||||||
logger.verbose("Starting word counter")
|
|
||||||
self.wCounter.start()
|
|
||||||
return
|
|
||||||
|
|
||||||
def _updateCounts(self):
|
|
||||||
"""Slot for the word counter's finished signal
|
|
||||||
"""
|
|
||||||
logger.verbose("Updating word count")
|
|
||||||
|
|
||||||
tHandle = self.nwDocument.docHandle
|
|
||||||
self.charCount = self.wCounter.charCount
|
|
||||||
self.wordCount = self.wCounter.wordCount
|
|
||||||
self.paraCount = self.wCounter.paraCount
|
|
||||||
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount)
|
|
||||||
self.theParent.treeView.propagateCount(tHandle, self.wordCount)
|
|
||||||
self.theParent.treeView.projectWordCount()
|
|
||||||
self._checkDocSize(self.charCount)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def _checkDocSize(self, theSize):
|
def _checkDocSize(self, theSize):
|
||||||
"""Check if document size crosses the big document limit set in
|
"""Check if document size crosses the big document limit set in
|
||||||
config. If so, we will set the big document flag to True.
|
config. If so, we will set the big document flag to True.
|
||||||
@@ -761,6 +780,87 @@ class GuiDocEditor(QTextEdit):
|
|||||||
logger.warning("No selection made, nothing to do")
|
logger.warning("No selection made, nothing to do")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _formatBlock(self, docAction):
|
||||||
|
"""Changes the block format of the block under the cursor.
|
||||||
|
"""
|
||||||
|
|
||||||
|
theCursor = self.textCursor()
|
||||||
|
theBlock = theCursor.block()
|
||||||
|
if not theBlock.isValid():
|
||||||
|
logger.debug("Invalid block selected for action %s" % str(docAction))
|
||||||
|
return
|
||||||
|
|
||||||
|
theText = theBlock.text()
|
||||||
|
if len(theText.strip()) == 0:
|
||||||
|
logger.debug("Empty block selected for action %s" % str(docAction))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Remove existing format first, if any
|
||||||
|
if theText.startswith("@"):
|
||||||
|
logger.error("Cannot apply block format to keyword/value line")
|
||||||
|
return
|
||||||
|
elif theText.startswith("% "):
|
||||||
|
newText = theText[2:]
|
||||||
|
cOffset = 2
|
||||||
|
elif theText.startswith("%"):
|
||||||
|
newText = theText[1:]
|
||||||
|
cOffset = 1
|
||||||
|
elif theText.startswith("# "):
|
||||||
|
newText = theText[2:]
|
||||||
|
cOffset = 2
|
||||||
|
elif theText.startswith("## "):
|
||||||
|
newText = theText[3:]
|
||||||
|
cOffset = 3
|
||||||
|
elif theText.startswith("### "):
|
||||||
|
newText = theText[4:]
|
||||||
|
cOffset = 4
|
||||||
|
elif theText.startswith("#### "):
|
||||||
|
newText = theText[5:]
|
||||||
|
cOffset = 5
|
||||||
|
else:
|
||||||
|
newText = theText
|
||||||
|
cOffset = 0
|
||||||
|
|
||||||
|
# Apply new format
|
||||||
|
if docAction == nwDocAction.BLOCK_COM:
|
||||||
|
theText = "% "+newText
|
||||||
|
cOffset -= 2
|
||||||
|
elif docAction == nwDocAction.BLOCK_H1:
|
||||||
|
theText = "# "+newText
|
||||||
|
cOffset -= 2
|
||||||
|
elif docAction == nwDocAction.BLOCK_H2:
|
||||||
|
theText = "## "+newText
|
||||||
|
cOffset -= 3
|
||||||
|
elif docAction == nwDocAction.BLOCK_H3:
|
||||||
|
theText = "### "+newText
|
||||||
|
cOffset -= 4
|
||||||
|
elif docAction == nwDocAction.BLOCK_H4:
|
||||||
|
theText = "#### "+newText
|
||||||
|
cOffset -= 5
|
||||||
|
elif docAction == nwDocAction.BLOCK_TXT:
|
||||||
|
theText = newText
|
||||||
|
cOffset -= 0
|
||||||
|
else:
|
||||||
|
logger.error("Unknown or unsupported block format requested: %s" % str(docAction))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Replace the block text
|
||||||
|
theCursor.beginEditBlock()
|
||||||
|
posO = theCursor.position()
|
||||||
|
theCursor.select(QTextCursor.BlockUnderCursor)
|
||||||
|
posS = theCursor.selectionStart()
|
||||||
|
theCursor.removeSelectedText()
|
||||||
|
theCursor.setPosition(posS)
|
||||||
|
if posS > 0:
|
||||||
|
theCursor.insertBlock()
|
||||||
|
theCursor.insertText(theText)
|
||||||
|
if posO - cOffset >= 0:
|
||||||
|
theCursor.setPosition(posO - cOffset)
|
||||||
|
theCursor.endEditBlock()
|
||||||
|
self.setTextCursor(theCursor)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def _makeSelection(self, selMode):
|
def _makeSelection(self, selMode):
|
||||||
theCursor = self.textCursor()
|
theCursor = self.textCursor()
|
||||||
theCursor.clearSelection()
|
theCursor.clearSelection()
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ import nw
|
|||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import QTextBrowser
|
from PyQt5.QtWidgets import QTextBrowser
|
||||||
from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor
|
from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor
|
||||||
|
|
||||||
from nw.convert import ToHtml
|
from nw.convert import ToHtml
|
||||||
from nw.constants import nwAlert, nwItemType
|
from nw.constants import nwAlert, nwItemType, nwDocAction
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
self.qDocument.setDefaultTextOption(theOpt)
|
self.qDocument.setDefaultTextOption(theOpt)
|
||||||
|
|
||||||
self.anchorClicked.connect(self._linkClicked)
|
self.anchorClicked.connect(self._linkClicked)
|
||||||
|
self.setFocusPolicy(Qt.StrongFocus)
|
||||||
|
|
||||||
logger.debug("DocViewer initialisation complete")
|
logger.debug("DocViewer initialisation complete")
|
||||||
|
|
||||||
@@ -142,10 +143,35 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def docAction(self, theAction):
|
||||||
|
logger.verbose("Requesting action: %s" % theAction.name)
|
||||||
|
if self.theHandle is None:
|
||||||
|
logger.error("No document open")
|
||||||
|
return False
|
||||||
|
if theAction == nwDocAction.CUT:
|
||||||
|
self.copy()
|
||||||
|
elif theAction == nwDocAction.COPY:
|
||||||
|
self.copy()
|
||||||
|
elif theAction == nwDocAction.SEL_ALL:
|
||||||
|
self._makeSelection(QTextCursor.Document)
|
||||||
|
elif theAction == nwDocAction.SEL_PARA:
|
||||||
|
self._makeSelection(QTextCursor.BlockUnderCursor)
|
||||||
|
else:
|
||||||
|
logger.debug("Unknown or unsupported document action %s" % str(theAction))
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
|
def _makeSelection(self, selMode):
|
||||||
|
theCursor = self.textCursor()
|
||||||
|
theCursor.clearSelection()
|
||||||
|
theCursor.select(selMode)
|
||||||
|
self.setTextCursor(theCursor)
|
||||||
|
return
|
||||||
|
|
||||||
def _linkClicked(self, theURL):
|
def _linkClicked(self, theURL):
|
||||||
|
|
||||||
theLink = theURL.url()
|
theLink = theURL.url()
|
||||||
|
|||||||
+51
-6
@@ -40,7 +40,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self._buildHelpMenu()
|
self._buildHelpMenu()
|
||||||
|
|
||||||
# Function Pointers
|
# Function Pointers
|
||||||
self._docAction = self.theParent.docEditor.docAction
|
self._docAction = self.theParent.passDocumentAction
|
||||||
self._moveTreeItem = self.theParent.treeView.moveTreeItem
|
self._moveTreeItem = self.theParent.treeView.moveTreeItem
|
||||||
self._newTreeItem = self.theParent.treeView.newTreeItem
|
self._newTreeItem = self.theParent.treeView.newTreeItem
|
||||||
|
|
||||||
@@ -379,21 +379,21 @@ class GuiMainMenu(QMenuBar):
|
|||||||
# View > TreeView
|
# View > TreeView
|
||||||
self.aFocusTree = QAction("TreeView", self)
|
self.aFocusTree = QAction("TreeView", self)
|
||||||
self.aFocusTree.setStatusTip("Move focus to project tree")
|
self.aFocusTree.setStatusTip("Move focus to project tree")
|
||||||
self.aFocusTree.setShortcut("Ctrl+1")
|
self.aFocusTree.setShortcut("Alt+1")
|
||||||
self.aFocusTree.triggered.connect(lambda : self.theParent.setFocus(1))
|
self.aFocusTree.triggered.connect(lambda : self.theParent.setFocus(1))
|
||||||
self.viewMenu.addAction(self.aFocusTree)
|
self.viewMenu.addAction(self.aFocusTree)
|
||||||
|
|
||||||
# View > Document Pane 1
|
# View > Document Pane 1
|
||||||
self.aFocusEditor = QAction("Left Document Pane", self)
|
self.aFocusEditor = QAction("Left Document Pane", self)
|
||||||
self.aFocusEditor.setStatusTip("Move focus to left document pane")
|
self.aFocusEditor.setStatusTip("Move focus to left document pane")
|
||||||
self.aFocusEditor.setShortcut("Ctrl+2")
|
self.aFocusEditor.setShortcut("Alt+2")
|
||||||
self.aFocusEditor.triggered.connect(lambda : self.theParent.setFocus(2))
|
self.aFocusEditor.triggered.connect(lambda : self.theParent.setFocus(2))
|
||||||
self.viewMenu.addAction(self.aFocusEditor)
|
self.viewMenu.addAction(self.aFocusEditor)
|
||||||
|
|
||||||
# View > Document Pane 2
|
# View > Document Pane 2
|
||||||
self.aFocusView = QAction("Right Document Pane", self)
|
self.aFocusView = QAction("Right Document Pane", self)
|
||||||
self.aFocusView.setStatusTip("Move focus to right document pane")
|
self.aFocusView.setStatusTip("Move focus to right document pane")
|
||||||
self.aFocusView.setShortcut("Ctrl+3")
|
self.aFocusView.setShortcut("Alt+3")
|
||||||
self.aFocusView.triggered.connect(lambda : self.theParent.setFocus(3))
|
self.aFocusView.triggered.connect(lambda : self.theParent.setFocus(3))
|
||||||
self.viewMenu.addAction(self.aFocusView)
|
self.viewMenu.addAction(self.aFocusView)
|
||||||
|
|
||||||
@@ -570,6 +570,51 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aFmtSQuote.triggered.connect(lambda: self._docAction(nwDocAction.S_QUOTE))
|
self.aFmtSQuote.triggered.connect(lambda: self._docAction(nwDocAction.S_QUOTE))
|
||||||
self.fmtMenu.addAction(self.aFmtSQuote)
|
self.fmtMenu.addAction(self.aFmtSQuote)
|
||||||
|
|
||||||
|
# Edit > Separator
|
||||||
|
self.fmtMenu.addSeparator()
|
||||||
|
|
||||||
|
# Format > Header 1
|
||||||
|
self.aFmtHead1 = QAction("Header 1", self)
|
||||||
|
self.aFmtHead1.setStatusTip("Change the block format to Header 1")
|
||||||
|
self.aFmtHead1.setShortcut("Ctrl+1")
|
||||||
|
self.aFmtHead1.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H1))
|
||||||
|
self.fmtMenu.addAction(self.aFmtHead1)
|
||||||
|
|
||||||
|
# Format > Header 2
|
||||||
|
self.aFmtHead2 = QAction("Header 2", self)
|
||||||
|
self.aFmtHead2.setStatusTip("Change the block format to Header 2")
|
||||||
|
self.aFmtHead2.setShortcut("Ctrl+2")
|
||||||
|
self.aFmtHead2.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H2))
|
||||||
|
self.fmtMenu.addAction(self.aFmtHead2)
|
||||||
|
|
||||||
|
# Format > Header 3
|
||||||
|
self.aFmtHead3 = QAction("Header 3", self)
|
||||||
|
self.aFmtHead3.setStatusTip("Change the block format to Header 3")
|
||||||
|
self.aFmtHead3.setShortcut("Ctrl+3")
|
||||||
|
self.aFmtHead3.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H3))
|
||||||
|
self.fmtMenu.addAction(self.aFmtHead3)
|
||||||
|
|
||||||
|
# Format > Header 4
|
||||||
|
self.aFmtHead4 = QAction("Header 4", self)
|
||||||
|
self.aFmtHead4.setStatusTip("Change the block format to Header 4")
|
||||||
|
self.aFmtHead4.setShortcut("Ctrl+4")
|
||||||
|
self.aFmtHead4.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H4))
|
||||||
|
self.fmtMenu.addAction(self.aFmtHead4)
|
||||||
|
|
||||||
|
# Format > Comment
|
||||||
|
self.aFmtComment = QAction("Comment", self)
|
||||||
|
self.aFmtComment.setStatusTip("Change the block format to comment")
|
||||||
|
self.aFmtComment.setShortcut("Ctrl+/")
|
||||||
|
self.aFmtComment.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_COM))
|
||||||
|
self.fmtMenu.addAction(self.aFmtComment)
|
||||||
|
|
||||||
|
# Format > Remove Format
|
||||||
|
self.aFmtNoFormat = QAction("Remove Format", self)
|
||||||
|
self.aFmtNoFormat.setStatusTip("Strips block format")
|
||||||
|
self.aFmtNoFormat.setShortcuts(["Ctrl+0","Ctrl+Shift+/"])
|
||||||
|
self.aFmtNoFormat.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_TXT))
|
||||||
|
self.fmtMenu.addAction(self.aFmtNoFormat)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _buildToolsMenu(self):
|
def _buildToolsMenu(self):
|
||||||
@@ -657,8 +702,8 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.helpMenu.addSeparator()
|
self.helpMenu.addSeparator()
|
||||||
|
|
||||||
# Document > Preview
|
# Document > Preview
|
||||||
self.aHelp = QAction("Documentation", self)
|
self.aHelp = QAction("Online Documentation", self)
|
||||||
self.aHelp.setStatusTip("View documentation")
|
self.aHelp.setStatusTip("View online documentation")
|
||||||
self.aHelp.setShortcut("F1")
|
self.aHelp.setShortcut("F1")
|
||||||
self.aHelp.triggered.connect(self._openHelp)
|
self.aHelp.triggered.connect(self._openHelp)
|
||||||
self.helpMenu.addAction(self.aHelp)
|
self.helpMenu.addAction(self.aHelp)
|
||||||
|
|||||||
@@ -469,6 +469,18 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def passDocumentAction(self, theAction):
|
||||||
|
"""Pass on document action theAction to whatever document has
|
||||||
|
the focus. If no document has focus, the action is discarded.
|
||||||
|
"""
|
||||||
|
if self.docEditor.hasFocus():
|
||||||
|
self.docEditor.docAction(theAction)
|
||||||
|
elif self.docViewer.hasFocus():
|
||||||
|
self.docViewer.docAction(theAction)
|
||||||
|
else:
|
||||||
|
logger.debug("Document action requested, but no document has focus")
|
||||||
|
return True
|
||||||
|
|
||||||
##
|
##
|
||||||
# Tree Item Actions
|
# Tree Item Actions
|
||||||
##
|
##
|
||||||
|
|||||||
Reference in New Issue
Block a user