From 711766cf52b5b54ae6982933768e5bfc16244188 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Wed, 8 Nov 2023 18:00:43 +0100
Subject: [PATCH] Change main menu to emit signals
---
.../icons/typicons_light/nw_tb-subscript.svg | 5 +
.../typicons_light/nw_tb-superscript.svg | 5 +
novelwriter/config.py | 30 +-
novelwriter/gui/doceditor.py | 106 ++++++--
novelwriter/gui/mainmenu.py | 256 +++++++++++++-----
novelwriter/guimain.py | 45 ++-
6 files changed, 324 insertions(+), 123 deletions(-)
create mode 100644 novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg
create mode 100644 novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg
diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg b/novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg
new file mode 100644
index 00000000..db909aed
--- /dev/null
+++ b/novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg b/novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg
new file mode 100644
index 00000000..1634872e
--- /dev/null
+++ b/novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/novelwriter/config.py b/novelwriter/config.py
index 50c8c1ab..ebd0d05f 100644
--- a/novelwriter/config.py
+++ b/novelwriter/config.py
@@ -178,9 +178,11 @@ class Config:
self.spellLanguage = "en"
# State
- self.showRefPanel = True # The reference panel for the viewer is visible
- self.viewComments = True # Comments are shown in the viewer
- self.viewSynopsis = True # Synopsis is shown in the viewer
+ self.showRefPanel = True # The reference panel for the viewer is visible
+ self.showEditToolBar = False # The document editor toolbar visibility
+ self.useShortcodes = False # Use shorcodes for basic formatting
+ self.viewComments = True # Comments are shown in the viewer
+ self.viewSynopsis = True # Synopsis is shown in the viewer
# Search Bar Switches
self.searchCase = False
@@ -598,15 +600,17 @@ class Config:
# State
sec = "State"
- self.showRefPanel = conf.rdBool(sec, "showrefpanel", self.showRefPanel)
- self.viewComments = conf.rdBool(sec, "viewcomments", self.viewComments)
- self.viewSynopsis = conf.rdBool(sec, "viewsynopsis", self.viewSynopsis)
- self.searchCase = conf.rdBool(sec, "searchcase", self.searchCase)
- self.searchWord = conf.rdBool(sec, "searchword", self.searchWord)
- self.searchRegEx = conf.rdBool(sec, "searchregex", self.searchRegEx)
- self.searchLoop = conf.rdBool(sec, "searchloop", self.searchLoop)
- self.searchNextFile = conf.rdBool(sec, "searchnextfile", self.searchNextFile)
- self.searchMatchCap = conf.rdBool(sec, "searchmatchcap", self.searchMatchCap)
+ self.showRefPanel = conf.rdBool(sec, "showrefpanel", self.showRefPanel)
+ self.showEditToolBar = conf.rdBool(sec, "showedittoolbar", self.showEditToolBar)
+ self.useShortcodes = conf.rdBool(sec, "useshortcodes", self.useShortcodes)
+ self.viewComments = conf.rdBool(sec, "viewcomments", self.viewComments)
+ self.viewSynopsis = conf.rdBool(sec, "viewsynopsis", self.viewSynopsis)
+ self.searchCase = conf.rdBool(sec, "searchcase", self.searchCase)
+ self.searchWord = conf.rdBool(sec, "searchword", self.searchWord)
+ self.searchRegEx = conf.rdBool(sec, "searchregex", self.searchRegEx)
+ self.searchLoop = conf.rdBool(sec, "searchloop", self.searchLoop)
+ self.searchNextFile = conf.rdBool(sec, "searchnextfile", self.searchNextFile)
+ self.searchMatchCap = conf.rdBool(sec, "searchmatchcap", self.searchMatchCap)
# Deprecated Settings or Locations as of 2.0
# ToDo: These will be loaded for a few minor releases until the users have converted them
@@ -721,6 +725,8 @@ class Config:
conf["State"] = {
"showrefpanel": str(self.showRefPanel),
+ "showedittoolbar": str(self.showEditToolBar),
+ "useshortcodes": str(self.useShortcodes),
"viewcomments": str(self.viewComments),
"viewsynopsis": str(self.viewSynopsis),
"searchcase": str(self.searchCase),
diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py
index 6e204219..efccc361 100644
--- a/novelwriter/gui/doceditor.py
+++ b/novelwriter/gui/doceditor.py
@@ -138,9 +138,12 @@ class GuiDocEditor(QPlainTextEdit):
self.docFooter = GuiDocEditFooter(self)
self.docSearch = GuiDocEditSearch(self)
self.docToolBar = GuiDocToolBar(self)
+ self.docToolBar.setVisible(CONFIG.showEditToolBar)
# Connect Signals
self.docHeader.closeDocumentRequest.connect(self._closeCurrentDocument)
+ self.docHeader.toggleToolBarRequest.connect(self._toggleToolBarVisibility)
+ self.docToolBar.requestDocAction.connect(self.docAction)
# Context Menu
self.setContextMenuPolicy(Qt.CustomContextMenu)
@@ -849,31 +852,11 @@ class GuiDocEditor(QPlainTextEdit):
return True
- def insertKeyWord(self, keyword: str) -> bool:
- """Insert a keyword in the text editor, at the cursor position.
- If the insert line is not blank, a new line is started.
- """
- if keyword not in nwKeyWords.VALID_KEYS:
- logger.error("Invalid keyword '%s'", keyword)
- return False
- logger.debug("Inserting keyword '%s'", keyword)
- state = self.insertNewBlock("%s: " % keyword)
- return state
-
def closeSearch(self) -> bool:
"""Close the search box."""
self.docSearch.closeSearch()
return self.docSearch.isVisible()
- @pyqtSlot()
- def toggleSearch(self) -> None:
- """Toggle the visibility of the search box."""
- if self.docSearch.isVisible():
- self.docSearch.closeSearch()
- else:
- self.beginSearch()
- return
-
##
# Document Events and Maintenance
##
@@ -968,6 +951,27 @@ class GuiDocEditor(QPlainTextEdit):
self.updateDocMargins()
return
+ @pyqtSlot(str)
+ def insertKeyWord(self, keyword: str) -> bool:
+ """Insert a keyword in the text editor, at the cursor position.
+ If the insert line is not blank, a new line is started.
+ """
+ if keyword not in nwKeyWords.VALID_KEYS:
+ logger.error("Invalid keyword '%s'", keyword)
+ return False
+ logger.debug("Inserting keyword '%s'", keyword)
+ state = self.insertNewBlock("%s: " % keyword)
+ return state
+
+ @pyqtSlot()
+ def toggleSearch(self) -> None:
+ """Toggle the visibility of the search box."""
+ if self.docSearch.isVisible():
+ self.docSearch.closeSearch()
+ else:
+ self.beginSearch()
+ return
+
##
# Private Slots
##
@@ -1194,6 +1198,14 @@ class GuiDocEditor(QPlainTextEdit):
self.closeDocumentRequest.emit()
return
+ @pyqtSlot()
+ def _toggleToolBarVisibility(self) -> None:
+ """Toggle the visibility of the tool bar."""
+ state = not self.docToolBar.isVisible()
+ self.docToolBar.setVisible(state)
+ CONFIG.showEditToolBar = state
+ return
+
##
# Search & Replace
##
@@ -2094,6 +2106,8 @@ class BackgroundWordCounterSignals(QObject):
class GuiDocToolBar(QWidget):
+ requestDocAction = pyqtSignal(nwDocAction)
+
def __init__(self, docEditor: GuiDocEditor) -> None:
super().__init__(parent=docEditor)
@@ -2108,26 +2122,41 @@ class GuiDocToolBar(QWidget):
# ===============
self.tbMode = QToolButton(self)
+ self.tbMode.setToolTip(self.tr("Toggle Markdown or Shortcodes Mode"))
self.tbMode.setIconSize(iconSize)
self.tbMode.setCheckable(True)
+ self.tbMode.setChecked(CONFIG.useShortcodes)
+ self.tbMode.toggled.connect(self._toggleFormatMode)
self.tbBold = QToolButton(self)
self.tbBold.setIconSize(iconSize)
+ self.tbBold.clicked.connect(self._formatBold)
self.tbItalic = QToolButton(self)
self.tbItalic.setIconSize(iconSize)
+ self.tbItalic.clicked.connect(self._formatItalic)
self.tbStrike = QToolButton(self)
self.tbStrike.setIconSize(iconSize)
+ self.tbStrike.clicked.connect(self._formatStrike)
self.tbUnderline = QToolButton(self)
self.tbUnderline.setIconSize(iconSize)
+ self.tbUnderline.clicked.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_ULINE)
+ )
self.tbSuperscript = QToolButton(self)
self.tbSuperscript.setIconSize(iconSize)
+ self.tbSuperscript.clicked.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_SUP)
+ )
self.tbSubscript = QToolButton(self)
self.tbSubscript.setIconSize(iconSize)
+ self.tbSubscript.clicked.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_SUB)
+ )
# Assemble
# ========
@@ -2156,7 +2185,6 @@ class GuiDocToolBar(QWidget):
palette.setColor(QPalette.Window, QColor(*SHARED.theme.colBack))
palette.setColor(QPalette.WindowText, QColor(*SHARED.theme.colText))
palette.setColor(QPalette.Text, QColor(*SHARED.theme.colText))
-
self.setPalette(palette)
# qPalette = self.palette()
@@ -2182,6 +2210,40 @@ class GuiDocToolBar(QWidget):
return
+ ##
+ # Internal Slots
+ ##
+
+ @pyqtSlot(bool)
+ def _toggleFormatMode(self, checked: bool) -> None:
+ """Toggle the formatting mode."""
+ CONFIG.useShortcodes = checked
+ return
+
+ @pyqtSlot()
+ def _formatBold(self):
+ """Call the bold format action."""
+ self.requestDocAction.emit(
+ nwDocAction.SC_BOLD if self.tbMode.isChecked() else nwDocAction.STRONG
+ )
+ return
+
+ @pyqtSlot()
+ def _formatItalic(self):
+ """Call the italic format action."""
+ self.requestDocAction.emit(
+ nwDocAction.SC_ITALIC if self.tbMode.isChecked() else nwDocAction.EMPH
+ )
+ return
+
+ @pyqtSlot()
+ def _formatStrike(self):
+ """Call the strikethrough format action."""
+ self.requestDocAction.emit(
+ nwDocAction.SC_STRIKE if self.tbMode.isChecked() else nwDocAction.STRIKE
+ )
+ return
+
# END Class GuiDocToolBar
@@ -2600,8 +2662,8 @@ class GuiDocEditSearch(QFrame):
class GuiDocEditHeader(QWidget):
- toggleToolBarRequest = pyqtSignal()
closeDocumentRequest = pyqtSignal()
+ toggleToolBarRequest = pyqtSignal()
def __init__(self, docEditor: GuiDocEditor) -> None:
super().__init__(parent=docEditor)
diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py
index 6355ca63..e6453a82 100644
--- a/novelwriter/gui/mainmenu.py
+++ b/novelwriter/gui/mainmenu.py
@@ -30,7 +30,7 @@ from pathlib import Path
from urllib.parse import urljoin
from urllib.request import pathname2url
-from PyQt5.QtCore import QUrl, pyqtSlot
+from PyQt5.QtCore import QUrl, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QMenuBar, QAction
@@ -50,6 +50,11 @@ class GuiMainMenu(QMenuBar):
add them from this class.
"""
+ requestDocAction = pyqtSignal(nwDocAction)
+ requestDocInsert = pyqtSignal(nwDocInsert)
+ requestDocInsertText = pyqtSignal(str)
+ requestDocKeyWordInsert = pyqtSignal(str)
+
def __init__(self, mainGui: GuiMain) -> None:
super().__init__(parent=mainGui)
@@ -68,11 +73,6 @@ class GuiMainMenu(QMenuBar):
self._buildToolsMenu()
self._buildHelpMenu()
- # Function Pointers
- self._docAction = self.mainGui.passDocumentAction
- self._docInsert = self.mainGui.docEditor.insertText
- self._insertKeyWord = self.mainGui.docEditor.insertKeyWord
-
logger.debug("Ready: GuiMainMenu")
return
@@ -246,12 +246,12 @@ class GuiMainMenu(QMenuBar):
# Edit > Undo
self.aEditUndo = self.editMenu.addAction(self.tr("Undo"))
self.aEditUndo.setShortcut("Ctrl+Z")
- self.aEditUndo.triggered.connect(lambda: self._docAction(nwDocAction.UNDO))
+ self.aEditUndo.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.UNDO))
# Edit > Redo
self.aEditRedo = self.editMenu.addAction(self.tr("Redo"))
self.aEditRedo.setShortcut("Ctrl+Y")
- self.aEditRedo.triggered.connect(lambda: self._docAction(nwDocAction.REDO))
+ self.aEditRedo.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.REDO))
# Edit > Separator
self.editMenu.addSeparator()
@@ -259,17 +259,17 @@ class GuiMainMenu(QMenuBar):
# Edit > Cut
self.aEditCut = self.editMenu.addAction(self.tr("Cut"))
self.aEditCut.setShortcut("Ctrl+X")
- self.aEditCut.triggered.connect(lambda: self._docAction(nwDocAction.CUT))
+ self.aEditCut.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.CUT))
# Edit > Copy
self.aEditCopy = self.editMenu.addAction(self.tr("Copy"))
self.aEditCopy.setShortcut("Ctrl+C")
- self.aEditCopy.triggered.connect(lambda: self._docAction(nwDocAction.COPY))
+ self.aEditCopy.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.COPY))
# Edit > Paste
self.aEditPaste = self.editMenu.addAction(self.tr("Paste"))
self.aEditPaste.setShortcut("Ctrl+V")
- self.aEditPaste.triggered.connect(lambda: self._docAction(nwDocAction.PASTE))
+ self.aEditPaste.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.PASTE))
# Edit > Separator
self.editMenu.addSeparator()
@@ -277,12 +277,12 @@ class GuiMainMenu(QMenuBar):
# Edit > Select All
self.aSelectAll = self.editMenu.addAction(self.tr("Select All"))
self.aSelectAll.setShortcut("Ctrl+A")
- self.aSelectAll.triggered.connect(lambda: self._docAction(nwDocAction.SEL_ALL))
+ self.aSelectAll.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.SEL_ALL))
# Edit > Select Paragraph
self.aSelectPar = self.editMenu.addAction(self.tr("Select Paragraph"))
self.aSelectPar.setShortcut("Ctrl+Shift+A")
- self.aSelectPar.triggered.connect(lambda: self._docAction(nwDocAction.SEL_PARA))
+ self.aSelectPar.triggered.connect(lambda: self.requestDocAction.emit(nwDocAction.SEL_PARA))
return
@@ -350,22 +350,30 @@ class GuiMainMenu(QMenuBar):
# Insert > Short Dash
self.aInsENDash = self.mInsDashes.addAction(self.tr("Short Dash"))
self.aInsENDash.setShortcut("Ctrl+K, -")
- self.aInsENDash.triggered.connect(lambda: self._docInsert(nwUnicode.U_ENDASH))
+ self.aInsENDash.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_ENDASH)
+ )
# Insert > Long Dash
self.aInsEMDash = self.mInsDashes.addAction(self.tr("Long Dash"))
self.aInsEMDash.setShortcut("Ctrl+K, _")
- self.aInsEMDash.triggered.connect(lambda: self._docInsert(nwUnicode.U_EMDASH))
+ self.aInsEMDash.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_EMDASH)
+ )
# Insert > Long Dash
self.aInsHorBar = self.mInsDashes.addAction(self.tr("Horizontal Bar"))
self.aInsHorBar.setShortcut("Ctrl+K, Ctrl+_")
- self.aInsHorBar.triggered.connect(lambda: self._docInsert(nwUnicode.U_HBAR))
+ self.aInsHorBar.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_HBAR)
+ )
# Insert > Figure Dash
self.aInsFigDash = self.mInsDashes.addAction(self.tr("Figure Dash"))
self.aInsFigDash.setShortcut("Ctrl+K, ~")
- self.aInsFigDash.triggered.connect(lambda: self._docInsert(nwUnicode.U_FGDASH))
+ self.aInsFigDash.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_FGDASH)
+ )
# Insert > Quote Marks
self.mInsQuotes = self.insMenu.addMenu(self.tr("Quote Marks"))
@@ -373,27 +381,37 @@ class GuiMainMenu(QMenuBar):
# Insert > Left Single Quote
self.aInsQuoteLS = self.mInsQuotes.addAction(self.tr("Left Single Quote"))
self.aInsQuoteLS.setShortcut("Ctrl+K, 1")
- self.aInsQuoteLS.triggered.connect(lambda: self._docInsert(nwDocInsert.QUOTE_LS))
+ self.aInsQuoteLS.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_LS)
+ )
# Insert > Right Single Quote
self.aInsQuoteRS = self.mInsQuotes.addAction(self.tr("Right Single Quote"))
self.aInsQuoteRS.setShortcut("Ctrl+K, 2")
- self.aInsQuoteRS.triggered.connect(lambda: self._docInsert(nwDocInsert.QUOTE_RS))
+ self.aInsQuoteRS.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_RS)
+ )
# Insert > Left Double Quote
self.aInsQuoteLD = self.mInsQuotes.addAction(self.tr("Left Double Quote"))
self.aInsQuoteLD.setShortcut("Ctrl+K, 3")
- self.aInsQuoteLD.triggered.connect(lambda: self._docInsert(nwDocInsert.QUOTE_LD))
+ self.aInsQuoteLD.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_LD)
+ )
# Insert > Right Double Quote
self.aInsQuoteRD = self.mInsQuotes.addAction(self.tr("Right Double Quote"))
self.aInsQuoteRD.setShortcut("Ctrl+K, 4")
- self.aInsQuoteRD.triggered.connect(lambda: self._docInsert(nwDocInsert.QUOTE_RD))
+ self.aInsQuoteRD.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_RD)
+ )
# Insert > Alternative Apostrophe
self.aInsMSApos = self.mInsQuotes.addAction(self.tr("Alternative Apostrophe"))
self.aInsMSApos.setShortcut("Ctrl+K, '")
- self.aInsMSApos.triggered.connect(lambda: self._docInsert(nwUnicode.U_MAPOSS))
+ self.aInsMSApos.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_MAPOSS)
+ )
# Insert > Symbols
self.mInsPunct = self.insMenu.addMenu(self.tr("General Punctuation"))
@@ -401,17 +419,23 @@ class GuiMainMenu(QMenuBar):
# Insert > Ellipsis
self.aInsEllipsis = self.mInsPunct.addAction(self.tr("Ellipsis"))
self.aInsEllipsis.setShortcut("Ctrl+K, .")
- self.aInsEllipsis.triggered.connect(lambda: self._docInsert(nwUnicode.U_HELLIP))
+ self.aInsEllipsis.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_HELLIP)
+ )
# Insert > Prime
self.aInsPrime = self.mInsPunct.addAction(self.tr("Prime"))
self.aInsPrime.setShortcut("Ctrl+K, Ctrl+'")
- self.aInsPrime.triggered.connect(lambda: self._docInsert(nwUnicode.U_PRIME))
+ self.aInsPrime.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_PRIME)
+ )
# Insert > Double Prime
self.aInsDPrime = self.mInsPunct.addAction(self.tr("Double Prime"))
self.aInsDPrime.setShortcut("Ctrl+K, Ctrl+\"")
- self.aInsDPrime.triggered.connect(lambda: self._docInsert(nwUnicode.U_DPRIME))
+ self.aInsDPrime.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_DPRIME)
+ )
# Insert > White Spaces
self.mInsSpace = self.insMenu.addMenu(self.tr("White Spaces"))
@@ -419,17 +443,23 @@ class GuiMainMenu(QMenuBar):
# Insert > Non-Breaking Space
self.aInsNBSpace = self.mInsSpace.addAction(self.tr("Non-Breaking Space"))
self.aInsNBSpace.setShortcut("Ctrl+K, Space")
- self.aInsNBSpace.triggered.connect(lambda: self._docInsert(nwUnicode.U_NBSP))
+ self.aInsNBSpace.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_NBSP)
+ )
# Insert > Thin Space
self.aInsThinSpace = self.mInsSpace.addAction(self.tr("Thin Space"))
self.aInsThinSpace.setShortcut("Ctrl+K, Shift+Space")
- self.aInsThinSpace.triggered.connect(lambda: self._docInsert(nwUnicode.U_THSP))
+ self.aInsThinSpace.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_THSP)
+ )
# Insert > Thin Non-Breaking Space
self.aInsThinNBSpace = self.mInsSpace.addAction(self.tr("Thin Non-Breaking Space"))
self.aInsThinNBSpace.setShortcut("Ctrl+K, Ctrl+Space")
- self.aInsThinNBSpace.triggered.connect(lambda: self._docInsert(nwUnicode.U_THNBSP))
+ self.aInsThinNBSpace.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_THNBSP)
+ )
# Insert > Symbols
self.mInsSymbol = self.insMenu.addMenu(self.tr("Other Symbols"))
@@ -437,42 +467,58 @@ class GuiMainMenu(QMenuBar):
# Insert > List Bullet
self.aInsBullet = self.mInsSymbol.addAction(self.tr("List Bullet"))
self.aInsBullet.setShortcut("Ctrl+K, *")
- self.aInsBullet.triggered.connect(lambda: self._docInsert(nwUnicode.U_BULL))
+ self.aInsBullet.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_BULL)
+ )
# Insert > Hyphen Bullet
self.aInsHyBull = self.mInsSymbol.addAction(self.tr("Hyphen Bullet"))
self.aInsHyBull.setShortcut("Ctrl+K, Ctrl+-")
- self.aInsHyBull.triggered.connect(lambda: self._docInsert(nwUnicode.U_HYBULL))
+ self.aInsHyBull.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_HYBULL)
+ )
# Insert > Flower Mark
self.aInsFlower = self.mInsSymbol.addAction(self.tr("Flower Mark"))
self.aInsFlower.setShortcut("Ctrl+K, Ctrl+*")
- self.aInsFlower.triggered.connect(lambda: self._docInsert(nwUnicode.U_FLOWER))
+ self.aInsFlower.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_FLOWER)
+ )
# Insert > Per Mille
self.aInsPerMille = self.mInsSymbol.addAction(self.tr("Per Mille"))
self.aInsPerMille.setShortcut("Ctrl+K, %")
- self.aInsPerMille.triggered.connect(lambda: self._docInsert(nwUnicode.U_PERMIL))
+ self.aInsPerMille.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_PERMIL)
+ )
# Insert > Degree Symbol
self.aInsDegree = self.mInsSymbol.addAction(self.tr("Degree Symbol"))
self.aInsDegree.setShortcut("Ctrl+K, Ctrl+O")
- self.aInsDegree.triggered.connect(lambda: self._docInsert(nwUnicode.U_DEGREE))
+ self.aInsDegree.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_DEGREE)
+ )
# Insert > Minus Sign
self.aInsMinus = self.mInsSymbol.addAction(self.tr("Minus Sign"))
self.aInsMinus.setShortcut("Ctrl+K, Ctrl+M")
- self.aInsMinus.triggered.connect(lambda: self._docInsert(nwUnicode.U_MINUS))
+ self.aInsMinus.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_MINUS)
+ )
# Insert > Times Sign
self.aInsTimes = self.mInsSymbol.addAction(self.tr("Times Sign"))
self.aInsTimes.setShortcut("Ctrl+K, Ctrl+X")
- self.aInsTimes.triggered.connect(lambda: self._docInsert(nwUnicode.U_TIMES))
+ self.aInsTimes.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_TIMES)
+ )
# Insert > Division
self.aInsDivide = self.mInsSymbol.addAction(self.tr("Division Sign"))
self.aInsDivide.setShortcut("Ctrl+K, Ctrl+D")
- self.aInsDivide.triggered.connect(lambda: self._docInsert(nwUnicode.U_DIVIDE))
+ self.aInsDivide.triggered.connect(
+ lambda: self.requestDocInsertText.emit(nwUnicode.U_DIVIDE)
+ )
# Insert > Tags and References
self.mInsKeywords = self.insMenu.addMenu(self.tr("Tags and References"))
@@ -491,7 +537,7 @@ class GuiMainMenu(QMenuBar):
self.mInsKWItems[keyWord][0].setText(trConst(nwLabels.KEY_NAME[keyWord]))
self.mInsKWItems[keyWord][0].setShortcut(self.mInsKWItems[keyWord][1])
self.mInsKWItems[keyWord][0].triggered.connect(
- lambda n, keyWord=keyWord: self._insertKeyWord(keyWord)
+ lambda n, keyWord=keyWord: self.requestDocKeyWordInsert.emit(keyWord)
)
self.mInsKeywords.addAction(self.mInsKWItems[keyWord][0])
@@ -501,22 +547,30 @@ class GuiMainMenu(QMenuBar):
# Insert > Synopsis Comment
self.aInsSynopsis = self.mInsComments.addAction(self.tr("Synopsis Comment"))
self.aInsSynopsis.setShortcut("Ctrl+K, S")
- self.aInsSynopsis.triggered.connect(lambda: self._docInsert(nwDocInsert.SYNOPSIS))
+ self.aInsSynopsis.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.SYNOPSIS)
+ )
# Insert > Symbols
self.mInsBreaks = self.insMenu.addMenu(self.tr("Page Break and Space"))
# Insert > New Page
self.aInsNewPage = self.mInsBreaks.addAction(self.tr("Page Break"))
- self.aInsNewPage.triggered.connect(lambda: self._docInsert(nwDocInsert.NEW_PAGE))
+ self.aInsNewPage.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.NEW_PAGE)
+ )
# Insert > Vertical Space (Single)
self.aInsVSpaceS = self.mInsBreaks.addAction(self.tr("Vertical Space (Single)"))
- self.aInsVSpaceS.triggered.connect(lambda: self._docInsert(nwDocInsert.VSPACE_S))
+ self.aInsVSpaceS.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.VSPACE_S)
+ )
# Insert > Vertical Space (Multi)
self.aInsVSpaceM = self.mInsBreaks.addAction(self.tr("Vertical Space (Multi)"))
- self.aInsVSpaceM.triggered.connect(lambda: self._docInsert(nwDocInsert.VSPACE_M))
+ self.aInsVSpaceM.triggered.connect(
+ lambda: self.requestDocInsert.emit(nwDocInsert.VSPACE_M)
+ )
# Insert > Placeholder Text
self.aLipsumText = self.mInsBreaks.addAction(self.tr("Placeholder Text"))
@@ -532,17 +586,23 @@ class GuiMainMenu(QMenuBar):
# Format > Emphasis
self.aFmtEmph = self.fmtMenu.addAction(self.tr("Emphasis"))
self.aFmtEmph.setShortcut("Ctrl+I")
- self.aFmtEmph.triggered.connect(lambda: self._docAction(nwDocAction.EMPH))
+ self.aFmtEmph.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.EMPH)
+ )
# Format > Strong Emphasis
self.aFmtStrong = self.fmtMenu.addAction(self.tr("Strong Emphasis"))
self.aFmtStrong.setShortcut("Ctrl+B")
- self.aFmtStrong.triggered.connect(lambda: self._docAction(nwDocAction.STRONG))
+ self.aFmtStrong.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.STRONG)
+ )
# Format > Strikethrough
self.aFmtStrike = self.fmtMenu.addAction(self.tr("Strikethrough"))
self.aFmtStrike.setShortcut("Ctrl+D")
- self.aFmtStrike.triggered.connect(lambda: self._docAction(nwDocAction.STRIKE))
+ self.aFmtStrike.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.STRIKE)
+ )
# Edit > Separator
self.fmtMenu.addSeparator()
@@ -550,12 +610,16 @@ class GuiMainMenu(QMenuBar):
# Format > Double Quotes
self.aFmtDQuote = self.fmtMenu.addAction(self.tr("Wrap Double Quotes"))
self.aFmtDQuote.setShortcut("Ctrl+\"")
- self.aFmtDQuote.triggered.connect(lambda: self._docAction(nwDocAction.D_QUOTE))
+ self.aFmtDQuote.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.D_QUOTE)
+ )
# Format > Single Quotes
self.aFmtSQuote = self.fmtMenu.addAction(self.tr("Wrap Single Quotes"))
self.aFmtSQuote.setShortcut("Ctrl+'")
- self.aFmtSQuote.triggered.connect(lambda: self._docAction(nwDocAction.S_QUOTE))
+ self.aFmtSQuote.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.S_QUOTE)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
@@ -564,28 +628,40 @@ class GuiMainMenu(QMenuBar):
self.mShortcodes = self.fmtMenu.addMenu(self.tr("More Formats ..."))
# Shortcode Italic
- self.aScItalic = self.mShortcodes.addAction(self.tr("Italics Shortcode"))
- self.aScItalic.triggered.connect(lambda: self._docAction(nwDocAction.SC_ITALIC))
+ self.aScItalic = self.mShortcodes.addAction(self.tr("Italics (Shortcode)"))
+ self.aScItalic.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
+ )
# Shortcode Bold
- self.aScBold = self.mShortcodes.addAction(self.tr("Bold Shortcode"))
- self.aScBold.triggered.connect(lambda: self._docAction(nwDocAction.SC_BOLD))
-
- # Shortcode Underline
- self.aScULine = self.mShortcodes.addAction(self.tr("Underline Shortcode"))
- self.aScULine.triggered.connect(lambda: self._docAction(nwDocAction.SC_ULINE))
+ self.aScBold = self.mShortcodes.addAction(self.tr("Bold (Shortcode)"))
+ self.aScBold.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
+ )
# Shortcode Strikethrough
- self.aScStrike = self.mShortcodes.addAction(self.tr("Strikethrough Shortcode"))
- self.aScStrike.triggered.connect(lambda: self._docAction(nwDocAction.SC_STRIKE))
+ self.aScStrike = self.mShortcodes.addAction(self.tr("Strikethrough (Shortcode)"))
+ self.aScStrike.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_STRIKE)
+ )
+
+ # Shortcode Underline
+ self.aScULine = self.mShortcodes.addAction(self.tr("Underline"))
+ self.aScULine.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_ULINE)
+ )
# Shortcode Superscript
self.aScSuper = self.mShortcodes.addAction(self.tr("Superscript"))
- self.aScSuper.triggered.connect(lambda: self._docAction(nwDocAction.SC_SUP))
+ self.aScSuper.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_SUP)
+ )
# Shortcode Subscript
self.aScSub = self.mShortcodes.addAction(self.tr("Subscript"))
- self.aScSub.triggered.connect(lambda: self._docAction(nwDocAction.SC_SUB))
+ self.aScSub.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.SC_SUB)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
@@ -593,33 +669,45 @@ class GuiMainMenu(QMenuBar):
# Format > Header 1 (Partition)
self.aFmtHead1 = self.fmtMenu.addAction(self.tr("Header 1 (Partition)"))
self.aFmtHead1.setShortcut("Ctrl+1")
- self.aFmtHead1.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H1))
+ self.aFmtHead1.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H1)
+ )
# Format > Header 2 (Chapter)
self.aFmtHead2 = self.fmtMenu.addAction(self.tr("Header 2 (Chapter)"))
self.aFmtHead2.setShortcut("Ctrl+2")
- self.aFmtHead2.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H2))
+ self.aFmtHead2.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H2)
+ )
# Format > Header 3 (Scene)
self.aFmtHead3 = self.fmtMenu.addAction(self.tr("Header 3 (Scene)"))
self.aFmtHead3.setShortcut("Ctrl+3")
- self.aFmtHead3.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H3))
+ self.aFmtHead3.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H3)
+ )
# Format > Header 4 (Section)
self.aFmtHead4 = self.fmtMenu.addAction(self.tr("Header 4 (Section)"))
self.aFmtHead4.setShortcut("Ctrl+4")
- self.aFmtHead4.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_H4))
+ self.aFmtHead4.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H4)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
# Format > Novel Title
self.aFmtTitle = self.fmtMenu.addAction(self.tr("Novel Title"))
- self.aFmtTitle.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_TTL))
+ self.aFmtTitle.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_TTL)
+ )
# Format > Unnumbered Chapter
self.aFmtUnNum = self.fmtMenu.addAction(self.tr("Unnumbered Chapter"))
- self.aFmtUnNum.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_UNN))
+ self.aFmtUnNum.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_UNN)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
@@ -627,17 +715,23 @@ class GuiMainMenu(QMenuBar):
# Format > Align Left
self.aFmtAlignLeft = self.fmtMenu.addAction(self.tr("Align Left"))
self.aFmtAlignLeft.setShortcut("Ctrl+5")
- self.aFmtAlignLeft.triggered.connect(lambda: self._docAction(nwDocAction.ALIGN_L))
+ self.aFmtAlignLeft.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.ALIGN_L)
+ )
# Format > Align Centre
self.aFmtAlignCentre = self.fmtMenu.addAction(self.tr("Align Centre"))
self.aFmtAlignCentre.setShortcut("Ctrl+6")
- self.aFmtAlignCentre.triggered.connect(lambda: self._docAction(nwDocAction.ALIGN_C))
+ self.aFmtAlignCentre.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.ALIGN_C)
+ )
# Format > Align Right
self.aFmtAlignRight = self.fmtMenu.addAction(self.tr("Align Right"))
self.aFmtAlignRight.setShortcut("Ctrl+7")
- self.aFmtAlignRight.triggered.connect(lambda: self._docAction(nwDocAction.ALIGN_R))
+ self.aFmtAlignRight.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.ALIGN_R)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
@@ -645,12 +739,16 @@ class GuiMainMenu(QMenuBar):
# Format > Indent Left
self.aFmtIndentLeft = self.fmtMenu.addAction(self.tr("Indent Left"))
self.aFmtIndentLeft.setShortcut("Ctrl+8")
- self.aFmtIndentLeft.triggered.connect(lambda: self._docAction(nwDocAction.INDENT_L))
+ self.aFmtIndentLeft.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.INDENT_L)
+ )
# Format > Indent Right
self.aFmtIndentRight = self.fmtMenu.addAction(self.tr("Indent Right"))
self.aFmtIndentRight.setShortcut("Ctrl+9")
- self.aFmtIndentRight.triggered.connect(lambda: self._docAction(nwDocAction.INDENT_R))
+ self.aFmtIndentRight.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.INDENT_R)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
@@ -658,27 +756,37 @@ class GuiMainMenu(QMenuBar):
# Format > Comment
self.aFmtComment = self.fmtMenu.addAction(self.tr("Toggle Comment"))
self.aFmtComment.setShortcut("Ctrl+/")
- self.aFmtComment.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_COM))
+ self.aFmtComment.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_COM)
+ )
# Format > Remove Block Format
self.aFmtNoFormat = self.fmtMenu.addAction(self.tr("Remove Block Format"))
self.aFmtNoFormat.setShortcuts(["Ctrl+0", "Ctrl+Shift+/"])
- self.aFmtNoFormat.triggered.connect(lambda: self._docAction(nwDocAction.BLOCK_TXT))
+ self.aFmtNoFormat.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.BLOCK_TXT)
+ )
# Format > Separator
self.fmtMenu.addSeparator()
# Format > Replace Single Quotes
self.aFmtReplSng = self.fmtMenu.addAction(self.tr("Convert Single Quotes"))
- self.aFmtReplSng.triggered.connect(lambda: self._docAction(nwDocAction.REPL_SNG))
+ self.aFmtReplSng.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.REPL_SNG)
+ )
# Format > Replace Double Quotes
self.aFmtReplDbl = self.fmtMenu.addAction(self.tr("Convert Double Quotes"))
- self.aFmtReplDbl.triggered.connect(lambda: self._docAction(nwDocAction.REPL_DBL))
+ self.aFmtReplDbl.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.REPL_DBL)
+ )
# Format > Remove In-Paragraph Breaks
self.aFmtRmBreaks = self.fmtMenu.addAction(self.tr("Remove In-Paragraph Breaks"))
- self.aFmtRmBreaks.triggered.connect(lambda: self._docAction(nwDocAction.RM_BREAKS))
+ self.aFmtRmBreaks.triggered.connect(
+ lambda: self.requestDocAction.emit(nwDocAction.RM_BREAKS)
+ )
return
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index adcebca8..41301476 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -62,7 +62,7 @@ from novelwriter.tools.writingstats import GuiWritingStats
from novelwriter.core.coretools import ProjectBuilder
from novelwriter.enum import (
- nwDocAction, nwDocMode, nwItemType, nwItemClass, nwWidget, nwView
+ nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwItemClass, nwWidget, nwView
)
from novelwriter.common import getGuiItem, hexToInt
from novelwriter.constants import nwFiles
@@ -243,6 +243,11 @@ class GuiMain(QMainWindow):
SHARED.projectStatusMessage.connect(self.mainStatus.setStatusMessage)
SHARED.spellLanguageChanged.connect(self.mainStatus.setLanguage)
+ self.mainMenu.requestDocAction.connect(self._passDocumentAction)
+ self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
+ self.mainMenu.requestDocInsertText.connect(self._passDocumentInsert)
+ self.mainMenu.requestDocKeyWordInsert.connect(self.docEditor.insertKeyWord)
+
self.sideBar.viewChangeRequested.connect(self._changeView)
self.projView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
@@ -735,20 +740,6 @@ class GuiMain(QMainWindow):
return True
- def passDocumentAction(self, action: nwDocAction) -> None:
- """Pass on document action to the document viewer if it has
- focus, or pass it to the document editor if it or any of
- its child widgets have focus. If neither has focus, ignore the
- action.
- """
- if self.docViewer.hasFocus():
- self.docViewer.docAction(action)
- elif self.docEditor.hasFocus():
- self.docEditor.docAction(action)
- else:
- logger.debug("Action cancelled as neither editor nor viewer has focus")
- return
-
##
# Tree Item Actions
##
@@ -1247,6 +1238,30 @@ class GuiMain(QMainWindow):
return
+ @pyqtSlot(nwDocAction)
+ def _passDocumentAction(self, action: nwDocAction) -> None:
+ """Pass on a document action to the document viewer if it has
+ focus, or pass it to the document editor if it or any of its
+ child widgets have focus. If neither has focus, ignore it.
+ """
+ if self.docViewer.hasFocus():
+ self.docViewer.docAction(action)
+ elif self.docEditor.hasFocus():
+ self.docEditor.docAction(action)
+ else:
+ logger.debug("Action cancelled as neither editor nor viewer has focus")
+ return
+
+ @pyqtSlot(str)
+ @pyqtSlot(nwDocInsert)
+ def _passDocumentInsert(self, content: str | nwDocInsert) -> None:
+ """Pass on a document insert action to the document editor if it
+ has focus. If not, ignore it.
+ """
+ if self.docEditor.hasFocus():
+ self.docEditor.insertText(content)
+ return
+
@pyqtSlot()
def _timeTick(self) -> None:
"""Process time tick of the main timer."""