Redesign main sidebar
This commit is contained in:
@@ -329,7 +329,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
self.setFormat(0, 4, self._hStyles["header4h"])
|
||||
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(2, len(text), self._hStyles["header1"])
|
||||
|
||||
|
||||
+97
-67
@@ -25,99 +25,108 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtCore import Qt, QSize, pyqtSignal
|
||||
from PyQt5.QtWidgets import (
|
||||
QToolBar, QWidget, QSizePolicy, QAction, QMenu, QToolButton
|
||||
)
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
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.enum import nwView
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
|
||||
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)
|
||||
|
||||
def __init__(self, mainGui):
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
logger.debug("Create: GuiSideBar")
|
||||
|
||||
self.mainGui = mainGui
|
||||
|
||||
# Style
|
||||
iPx = CONFIG.pxInt(22)
|
||||
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)
|
||||
iPx = CONFIG.pxInt(24)
|
||||
iconSize = QSize(iPx, iPx)
|
||||
self.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
stretch = QWidget(self)
|
||||
stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
# Actions
|
||||
self.aProject = QAction(self.tr("Project"), self)
|
||||
self.aProject.setFont(lblFont)
|
||||
self.aProject.setToolTip(self.tr("Project Tree View"))
|
||||
self.aProject.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.PROJECT))
|
||||
self.tbProject = QToolButton(self)
|
||||
self.tbProject.setToolTip(self.tr("Project Tree View"))
|
||||
self.tbProject.setIconSize(iconSize)
|
||||
self.tbProject.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.PROJECT))
|
||||
|
||||
self.aNovel = QAction(self.tr("Novel"), self)
|
||||
self.aNovel.setFont(lblFont)
|
||||
self.aNovel.setToolTip(self.tr("Novel Tree View"))
|
||||
self.aNovel.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL))
|
||||
self.tbNovel = QToolButton(self)
|
||||
self.tbNovel.setToolTip(self.tr("Novel Tree View"))
|
||||
self.tbNovel.setIconSize(iconSize)
|
||||
self.tbNovel.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL))
|
||||
|
||||
self.aOutline = QAction(self.tr("Outline"), self)
|
||||
self.aOutline.setFont(lblFont)
|
||||
self.aOutline.setToolTip(self.tr("Novel Outline View"))
|
||||
self.aOutline.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE))
|
||||
self.tbOutline = QToolButton(self)
|
||||
self.tbOutline.setToolTip(self.tr("Novel Outline View"))
|
||||
self.tbOutline.setIconSize(iconSize)
|
||||
self.tbOutline.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE))
|
||||
|
||||
self.aBuild = QAction(self.tr("Build"), self)
|
||||
self.aBuild.setFont(lblFont)
|
||||
self.aBuild.setToolTip(self.tr("Build Manuscript"))
|
||||
self.aBuild.triggered.connect(lambda: self.mainGui.showBuildManuscriptDialog())
|
||||
self.tbBuild = QToolButton(self)
|
||||
self.tbBuild.setToolTip(self.tr("Build Manuscript"))
|
||||
self.tbBuild.setIconSize(iconSize)
|
||||
self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
|
||||
|
||||
self.aDetails = QAction(self.tr("Details"), self)
|
||||
self.aDetails.setFont(lblFont)
|
||||
self.aDetails.setToolTip(self.tr("Project Details"))
|
||||
self.aDetails.triggered.connect(lambda: self.mainGui.showProjectDetailsDialog())
|
||||
self.tbDetails = QToolButton(self)
|
||||
self.tbDetails.setToolTip(self.tr("Project Details"))
|
||||
self.tbDetails.setIconSize(iconSize)
|
||||
self.tbDetails.clicked.connect(self.mainGui.showProjectDetailsDialog)
|
||||
|
||||
self.aStats = QAction(self.tr("Stats"), self)
|
||||
self.aStats.setFont(lblFont)
|
||||
self.aStats.setToolTip(self.tr("Writing Statistics"))
|
||||
self.aStats.triggered.connect(lambda: self.mainGui.showWritingStatsDialog())
|
||||
self.tbStats = QToolButton(self)
|
||||
self.tbStats.setToolTip(self.tr("Writing Statistics"))
|
||||
self.tbStats.setIconSize(iconSize)
|
||||
self.tbStats.clicked.connect(self.mainGui.showWritingStatsDialog)
|
||||
|
||||
# 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.aProjectSettings)
|
||||
self.mSettings.addSeparator()
|
||||
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.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||
self.tbSettings.setPopupMode(QToolButton.InstantPopup)
|
||||
|
||||
# Assemble
|
||||
self.addAction(self.aProject)
|
||||
self.addAction(self.aNovel)
|
||||
self.addAction(self.aOutline)
|
||||
self.addAction(self.aBuild)
|
||||
self.addWidget(stretch)
|
||||
self.addAction(self.aDetails)
|
||||
self.addAction(self.aStats)
|
||||
self.addWidget(self.tbSettings)
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.addWidget(self.tbProject)
|
||||
self.outerBox.addWidget(self.tbNovel)
|
||||
self.outerBox.addWidget(self.tbOutline)
|
||||
self.outerBox.addWidget(self.tbBuild)
|
||||
self.outerBox.addStretch(1)
|
||||
self.outerBox.addWidget(self.tbDetails)
|
||||
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()
|
||||
|
||||
@@ -125,18 +134,39 @@ class GuiSideBar(QToolBar):
|
||||
|
||||
return
|
||||
|
||||
def updateTheme(self):
|
||||
"""Initialise GUI elements that depend on specific settings.
|
||||
"""
|
||||
self.setStyleSheet("QToolBar {border: 0px;}")
|
||||
def updateTheme(self) -> None:
|
||||
"""Initialise GUI elements that depend on specific settings."""
|
||||
qPalette = self.palette()
|
||||
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.setStyleSheet(buttonStyleMenu)
|
||||
|
||||
return
|
||||
|
||||
|
||||
+24
-16
@@ -33,8 +33,8 @@ from datetime import datetime
|
||||
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence
|
||||
from PyQt5.QtWidgets import (
|
||||
qApp, QDialog, QFileDialog, QMainWindow, QMessageBox, QShortcut, QSplitter,
|
||||
QStackedWidget, QVBoxLayout, QWidget
|
||||
QDialog, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut,
|
||||
QSplitter, QStackedWidget, QVBoxLayout, QWidget, qApp
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED, __hexversion__
|
||||
@@ -95,7 +95,7 @@ class GuiMain(QMainWindow):
|
||||
|
||||
logger.debug("Create: GUI")
|
||||
self.setObjectName("GuiMain")
|
||||
self.threadPool = QThreadPool()
|
||||
self.threadPool = QThreadPool(self)
|
||||
|
||||
# System Info
|
||||
# ===========
|
||||
@@ -146,14 +146,14 @@ class GuiMain(QMainWindow):
|
||||
self.viewsBar = GuiSideBar(self)
|
||||
|
||||
# Project Tree Stack
|
||||
self.projStack = QStackedWidget()
|
||||
self.projStack = QStackedWidget(self)
|
||||
self.projStack.addWidget(self.projView)
|
||||
self.projStack.addWidget(self.novelView)
|
||||
self.projStack.currentChanged.connect(self._projStackChanged)
|
||||
|
||||
# Project Tree View
|
||||
self.treePane = QWidget()
|
||||
self.treeBox = QVBoxLayout()
|
||||
self.treePane = QWidget(self)
|
||||
self.treeBox = QVBoxLayout(self)
|
||||
self.treeBox.setContentsMargins(0, 0, 0, 0)
|
||||
self.treeBox.setSpacing(mPx)
|
||||
self.treeBox.addWidget(self.projStack)
|
||||
@@ -161,7 +161,7 @@ class GuiMain(QMainWindow):
|
||||
self.treePane.setLayout(self.treeBox)
|
||||
|
||||
# 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.viewMeta)
|
||||
self.splitView.setHandleWidth(hWd)
|
||||
@@ -169,7 +169,7 @@ class GuiMain(QMainWindow):
|
||||
self.splitView.setSizes(CONFIG.viewPanePos)
|
||||
|
||||
# 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.splitView)
|
||||
self.splitDocs.setOpaqueResize(False)
|
||||
@@ -185,7 +185,7 @@ class GuiMain(QMainWindow):
|
||||
self.splitMain.setSizes(CONFIG.mainPanePos)
|
||||
|
||||
# Main Stack : Editor / Outline
|
||||
self.mainStack = QStackedWidget()
|
||||
self.mainStack = QStackedWidget(self)
|
||||
self.mainStack.addWidget(self.splitMain)
|
||||
self.mainStack.addWidget(self.outlineView)
|
||||
self.mainStack.currentChanged.connect(self._mainStackChanged)
|
||||
@@ -222,11 +222,19 @@ class GuiMain(QMainWindow):
|
||||
# Initialise the Project Tree
|
||||
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.setCentralWidget(self.mainStack)
|
||||
self.setCentralWidget(self.mainWidget)
|
||||
self.setStatusBar(self.mainStatus)
|
||||
self.addToolBar(Qt.LeftToolBarArea, self.viewsBar)
|
||||
self.setContextMenuPolicy(Qt.NoContextMenu) # Issue #1147
|
||||
|
||||
# Connect Signals
|
||||
@@ -269,15 +277,15 @@ class GuiMain(QMainWindow):
|
||||
# =======================
|
||||
|
||||
# Set Up Auto-Save Project Timer
|
||||
self.asProjTimer = QTimer()
|
||||
self.asProjTimer = QTimer(self)
|
||||
self.asProjTimer.timeout.connect(self._autoSaveProject)
|
||||
|
||||
# Set Up Auto-Save Document Timer
|
||||
self.asDocTimer = QTimer()
|
||||
self.asDocTimer = QTimer(self)
|
||||
self.asDocTimer.timeout.connect(self._autoSaveDocument)
|
||||
|
||||
# Main Clock
|
||||
self.mainTimer = QTimer()
|
||||
self.mainTimer = QTimer(self)
|
||||
self.mainTimer.setInterval(1000)
|
||||
self.mainTimer.timeout.connect(self._timeTick)
|
||||
self.mainTimer.start()
|
||||
@@ -1022,7 +1030,7 @@ class GuiMain(QMainWindow):
|
||||
|
||||
def showAboutQtDialog(self) -> None:
|
||||
"""Show the about dialog for Qt."""
|
||||
msgBox = QMessageBox()
|
||||
msgBox = QMessageBox(self)
|
||||
msgBox.aboutQt(self, "About Qt")
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user