Redesign main sidebar

This commit is contained in:
Veronica Berglyd Olsen
2023-09-05 21:55:42 +02:00
parent ca3a493932
commit f754c80352
3 changed files with 122 additions and 84 deletions
+1 -1
View File
@@ -329,7 +329,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.setFormat(0, 4, self._hStyles["header4h"]) self.setFormat(0, 4, self._hStyles["header4h"])
self.setFormat(4, len(text), self._hStyles["header4"]) self.setFormat(4, len(text), self._hStyles["header4"])
if text.startswith("#! "): # Title elif text.startswith("#! "): # Title
self.setFormat(0, 2, self._hStyles["header1h"]) self.setFormat(0, 2, self._hStyles["header1h"])
self.setFormat(2, len(text), self._hStyles["header1"]) self.setFormat(2, len(text), self._hStyles["header1"])
+97 -67
View File
@@ -25,99 +25,108 @@ from __future__ import annotations
import logging import logging
from PyQt5.QtCore import Qt, QSize, pyqtSignal from typing import TYPE_CHECKING
from PyQt5.QtWidgets import (
QToolBar, QWidget, QSizePolicy, QAction, QMenu, QToolButton from PyQt5.QtCore import QEvent, QPoint, Qt, QSize, pyqtSignal
) from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QMenu, QToolButton, QVBoxLayout, QWidget
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwView from novelwriter.enum import nwView
if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiSideBar(QToolBar): class PopRightMenu(QMenu):
def event(self, event: QEvent):
"""Overload the show event and move the menu popup location."""
if event.type() == QEvent.Show:
parent = self.parent()
if isinstance(parent, QWidget):
offset = QPoint(parent.width(), parent.height() - self.height())
self.move(parent.mapToGlobal(offset))
return super(PopRightMenu, self).event(event)
class GuiSideBar(QWidget):
viewChangeRequested = pyqtSignal(nwView) viewChangeRequested = pyqtSignal(nwView)
def __init__(self, mainGui): def __init__(self, mainGui: GuiMain) -> None:
super().__init__(parent=mainGui) super().__init__(parent=mainGui)
logger.debug("Create: GuiSideBar") logger.debug("Create: GuiSideBar")
self.mainGui = mainGui self.mainGui = mainGui
# Style iPx = CONFIG.pxInt(24)
iPx = CONFIG.pxInt(22) iconSize = QSize(iPx, iPx)
mPx = CONFIG.pxInt(60)
lblFont = SHARED.theme.guiFont
lblFont.setPointSizeF(0.65*SHARED.theme.fontPointSize)
self.setMovable(False)
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.setIconSize(QSize(iPx, iPx))
self.setMaximumWidth(mPx)
self.setContentsMargins(0, 0, 0, 0) self.setContentsMargins(0, 0, 0, 0)
stretch = QWidget(self)
stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# Actions # Actions
self.aProject = QAction(self.tr("Project"), self) self.tbProject = QToolButton(self)
self.aProject.setFont(lblFont) self.tbProject.setToolTip(self.tr("Project Tree View"))
self.aProject.setToolTip(self.tr("Project Tree View")) self.tbProject.setIconSize(iconSize)
self.aProject.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.PROJECT)) self.tbProject.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.PROJECT))
self.aNovel = QAction(self.tr("Novel"), self) self.tbNovel = QToolButton(self)
self.aNovel.setFont(lblFont) self.tbNovel.setToolTip(self.tr("Novel Tree View"))
self.aNovel.setToolTip(self.tr("Novel Tree View")) self.tbNovel.setIconSize(iconSize)
self.aNovel.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL)) self.tbNovel.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL))
self.aOutline = QAction(self.tr("Outline"), self) self.tbOutline = QToolButton(self)
self.aOutline.setFont(lblFont) self.tbOutline.setToolTip(self.tr("Novel Outline View"))
self.aOutline.setToolTip(self.tr("Novel Outline View")) self.tbOutline.setIconSize(iconSize)
self.aOutline.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE)) self.tbOutline.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE))
self.aBuild = QAction(self.tr("Build"), self) self.tbBuild = QToolButton(self)
self.aBuild.setFont(lblFont) self.tbBuild.setToolTip(self.tr("Build Manuscript"))
self.aBuild.setToolTip(self.tr("Build Manuscript")) self.tbBuild.setIconSize(iconSize)
self.aBuild.triggered.connect(lambda: self.mainGui.showBuildManuscriptDialog()) self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
self.aDetails = QAction(self.tr("Details"), self) self.tbDetails = QToolButton(self)
self.aDetails.setFont(lblFont) self.tbDetails.setToolTip(self.tr("Project Details"))
self.aDetails.setToolTip(self.tr("Project Details")) self.tbDetails.setIconSize(iconSize)
self.aDetails.triggered.connect(lambda: self.mainGui.showProjectDetailsDialog()) self.tbDetails.clicked.connect(self.mainGui.showProjectDetailsDialog)
self.aStats = QAction(self.tr("Stats"), self) self.tbStats = QToolButton(self)
self.aStats.setFont(lblFont) self.tbStats.setToolTip(self.tr("Writing Statistics"))
self.aStats.setToolTip(self.tr("Writing Statistics")) self.tbStats.setIconSize(iconSize)
self.aStats.triggered.connect(lambda: self.mainGui.showWritingStatsDialog()) self.tbStats.clicked.connect(self.mainGui.showWritingStatsDialog)
# Settings Menu # Settings Menu
self.mSettings = QMenu() self.tbSettings = QToolButton(self)
self.tbSettings.setToolTip(self.tr("Settings"))
self.tbSettings.setIconSize(iconSize)
self.tbSettings.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
self.mSettings = PopRightMenu(self.tbSettings)
self.mSettings.addAction(self.mainGui.mainMenu.aEditWordList) self.mSettings.addAction(self.mainGui.mainMenu.aEditWordList)
self.mSettings.addAction(self.mainGui.mainMenu.aProjectSettings) self.mSettings.addAction(self.mainGui.mainMenu.aProjectSettings)
self.mSettings.addSeparator() self.mSettings.addSeparator()
self.mSettings.addAction(self.mainGui.mainMenu.aPreferences) self.mSettings.addAction(self.mainGui.mainMenu.aPreferences)
self.tbSettings = QToolButton(self)
self.tbSettings.setFont(lblFont)
self.tbSettings.setText(self.tr("Settings"))
self.tbSettings.setMenu(self.mSettings) self.tbSettings.setMenu(self.mSettings)
self.tbSettings.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.tbSettings.setPopupMode(QToolButton.InstantPopup) self.tbSettings.setPopupMode(QToolButton.InstantPopup)
# Assemble # Assemble
self.addAction(self.aProject) self.outerBox = QVBoxLayout()
self.addAction(self.aNovel) self.outerBox.addWidget(self.tbProject)
self.addAction(self.aOutline) self.outerBox.addWidget(self.tbNovel)
self.addAction(self.aBuild) self.outerBox.addWidget(self.tbOutline)
self.addWidget(stretch) self.outerBox.addWidget(self.tbBuild)
self.addAction(self.aDetails) self.outerBox.addStretch(1)
self.addAction(self.aStats) self.outerBox.addWidget(self.tbDetails)
self.addWidget(self.tbSettings) self.outerBox.addWidget(self.tbStats)
self.outerBox.addWidget(self.tbSettings)
self.outerBox.setContentsMargins(0, 0, CONFIG.pxInt(2), 0)
self.outerBox.setSpacing(CONFIG.pxInt(4))
self.setLayout(self.outerBox)
self.updateTheme() self.updateTheme()
@@ -125,18 +134,39 @@ class GuiSideBar(QToolBar):
return return
def updateTheme(self): def updateTheme(self) -> None:
"""Initialise GUI elements that depend on specific settings. """Initialise GUI elements that depend on specific settings."""
""" qPalette = self.palette()
self.setStyleSheet("QToolBar {border: 0px;}") qPalette.setBrush(QPalette.Window, qPalette.base())
self.setPalette(qPalette)
fadeCol = qPalette.text().color()
buttonStyle = (
"QToolButton {{padding: {0}px; border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
).format(CONFIG.pxInt(4), fadeCol.red(), fadeCol.green(), fadeCol.blue())
buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}"
self.tbProject.setIcon(SHARED.theme.getIcon("view_editor"))
self.tbProject.setStyleSheet(buttonStyle)
self.tbNovel.setIcon(SHARED.theme.getIcon("view_novel"))
self.tbNovel.setStyleSheet(buttonStyle)
self.tbOutline.setIcon(SHARED.theme.getIcon("view_outline"))
self.tbOutline.setStyleSheet(buttonStyle)
self.tbBuild.setIcon(SHARED.theme.getIcon("view_build"))
self.tbBuild.setStyleSheet(buttonStyle)
self.tbDetails.setIcon(SHARED.theme.getIcon("proj_details"))
self.tbDetails.setStyleSheet(buttonStyle)
self.tbStats.setIcon(SHARED.theme.getIcon("proj_stats"))
self.tbStats.setStyleSheet(buttonStyle)
self.aProject.setIcon(SHARED.theme.getIcon("view_editor"))
self.aNovel.setIcon(SHARED.theme.getIcon("view_novel"))
self.aOutline.setIcon(SHARED.theme.getIcon("view_outline"))
self.aBuild.setIcon(SHARED.theme.getIcon("view_build"))
self.aDetails.setIcon(SHARED.theme.getIcon("proj_details"))
self.aStats.setIcon(SHARED.theme.getIcon("proj_stats"))
self.tbSettings.setIcon(SHARED.theme.getIcon("settings")) self.tbSettings.setIcon(SHARED.theme.getIcon("settings"))
self.tbSettings.setStyleSheet(buttonStyleMenu)
return return
+24 -16
View File
@@ -33,8 +33,8 @@ from datetime import datetime
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
qApp, QDialog, QFileDialog, QMainWindow, QMessageBox, QShortcut, QSplitter, QDialog, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut,
QStackedWidget, QVBoxLayout, QWidget QSplitter, QStackedWidget, QVBoxLayout, QWidget, qApp
) )
from novelwriter import CONFIG, SHARED, __hexversion__ from novelwriter import CONFIG, SHARED, __hexversion__
@@ -95,7 +95,7 @@ class GuiMain(QMainWindow):
logger.debug("Create: GUI") logger.debug("Create: GUI")
self.setObjectName("GuiMain") self.setObjectName("GuiMain")
self.threadPool = QThreadPool() self.threadPool = QThreadPool(self)
# System Info # System Info
# =========== # ===========
@@ -146,14 +146,14 @@ class GuiMain(QMainWindow):
self.viewsBar = GuiSideBar(self) self.viewsBar = GuiSideBar(self)
# Project Tree Stack # Project Tree Stack
self.projStack = QStackedWidget() self.projStack = QStackedWidget(self)
self.projStack.addWidget(self.projView) self.projStack.addWidget(self.projView)
self.projStack.addWidget(self.novelView) self.projStack.addWidget(self.novelView)
self.projStack.currentChanged.connect(self._projStackChanged) self.projStack.currentChanged.connect(self._projStackChanged)
# Project Tree View # Project Tree View
self.treePane = QWidget() self.treePane = QWidget(self)
self.treeBox = QVBoxLayout() self.treeBox = QVBoxLayout(self)
self.treeBox.setContentsMargins(0, 0, 0, 0) self.treeBox.setContentsMargins(0, 0, 0, 0)
self.treeBox.setSpacing(mPx) self.treeBox.setSpacing(mPx)
self.treeBox.addWidget(self.projStack) self.treeBox.addWidget(self.projStack)
@@ -161,7 +161,7 @@ class GuiMain(QMainWindow):
self.treePane.setLayout(self.treeBox) self.treePane.setLayout(self.treeBox)
# Splitter : Document Viewer / Document Meta # Splitter : Document Viewer / Document Meta
self.splitView = QSplitter(Qt.Vertical) self.splitView = QSplitter(Qt.Vertical, self)
self.splitView.addWidget(self.docViewer) self.splitView.addWidget(self.docViewer)
self.splitView.addWidget(self.viewMeta) self.splitView.addWidget(self.viewMeta)
self.splitView.setHandleWidth(hWd) self.splitView.setHandleWidth(hWd)
@@ -169,7 +169,7 @@ class GuiMain(QMainWindow):
self.splitView.setSizes(CONFIG.viewPanePos) self.splitView.setSizes(CONFIG.viewPanePos)
# Splitter : Document Editor / Document Viewer # Splitter : Document Editor / Document Viewer
self.splitDocs = QSplitter(Qt.Horizontal) self.splitDocs = QSplitter(Qt.Horizontal, self)
self.splitDocs.addWidget(self.docEditor) self.splitDocs.addWidget(self.docEditor)
self.splitDocs.addWidget(self.splitView) self.splitDocs.addWidget(self.splitView)
self.splitDocs.setOpaqueResize(False) self.splitDocs.setOpaqueResize(False)
@@ -185,7 +185,7 @@ class GuiMain(QMainWindow):
self.splitMain.setSizes(CONFIG.mainPanePos) self.splitMain.setSizes(CONFIG.mainPanePos)
# Main Stack : Editor / Outline # Main Stack : Editor / Outline
self.mainStack = QStackedWidget() self.mainStack = QStackedWidget(self)
self.mainStack.addWidget(self.splitMain) self.mainStack.addWidget(self.splitMain)
self.mainStack.addWidget(self.outlineView) self.mainStack.addWidget(self.outlineView)
self.mainStack.currentChanged.connect(self._mainStackChanged) self.mainStack.currentChanged.connect(self._mainStackChanged)
@@ -222,11 +222,19 @@ class GuiMain(QMainWindow):
# Initialise the Project Tree # Initialise the Project Tree
self.rebuildTrees() self.rebuildTrees()
# Set Main Window Elements # Assemble Main Window Elements
self.mainBox = QHBoxLayout(self)
self.mainBox.addWidget(self.viewsBar)
self.mainBox.addWidget(self.mainStack)
self.mainBox.setContentsMargins(0, 0, 0, 0)
self.mainBox.setSpacing(0)
self.mainWidget = QWidget(self)
self.mainWidget.setLayout(self.mainBox)
self.setMenuBar(self.mainMenu) self.setMenuBar(self.mainMenu)
self.setCentralWidget(self.mainStack) self.setCentralWidget(self.mainWidget)
self.setStatusBar(self.mainStatus) self.setStatusBar(self.mainStatus)
self.addToolBar(Qt.LeftToolBarArea, self.viewsBar)
self.setContextMenuPolicy(Qt.NoContextMenu) # Issue #1147 self.setContextMenuPolicy(Qt.NoContextMenu) # Issue #1147
# Connect Signals # Connect Signals
@@ -269,15 +277,15 @@ class GuiMain(QMainWindow):
# ======================= # =======================
# Set Up Auto-Save Project Timer # Set Up Auto-Save Project Timer
self.asProjTimer = QTimer() self.asProjTimer = QTimer(self)
self.asProjTimer.timeout.connect(self._autoSaveProject) self.asProjTimer.timeout.connect(self._autoSaveProject)
# Set Up Auto-Save Document Timer # Set Up Auto-Save Document Timer
self.asDocTimer = QTimer() self.asDocTimer = QTimer(self)
self.asDocTimer.timeout.connect(self._autoSaveDocument) self.asDocTimer.timeout.connect(self._autoSaveDocument)
# Main Clock # Main Clock
self.mainTimer = QTimer() self.mainTimer = QTimer(self)
self.mainTimer.setInterval(1000) self.mainTimer.setInterval(1000)
self.mainTimer.timeout.connect(self._timeTick) self.mainTimer.timeout.connect(self._timeTick)
self.mainTimer.start() self.mainTimer.start()
@@ -1022,7 +1030,7 @@ class GuiMain(QMainWindow):
def showAboutQtDialog(self) -> None: def showAboutQtDialog(self) -> None:
"""Show the about dialog for Qt.""" """Show the about dialog for Qt."""
msgBox = QMessageBox() msgBox = QMessageBox(self)
msgBox.aboutQt(self, "About Qt") msgBox.aboutQt(self, "About Qt")
return return