From b2d71acd932f51147840a8591998af813ac2f682 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:36:54 +0100 Subject: [PATCH 1/2] Connect menu actions to main GUI in the menu class --- novelwriter/gui/mainmenu.py | 66 +++++++++++++++++++++++++ novelwriter/guimain.py | 97 +------------------------------------ 2 files changed, 67 insertions(+), 96 deletions(-) diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py index 28cc7d882..ddddf0b19 100644 --- a/novelwriter/gui/mainmenu.py +++ b/novelwriter/gui/mainmenu.py @@ -142,6 +142,7 @@ def _buildProjectMenu(self) -> None: self.aSaveProject = self.projMenu.addAction(self.tr("Save Project")) self.aSaveProject.setShortcut("Ctrl+Shift+S") self.aSaveProject.triggered.connect(lambda: self.mainGui.saveProject()) + self.mainGui.addAction(self.aSaveProject) # Project > Close Project self.aCloseProject = self.projMenu.addAction(self.tr("Close Project")) @@ -168,6 +169,7 @@ def _buildProjectMenu(self) -> None: self.aEditItem = self.projMenu.addAction(self.tr("Rename Item")) self.aEditItem.setShortcut("F2") self.aEditItem.triggered.connect(lambda: self.mainGui.projView.renameTreeItem(None)) + self.mainGui.addAction(self.aEditItem) # Project > Delete self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item")) @@ -186,6 +188,7 @@ def _buildProjectMenu(self) -> None: self.aExitNW.setShortcut("Ctrl+Q") self.aExitNW.setMenuRole(QAction.MenuRole.QuitRole) self.aExitNW.triggered.connect(lambda: self.mainGui.closeMain()) + self.mainGui.addAction(self.aExitNW) return @@ -203,11 +206,13 @@ def _buildDocumentMenu(self) -> None: self.aSaveDoc = self.docuMenu.addAction(self.tr("Save Document")) self.aSaveDoc.setShortcut("Ctrl+S") self.aSaveDoc.triggered.connect(self.mainGui.forceSaveDocument) + self.mainGui.addAction(self.aSaveDoc) # Document > Close self.aCloseDoc = self.docuMenu.addAction(self.tr("Close Document")) self.aCloseDoc.setShortcut("Ctrl+W") self.aCloseDoc.triggered.connect(self.mainGui.closeDocEditor) + self.mainGui.addAction(self.aCloseDoc) # Document > Separator self.docuMenu.addSeparator() @@ -246,6 +251,7 @@ def _buildEditMenu(self) -> None: self.aEditUndo.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.UNDO) ) + self.mainGui.addAction(self.aEditUndo) # Edit > Redo self.aEditRedo = self.editMenu.addAction(self.tr("Redo")) @@ -253,6 +259,7 @@ def _buildEditMenu(self) -> None: self.aEditRedo.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.REDO) ) + self.mainGui.addAction(self.aEditRedo) # Edit > Separator self.editMenu.addSeparator() @@ -263,6 +270,7 @@ def _buildEditMenu(self) -> None: self.aEditCut.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.CUT) ) + self.mainGui.addAction(self.aEditCut) # Edit > Copy self.aEditCopy = self.editMenu.addAction(self.tr("Copy")) @@ -270,6 +278,7 @@ def _buildEditMenu(self) -> None: self.aEditCopy.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.COPY) ) + self.mainGui.addAction(self.aEditCopy) # Edit > Paste self.aEditPaste = self.editMenu.addAction(self.tr("Paste")) @@ -277,6 +286,7 @@ def _buildEditMenu(self) -> None: self.aEditPaste.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.PASTE) ) + self.mainGui.addAction(self.aEditPaste) # Edit > Separator self.editMenu.addSeparator() @@ -287,6 +297,7 @@ def _buildEditMenu(self) -> None: self.aSelectAll.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.SEL_ALL) ) + self.mainGui.addAction(self.aSelectAll) # Edit > Select Paragraph self.aSelectPar = self.editMenu.addAction(self.tr("Select Paragraph")) @@ -294,6 +305,7 @@ def _buildEditMenu(self) -> None: self.aSelectPar.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.SEL_PARA) ) + self.mainGui.addAction(self.aSelectPar) return @@ -343,11 +355,13 @@ def _buildViewMenu(self) -> None: self.aFocusMode = self.viewMenu.addAction(self.tr("Focus Mode")) self.aFocusMode.setShortcut("F8") self.aFocusMode.triggered.connect(self.mainGui.toggleFocusMode) + self.mainGui.addAction(self.aFocusMode) # View > Toggle Full Screen self.aFullScreen = self.viewMenu.addAction(self.tr("Full Screen Mode")) self.aFullScreen.setShortcut("F11") self.aFullScreen.triggered.connect(lambda: self.mainGui.toggleFullScreenMode()) + self.mainGui.addAction(self.aFullScreen) return @@ -365,6 +379,7 @@ def _buildInsertMenu(self) -> None: self.aInsENDash.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_ENDASH) ) + self.mainGui.addAction(self.aInsENDash) # Insert > Long Dash self.aInsEMDash = self.mInsDashes.addAction(self.tr("Long Dash")) @@ -372,6 +387,7 @@ def _buildInsertMenu(self) -> None: self.aInsEMDash.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_EMDASH) ) + self.mainGui.addAction(self.aInsEMDash) # Insert > Long Dash self.aInsHorBar = self.mInsDashes.addAction(self.tr("Horizontal Bar")) @@ -379,6 +395,7 @@ def _buildInsertMenu(self) -> None: self.aInsHorBar.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_HBAR) ) + self.mainGui.addAction(self.aInsHorBar) # Insert > Figure Dash self.aInsFigDash = self.mInsDashes.addAction(self.tr("Figure Dash")) @@ -386,6 +403,7 @@ def _buildInsertMenu(self) -> None: self.aInsFigDash.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_FGDASH) ) + self.mainGui.addAction(self.aInsFigDash) # Insert > Quote Marks self.mInsQuotes = self.insMenu.addMenu(self.tr("Quote Marks")) @@ -396,6 +414,7 @@ def _buildInsertMenu(self) -> None: self.aInsQuoteLS.triggered.connect( lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_LS) ) + self.mainGui.addAction(self.aInsQuoteLS) # Insert > Right Single Quote self.aInsQuoteRS = self.mInsQuotes.addAction(self.tr("Right Single Quote")) @@ -403,6 +422,7 @@ def _buildInsertMenu(self) -> None: self.aInsQuoteRS.triggered.connect( lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_RS) ) + self.mainGui.addAction(self.aInsQuoteRS) # Insert > Left Double Quote self.aInsQuoteLD = self.mInsQuotes.addAction(self.tr("Left Double Quote")) @@ -410,6 +430,7 @@ def _buildInsertMenu(self) -> None: self.aInsQuoteLD.triggered.connect( lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_LD) ) + self.mainGui.addAction(self.aInsQuoteLD) # Insert > Right Double Quote self.aInsQuoteRD = self.mInsQuotes.addAction(self.tr("Right Double Quote")) @@ -417,6 +438,7 @@ def _buildInsertMenu(self) -> None: self.aInsQuoteRD.triggered.connect( lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_RD) ) + self.mainGui.addAction(self.aInsQuoteRD) # Insert > Alternative Apostrophe self.aInsMSApos = self.mInsQuotes.addAction(self.tr("Alternative Apostrophe")) @@ -424,6 +446,7 @@ def _buildInsertMenu(self) -> None: self.aInsMSApos.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_MAPOS) ) + self.mainGui.addAction(self.aInsMSApos) # Insert > Symbols self.mInsPunct = self.insMenu.addMenu(self.tr("General Punctuation")) @@ -434,6 +457,7 @@ def _buildInsertMenu(self) -> None: self.aInsEllipsis.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_HELLIP) ) + self.mainGui.addAction(self.aInsEllipsis) # Insert > Prime self.aInsPrime = self.mInsPunct.addAction(self.tr("Prime")) @@ -441,6 +465,7 @@ def _buildInsertMenu(self) -> None: self.aInsPrime.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_PRIME) ) + self.mainGui.addAction(self.aInsPrime) # Insert > Double Prime self.aInsDPrime = self.mInsPunct.addAction(self.tr("Double Prime")) @@ -448,6 +473,7 @@ def _buildInsertMenu(self) -> None: self.aInsDPrime.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_DPRIME) ) + self.mainGui.addAction(self.aInsDPrime) # Insert > White Spaces self.mInsSpace = self.insMenu.addMenu(self.tr("White Spaces")) @@ -458,6 +484,7 @@ def _buildInsertMenu(self) -> None: self.aInsNBSpace.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_NBSP) ) + self.mainGui.addAction(self.aInsNBSpace) # Insert > Thin Space self.aInsThinSpace = self.mInsSpace.addAction(self.tr("Thin Space")) @@ -465,6 +492,7 @@ def _buildInsertMenu(self) -> None: self.aInsThinSpace.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_THSP) ) + self.mainGui.addAction(self.aInsThinSpace) # Insert > Thin Non-Breaking Space self.aInsThinNBSpace = self.mInsSpace.addAction(self.tr("Thin Non-Breaking Space")) @@ -472,6 +500,7 @@ def _buildInsertMenu(self) -> None: self.aInsThinNBSpace.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_THNBSP) ) + self.mainGui.addAction(self.aInsThinNBSpace) # Insert > Symbols self.mInsSymbol = self.insMenu.addMenu(self.tr("Other Symbols")) @@ -482,6 +511,7 @@ def _buildInsertMenu(self) -> None: self.aInsBullet.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_BULL) ) + self.mainGui.addAction(self.aInsBullet) # Insert > Hyphen Bullet self.aInsHyBull = self.mInsSymbol.addAction(self.tr("Hyphen Bullet")) @@ -489,6 +519,7 @@ def _buildInsertMenu(self) -> None: self.aInsHyBull.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_HYBULL) ) + self.mainGui.addAction(self.aInsHyBull) # Insert > Flower Mark self.aInsFlower = self.mInsSymbol.addAction(self.tr("Flower Mark")) @@ -496,6 +527,7 @@ def _buildInsertMenu(self) -> None: self.aInsFlower.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_FLOWER) ) + self.mainGui.addAction(self.aInsFlower) # Insert > Per Mille self.aInsPerMille = self.mInsSymbol.addAction(self.tr("Per Mille")) @@ -503,6 +535,7 @@ def _buildInsertMenu(self) -> None: self.aInsPerMille.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_PERMIL) ) + self.mainGui.addAction(self.aInsPerMille) # Insert > Degree Symbol self.aInsDegree = self.mInsSymbol.addAction(self.tr("Degree Symbol")) @@ -510,6 +543,7 @@ def _buildInsertMenu(self) -> None: self.aInsDegree.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_DEGREE) ) + self.mainGui.addAction(self.aInsDegree) # Insert > Minus Sign self.aInsMinus = self.mInsSymbol.addAction(self.tr("Minus Sign")) @@ -517,6 +551,7 @@ def _buildInsertMenu(self) -> None: self.aInsMinus.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_MINUS) ) + self.mainGui.addAction(self.aInsMinus) # Insert > Times Sign self.aInsTimes = self.mInsSymbol.addAction(self.tr("Times Sign")) @@ -524,6 +559,7 @@ def _buildInsertMenu(self) -> None: self.aInsTimes.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_TIMES) ) + self.mainGui.addAction(self.aInsTimes) # Insert > Division self.aInsDivide = self.mInsSymbol.addAction(self.tr("Division Sign")) @@ -531,6 +567,7 @@ def _buildInsertMenu(self) -> None: self.aInsDivide.triggered.connect( lambda: self.requestDocInsertText.emit(nwUnicode.U_DIVIDE) ) + self.mainGui.addAction(self.aInsDivide) # Insert > Tags and References self.mInsKeywords = self.insMenu.addMenu(self.tr("Tags and References")) @@ -553,6 +590,7 @@ def _buildInsertMenu(self) -> None: lambda n, keyWord=keyWord: self.requestDocKeyWordInsert.emit(keyWord) ) self.mInsKeywords.addAction(self.mInsKWItems[keyWord][0]) + self.mainGui.addAction(self.mInsKWItems[keyWord][0]) # Insert > Special Comments self.mInsComments = self.insMenu.addMenu(self.tr("Special Comments")) @@ -563,6 +601,7 @@ def _buildInsertMenu(self) -> None: self.aInsSynopsis.triggered.connect( lambda: self.requestDocInsert.emit(nwDocInsert.SYNOPSIS) ) + self.mainGui.addAction(self.aInsSynopsis) # Insert > Short Description Comment self.aInsShort = self.mInsComments.addAction(self.tr("Short Description Comment")) @@ -570,6 +609,7 @@ def _buildInsertMenu(self) -> None: self.aInsShort.triggered.connect( lambda: self.requestDocInsert.emit(nwDocInsert.SHORT) ) + self.mainGui.addAction(self.aInsShort) # Insert > Breaks and Vertical Space self.mInsBreaks = self.insMenu.addMenu(self.tr("Breaks and Vertical Space")) @@ -623,6 +663,7 @@ def _buildFormatMenu(self) -> None: self.aFmtBold.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD) ) + self.mainGui.addAction(self.aFmtBold) # Format > Italic self.aFmtItalic = self.fmtMenu.addAction(self.tr("Italic")) @@ -630,6 +671,7 @@ def _buildFormatMenu(self) -> None: self.aFmtItalic.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC) ) + self.mainGui.addAction(self.aFmtItalic) # Format > Strikethrough self.aFmtStrike = self.fmtMenu.addAction(self.tr("Strikethrough")) @@ -637,6 +679,7 @@ def _buildFormatMenu(self) -> None: self.aFmtStrike.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE) ) + self.mainGui.addAction(self.aFmtStrike) # Edit > Separator self.fmtMenu.addSeparator() @@ -647,6 +690,7 @@ def _buildFormatMenu(self) -> None: self.aFmtDQuote.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.D_QUOTE) ) + self.mainGui.addAction(self.aFmtDQuote) # Format > Single Quotes self.aFmtSQuote = self.fmtMenu.addAction(self.tr("Wrap Single Quotes")) @@ -654,6 +698,7 @@ def _buildFormatMenu(self) -> None: self.aFmtSQuote.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.S_QUOTE) ) + self.mainGui.addAction(self.aFmtSQuote) # Format > Separator self.fmtMenu.addSeparator() @@ -712,6 +757,7 @@ def _buildFormatMenu(self) -> None: self.aFmtHead1.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H1) ) + self.mainGui.addAction(self.aFmtHead1) # Format > Heading 2 (Chapter) self.aFmtHead2 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H2"])) @@ -719,6 +765,7 @@ def _buildFormatMenu(self) -> None: self.aFmtHead2.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H2) ) + self.mainGui.addAction(self.aFmtHead2) # Format > Heading 3 (Scene) self.aFmtHead3 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H3"])) @@ -726,6 +773,7 @@ def _buildFormatMenu(self) -> None: self.aFmtHead3.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H3) ) + self.mainGui.addAction(self.aFmtHead3) # Format > Heading 4 (Section) self.aFmtHead4 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H4"])) @@ -733,6 +781,7 @@ def _buildFormatMenu(self) -> None: self.aFmtHead4.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H4) ) + self.mainGui.addAction(self.aFmtHead4) # Format > Separator self.fmtMenu.addSeparator() @@ -764,6 +813,7 @@ def _buildFormatMenu(self) -> None: self.aFmtAlignLeft.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.ALIGN_L) ) + self.mainGui.addAction(self.aFmtAlignLeft) # Format > Align Centre self.aFmtAlignCentre = self.fmtMenu.addAction(self.tr("Align Centre")) @@ -771,6 +821,7 @@ def _buildFormatMenu(self) -> None: self.aFmtAlignCentre.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.ALIGN_C) ) + self.mainGui.addAction(self.aFmtAlignCentre) # Format > Align Right self.aFmtAlignRight = self.fmtMenu.addAction(self.tr("Align Right")) @@ -778,6 +829,7 @@ def _buildFormatMenu(self) -> None: self.aFmtAlignRight.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.ALIGN_R) ) + self.mainGui.addAction(self.aFmtAlignRight) # Format > Separator self.fmtMenu.addSeparator() @@ -788,6 +840,7 @@ def _buildFormatMenu(self) -> None: self.aFmtIndentLeft.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.INDENT_L) ) + self.mainGui.addAction(self.aFmtIndentLeft) # Format > Indent Right self.aFmtIndentRight = self.fmtMenu.addAction(self.tr("Indent Right")) @@ -795,6 +848,7 @@ def _buildFormatMenu(self) -> None: self.aFmtIndentRight.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.INDENT_R) ) + self.mainGui.addAction(self.aFmtIndentRight) # Format > Separator self.fmtMenu.addSeparator() @@ -805,6 +859,7 @@ def _buildFormatMenu(self) -> None: self.aFmtComment.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.BLOCK_COM) ) + self.mainGui.addAction(self.aFmtComment) # Format > Ignore Text self.aFmtIgnore = self.fmtMenu.addAction(self.tr("Toggle Ignore Text")) @@ -819,6 +874,7 @@ def _buildFormatMenu(self) -> None: self.aFmtNoFormat.triggered.connect( lambda: self.requestDocAction.emit(nwDocAction.BLOCK_TXT) ) + self.mainGui.addAction(self.aFmtNoFormat) # Format > Separator self.fmtMenu.addSeparator() @@ -852,16 +908,19 @@ def _buildSearchMenu(self) -> None: self.aFind = self.srcMenu.addAction(self.tr("Find")) self.aFind.setShortcut("Ctrl+F") self.aFind.triggered.connect(lambda: self.mainGui.docEditor.beginSearch()) + self.mainGui.addAction(self.aFind) # Search > Replace self.aReplace = self.srcMenu.addAction(self.tr("Replace")) self.aReplace.setShortcut("Ctrl+=" if CONFIG.osDarwin else "Ctrl+H") self.aReplace.triggered.connect(lambda: self.mainGui.docEditor.beginReplace()) + self.mainGui.addAction(self.aReplace) # Search > Find Next self.aFindNext = self.srcMenu.addAction(self.tr("Find Next")) self.aFindNext.setShortcuts(["Ctrl+G", "F3"] if CONFIG.osDarwin else ["F3", "Ctrl+G"]) self.aFindNext.triggered.connect(lambda: self.mainGui.docEditor.findNext()) + self.mainGui.addAction(self.aFindNext) # Search > Find Prev self.aFindPrev = self.srcMenu.addAction(self.tr("Find Previous")) @@ -869,11 +928,13 @@ def _buildSearchMenu(self) -> None: ["Ctrl+Shift+G", "Shift+F3"] if CONFIG.osDarwin else ["Shift+F3", "Ctrl+Shift+G"] ) self.aFindPrev.triggered.connect(lambda: self.mainGui.docEditor.findNext(goBack=True)) + self.mainGui.addAction(self.aFindPrev) # Search > Replace Next self.aReplaceNext = self.srcMenu.addAction(self.tr("Replace Next")) self.aReplaceNext.setShortcut("Ctrl+Shift+1") self.aReplaceNext.triggered.connect(lambda: self.mainGui.docEditor.replaceNext()) + self.mainGui.addAction(self.aReplaceNext) # Search > Separator self.srcMenu.addSeparator() @@ -896,6 +957,7 @@ def _buildToolsMenu(self) -> None: self.aSpellCheck.setChecked(SHARED.project.data.spellCheck) self.aSpellCheck.triggered.connect(self._toggleSpellCheck) # triggered, not toggled! self.aSpellCheck.setShortcut("Ctrl+F7") + self.mainGui.addAction(self.aSpellCheck) self.mSelectLanguage = self.toolsMenu.addMenu(self.tr("Spell Check Language")) languages = SHARED.spelling.listDictionaries() @@ -910,6 +972,7 @@ def _buildToolsMenu(self) -> None: self.aReRunSpell = self.toolsMenu.addAction(self.tr("Re-Run Spell Check")) self.aReRunSpell.setShortcut("F7") self.aReRunSpell.triggered.connect(lambda: self.mainGui.docEditor.spellCheckDocument()) + self.mainGui.addAction(self.aReRunSpell) # Tools > Project Word List self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List")) @@ -950,6 +1013,7 @@ def _buildToolsMenu(self) -> None: self.aPreferences.setShortcut("Ctrl+,") self.aPreferences.setMenuRole(QAction.MenuRole.PreferencesRole) self.aPreferences.triggered.connect(self.mainGui.showPreferencesDialog) + self.mainGui.addAction(self.aPreferences) return @@ -975,12 +1039,14 @@ def _buildHelpMenu(self) -> None: self.aHelpDocs = self.helpMenu.addAction(self.tr("User Manual (Online)")) self.aHelpDocs.setShortcut("F1") self.aHelpDocs.triggered.connect(lambda: self._openWebsite(nwConst.URL_DOCS)) + self.mainGui.addAction(self.aHelpDocs) # Help > User Manual (PDF) if isinstance(CONFIG.pdfDocs, Path): self.aPdfDocs = self.helpMenu.addAction(self.tr("User Manual (PDF)")) self.aPdfDocs.setShortcut("Shift+F1") self.aPdfDocs.triggered.connect(self._openUserManualFile) + self.mainGui.addAction(self.aPdfDocs) # Help > Separator self.helpMenu.addSeparator() diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 3966ff491..394037172 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -289,9 +289,7 @@ def __init__(self) -> None: self.asDocTimer = QTimer(self) self.asDocTimer.timeout.connect(self._autoSaveDocument) - # Shortcuts and Actions - self._connectMenuActions() - + # Shortcuts self.keyReturn = QShortcut(self) self.keyReturn.setKey("Return") self.keyReturn.activated.connect(self._keyPressReturn) @@ -1299,99 +1297,6 @@ def _projStackChanged(self, index: int) -> None: # Internal Functions ## - def _connectMenuActions(self) -> None: - """Connect to the main window all menu actions that need to be - available also when the main menu is hidden. - """ - # Project - self.addAction(self.mainMenu.aSaveProject) - self.addAction(self.mainMenu.aEditItem) - self.addAction(self.mainMenu.aExitNW) - - # Document - self.addAction(self.mainMenu.aSaveDoc) - self.addAction(self.mainMenu.aCloseDoc) - - # Edit - self.addAction(self.mainMenu.aEditUndo) - self.addAction(self.mainMenu.aEditRedo) - self.addAction(self.mainMenu.aEditCut) - self.addAction(self.mainMenu.aEditCopy) - self.addAction(self.mainMenu.aEditPaste) - self.addAction(self.mainMenu.aSelectAll) - self.addAction(self.mainMenu.aSelectPar) - - # View - self.addAction(self.mainMenu.aFocusMode) - self.addAction(self.mainMenu.aFullScreen) - - # Insert - self.addAction(self.mainMenu.aInsENDash) - self.addAction(self.mainMenu.aInsEMDash) - self.addAction(self.mainMenu.aInsHorBar) - self.addAction(self.mainMenu.aInsFigDash) - self.addAction(self.mainMenu.aInsQuoteLS) - self.addAction(self.mainMenu.aInsQuoteRS) - self.addAction(self.mainMenu.aInsQuoteLD) - self.addAction(self.mainMenu.aInsQuoteRD) - self.addAction(self.mainMenu.aInsMSApos) - self.addAction(self.mainMenu.aInsEllipsis) - self.addAction(self.mainMenu.aInsPrime) - self.addAction(self.mainMenu.aInsDPrime) - self.addAction(self.mainMenu.aInsNBSpace) - self.addAction(self.mainMenu.aInsThinSpace) - self.addAction(self.mainMenu.aInsThinNBSpace) - self.addAction(self.mainMenu.aInsBullet) - self.addAction(self.mainMenu.aInsHyBull) - self.addAction(self.mainMenu.aInsFlower) - self.addAction(self.mainMenu.aInsPerMille) - self.addAction(self.mainMenu.aInsDegree) - self.addAction(self.mainMenu.aInsMinus) - self.addAction(self.mainMenu.aInsTimes) - self.addAction(self.mainMenu.aInsDivide) - self.addAction(self.mainMenu.aInsSynopsis) - self.addAction(self.mainMenu.aInsShort) - - for mAction, _ in self.mainMenu.mInsKWItems.values(): - self.addAction(mAction) - - # Search - self.addAction(self.mainMenu.aFind) - self.addAction(self.mainMenu.aReplace) - self.addAction(self.mainMenu.aFindNext) - self.addAction(self.mainMenu.aFindPrev) - self.addAction(self.mainMenu.aReplaceNext) - - # Format - self.addAction(self.mainMenu.aFmtItalic) - self.addAction(self.mainMenu.aFmtBold) - self.addAction(self.mainMenu.aFmtStrike) - self.addAction(self.mainMenu.aFmtDQuote) - self.addAction(self.mainMenu.aFmtSQuote) - self.addAction(self.mainMenu.aFmtHead1) - self.addAction(self.mainMenu.aFmtHead2) - self.addAction(self.mainMenu.aFmtHead3) - self.addAction(self.mainMenu.aFmtHead4) - self.addAction(self.mainMenu.aFmtAlignLeft) - self.addAction(self.mainMenu.aFmtAlignCentre) - self.addAction(self.mainMenu.aFmtAlignRight) - self.addAction(self.mainMenu.aFmtIndentLeft) - self.addAction(self.mainMenu.aFmtIndentRight) - self.addAction(self.mainMenu.aFmtComment) - self.addAction(self.mainMenu.aFmtNoFormat) - - # Tools - self.addAction(self.mainMenu.aSpellCheck) - self.addAction(self.mainMenu.aReRunSpell) - self.addAction(self.mainMenu.aPreferences) - - # Help - self.addAction(self.mainMenu.aHelpDocs) - if isinstance(CONFIG.pdfDocs, Path): - self.addAction(self.mainMenu.aPdfDocs) - - return - def _updateWindowTitle(self, projName: str | None = None) -> None: """Set the window title and add the project's name.""" self.setWindowTitle(" - ".join(filter(None, [projName, CONFIG.appName]))) From 4eace705e32e089f710737851969a3aa900c99c7 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:37:50 +0100 Subject: [PATCH 2/2] Add a function wrapper that makes the linter happy when used for Qt slots --- novelwriter/common.py | 12 ++++++++ novelwriter/gui/mainmenu.py | 61 ++++++++++++++++++------------------- novelwriter/guimain.py | 11 ++++--- 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/novelwriter/common.py b/novelwriter/common.py index e96e5968a..397f6dc5d 100644 --- a/novelwriter/common.py +++ b/novelwriter/common.py @@ -29,6 +29,7 @@ import uuid import xml.etree.ElementTree as ET +from collections.abc import Callable from configparser import ConfigParser from datetime import datetime from pathlib import Path @@ -414,6 +415,10 @@ def numberToRoman(value: int, toLower: bool = False) -> str: return roman.lower() if toLower else roman +## +# Qt Helpers +## + def cssCol(col: QColor, alpha: int | None = None) -> str: """Convert a QColor object to an rgba entry to use in CSS.""" return f"rgba({col.red()}, {col.green()}, {col.blue()}, {alpha or col.alpha()})" @@ -429,6 +434,13 @@ def describeFont(font: QFont) -> str: return "Error" +def qtLambda(func: Callable, *args: Any, **kwargs: Any) -> Callable: + """A replacement for Python lambdas that works for Qt slots.""" + def wrapper(*args_: Any, **kwargs_: Any) -> None: + func(*args, **kwargs) + return wrapper + + ## # Encoder Functions ## diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py index ddddf0b19..449b9b708 100644 --- a/novelwriter/gui/mainmenu.py +++ b/novelwriter/gui/mainmenu.py @@ -33,7 +33,7 @@ from PyQt5.QtWidgets import QAction, QMenuBar from novelwriter import CONFIG, SHARED -from novelwriter.common import openExternalPath +from novelwriter.common import openExternalPath, qtLambda from novelwriter.constants import nwConst, nwKeyWords, nwLabels, nwStyles, nwUnicode, trConst from novelwriter.enum import nwDocAction, nwDocInsert, nwFocus, nwView from novelwriter.extensions.eventfilters import StatusTipFilter @@ -141,13 +141,13 @@ def _buildProjectMenu(self) -> None: # Project > Save Project self.aSaveProject = self.projMenu.addAction(self.tr("Save Project")) self.aSaveProject.setShortcut("Ctrl+Shift+S") - self.aSaveProject.triggered.connect(lambda: self.mainGui.saveProject()) + self.aSaveProject.triggered.connect(qtLambda(self.mainGui.saveProject)) self.mainGui.addAction(self.aSaveProject) # Project > Close Project self.aCloseProject = self.projMenu.addAction(self.tr("Close Project")) self.aCloseProject.setShortcut("Ctrl+Shift+W") - self.aCloseProject.triggered.connect(lambda: self.mainGui.closeProject(False)) + self.aCloseProject.triggered.connect(qtLambda(self.mainGui.closeProject, False)) # Project > Separator self.projMenu.addSeparator() @@ -168,17 +168,17 @@ def _buildProjectMenu(self) -> None: # Project > Edit self.aEditItem = self.projMenu.addAction(self.tr("Rename Item")) self.aEditItem.setShortcut("F2") - self.aEditItem.triggered.connect(lambda: self.mainGui.projView.renameTreeItem(None)) + self.aEditItem.triggered.connect(qtLambda(self.mainGui.projView.renameTreeItem, None)) self.mainGui.addAction(self.aEditItem) # Project > Delete self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item")) self.aDeleteItem.setShortcut("Ctrl+Shift+Del") # Cannot be Ctrl+Del, see #629 - self.aDeleteItem.triggered.connect(lambda: self.mainGui.projView.requestDeleteItem(None)) + self.aDeleteItem.triggered.connect(qtLambda(self.mainGui.projView.requestDeleteItem, None)) # Project > Empty Trash self.aEmptyTrash = self.projMenu.addAction(self.tr("Empty Trash")) - self.aEmptyTrash.triggered.connect(lambda: self.mainGui.projView.emptyTrash()) + self.aEmptyTrash.triggered.connect(qtLambda(self.mainGui.projView.emptyTrash)) # Project > Separator self.projMenu.addSeparator() @@ -187,7 +187,7 @@ def _buildProjectMenu(self) -> None: self.aExitNW = self.projMenu.addAction(self.tr("Exit")) self.aExitNW.setShortcut("Ctrl+Q") self.aExitNW.setMenuRole(QAction.MenuRole.QuitRole) - self.aExitNW.triggered.connect(lambda: self.mainGui.closeMain()) + self.aExitNW.triggered.connect(qtLambda(self.mainGui.closeMain)) self.mainGui.addAction(self.aExitNW) return @@ -220,7 +220,7 @@ def _buildDocumentMenu(self) -> None: # Document > Preview self.aViewDoc = self.docuMenu.addAction(self.tr("View Document")) self.aViewDoc.setShortcut("Ctrl+R") - self.aViewDoc.triggered.connect(lambda: self.mainGui.viewDocument(None)) + self.aViewDoc.triggered.connect(qtLambda(self.mainGui.viewDocument, None)) # Document > Close Preview self.aCloseView = self.docuMenu.addAction(self.tr("Close Document View")) @@ -232,11 +232,11 @@ def _buildDocumentMenu(self) -> None: # Document > Show File Details self.aFileDetails = self.docuMenu.addAction(self.tr("Show File Details")) - self.aFileDetails.triggered.connect(lambda: self.mainGui.docEditor.revealLocation()) + self.aFileDetails.triggered.connect(qtLambda(self.mainGui.docEditor.revealLocation)) # Document > Import From File self.aImportFile = self.docuMenu.addAction(self.tr("Import Text from File")) - self.aImportFile.triggered.connect(lambda: self.mainGui.importDocument()) + self.aImportFile.triggered.connect(qtLambda(self.mainGui.importDocument)) return @@ -360,7 +360,7 @@ def _buildViewMenu(self) -> None: # View > Toggle Full Screen self.aFullScreen = self.viewMenu.addAction(self.tr("Full Screen Mode")) self.aFullScreen.setShortcut("F11") - self.aFullScreen.triggered.connect(lambda: self.mainGui.toggleFullScreenMode()) + self.aFullScreen.triggered.connect(self.mainGui.toggleFullScreenMode) self.mainGui.addAction(self.aFullScreen) return @@ -583,14 +583,13 @@ def _buildInsertMenu(self) -> None: self.mInsKWItems[nwKeyWords.ENTITY_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, E") self.mInsKWItems[nwKeyWords.CUSTOM_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, X") self.mInsKWItems[nwKeyWords.MENTION_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, M") - for n, keyWord in enumerate(self.mInsKWItems): - 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.requestDocKeyWordInsert.emit(keyWord) - ) - self.mInsKeywords.addAction(self.mInsKWItems[keyWord][0]) - self.mainGui.addAction(self.mInsKWItems[keyWord][0]) + for key in self.mInsKWItems: + action = self.mInsKWItems[key][0] + action.setText(trConst(nwLabels.KEY_NAME[key])) + action.setShortcut(self.mInsKWItems[key][1]) + action.triggered.connect(qtLambda(self.requestDocKeyWordInsert.emit, key)) + self.mInsKeywords.addAction(action) + self.mainGui.addAction(self.mInsKWItems[key][0]) # Insert > Special Comments self.mInsComments = self.insMenu.addMenu(self.tr("Special Comments")) @@ -907,19 +906,19 @@ def _buildSearchMenu(self) -> None: # Search > Find self.aFind = self.srcMenu.addAction(self.tr("Find")) self.aFind.setShortcut("Ctrl+F") - self.aFind.triggered.connect(lambda: self.mainGui.docEditor.beginSearch()) + self.aFind.triggered.connect(qtLambda(self.mainGui.docEditor.beginSearch)) self.mainGui.addAction(self.aFind) # Search > Replace self.aReplace = self.srcMenu.addAction(self.tr("Replace")) self.aReplace.setShortcut("Ctrl+=" if CONFIG.osDarwin else "Ctrl+H") - self.aReplace.triggered.connect(lambda: self.mainGui.docEditor.beginReplace()) + self.aReplace.triggered.connect(qtLambda(self.mainGui.docEditor.beginReplace)) self.mainGui.addAction(self.aReplace) # Search > Find Next self.aFindNext = self.srcMenu.addAction(self.tr("Find Next")) self.aFindNext.setShortcuts(["Ctrl+G", "F3"] if CONFIG.osDarwin else ["F3", "Ctrl+G"]) - self.aFindNext.triggered.connect(lambda: self.mainGui.docEditor.findNext()) + self.aFindNext.triggered.connect(qtLambda(self.mainGui.docEditor.findNext)) self.mainGui.addAction(self.aFindNext) # Search > Find Prev @@ -927,13 +926,13 @@ def _buildSearchMenu(self) -> None: self.aFindPrev.setShortcuts( ["Ctrl+Shift+G", "Shift+F3"] if CONFIG.osDarwin else ["Shift+F3", "Ctrl+Shift+G"] ) - self.aFindPrev.triggered.connect(lambda: self.mainGui.docEditor.findNext(goBack=True)) + self.aFindPrev.triggered.connect(qtLambda(self.mainGui.docEditor.findNext, goBack=True)) self.mainGui.addAction(self.aFindPrev) # Search > Replace Next self.aReplaceNext = self.srcMenu.addAction(self.tr("Replace Next")) self.aReplaceNext.setShortcut("Ctrl+Shift+1") - self.aReplaceNext.triggered.connect(lambda: self.mainGui.docEditor.replaceNext()) + self.aReplaceNext.triggered.connect(qtLambda(self.mainGui.docEditor.replaceNext)) self.mainGui.addAction(self.aReplaceNext) # Search > Separator @@ -971,7 +970,7 @@ def _buildToolsMenu(self) -> None: # Tools > Re-Run Spell Check self.aReRunSpell = self.toolsMenu.addAction(self.tr("Re-Run Spell Check")) self.aReRunSpell.setShortcut("F7") - self.aReRunSpell.triggered.connect(lambda: self.mainGui.docEditor.spellCheckDocument()) + self.aReRunSpell.triggered.connect(qtLambda(self.mainGui.docEditor.spellCheckDocument)) self.mainGui.addAction(self.aReRunSpell) # Tools > Project Word List @@ -989,14 +988,14 @@ def _buildToolsMenu(self) -> None: # Tools > Rebuild Index self.aRebuildIndex = self.toolsMenu.addAction(self.tr("Rebuild Index")) self.aRebuildIndex.setShortcut("F9") - self.aRebuildIndex.triggered.connect(lambda: self.mainGui.rebuildIndex()) + self.aRebuildIndex.triggered.connect(qtLambda(self.mainGui.rebuildIndex)) # Tools > Separator self.toolsMenu.addSeparator() # Tools > Backup Project self.aBackupProject = self.toolsMenu.addAction(self.tr("Backup Project")) - self.aBackupProject.triggered.connect(lambda: SHARED.project.backupProject(True)) + self.aBackupProject.triggered.connect(qtLambda(SHARED.project.backupProject, True)) # Tools > Build Manuscript self.aBuildManuscript = self.toolsMenu.addAction(self.tr("Build Manuscript")) @@ -1038,7 +1037,7 @@ def _buildHelpMenu(self) -> None: # Help > User Manual (Online) self.aHelpDocs = self.helpMenu.addAction(self.tr("User Manual (Online)")) self.aHelpDocs.setShortcut("F1") - self.aHelpDocs.triggered.connect(lambda: self._openWebsite(nwConst.URL_DOCS)) + self.aHelpDocs.triggered.connect(qtLambda(self._openWebsite, nwConst.URL_DOCS)) self.mainGui.addAction(self.aHelpDocs) # Help > User Manual (PDF) @@ -1053,14 +1052,14 @@ def _buildHelpMenu(self) -> None: # Document > Report an Issue self.aIssue = self.helpMenu.addAction(self.tr("Report an Issue (GitHub)")) - self.aIssue.triggered.connect(lambda: self._openWebsite(nwConst.URL_REPORT)) + self.aIssue.triggered.connect(qtLambda(self._openWebsite, nwConst.URL_REPORT)) # Document > Ask a Question self.aQuestion = self.helpMenu.addAction(self.tr("Ask a Question (GitHub)")) - self.aQuestion.triggered.connect(lambda: self._openWebsite(nwConst.URL_HELP)) + self.aQuestion.triggered.connect(qtLambda(self._openWebsite, nwConst.URL_HELP)) # Document > Main Website self.aWebsite = self.helpMenu.addAction(self.tr("The novelWriter Website")) - self.aWebsite.triggered.connect(lambda: self._openWebsite(nwConst.URL_WEB)) + self.aWebsite.triggered.connect(qtLambda(self._openWebsite, nwConst.URL_WEB)) return diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 394037172..e29d491d9 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -904,11 +904,6 @@ def closeViewerPanel(self, byUser: bool = True) -> bool: return not self.splitView.isVisible() - def toggleFullScreenMode(self) -> None: - """Toggle full screen mode""" - self.setWindowState(self.windowState() ^ Qt.WindowState.WindowFullScreen) - return - ## # Events ## @@ -924,6 +919,12 @@ def closeEvent(self, event: QCloseEvent) -> None: # Public Slots ## + @pyqtSlot() + def toggleFullScreenMode(self) -> None: + """Toggle full screen mode""" + self.setWindowState(self.windowState() ^ Qt.WindowState.WindowFullScreen) + return + @pyqtSlot() def closeDocEditor(self) -> None: """Close the document editor. This does not hide the editor."""