Shift all view changing functionality to the new Views bar
This commit is contained in:
@@ -130,6 +130,19 @@ class nwState(Enum):
|
||||
# END Enum nwState
|
||||
|
||||
|
||||
class nwView(Enum):
|
||||
|
||||
PROJECT = 0
|
||||
NOVEL = 1
|
||||
OUTLINE = 2
|
||||
DETAILS = 3
|
||||
STATS = 4
|
||||
SET_PROJ = 5
|
||||
SET_MAIN = 6
|
||||
|
||||
# END Enum nwView
|
||||
|
||||
|
||||
class nwWidget(Enum):
|
||||
|
||||
TREE = 1
|
||||
|
||||
@@ -26,14 +26,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import logging
|
||||
import novelwriter
|
||||
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtCore import Qt, QSize, pyqtSignal
|
||||
from PyQt5.QtWidgets import QToolBar, QWidget, QSizePolicy, QAction
|
||||
|
||||
from novelwriter.enum import nwView
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GuiViewsBar(QToolBar):
|
||||
|
||||
viewChangeRequested = pyqtSignal(nwView)
|
||||
|
||||
def __init__(self, theParent):
|
||||
QToolBar.__init__(self, theParent)
|
||||
|
||||
@@ -60,17 +64,35 @@ class GuiViewsBar(QToolBar):
|
||||
|
||||
# Actions
|
||||
self.aProject = QAction(self.tr("Project"))
|
||||
self.aProject.setIcon(self.theTheme.getIcon("status_lines"))
|
||||
self.aProject.setIcon(self.theTheme.getIcon("proj_folder"))
|
||||
self.aProject.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.PROJECT))
|
||||
|
||||
self.aNovel = QAction(self.tr("Novel"))
|
||||
self.aNovel.setIcon(self.theTheme.getIcon("cls_novel"))
|
||||
self.aNovel.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL))
|
||||
|
||||
self.aOutline = QAction(self.tr("Outline"))
|
||||
self.aOutline.setIcon(self.theTheme.getIcon("cls_plot"))
|
||||
self.aOutline.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE))
|
||||
|
||||
self.aDetails = QAction(self.tr("Details"))
|
||||
self.aDetails.setIcon(self.theTheme.getIcon("status_lines"))
|
||||
self.aDetails.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.DETAILS))
|
||||
|
||||
self.aStats = QAction(self.tr("Stats"))
|
||||
self.aStats.setIcon(self.theTheme.getIcon("status_stats"))
|
||||
self.aStats.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.STATS))
|
||||
|
||||
self.aSettings = QAction(self.tr("Settings"))
|
||||
self.aSettings.setIcon(self.theTheme.getIcon("settings"))
|
||||
self.aSettings.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.SET_PROJ))
|
||||
|
||||
# Assemble
|
||||
self.addWidget(stretch)
|
||||
self.addAction(self.aProject)
|
||||
self.addAction(self.aNovel)
|
||||
self.addAction(self.aOutline)
|
||||
self.addWidget(stretch)
|
||||
self.addAction(self.aDetails)
|
||||
self.addAction(self.aStats)
|
||||
self.addAction(self.aSettings)
|
||||
|
||||
|
||||
+60
-67
@@ -30,11 +30,11 @@ import novelwriter
|
||||
from time import time
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt5.QtCore import Qt, QTimer, QSize, QThreadPool, pyqtSlot
|
||||
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
|
||||
from PyQt5.QtGui import QIcon, QKeySequence, QCursor
|
||||
from PyQt5.QtWidgets import (
|
||||
qApp, QMainWindow, QVBoxLayout, QWidget, QSplitter, QFileDialog, QShortcut,
|
||||
QMessageBox, QDialog, QTabWidget, QToolBar, QAction
|
||||
QMessageBox, QDialog, QStackedWidget
|
||||
)
|
||||
|
||||
from novelwriter.gui import (
|
||||
@@ -52,7 +52,7 @@ from novelwriter.tools import (
|
||||
)
|
||||
from novelwriter.core import NWProject, NWIndex
|
||||
from novelwriter.enum import (
|
||||
nwItemType, nwItemClass, nwAlert, nwWidget, nwState
|
||||
nwItemType, nwItemClass, nwAlert, nwWidget, nwState, nwView
|
||||
)
|
||||
from novelwriter.common import getGuiItem, hexToInt
|
||||
|
||||
@@ -102,8 +102,6 @@ class GuiMain(QMainWindow):
|
||||
|
||||
# Sizes
|
||||
mPx = self.mainConf.pxInt(4)
|
||||
fPx = self.theTheme.fontPixelSize
|
||||
fPt = self.theTheme.fontPointSize
|
||||
|
||||
# Main GUI Elements
|
||||
self.statusBar = GuiMainStatus(self)
|
||||
@@ -129,48 +127,20 @@ class GuiMain(QMainWindow):
|
||||
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
|
||||
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
|
||||
|
||||
# Project Tree Tabs
|
||||
self.projTabs = QTabWidget()
|
||||
self.projTabs.setTabPosition(QTabWidget.South)
|
||||
self.projTabs.setStyleSheet("QTabWidget::pane {border: 0;};")
|
||||
self.projTabs.addTab(self.treeView, self.tr("Project"))
|
||||
self.projTabs.addTab(self.novelView, self.tr("Novel"))
|
||||
self.projTabs.currentChanged.connect(self._projTabsChanged)
|
||||
self.viewsBar.viewChangeRequested.connect(self._changeView)
|
||||
|
||||
tabFont = self.projTabs.tabBar().font()
|
||||
tabFont.setPointSizeF(0.9*fPt)
|
||||
self.projTabs.tabBar().setFont(tabFont)
|
||||
|
||||
# Project Tree Action Buttons
|
||||
btnSize = int(round(0.7*fPx))
|
||||
self.treeButtons = QToolBar()
|
||||
self.treeButtons.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.treeButtons.setIconSize(QSize(btnSize, btnSize))
|
||||
self.treeButtons.setContentsMargins(0, 0, 0, 0)
|
||||
self.treeButtons.setStyleSheet("QToolBar {padding: 0;}")
|
||||
self.projTabs.setCornerWidget(self.treeButtons, Qt.BottomRightCorner)
|
||||
|
||||
self.projDetailsBtn = QAction(self.tr("Project Details"))
|
||||
self.projDetailsBtn.setIcon(self.theTheme.getIcon("status_lines"))
|
||||
self.projDetailsBtn.triggered.connect(lambda: self.showProjectDetailsDialog())
|
||||
self.treeButtons.addAction(self.projDetailsBtn)
|
||||
|
||||
self.projStatsBtn = QAction(self.tr("Writing Statistics"))
|
||||
self.projStatsBtn.setIcon(self.theTheme.getIcon("status_stats"))
|
||||
self.projStatsBtn.triggered.connect(lambda: self.showWritingStatsDialog())
|
||||
self.treeButtons.addAction(self.projStatsBtn)
|
||||
|
||||
self.projSettingsBtn = QAction(self.tr("Project Settings"))
|
||||
self.projSettingsBtn.setIcon(self.theTheme.getIcon("settings"))
|
||||
self.projSettingsBtn.triggered.connect(lambda: self.showProjectSettingsDialog())
|
||||
self.treeButtons.addAction(self.projSettingsBtn)
|
||||
# Project Tree Stack
|
||||
self.projStack = QStackedWidget()
|
||||
self.projStack.addWidget(self.treeView)
|
||||
self.projStack.addWidget(self.novelView)
|
||||
self.projStack.currentChanged.connect(self._projStackChanged)
|
||||
|
||||
# Project Tree View
|
||||
self.treePane = QWidget()
|
||||
self.treeBox = QVBoxLayout()
|
||||
self.treeBox.setContentsMargins(0, 0, 0, 0)
|
||||
self.treeBox.setSpacing(mPx)
|
||||
self.treeBox.addWidget(self.projTabs)
|
||||
self.treeBox.addWidget(self.projStack)
|
||||
self.treeBox.addWidget(self.treeMeta)
|
||||
self.treePane.setLayout(self.treeBox)
|
||||
|
||||
@@ -192,33 +162,31 @@ class GuiMain(QMainWindow):
|
||||
self.splitOutline.setSizes(self.mainConf.getOutlinePanePos())
|
||||
|
||||
# Main Tabs : Editor / Outline
|
||||
self.mainTabs = QTabWidget()
|
||||
self.mainTabs.setTabPosition(QTabWidget.East)
|
||||
self.mainTabs.setStyleSheet("QTabWidget::pane {border: 0;}")
|
||||
self.mainTabs.addTab(self.splitDocs, self.tr("Editor"))
|
||||
self.mainTabs.addTab(self.splitOutline, self.tr("Outline"))
|
||||
self.mainTabs.currentChanged.connect(self._mainTabChanged)
|
||||
self.mainStack = QStackedWidget()
|
||||
self.mainStack.addWidget(self.splitDocs)
|
||||
self.mainStack.addWidget(self.splitOutline)
|
||||
self.mainStack.currentChanged.connect(self._mainStackChanged)
|
||||
|
||||
# Splitter : Project Tree / Main Tabs
|
||||
self.splitMain = QSplitter(Qt.Horizontal)
|
||||
self.splitMain.setContentsMargins(mPx, mPx, mPx, mPx)
|
||||
self.splitMain.addWidget(self.treePane)
|
||||
self.splitMain.addWidget(self.mainTabs)
|
||||
self.splitMain.addWidget(self.mainStack)
|
||||
self.splitMain.setSizes(self.mainConf.getMainPanePos())
|
||||
|
||||
# Indices of Splitter Widgets
|
||||
self.idxTree = self.splitMain.indexOf(self.treePane)
|
||||
self.idxMain = self.splitMain.indexOf(self.mainTabs)
|
||||
self.idxMain = self.splitMain.indexOf(self.mainStack)
|
||||
self.idxEditor = self.splitDocs.indexOf(self.docEditor)
|
||||
self.idxViewer = self.splitDocs.indexOf(self.splitView)
|
||||
self.idxViewDoc = self.splitView.indexOf(self.docViewer)
|
||||
self.idxViewMeta = self.splitView.indexOf(self.viewMeta)
|
||||
|
||||
# Indices of Tab Widgets
|
||||
self.idxTabEdit = self.mainTabs.indexOf(self.splitDocs)
|
||||
self.idxTabProj = self.mainTabs.indexOf(self.splitOutline)
|
||||
self.idxTreeView = self.projTabs.indexOf(self.treeView)
|
||||
self.idxNovelView = self.projTabs.indexOf(self.novelView)
|
||||
self.idxTabEdit = self.mainStack.indexOf(self.splitDocs)
|
||||
self.idxTabProj = self.mainStack.indexOf(self.splitOutline)
|
||||
self.idxTreeView = self.projStack.indexOf(self.treeView)
|
||||
self.idxNovelView = self.projStack.indexOf(self.novelView)
|
||||
|
||||
# Splitter Behaviour
|
||||
self.splitMain.setCollapsible(self.idxTree, False)
|
||||
@@ -450,7 +418,7 @@ class GuiMain(QMainWindow):
|
||||
self.theIndex.clearIndex()
|
||||
self.clearGUI()
|
||||
self.hasProject = False
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
|
||||
return saveOK
|
||||
|
||||
@@ -466,7 +434,7 @@ class GuiMain(QMainWindow):
|
||||
return False
|
||||
|
||||
# Switch main tab to editor view
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
|
||||
# Try to open the project
|
||||
if not self.theProject.openProject(projFile):
|
||||
@@ -605,7 +573,7 @@ class GuiMain(QMainWindow):
|
||||
return False
|
||||
|
||||
self.closeDocument()
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
if self.docEditor.loadText(tHandle, tLine):
|
||||
if changeFocus:
|
||||
self.docEditor.setFocus()
|
||||
@@ -688,7 +656,7 @@ class GuiMain(QMainWindow):
|
||||
return False
|
||||
|
||||
# Make sure main tab is in Editor view
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
|
||||
logger.debug("Viewing document with handle '%s'", tHandle)
|
||||
if self.docViewer.loadText(tHandle):
|
||||
@@ -873,7 +841,7 @@ class GuiMain(QMainWindow):
|
||||
def requestNovelTreeRefresh(self):
|
||||
"""Update the novel tree, but only if it is visible.
|
||||
"""
|
||||
if self.projTabs.currentIndex() == self.idxNovelView and self.hasProject:
|
||||
if self.projStack.currentIndex() == self.idxNovelView and self.hasProject:
|
||||
self.novelView.refreshTree()
|
||||
return True
|
||||
return False
|
||||
@@ -934,7 +902,7 @@ class GuiMain(QMainWindow):
|
||||
return False
|
||||
|
||||
logger.verbose("Forcing a rebuild of the Project Outline")
|
||||
self.mainTabs.setCurrentWidget(self.splitOutline)
|
||||
self.mainStack.setCurrentWidget(self.splitOutline)
|
||||
self.projView.refreshTree(overRide=True)
|
||||
|
||||
return True
|
||||
@@ -1247,19 +1215,19 @@ class GuiMain(QMainWindow):
|
||||
"""Switch focus between main GUI views.
|
||||
"""
|
||||
if paneNo == nwWidget.TREE:
|
||||
tabIdx = self.projTabs.currentIndex()
|
||||
tabIdx = self.projStack.currentIndex()
|
||||
if tabIdx == self.idxTreeView:
|
||||
self.treeView.setFocus()
|
||||
elif tabIdx == self.idxNovelView:
|
||||
self.novelView.setFocus()
|
||||
elif paneNo == nwWidget.EDITOR:
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
self.docEditor.setFocus()
|
||||
elif paneNo == nwWidget.VIEWER:
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
self.docViewer.setFocus()
|
||||
elif paneNo == nwWidget.OUTLINE:
|
||||
self.mainTabs.setCurrentWidget(self.splitOutline)
|
||||
self.mainStack.setCurrentWidget(self.splitOutline)
|
||||
self.projView.setFocus()
|
||||
return
|
||||
|
||||
@@ -1292,7 +1260,7 @@ class GuiMain(QMainWindow):
|
||||
self.mainMenu.setFocusMode(self.isFocusMode)
|
||||
if self.isFocusMode:
|
||||
logger.debug("Activating Focus Mode")
|
||||
self.mainTabs.setCurrentWidget(self.splitDocs)
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
self.switchFocus(nwWidget.EDITOR)
|
||||
else:
|
||||
logger.debug("Deactivating Focus Mode")
|
||||
@@ -1302,7 +1270,6 @@ class GuiMain(QMainWindow):
|
||||
self.statusBar.setVisible(isVisible)
|
||||
self.mainMenu.setVisible(isVisible)
|
||||
self.viewsBar.setVisible(isVisible)
|
||||
self.mainTabs.tabBar().setVisible(isVisible)
|
||||
|
||||
hideDocFooter = self.isFocusMode and self.mainConf.hideFocusFooter
|
||||
self.docEditor.docFooter.setVisible(not hideDocFooter)
|
||||
@@ -1516,6 +1483,32 @@ class GuiMain(QMainWindow):
|
||||
# Slots
|
||||
##
|
||||
|
||||
@pyqtSlot(nwView)
|
||||
def _changeView(self, view):
|
||||
"""Handle the requested change of view from the GuiViewBar.
|
||||
"""
|
||||
if view == nwView.PROJECT:
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
self.projStack.setCurrentWidget(self.treeView)
|
||||
|
||||
elif view == nwView.NOVEL:
|
||||
self.mainStack.setCurrentWidget(self.splitDocs)
|
||||
self.projStack.setCurrentWidget(self.novelView)
|
||||
|
||||
elif view == nwView.OUTLINE:
|
||||
self.mainStack.setCurrentWidget(self.splitOutline)
|
||||
|
||||
elif view == nwView.DETAILS:
|
||||
self.showProjectDetailsDialog()
|
||||
|
||||
elif view == nwView.STATS:
|
||||
self.showWritingStatsDialog()
|
||||
|
||||
elif view == nwView.SET_PROJ:
|
||||
self.showProjectSettingsDialog()
|
||||
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _timeTick(self):
|
||||
"""Triggered on every tick of the main timer.
|
||||
@@ -1589,7 +1582,7 @@ class GuiMain(QMainWindow):
|
||||
"""Triggered when there is a change to a novel item in the
|
||||
project tree.
|
||||
"""
|
||||
if self.mainTabs.currentIndex() == self.idxTabProj:
|
||||
if self.mainStack.currentIndex() == self.idxTabProj:
|
||||
logger.verbose("Novel tree changed while Outline tab active")
|
||||
if self.hasProject:
|
||||
self.treeView.flushTreeOrder()
|
||||
@@ -1618,7 +1611,7 @@ class GuiMain(QMainWindow):
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
def _mainTabChanged(self, tabIndex):
|
||||
def _mainStackChanged(self, tabIndex):
|
||||
"""Activated when the main window tab is changed.
|
||||
"""
|
||||
if tabIndex == self.idxTabEdit:
|
||||
@@ -1631,7 +1624,7 @@ class GuiMain(QMainWindow):
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
def _projTabsChanged(self, tabIndex):
|
||||
def _projStackChanged(self, tabIndex):
|
||||
"""Activated when the project view tab is changed.
|
||||
"""
|
||||
sHandle = None
|
||||
|
||||
@@ -85,7 +85,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
||||
|
||||
# Project Tree has focus
|
||||
nwGUI.switchFocus(nwWidget.TREE)
|
||||
nwGUI.projTabs.setCurrentIndex(0)
|
||||
nwGUI.projStack.setCurrentIndex(0)
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
|
||||
assert nwGUI.docEditor.docHandle() is None
|
||||
@@ -95,7 +95,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
||||
assert nwGUI.closeDocument() is True
|
||||
|
||||
# Novel Tree has focus
|
||||
nwGUI.projTabs.setCurrentIndex(1)
|
||||
nwGUI.projStack.setCurrentIndex(1)
|
||||
nwGUI.novelView.refreshTree(True)
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr(GuiNovelTree, "hasFocus", lambda *a: True)
|
||||
|
||||
@@ -59,7 +59,7 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
# Populate Tree
|
||||
##
|
||||
|
||||
nwGUI.projTabs.setCurrentIndex(nwGUI.idxNovelView)
|
||||
nwGUI.projStack.setCurrentIndex(nwGUI.idxNovelView)
|
||||
nwGUI.rebuildIndex()
|
||||
nwTree._populateTree()
|
||||
assert nwTree.topLevelItemCount() == 1
|
||||
|
||||
@@ -43,7 +43,7 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
|
||||
nwGUI.mainConf.lastPath = nwLipsum
|
||||
|
||||
nwGUI.rebuildIndex()
|
||||
nwGUI.mainTabs.setCurrentIndex(nwGUI.idxTabProj)
|
||||
nwGUI.mainStack.setCurrentIndex(nwGUI.idxTabProj)
|
||||
|
||||
assert nwGUI.projView.topLevelItemCount() > 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user