Added format menu back in, and added a generic wrapping function that can do text formatting and wrap selection in quotes.

This commit is contained in:
Veronica K. B. Olsen
2019-04-23 16:37:48 +02:00
parent bc036b4e2a
commit ffc577c943
7 changed files with 192 additions and 79 deletions
+4
View File
@@ -61,6 +61,7 @@ class Config:
self.textFixedW = True
self.textWidth = 600
self.textMargin = [40, 40]
self.autoSelect = True
self.doReplace = True
self.doReplaceSQuote = True
self.doReplaceDQuote = True
@@ -121,6 +122,8 @@ class Config:
self.textMargin = self.unpackList(
confParser.get(cnfSec,"margins"), 2, self.textMargin
)
if confParser.has_option(cnfSec,"autoselect"):
self.autoSelect = confParser.getboolean(cnfSec,"autoselect")
if confParser.has_option(cnfSec,"autoreplace"):
self.doReplace = confParser.getboolean(cnfSec,"autoreplace")
if confParser.has_option(cnfSec,"repsquotes"):
@@ -166,6 +169,7 @@ class Config:
confParser.set(cnfSec,"fixedwidth", str(self.textFixedW))
confParser.set(cnfSec,"width", str(self.textWidth))
confParser.set(cnfSec,"margins", self.packList(self.textMargin))
confParser.set(cnfSec,"autoselect", str(self.autoSelect))
confParser.set(cnfSec,"autoreplace",str(self.doReplace))
confParser.set(cnfSec,"repsquotes", str(self.doReplaceSQuote))
confParser.set(cnfSec,"repdquotes", str(self.doReplaceDQuote))
+16
View File
@@ -54,3 +54,19 @@ class nwItemAction(Enum):
EMPTY_TRASH = 12
# END Enum nwItemAction
class nwDocAction(Enum):
NONE = 0
UNDO = 1
REDO = 2
CUT = 3
COPY = 4
PASTE = 5
BOLD = 6
ITALIC = 7
U_LINE = 8
S_QUOTE = 9
D_QUOTE = 10
# END Enum nwDocAction
+41 -1
View File
@@ -13,13 +13,15 @@
import logging
import nw
from time import time
from time import time
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QTextCursor
from nw.gui.dochighlight import GuiDocHighlighter
from nw.gui.wordcounter import WordCounter
from nw.enum import nwDocAction
logger = logging.getLogger(__name__)
@@ -106,6 +108,22 @@ class GuiDocEditor(QTextEdit):
self.setViewportMargins(tM,mTB,0,mTB)
return
def docAction(self, theAction):
logger.verbose("Requesting action: %s" % theAction.name)
if theAction == nwDocAction.UNDO: self.undo()
elif theAction == nwDocAction.REDO: self.redo()
elif theAction == nwDocAction.CUT: self.cut()
elif theAction == nwDocAction.COPY: self.copy()
elif theAction == nwDocAction.PASTE: self.paste()
elif theAction == nwDocAction.BOLD: self._wrapSelection("**","**")
elif theAction == nwDocAction.ITALIC: self._wrapSelection("_","_")
elif theAction == nwDocAction.U_LINE: self._wrapSelection("__","__")
elif theAction == nwDocAction.S_QUOTE: self._wrapSelection(self.typSQOpen,self.typSQClose)
elif theAction == nwDocAction.D_QUOTE: self._wrapSelection(self.typDQOpen,self.typDQClose)
else:
logger.error("Unknown or unsupported document action %s" % str(theAction))
return
##
# Document Events and Maintenance
##
@@ -217,4 +235,26 @@ class GuiDocEditor(QTextEdit):
return
def _wrapSelection(self, tBefore, tAfter):
"""Wraps the selected text in whatever is in tBefore and tAfter. If there is no selection, the autoSelect setting decides
the action. AutoSelect will select the word under the cursor before wrapping it. If this feature is disabled, nothing is
done.
"""
theCursor = self.textCursor()
if self.mainConf.autoSelect and not theCursor.hasSelection():
theCursor.select(QTextCursor.WordUnderCursor)
if theCursor.hasSelection():
posS = theCursor.selectionStart()
posE = theCursor.selectionEnd()
theCursor.clearSelection()
theCursor.beginEditBlock()
theCursor.setPosition(posE)
theCursor.insertText(tAfter)
theCursor.setPosition(posS)
theCursor.insertText(tBefore)
theCursor.endEditBlock()
else:
logger.warning("No selection made, nothing to do")
return
# END Class GuiDocEditor
+15 -10
View File
@@ -27,12 +27,14 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.mainConf = nw.CONFIG
self.theDoc = theDoc
self.colHead = ( 0,155,200,255)
self.colEmph = (200,120, 0,255)
self.colDial = (184,200, 0,255)
self.colComm = (120,120,120,255)
self.colKey = (200, 0, 0,255)
self.colVal = (184,200, 0,255)
self.colHead = ( 0,155,200,255)
self.colEmph = (200,120, 0,255)
self.colDialN = (48, 200, 0,255)
self.colDialD = (184,200, 0,255)
self.colDialS = (136,200, 0,255)
self.colComm = (120,120,120,255)
self.colKey = (200, 0, 0,255)
self.colVal = (184,200, 0,255)
self.hStyles = {
"header1" : self._makeFormat(self.colHead,"bold",20),
@@ -43,7 +45,9 @@ class GuiDocHighlighter(QSyntaxHighlighter):
"italic" : self._makeFormat(self.colEmph,"italic"),
"strike" : self._makeFormat(self.colEmph,"strike"),
"underline" : self._makeFormat(self.colEmph,"underline"),
"dialogue" : self._makeFormat(self.colDial),
"dialogue1" : self._makeFormat(self.colDialN),
"dialogue2" : self._makeFormat(self.colDialD),
"dialogue3" : self._makeFormat(self.colDialS),
"hidden" : self._makeFormat(self.colComm),
"keyword" : self._makeFormat(self.colKey),
"value" : self._makeFormat(self.colVal),
@@ -56,18 +60,19 @@ class GuiDocHighlighter(QSyntaxHighlighter):
(r"^#{4}[^#].*[^\n]", 0, self.hStyles["header4"]),
(r"(?<![\w|\\])([\*]{2})(?!\s)(?m:(.+?))(?<![\s|\\])(\1)(?!\w)", 2, self.hStyles["bold"]),
(r"(?<![\w|_|\\])([_])(?!\s|\1)(?m:(.+?))(?<![\s|\\])(\1)(?!\w)", 2, self.hStyles["italic"]),
(r"(?<![\w|\\])([_]{2})(?!\s)(?m:(.+?))(?<![\s|\\])(\1)(?!\w)", 2, self.hStyles["underline"]),
(r"^(@.+?)\s*:\s*(.+?)$", 1, self.hStyles["keyword"]),
(r"^(@.+?)\s*:\s*(.+?)$", 2, self.hStyles["value"]),
(r"^%.*$", 0, self.hStyles["hidden"]),
]
self.hRules.append(
("{:s}(.+?){:s}".format('"','"'),0,self.hStyles["dialogue"])
("{:s}(.+?){:s}".format('"','"'),0,self.hStyles["dialogue1"])
)
self.hRules.append(
("{:s}(.+?){:s}".format(*self.mainConf.fmtDoubleQuotes),0,self.hStyles["dialogue"])
("{:s}(.+?){:s}".format(*self.mainConf.fmtDoubleQuotes),0,self.hStyles["dialogue2"])
)
self.hRules.append(
("{:s}(.+?){:s}".format(*self.mainConf.fmtSingleQuotes),0,self.hStyles["dialogue"])
("{:s}(.+?){:s}".format(*self.mainConf.fmtSingleQuotes),0,self.hStyles["dialogue3"])
)
# Build a QRegExp for each pattern
+112 -64
View File
@@ -18,7 +18,6 @@ from PyQt5.QtWidgets import qApp, QWidget, QMainWindow, QVBoxLayout, QFrame
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon
from nw.enum import nwItemType
from nw.gui.doctree import GuiDocTree
from nw.gui.doctreectx import GuiDocTreeCtx
from nw.gui.doceditor import GuiDocEditor
@@ -26,6 +25,7 @@ from nw.gui.projecteditor import GuiProjectEditor
from nw.gui.statusbar import GuiMainStatus
from nw.project.project import NWProject
from nw.project.document import NWDoc
from nw.enum import nwItemType, nwDocAction
logger = logging.getLogger(__name__)
@@ -261,67 +261,67 @@ class GuiMain(QMainWindow):
fileMenu = menuBar.addMenu("&File")
# File > New Project
menuNewProject = QAction(QIcon.fromTheme("folder-new"), "New Project", menuBar)
menuNewProject.setStatusTip("Create New Project")
menuNewProject.triggered.connect(self.newProject)
fileMenu.addAction(menuNewProject)
menuItem = QAction(QIcon.fromTheme("folder-new"), "New Project", menuBar)
menuItem.setStatusTip("Create New Project")
menuItem.triggered.connect(self.newProject)
fileMenu.addAction(menuItem)
# File > Open Project
menuOpenProject = QAction(QIcon.fromTheme("folder-open"), "Open Project", menuBar)
menuOpenProject.setStatusTip("Open Project")
menuOpenProject.triggered.connect(self.openProject)
fileMenu.addAction(menuOpenProject)
menuItem = QAction(QIcon.fromTheme("folder-open"), "Open Project", menuBar)
menuItem.setStatusTip("Open Project")
menuItem.triggered.connect(self.openProject)
fileMenu.addAction(menuItem)
# File > Save Project
menuSaveProject = QAction(QIcon.fromTheme("document-save"), "Save Project", menuBar)
menuSaveProject.setStatusTip("Save Project")
menuSaveProject.triggered.connect(self.saveProject)
fileMenu.addAction(menuSaveProject)
menuItem = QAction(QIcon.fromTheme("document-save"), "Save Project", menuBar)
menuItem.setStatusTip("Save Project")
menuItem.triggered.connect(self.saveProject)
fileMenu.addAction(menuItem)
# File > Recent Project
recentMenu = fileMenu.addMenu(QIcon.fromTheme("document-open-recent"),"Recent Projects")
itemCount = 0
for recentProject in self.mainConf.recentList:
if recentProject == "": continue
menuRecentProject = QAction(QIcon.fromTheme("folder-open"), "%d: %s" % (itemCount,recentProject), fileMenu)
menuRecentProject.triggered.connect(self.openRecentProject, itemCount)
recentMenu.addAction(menuRecentProject)
menuItem = QAction(QIcon.fromTheme("folder-open"), "%d: %s" % (itemCount,recentProject), fileMenu)
menuItem.triggered.connect(self.openRecentProject, itemCount)
recentMenu.addAction(menuItem)
itemCount += 1
# File > Separator
fileMenu.addSeparator()
# File > Project Settings
menuProjectSettings = QAction(QIcon.fromTheme("document-properties"), "Project Settings", menuBar)
menuProjectSettings.setStatusTip("Project Settings")
menuProjectSettings.triggered.connect(self.editProject)
fileMenu.addAction(menuProjectSettings)
menuItem = QAction(QIcon.fromTheme("document-properties"), "Project Settings", menuBar)
menuItem.setStatusTip("Project Settings")
menuItem.triggered.connect(self.editProject)
fileMenu.addAction(menuItem)
# File > Separator
fileMenu.addSeparator()
# File > New
menuNew = QAction(QIcon.fromTheme("document-new"), "&New", menuBar)
menuNew.setShortcut("Ctrl+N")
menuNew.setStatusTip("Create new document")
fileMenu.addAction(menuNew)
menuItem = QAction(QIcon.fromTheme("document-new"), "&New", menuBar)
menuItem.setStatusTip("Create new document")
menuItem.setShortcut("Ctrl+N")
fileMenu.addAction(menuItem)
# File > Save
menuSave = QAction(QIcon.fromTheme("document-save"), "&Save", menuBar)
menuSave.setShortcut("Ctrl+S")
menuSave.setStatusTip("Save document")
menuSave.triggered.connect(self.saveDocument)
fileMenu.addAction(menuSave)
menuItem = QAction(QIcon.fromTheme("document-save"), "&Save", menuBar)
menuItem.setStatusTip("Save document")
menuItem.setShortcut("Ctrl+S")
menuItem.triggered.connect(self.saveDocument)
fileMenu.addAction(menuItem)
# File > Separator
fileMenu.addSeparator()
# File > Exit
menuExit = QAction(QIcon.fromTheme("application-exit"), "Exit", menuBar)
menuExit.setShortcut("Ctrl+Q")
menuExit.setStatusTip("Exit %s" % nw.__package__)
menuExit.triggered.connect(self._menuExit)
fileMenu.addAction(menuExit)
menuItem = QAction(QIcon.fromTheme("application-exit"), "Exit", menuBar)
menuItem.setStatusTip("Exit %s" % nw.__package__)
menuItem.setShortcut("Ctrl+Q")
menuItem.triggered.connect(self._menuExit)
fileMenu.addAction(menuItem)
############################################################################################
@@ -329,45 +329,93 @@ class GuiMain(QMainWindow):
editMenu = menuBar.addMenu("&Edit")
# Edit > Undo
menuUndo = QAction(QIcon.fromTheme("edit-undo"), "Undo", menuBar)
menuUndo.setShortcut("Ctrl+Z")
menuUndo.setStatusTip("Undo Last Change")
editMenu.addAction(menuUndo)
menuItem = QAction(QIcon.fromTheme("edit-undo"), "Undo", menuBar)
menuItem.setStatusTip("Undo Last Change")
menuItem.setShortcut("Ctrl+Z")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.UNDO))
editMenu.addAction(menuItem)
# Edit > Redo
menuRedo = QAction(QIcon.fromTheme("edit-redo"), "Redo", menuBar)
menuRedo.setShortcut("Ctrl+Y")
menuRedo.setStatusTip("Redo Last Change")
editMenu.addAction(menuRedo)
menuItem = QAction(QIcon.fromTheme("edit-redo"), "Redo", menuBar)
menuItem.setStatusTip("Redo Last Change")
menuItem.setShortcut("Ctrl+Y")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.REDO))
editMenu.addAction(menuItem)
# Edit > Separator
editMenu.addSeparator()
# Edit > Cut
menuCut = QAction(QIcon.fromTheme("edit-cut"), "Cut", menuBar)
menuCut.setShortcut("Ctrl+X")
menuCut.setStatusTip("Cut Selected Text")
editMenu.addAction(menuCut)
menuItem = QAction(QIcon.fromTheme("edit-cut"), "Cut", menuBar)
menuItem.setStatusTip("Cut Selected Text")
menuItem.setShortcut("Ctrl+X")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.CUT))
editMenu.addAction(menuItem)
# Edit > Copy
menuCopy = QAction(QIcon.fromTheme("edit-copy"), "Copy", menuBar)
menuCopy.setShortcut("Ctrl+C")
menuCopy.setStatusTip("Copy Selected Text")
editMenu.addAction(menuCopy)
menuItem = QAction(QIcon.fromTheme("edit-copy"), "Copy", menuBar)
menuItem.setStatusTip("Copy Selected Text")
menuItem.setShortcut("Ctrl+C")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.COPY))
editMenu.addAction(menuItem)
# Edit > Paste
menuPaste = QAction(QIcon.fromTheme("edit-paste"), "Paste", menuBar)
menuPaste.setShortcut("Ctrl+V")
menuPaste.setStatusTip("Paste Text from Clipboard")
editMenu.addAction(menuPaste)
menuItem = QAction(QIcon.fromTheme("edit-paste"), "Paste", menuBar)
menuItem.setStatusTip("Paste Text from Clipboard")
menuItem.setShortcut("Ctrl+V")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.PASTE))
editMenu.addAction(menuItem)
# Edit > Separator
editMenu.addSeparator()
# Edit > Settings
menuSettings = QAction(QIcon.fromTheme("applications-system"), "Program Setting", menuBar)
menuSettings.setStatusTip("Change %s Settings" % nw.__package__)
editMenu.addAction(menuSettings)
menuItem = QAction(QIcon.fromTheme("applications-system"), "Program Setting", menuBar)
menuItem.setStatusTip("Change %s Settings" % nw.__package__)
editMenu.addAction(menuItem)
############################################################################################
# Format
fmtMenu = menuBar.addMenu("&Format")
# Format > Bold Text
menuItem = QAction(QIcon.fromTheme("format-text-bold"), "Bold Text", menuBar)
menuItem.setStatusTip("Make Selected Text Bold")
menuItem.setShortcut("Ctrl+B")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.BOLD))
fmtMenu.addAction(menuItem)
# Format > Italic Text
menuItem = QAction(QIcon.fromTheme("format-text-italic"), "Italic Text", menuBar)
menuItem.setStatusTip("Make Selected Text Italic")
menuItem.setShortcut("Ctrl+I")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.ITALIC))
fmtMenu.addAction(menuItem)
# Format > Underline Text
menuItem = QAction(QIcon.fromTheme("format-text-underline"), "Underline Text", menuBar)
menuItem.setStatusTip("Underline Selected Text")
menuItem.setShortcut("Ctrl+U")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.U_LINE))
fmtMenu.addAction(menuItem)
# Edit > Separator
fmtMenu.addSeparator()
# Format > Double Quotes
menuItem = QAction(QIcon.fromTheme("insert-text"), "Wrap Double Quotes", menuBar)
menuItem.setStatusTip("Wrap Selected Text in Double Quotes")
menuItem.setShortcut("Ctrl+D")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.D_QUOTE))
fmtMenu.addAction(menuItem)
# Format > Single Quotes
menuItem = QAction(QIcon.fromTheme("insert-text"), "Wrap Single Quotes", menuBar)
menuItem.setStatusTip("Wrap Selected Text in Single Quotes")
menuItem.setShortcut("Ctrl+Shift+D")
menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.S_QUOTE))
fmtMenu.addAction(menuItem)
############################################################################################
@@ -375,15 +423,15 @@ class GuiMain(QMainWindow):
helpMenu = menuBar.addMenu("&Help")
# Help > About
menuAbout = QAction(QIcon.fromTheme("help-about"), "About %s" % nw.__package__, menuBar)
menuAbout.setStatusTip("About %s" % nw.__package__)
menuAbout.triggered.connect(self._showAbout)
helpMenu.addAction(menuAbout)
menuItem = QAction(QIcon.fromTheme("help-about"), "About %s" % nw.__package__, menuBar)
menuItem.setStatusTip("About %s" % nw.__package__)
menuItem.triggered.connect(self._showAbout)
helpMenu.addAction(menuItem)
# Help > About Qt5
menuAboutQt5 = QAction(QIcon.fromTheme("help-about"), "About Qt5", menuBar)
menuAboutQt5.setStatusTip("About Qt5")
helpMenu.addAction(menuAboutQt5)
menuItem = QAction(QIcon.fromTheme("help-about"), "About Qt5", menuBar)
menuItem.setStatusTip("About Qt5")
helpMenu.addAction(menuItem)
if not self.mainConf.debugGUI:
return
@@ -6,7 +6,7 @@
#### Header 4
**Lorem** ipsum dolor sit amet, consectetur "adipiscing" elit. Proin vitae nisi augue. Sed elementum lacus risus, eu lobortis ipsum malesuada rutrum. Nam egestas elit id commodo porta. **Ut eget lacinia ipsum, non interdum mi.** Sed tincidunt commodo metus, at faucibus nisi finibus eget. In malesuada egestas nulla et tempor. _Nulla eu sem_ vel mi sollicitudin cursus. Nullam ultricies ex eu dui scelerisque, ut venenatis turpis ultricies.
**Lorem** ipsum dolor sit amet, consectetur "adipiscing" elit. Proin vitae nisi augue. Sed elementum lacus risus, eu lobortis ipsum malesuada rutrum. Nam egestas elit id commodo porta. **Ut eget lacinia ipsum, non interdum mi.** Sed tincidunt commodo metus, at faucibus nisi finibus eget. In malesuada egestas nulla et tempor. _Nulla eu sem_ vel mi sollicitudin cursus. Nullam ultricies ex eu dui scelerisque, ut venenatis turpis ultricies.
Nunc in ex molestie, __efficitur__ diam ~~semper~~, pellentesque eros. Morbi vel lacus quis turpis sagittis iaculis. Sed rhoncus tortor et finibus lobortis. Suspendisse non ultrices odio, at venenatis mi. Sed congue congue tortor, et egestas neque malesuada ac. Nulla facilisi. Maecenas finibus elementum vestibulum. Nam id rhoncus mauris, vel “ullamcorper” «neque».
+3 -3
View File
@@ -1,12 +1,12 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.0.1" fileVersion="1.0" timeStamp="2019-04-22 16:39:21">
<novelWriterXML appVersion="0.0.1" fileVersion="1.0" timeStamp="2019-04-23 16:16:49">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
</project>
<content count="9">
<content count="8">
<item handle="7031beac91f75" order="0" parent="None">
<name>Novel</name>
<type>ROOT</type>
@@ -30,7 +30,7 @@
<depth>2</depth>
<children>False</children>
<expanded>False</expanded>
<charCount>2573</charCount>
<charCount>2575</charCount>
<wordCount>377</wordCount>
<paraCount>5</paraCount>
</item>