Merge pull request #137 from vkbo/zen_mode

Zen mode
This commit is contained in:
Veronica K. Berglyd Olsen
2019-11-09 15:00:51 +01:00
committed by GitHub
8 changed files with 168 additions and 103 deletions
+2
View File
@@ -106,7 +106,9 @@ These are as following:
":kbd:`F3`", "Find next occurrence of word in current document. (Same as :kbd:`Ctrl-G`)"
":kbd:`F5`", "Export project dialog."
":kbd:`F7`", "Re-run spell checker."
":kbd:`F8`", "Activate Zen Mode, hiding project tree and view panel."
":kbd:`F9`", "Re-build project indices."
":kbd:`F11`", "Activate full screen mode."
":kbd:`Shift-Enter`", "Insert a hard line break at the cursor position."
":kbd:`Shift-F3`", "Find previous occurrence of word in current document. (Same as :kbd:`Ctrl-Shift-G`"
":kbd:`Shift-Space`", "Insert a non-breaking space at the cursor position."
+14 -4
View File
@@ -69,6 +69,7 @@ class Config:
self.treeColWidth = [120, 30, 50]
self.mainPanePos = [300, 800]
self.docPanePos = [400, 400]
self.isFullScreen = False
## Project
self.autoSaveProj = 60
@@ -81,6 +82,7 @@ class Config:
self.textWidth = 600
self.textMargin = 40
self.tabWidth = 40
self.zenWidth = 800
self.doJustify = False
self.autoSelect = True
self.doReplace = True
@@ -245,6 +247,9 @@ class Config:
self.docPanePos = self._parseLine(
cnfParse, cnfSec, "docpane", self.CNF_LIST, self.docPanePos
)
self.isFullScreen = self._parseLine(
cnfParse, cnfSec, "fullscreen", self.CNF_BOOL, self.isFullScreen
)
## Project
cnfSec = "Project"
@@ -275,6 +280,9 @@ class Config:
self.tabWidth = self._parseLine(
cnfParse, cnfSec, "tabwidth", self.CNF_INT, self.tabWidth
)
self.zenWidth = self._parseLine(
cnfParse, cnfSec, "zenwidth", self.CNF_INT, self.zenWidth
)
self.doJustify = self._parseLine(
cnfParse, cnfSec, "justify", self.CNF_BOOL, self.doJustify
)
@@ -369,10 +377,11 @@ class Config:
## Sizes
cnfSec = "Sizes"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec,"geometry", self._packList(self.winGeometry))
cnfParse.set(cnfSec,"treecols", self._packList(self.treeColWidth))
cnfParse.set(cnfSec,"mainpane", self._packList(self.mainPanePos))
cnfParse.set(cnfSec,"docpane", self._packList(self.docPanePos))
cnfParse.set(cnfSec,"geometry", self._packList(self.winGeometry))
cnfParse.set(cnfSec,"treecols", self._packList(self.treeColWidth))
cnfParse.set(cnfSec,"mainpane", self._packList(self.mainPanePos))
cnfParse.set(cnfSec,"docpane", self._packList(self.docPanePos))
cnfParse.set(cnfSec,"fullscreen", str(self.isFullScreen))
## Project
cnfSec = "Project"
@@ -389,6 +398,7 @@ class Config:
cnfParse.set(cnfSec,"width", str(self.textWidth))
cnfParse.set(cnfSec,"margin", str(self.textMargin))
cnfParse.set(cnfSec,"tabwidth", str(self.tabWidth))
cnfParse.set(cnfSec,"zenwidth", str(self.zenWidth))
cnfParse.set(cnfSec,"justify", str(self.doJustify))
cnfParse.set(cnfSec,"autoselect", str(self.autoSelect))
cnfParse.set(cnfSec,"autoreplace", str(self.doReplace))
+35 -43
View File
@@ -373,10 +373,8 @@ class GuiConfigEditEditor(QWidget):
self.textFlowFixed = QCheckBox("Max text width",self)
self.textFlowFixed.setToolTip("Maximum width of the text.")
if self.mainConf.textFixedW:
self.textFlowFixed.setCheckState(Qt.Checked)
else:
self.textFlowFixed.setCheckState(Qt.Unchecked)
self.textFlowFixed.setChecked(self.mainConf.textFixedW)
self.textFlowMax = QSpinBox(self)
self.textFlowMax.setMinimum(300)
self.textFlowMax.setMaximum(10000)
@@ -385,10 +383,7 @@ class GuiConfigEditEditor(QWidget):
self.textFlowJustify = QCheckBox("Justify text",self)
self.textFlowJustify.setToolTip("Justify text in main document editor.")
if self.mainConf.doJustify:
self.textFlowJustify.setCheckState(Qt.Checked)
else:
self.textFlowJustify.setCheckState(Qt.Unchecked)
self.textFlowJustify.setChecked(self.mainConf.doJustify)
self.textFlowForm.addWidget(self.textFlowFixed, 0, 0)
self.textFlowForm.addWidget(self.textFlowMax, 0, 1)
@@ -422,6 +417,22 @@ class GuiConfigEditEditor(QWidget):
self.textMarginForm.addWidget(QLabel("px"), 2, 2)
self.textMarginForm.setColumnStretch(4, 1)
# Zen Mode
self.zenMode = QGroupBox("Zen Mode", self)
self.zenModeForm = QGridLayout(self)
self.zenMode.setLayout(self.zenModeForm)
self.zenDocWidth = QSpinBox(self)
self.zenDocWidth.setMinimum(300)
self.zenDocWidth.setMaximum(10000)
self.zenDocWidth.setSingleStep(10)
self.zenDocWidth.setValue(self.mainConf.zenWidth)
self.zenModeForm.addWidget(QLabel("Document width"), 0, 0)
self.zenModeForm.addWidget(self.zenDocWidth, 0, 1)
self.zenModeForm.addWidget(QLabel("px"), 0, 2)
self.zenModeForm.setColumnStretch(3, 1)
# Automatic Features
self.autoReplace = QGroupBox("Automatic Features", self)
self.autoReplaceForm = QGridLayout(self)
@@ -429,47 +440,29 @@ class GuiConfigEditEditor(QWidget):
self.autoSelect = QCheckBox(self)
self.autoSelect.setToolTip("Auto-select word under cursor when applying formatting.")
if self.mainConf.autoSelect:
self.autoSelect.setCheckState(Qt.Checked)
else:
self.autoSelect.setCheckState(Qt.Unchecked)
self.autoSelect.setChecked(self.mainConf.autoSelect)
self.autoReplaceMain = QCheckBox(self)
self.autoReplaceMain.setToolTip("Auto-replace text as you type.")
if self.mainConf.doReplace:
self.autoReplaceMain.setCheckState(Qt.Checked)
else:
self.autoReplaceMain.setCheckState(Qt.Unchecked)
self.autoReplaceMain.setChecked(self.mainConf.doReplace)
self.autoReplaceSQ = QCheckBox(self)
self.autoReplaceSQ.setToolTip("Auto-replace single quotes.")
if self.mainConf.doReplaceSQuote:
self.autoReplaceSQ.setCheckState(Qt.Checked)
else:
self.autoReplaceSQ.setCheckState(Qt.Unchecked)
self.autoReplaceSQ.setChecked(self.mainConf.doReplaceSQuote)
self.autoReplaceDQ = QCheckBox(self)
self.autoReplaceDQ.setToolTip("Auto-replace double quotes.")
if self.mainConf.doReplaceDQuote:
self.autoReplaceDQ.setCheckState(Qt.Checked)
else:
self.autoReplaceDQ.setCheckState(Qt.Unchecked)
self.autoReplaceDQ.setChecked(self.mainConf.doReplaceDQuote)
self.autoReplaceDash = QCheckBox(self)
self.autoReplaceDash.setToolTip(
"Auto-replace double and triple hyphens with short and long dash."
)
if self.mainConf.doReplaceDash:
self.autoReplaceDash.setCheckState(Qt.Checked)
else:
self.autoReplaceDash.setCheckState(Qt.Unchecked)
self.autoReplaceDash.setChecked(self.mainConf.doReplaceDash)
self.autoReplaceDots = QCheckBox(self)
self.autoReplaceDots.setToolTip("Auto-replace three dots with ellipsis.")
if self.mainConf.doReplaceDots:
self.autoReplaceDots.setCheckState(Qt.Checked)
else:
self.autoReplaceDots.setCheckState(Qt.Unchecked)
self.autoReplaceDots.setChecked(self.mainConf.doReplaceDots)
self.autoReplaceForm.addWidget(QLabel("Auto-select text"), 0, 0)
self.autoReplaceForm.addWidget(self.autoSelect, 0, 1)
@@ -534,16 +527,10 @@ class GuiConfigEditEditor(QWidget):
self.showGuides.setLayout(self.showGuidesForm)
self.showTabsNSpaces = QCheckBox("Show tabs and spaces",self)
if self.mainConf.showTabsNSpaces:
self.showTabsNSpaces.setCheckState(Qt.Checked)
else:
self.showTabsNSpaces.setCheckState(Qt.Unchecked)
self.showTabsNSpaces.setChecked(self.mainConf.showTabsNSpaces)
self.showLineEndings = QCheckBox("Show line endings",self)
if self.mainConf.showTabsNSpaces:
self.showLineEndings.setCheckState(Qt.Checked)
else:
self.showLineEndings.setCheckState(Qt.Unchecked)
self.showLineEndings.setChecked(self.mainConf.showLineEndings)
self.showGuidesForm.addWidget(self.showTabsNSpaces, 0, 0)
self.showGuidesForm.addWidget(self.showLineEndings, 1, 0)
@@ -552,9 +539,10 @@ class GuiConfigEditEditor(QWidget):
self.outerBox.addWidget(self.textStyle, 0, 0, 1, 2)
self.outerBox.addWidget(self.textFlow, 1, 0)
self.outerBox.addWidget(self.textMargin, 1, 1)
self.outerBox.addWidget(self.quoteStyle, 2, 0)
self.outerBox.addWidget(self.autoReplace, 2, 1, 2, 1)
self.outerBox.addWidget(self.showGuides, 3, 0)
self.outerBox.addWidget(self.zenMode, 2, 0)
self.outerBox.addWidget(self.autoReplace, 3, 0, 2, 1)
self.outerBox.addWidget(self.quoteStyle, 2, 1, 2, 1)
self.outerBox.addWidget(self.showGuides, 4, 1)
self.outerBox.setColumnStretch(2, 1)
self.setLayout(self.outerBox)
@@ -578,6 +566,10 @@ class GuiConfigEditEditor(QWidget):
self.mainConf.textFixedW = textFixedW
self.mainConf.doJustify = doJustify
zenWidth = self.zenDocWidth.value()
self.mainConf.zenWidth = zenWidth
textMargin = self.textMarginDoc.value()
tabWidth = self.textMarginTab.value()
+39 -24
View File
@@ -21,7 +21,7 @@ from PyQt5.QtWidgets import (
)
from PyQt5.QtGui import (
QTextCursor, QTextOption, QIcon, QKeySequence, QFont, QColor,
QPalette, QTextDocument,
QPalette, QTextDocument
)
from nw.project import NWDoc
@@ -185,7 +185,7 @@ class GuiDocEditor(QTextEdit):
tHandle = self.theHandle
self.clearEditor()
self.loadText(tHandle)
self.changeWidth()
self.updateDocMargins()
else:
self.clearEditor()
@@ -242,6 +242,35 @@ class GuiDocEditor(QTextEdit):
return True
def updateDocMargins(self):
"""Automatically adjust the margins so the text is centred, but
only if Config.textFixedW is set to True.
"""
if self.mainConf.textFixedW or self.theParent.isZenMode:
vBar = self.verticalScrollBar()
if vBar.isVisible():
sW = vBar.width()
else:
sW = 0
if self.theParent.isZenMode:
tW = self.mainConf.zenWidth
else:
tW = self.mainConf.textWidth
wW = self.width()
tM = int((wW - sW - tW)/2)
if tM < self.mainConf.textMargin:
tM = self.mainConf.textMargin
else:
tM = self.mainConf.textMargin
docFormat = self.qDocument.rootFrame().frameFormat()
docFormat.setLeftMargin(tM)
docFormat.setRightMargin(tM)
self.qDocument.rootFrame().setFrameFormat(docFormat)
return
##
# Setters and Getters
##
@@ -298,28 +327,6 @@ class GuiDocEditor(QTextEdit):
# General Class Methods
##
def changeWidth(self):
"""Automatically adjust the margins so the text is centred, but
only if Config.textFixedW is set to True.
"""
if self.mainConf.textFixedW:
vBar = self.verticalScrollBar()
if vBar.isVisible():
sW = vBar.width()
else:
sW = 0
tW = self.mainConf.textWidth
wW = self.width()
tM = int((wW - sW - tW)/2)
if tM < self.mainConf.textMargin:
tM = self.mainConf.textMargin
docFormat = self.qDocument.rootFrame().frameFormat()
docFormat.setLeftMargin(tM)
docFormat.setRightMargin(tM)
self.qDocument.rootFrame().setFrameFormat(docFormat)
return
def docAction(self, theAction):
logger.verbose("Requesting action: %s" % theAction.name)
if not self.theParent.hasProject:
@@ -425,6 +432,14 @@ class GuiDocEditor(QTextEdit):
QTextEdit.mouseReleaseEvent(self, mEvent)
return
def resizeEvent(self, theEvent):
"""If the text editor is resize, we must make sure the document
has its margins adjusted according to user preferences.
"""
QTextEdit.resizeEvent(self, theEvent)
self.updateDocMargins()
return
##
# Internal Functions
##
+1 -1
View File
@@ -46,7 +46,7 @@ class GuiIcons:
DECO_MAP = {
"export" : "export.svg",
"settings" : "settings.svg",
"settings" : "gear.svg",
}
def __init__(self, theParent):
+19
View File
@@ -410,6 +410,25 @@ class GuiMainMenu(QMenuBar):
# View > Separator
self.viewMenu.addSeparator()
# View > Toggle Distraction Free Mode
menuItem = QAction("Zen Mode", self)
menuItem.setStatusTip("Toggles distraction free mode, only showing text editor")
menuItem.setShortcut("F8")
menuItem.setCheckable(True)
menuItem.setChecked(self.theParent.isZenMode)
menuItem.toggled.connect(self.theParent.toggleZenMode)
self.viewMenu.addAction(menuItem)
# View > Toggle Full Screen
menuItem = QAction("Full Screen Mode", self)
menuItem.setStatusTip("Maximises the main window")
menuItem.setShortcut("F11")
menuItem.triggered.connect(self.theParent.toggleFullScreenMode)
self.viewMenu.addAction(menuItem)
# View > Separator
self.viewMenu.addSeparator()
# View > Project Timeline
menuItem = QAction("Show Project Timeline", self)
menuItem.setStatusTip("Open the project timeline window")
+55 -30
View File
@@ -47,6 +47,7 @@ class GuiMain(QMainWindow):
self.theProject = NWProject(self)
self.theIndex = NWIndex(self.theProject, self)
self.hasProject = False
self.isZenMode = False
logger.info("OS: %s" % (
self.mainConf.osType)
@@ -107,14 +108,12 @@ class GuiMain(QMainWindow):
self.splitView = QSplitter(Qt.Horizontal)
self.splitView.addWidget(self.editPane)
self.splitView.addWidget(self.viewPane)
self.splitView.splitterMoved.connect(self._splitViewMove)
self.splitMain = QSplitter(Qt.Horizontal)
self.splitMain.setContentsMargins(4,4,4,4)
self.splitMain.addWidget(self.treePane)
self.splitMain.addWidget(self.splitView)
self.splitMain.setSizes(self.mainConf.mainPanePos)
self.splitMain.splitterMoved.connect(self._splitMainMove)
self.setCentralWidget(self.splitMain)
@@ -174,6 +173,9 @@ class GuiMain(QMainWindow):
self.asDocTimer.start()
self.statusBar.clearStatus()
if self.mainConf.isFullScreen:
self.toggleFullScreenMode()
logger.debug("GUI initialisation complete")
return
@@ -359,7 +361,6 @@ class GuiMain(QMainWindow):
self.closeDocument()
if self.docEditor.loadText(tHandle):
self.docEditor.setFocus()
self.docEditor.changeWidth()
self.theProject.setLastEdited(tHandle)
else:
return False
@@ -391,7 +392,6 @@ class GuiMain(QMainWindow):
vPos[0] = int(bPos[1]/2)
vPos[1] = bPos[1]-vPos[0]
self.splitView.setSizes(vPos)
self.docEditor.changeWidth()
return True
@@ -667,10 +667,12 @@ class GuiMain(QMainWindow):
logger.info("Exiting %s" % nw.__package__)
self.closeProject(True)
self.mainConf.setWinSize(self.width(), self.height())
self.mainConf.setTreeColWidths(self.treeView.getColumnSizes())
self.mainConf.setMainPanePos(self.splitMain.sizes())
self.mainConf.setDocPanePos(self.splitView.sizes())
if not self.mainConf.isFullScreen:
self.mainConf.setWinSize(self.width(), self.height())
if not self.isZenMode:
self.mainConf.setMainPanePos(self.splitMain.sizes())
self.mainConf.setDocPanePos(self.splitView.sizes())
self.mainConf.saveConfig()
qApp.quit()
@@ -698,9 +700,54 @@ class GuiMain(QMainWindow):
self.viewPane.setVisible(False)
vPos = [bPos[1],0]
self.splitView.setSizes(vPos)
self.docEditor.changeWidth()
return not self.viewPane.isVisible()
def toggleZenMode(self):
"""Main GUI Zen Mode hides tree, view pane and optionally also
statusbar and menu.
"""
if self.docEditor.theHandle is None:
logger.error("No document open, so not activating Zen Mode")
return False
self.isZenMode = not self.isZenMode
if self.isZenMode:
logger.debug("Activating Zen mode")
else:
logger.debug("Deactivating Zen mode")
isVisible = not self.isZenMode
self.treePane.setVisible(isVisible)
self.statusBar.setVisible(isVisible)
if self.viewPane.isVisible():
self.viewPane.setVisible(False)
elif self.docViewer.theHandle is not None:
self.viewPane.setVisible(True)
return True
def toggleFullScreenMode(self):
"""Main GUI full screen mode. The mode is tracked by the flag
in config. This only tracks whether the window has been
maximised using the internal commands, and may not be correct
if the user uses the system window manager. Currently, Qt
doesn't have access to the exact state of the window.
"""
self.setWindowState(self.windowState() ^ Qt.WindowFullScreen)
winState = self.windowState() & Qt.WindowFullScreen == Qt.WindowFullScreen
if winState:
logger.debug("Activated full screen mode")
else:
logger.debug("Deactivated full screen mode")
self.mainConf.isFullScreen = winState
return
##
# Internal Functions
##
@@ -745,14 +792,6 @@ class GuiMain(QMainWindow):
# Events
##
def resizeEvent(self, theEvent):
"""Extend QMainWindow.resizeEvent to signal dependent GUI
elements that its pane may have changed size.
"""
QMainWindow.resizeEvent(self,theEvent)
self.docEditor.changeWidth()
return
def closeEvent(self, theEvent):
if self.closeMain():
theEvent.accept()
@@ -801,18 +840,4 @@ class GuiMain(QMainWindow):
return
return
def _splitMainMove(self, pWidth, pHeight):
"""Alert dependent GUI elements that the main pane splitter has
been moved.
"""
self.docEditor.changeWidth()
return
def _splitViewMove(self, pWidth, pHeight):
"""Alert dependent GUI elements that the edit/view pane splitter
has been moved.
"""
self.docEditor.changeWidth()
return
# END Class GuiMain
+3 -1
View File
@@ -1,5 +1,5 @@
[Main]
timestamp = 2019-11-08 18:43:21
timestamp = 2019-11-09 14:38:32
theme = default
syntax = default_light
guidark = False
@@ -9,6 +9,7 @@ geometry = 1100, 650
treecols = 120, 30, 50
mainpane = 300, 800
docpane = 400, 400
fullscreen = False
[Project]
autosaveproject = 60
@@ -21,6 +22,7 @@ fixedwidth = True
width = 600
margin = 40
tabwidth = 40
zenwidth = 800
justify = False
autoselect = True
autoreplace = True