diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py index 8800834d..820a2a48 100644 --- a/nw/gui/__init__.py +++ b/nw/gui/__init__.py @@ -2,7 +2,7 @@ from nw.gui.about import GuiAbout from nw.gui.build import GuiBuildNovel -from nw.gui.docbars import GuiDocTitleBar, GuiSearchBar +from nw.gui.docbars import GuiSearchBar from nw.gui.doceditor import GuiDocEditor from nw.gui.docmerge import GuiDocMerge from nw.gui.docsplit import GuiDocSplit @@ -23,7 +23,6 @@ from nw.gui.theme import GuiIcons, GuiTheme __all__ = [ "GuiAbout", "GuiBuildNovel", - "GuiDocTitleBar", "GuiSearchBar", "GuiDocEditor", "GuiDocMerge", diff --git a/nw/gui/docbars.py b/nw/gui/docbars.py index fcbc1869..079f989a 100644 --- a/nw/gui/docbars.py +++ b/nw/gui/docbars.py @@ -7,7 +7,6 @@ File History: Created: 2019-09-29 [0.2.1] GuiSearchBar - Created: 2020-04-25 [0.4.5] GuiDocTitleBar This file is a part of novelWriter Copyright 2020, Veronica Berglyd Olsen @@ -167,187 +166,3 @@ class GuiSearchBar(QWidget): return True # END Class GuiSearchBar - -class GuiDocTitleBar(QWidget): - - def __init__(self, theParent, isEditor): - QWidget.__init__(self, theParent) - - logger.debug("Initialising GuiDocTitleBar ...") - - self.mainConf = nw.CONFIG - self.theParent = theParent - self.theProject = theParent.theProject - self.theTheme = theParent.theTheme - self.theHandle = None - self.isEditor = isEditor - - # Make a QPalette that matches the Syntax Theme - self.thePalette = QPalette() - self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack)) - self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText)) - - fPx = int(0.9*self.theTheme.fontPixelSize) - hSp = self.mainConf.pxInt(6) - self.buttonSize = fPx + hSp - - # Main Widget Settings - self.setContentsMargins(2*self.buttonSize, 0, 0, 0) - self.setAutoFillBackground(True) - self.setPalette(self.thePalette) - - # Title Label - self.theTitle = QLabel() - self.theTitle.setText("") - self.theTitle.setIndent(0) - self.theTitle.setMargin(0) - self.theTitle.setContentsMargins(0, 0, 0, 0) - self.theTitle.setAutoFillBackground(True) - self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop) - self.theTitle.setFixedHeight(fPx) - self.theTitle.setFrameShape(QFrame.NoFrame) - self.theTitle.setLineWidth(0) - self.theTitle.setPalette(self.thePalette) - - lblFont = self.theTitle.font() - lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize) - self.theTitle.setFont(lblFont) - - buttonStyle = ( - "QToolButton {{border: none; background: transparent;}} " - "QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}" - ).format(*self.theTheme.colText) - - # Buttons - self.closeButton = QToolButton(self) - self.closeButton.setIcon(self.theTheme.getIcon("close")) - self.closeButton.setContentsMargins(0, 0, 0, 0) - self.closeButton.setIconSize(QSize(fPx, fPx)) - self.closeButton.setFixedSize(fPx, fPx) - self.closeButton.setStyleSheet(buttonStyle) - self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly) - self.closeButton.setVisible(False) - self.closeButton.clicked.connect(self._closeDocument) - - if self.isEditor: - self.minmaxButton = QToolButton(self) - self.minmaxButton.setIcon(self.theTheme.getIcon("maximise")) - self.minmaxButton.setContentsMargins(0, 0, 0, 0) - self.minmaxButton.setIconSize(QSize(fPx, fPx)) - self.minmaxButton.setFixedSize(fPx, fPx) - self.minmaxButton.setStyleSheet(buttonStyle) - self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly) - self.minmaxButton.setVisible(False) - self.minmaxButton.clicked.connect(self._minmaxDocument) - else: - self.refreshButton = QToolButton(self) - self.refreshButton.setIcon(self.theTheme.getIcon("refresh")) - self.refreshButton.setContentsMargins(0, 0, 0, 0) - self.refreshButton.setIconSize(QSize(fPx, fPx)) - self.refreshButton.setFixedSize(fPx, fPx) - self.refreshButton.setStyleSheet(buttonStyle) - self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly) - self.refreshButton.setVisible(False) - self.refreshButton.clicked.connect(self._refreshDocument) - - # Assemble Layout - self.outerBox = QHBoxLayout() - self.outerBox.setSpacing(hSp) - self.outerBox.addWidget(self.theTitle, 1) - if self.isEditor: - self.outerBox.addWidget(self.minmaxButton, 0) - else: - self.outerBox.addWidget(self.refreshButton, 0) - self.outerBox.addWidget(self.closeButton, 0) - self.setLayout(self.outerBox) - - logger.debug("GuiDocTitleBar initialisation complete") - - return - - ## - # Setters - ## - - def setTitleFromHandle(self, tHandle): - """Sets the document title from the handle, or alternatively, - set the whole document path. - """ - self.theTitle.setText("") - self.theHandle = tHandle - if tHandle is None: - self.closeButton.setVisible(False) - if self.isEditor: - self.minmaxButton.setVisible(False) - else: - self.refreshButton.setVisible(False) - return False - - if self.mainConf.showFullPath: - tTitle = [] - tTree = self.theProject.projTree.getItemPath(tHandle) - for aHandle in reversed(tTree): - nwItem = self.theProject.projTree[aHandle] - if nwItem is not None: - tTitle.append(nwItem.itemName) - sSep = " %s " % nwUnicode.U_RSAQUO - self.theTitle.setText(sSep.join(tTitle)) - else: - nwItem = self.theProject.projTree[tHandle] - if nwItem is None: - return False - self.theTitle.setText(nwItem.itemName) - - self.closeButton.setVisible(True) - if self.isEditor: - self.minmaxButton.setVisible(True) - else: - self.refreshButton.setVisible(True) - - return True - - ## - # Slots - ## - - def _closeDocument(self): - """Trigger the close editor/viewer on the main window. - """ - if self.isEditor: - self.theParent.theParent.closeDocEditor() - else: - self.theParent.theParent.closeDocViewer() - return - - def _minmaxDocument(self): - """Switch on or off zen mode. - """ - self.theParent.theParent.toggleZenMode() - if self.theParent.theParent.isZenMode: - self.minmaxButton.setIcon(self.theTheme.getIcon("minimise")) - self.setContentsMargins(self.buttonSize, 0, 0, 0) - self.closeButton.setVisible(False) - else: - self.minmaxButton.setIcon(self.theTheme.getIcon("maximise")) - self.setContentsMargins(2*self.buttonSize, 0, 0, 0) - self.closeButton.setVisible(True) - return - - def _refreshDocument(self): - """Reload the content of the document. - """ - self.theParent.reloadText() - return - - ## - # Events - ## - - def mousePressEvent(self, theEvent): - """Capture a click on the title and ensure that the item is - selected in the project tree. - """ - self.theParent.setSelectedHandle(self.theHandle) - return - -# END Class GuiDocTitleBar diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index fadd6dd5..9089110b 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -8,6 +8,7 @@ File History: Created: 2018-09-29 [0.0.1] GuiDocEditor Created: 2019-04-22 [0.0.1] WordCounter + Created: 2020-04-25 [0.4.5] GuiDocEditHeader This file is a part of novelWriter Copyright 2020, Veronica Berglyd Olsen @@ -31,18 +32,18 @@ import nw from time import time -from PyQt5.QtCore import Qt, QThread, QTimer, pyqtSlot -from PyQt5.QtWidgets import ( - qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox -) +from PyQt5.QtCore import Qt, QSize, QThread, QTimer, pyqtSlot from PyQt5.QtGui import ( QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette, QTextDocument, QCursor ) +from PyQt5.QtWidgets import ( + qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox, QWidget, QLabel, + QToolButton, QHBoxLayout +) from nw.core import NWDoc from nw.gui.dochighlight import GuiDocHighlighter -from nw.gui.docbars import GuiDocTitleBar from nw.core import NWSpellSimple, countWords from nw.constants import nwUnicode, nwDocAction @@ -85,9 +86,7 @@ class GuiDocEditor(QTextEdit): self.qDocument.contentsChange.connect(self._docChange) # Document Title - self.docTitle = GuiDocTitleBar(self, isEditor=True) - self.docTitle.setGeometry(0, 0, self.docTitle.width(), self.docTitle.height()) - self.setViewportMargins(0, self.docTitle.height(), 0, 0) + self.docHeader = GuiDocEditHeader(self) # Syntax self.hLight = GuiDocHighlighter(self.qDocument, self.theParent) @@ -158,7 +157,7 @@ class GuiDocEditor(QTextEdit): self.hasSelection = False self.setDocumentChanged(False) - self.docTitle.setTitleFromHandle(self.theHandle) + self.docHeader.setTitleFromHandle(self.theHandle) return True @@ -270,7 +269,7 @@ class GuiDocEditor(QTextEdit): self.theHandle = tHandle self.setReadOnly(False) - self.docTitle.setTitleFromHandle(self.theHandle) + self.docHeader.setTitleFromHandle(self.theHandle) self.updateDocMargins() self.hLight.spellCheck = spTemp qApp.restoreOverrideCursor() @@ -335,9 +334,9 @@ class GuiDocEditor(QTextEdit): tB = self.frameWidth() tW = self.width() - 2*tB - sW - tH = self.docTitle.height() + tH = self.docHeader.height() tT = cM - tH - self.docTitle.setGeometry(tB, tB, tW, tH) + self.docHeader.setGeometry(tB, tB, tW, tH) self.setViewportMargins(0, tH, 0, 0) docFormat = self.qDocument.rootFrame().frameFormat() @@ -368,7 +367,7 @@ class GuiDocEditor(QTextEdit): title bar needs updating, """ if tHandle == self.theHandle: - self.docTitle.setTitleFromHandle(self.theHandle) + self.docHeader.setTitleFromHandle(self.theHandle) self.updateDocMargins() return @@ -1105,3 +1104,154 @@ class WordCounter(QThread): return ## END Class WordCounter + +class GuiDocEditHeader(QWidget): + + def __init__(self, theParent): + QWidget.__init__(self, theParent) + + logger.debug("Initialising GuiDocEditHeader ...") + + self.mainConf = nw.CONFIG + self.theParent = theParent + self.theProject = theParent.theProject + self.theTheme = theParent.theTheme + self.theHandle = None + + # Make a QPalette that matches the Syntax Theme + self.thePalette = QPalette() + self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack)) + self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText)) + + fPx = int(0.9*self.theTheme.fontPixelSize) + hSp = self.mainConf.pxInt(6) + self.buttonSize = fPx + hSp + + # Main Widget Settings + self.setContentsMargins(2*self.buttonSize, 0, 0, 0) + self.setAutoFillBackground(True) + self.setPalette(self.thePalette) + + # Title Label + self.theTitle = QLabel() + self.theTitle.setText("") + self.theTitle.setIndent(0) + self.theTitle.setMargin(0) + self.theTitle.setContentsMargins(0, 0, 0, 0) + self.theTitle.setAutoFillBackground(True) + self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + self.theTitle.setFixedHeight(fPx) + self.theTitle.setPalette(self.thePalette) + + lblFont = self.theTitle.font() + lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize) + self.theTitle.setFont(lblFont) + + buttonStyle = ( + "QToolButton {{border: none; background: transparent;}} " + "QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}" + ).format(*self.theTheme.colText) + + # Buttons + self.minmaxButton = QToolButton(self) + self.minmaxButton.setIcon(self.theTheme.getIcon("maximise")) + self.minmaxButton.setContentsMargins(0, 0, 0, 0) + self.minmaxButton.setIconSize(QSize(fPx, fPx)) + self.minmaxButton.setFixedSize(fPx, fPx) + self.minmaxButton.setStyleSheet(buttonStyle) + self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly) + self.minmaxButton.setVisible(False) + self.minmaxButton.clicked.connect(self._minmaxDocument) + + self.closeButton = QToolButton(self) + self.closeButton.setIcon(self.theTheme.getIcon("close")) + self.closeButton.setContentsMargins(0, 0, 0, 0) + self.closeButton.setIconSize(QSize(fPx, fPx)) + self.closeButton.setFixedSize(fPx, fPx) + self.closeButton.setStyleSheet(buttonStyle) + self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly) + self.closeButton.setVisible(False) + self.closeButton.clicked.connect(self._closeDocument) + + # Assemble Layout + self.outerBox = QHBoxLayout() + self.outerBox.setSpacing(hSp) + self.outerBox.addWidget(self.theTitle, 1) + self.outerBox.addWidget(self.minmaxButton, 0) + self.outerBox.addWidget(self.closeButton, 0) + self.setLayout(self.outerBox) + + logger.debug("GuiDocEditHeader initialisation complete") + + return + + ## + # Setters + ## + + def setTitleFromHandle(self, tHandle): + """Sets the document title from the handle, or alternatively, + set the whole document path. + """ + self.theTitle.setText("") + self.theHandle = tHandle + if tHandle is None: + self.closeButton.setVisible(False) + self.minmaxButton.setVisible(False) + + if self.mainConf.showFullPath: + tTitle = [] + tTree = self.theProject.projTree.getItemPath(tHandle) + for aHandle in reversed(tTree): + nwItem = self.theProject.projTree[aHandle] + if nwItem is not None: + tTitle.append(nwItem.itemName) + sSep = " %s " % nwUnicode.U_RSAQUO + self.theTitle.setText(sSep.join(tTitle)) + else: + nwItem = self.theProject.projTree[tHandle] + if nwItem is None: + return False + self.theTitle.setText(nwItem.itemName) + + self.closeButton.setVisible(True) + self.minmaxButton.setVisible(True) + + return True + + ## + # Slots + ## + + def _closeDocument(self): + """Trigger the close editor/viewer on the main window. + """ + self.theParent.theParent.closeDocEditor() + return + + def _minmaxDocument(self): + """Switch on or off zen mode. + """ + self.theParent.theParent.toggleZenMode() + if self.theParent.theParent.isZenMode: + self.minmaxButton.setIcon(self.theTheme.getIcon("minimise")) + self.setContentsMargins(self.buttonSize, 0, 0, 0) + self.closeButton.setVisible(False) + else: + self.minmaxButton.setIcon(self.theTheme.getIcon("maximise")) + self.setContentsMargins(2*self.buttonSize, 0, 0, 0) + self.closeButton.setVisible(True) + return + + ## + # Events + ## + + def mousePressEvent(self, theEvent): + """Capture a click on the title and ensure that the item is + selected in the project tree. + """ + self.theParent.setSelectedHandle(self.theHandle) + return + +# END Class GuiDocEditHeader