diff --git a/CREDITS.md b/CREDITS.md index e770434f..74089153 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -32,7 +32,7 @@ The following libraries are dependencies of novelWriter: Some of the assets bundled with novelWriter were adapted from the following sources: -* Typicons icons by Stephen Hutchings (CC BY-SA 4.0) +* [Typicons](https://github.com/stephenhutchings/typicons.font) icons by Stephen Hutchings (CC BY-SA 4.0) * Tomorrow syntax themes by Chris Kempson (MIT License) * Owl syntax themes by Sarah Drasner (MIT License) * Solarized themes by Ethan Schoonover, added by @nullbasis (MIT License) diff --git a/novelwriter/assets/icons/typicons_dark/icons.conf b/novelwriter/assets/icons/typicons_dark/icons.conf index bcaef71a..ccc55222 100644 --- a/novelwriter/assets/icons/typicons_dark/icons.conf +++ b/novelwriter/assets/icons/typicons_dark/icons.conf @@ -49,10 +49,12 @@ hash = typ_hash.svg maximise = typ_arrow-maximise.svg minimise = typ_arrow-minimise.svg proj_chapter = mixed_document-chapter.svg +proj_details = typ_th-list-grey.svg proj_document = typ_document-text.svg proj_folder = typ_folder.svg proj_note = mixed_document-note.svg proj_scene = mixed_document-scene.svg +proj_stats = typ_chart-bar-grey.svg proj_title = mixed_document-title.svg reference = typ_at.svg refresh = typ_refresh.svg @@ -76,3 +78,6 @@ status_time = typ_stopwatch-grey.svg sticky-off = typ_pin-outline.svg sticky-on = typ_pin.svg up = typ_chevron-up.svg +view_editor = typ_edit.svg +view_novel = typ_book-grey.svg +view_outline = typ_puzzle-outline.svg diff --git a/novelwriter/assets/icons/typicons_dark/typ_book-grey.svg b/novelwriter/assets/icons/typicons_dark/typ_book-grey.svg new file mode 100644 index 00000000..a0f49771 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/typ_book-grey.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_dark/typ_edit.svg b/novelwriter/assets/icons/typicons_dark/typ_edit.svg new file mode 100644 index 00000000..652dda33 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/typ_edit.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg b/novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg new file mode 100644 index 00000000..526feec8 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_light/icons.conf b/novelwriter/assets/icons/typicons_light/icons.conf index 8639908f..a26d18b4 100644 --- a/novelwriter/assets/icons/typicons_light/icons.conf +++ b/novelwriter/assets/icons/typicons_light/icons.conf @@ -49,10 +49,12 @@ hash = typ_hash.svg maximise = typ_arrow-maximise.svg minimise = typ_arrow-minimise.svg proj_chapter = mixed_document-chapter.svg +proj_details = typ_th-list-grey.svg proj_document = typ_document-text.svg proj_folder = typ_folder.svg proj_note = mixed_document-note.svg proj_scene = mixed_document-scene.svg +proj_stats = typ_chart-bar-grey.svg proj_title = mixed_document-title.svg reference = typ_at.svg refresh = typ_refresh.svg @@ -76,3 +78,6 @@ status_time = typ_stopwatch-grey.svg sticky-off = typ_pin-outline.svg sticky-on = typ_pin.svg up = typ_chevron-up.svg +view_editor = typ_edit.svg +view_novel = typ_book-grey.svg +view_outline = typ_puzzle-outline.svg diff --git a/novelwriter/assets/icons/typicons_light/typ_book-grey.svg b/novelwriter/assets/icons/typicons_light/typ_book-grey.svg new file mode 100644 index 00000000..06f58ae1 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/typ_book-grey.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_light/typ_edit.svg b/novelwriter/assets/icons/typicons_light/typ_edit.svg new file mode 100644 index 00000000..512c1592 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/typ_edit.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg b/novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg new file mode 100644 index 00000000..e2792d41 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/novelwriter/enum.py b/novelwriter/enum.py index 56340541..20332b2f 100644 --- a/novelwriter/enum.py +++ b/novelwriter/enum.py @@ -130,6 +130,20 @@ class nwState(Enum): # END Enum nwState +class nwView(Enum): + + EDITOR = 0 + PROJECT = 1 + NOVEL = 2 + OUTLINE = 3 + DETAILS = 4 + STATS = 5 + SET_PROJ = 6 + SET_MAIN = 7 + +# END Enum nwView + + class nwWidget(Enum): TREE = 1 diff --git a/novelwriter/gui/__init__.py b/novelwriter/gui/__init__.py index 405549cb..8364e342 100644 --- a/novelwriter/gui/__init__.py +++ b/novelwriter/gui/__init__.py @@ -29,6 +29,7 @@ from novelwriter.gui.outlinedetails import GuiOutlineDetails from novelwriter.gui.projtree import GuiProjectTree from novelwriter.gui.statusbar import GuiMainStatus from novelwriter.gui.theme import GuiTheme +from novelwriter.gui.viewsbar import GuiViewsBar __all__ = [ "GuiDocEditor", @@ -42,4 +43,5 @@ __all__ = [ "GuiOutlineDetails", "GuiProjectTree", "GuiTheme", + "GuiViewsBar", ] diff --git a/novelwriter/gui/itemdetails.py b/novelwriter/gui/itemdetails.py index 73082fa5..8b42b752 100644 --- a/novelwriter/gui/itemdetails.py +++ b/novelwriter/gui/itemdetails.py @@ -115,6 +115,7 @@ class GuiItemDetails(QWidget): self.usageData = QLabel("") self.usageData.setFont(fntValue) self.usageData.setAlignment(Qt.AlignLeft) + self.usageData.setWordWrap(True) # Character Count self.cCountName = QLabel(" "+self.tr("Characters")) diff --git a/novelwriter/gui/outlinedetails.py b/novelwriter/gui/outlinedetails.py index b45c298f..358a6531 100644 --- a/novelwriter/gui/outlinedetails.py +++ b/novelwriter/gui/outlinedetails.py @@ -26,11 +26,12 @@ along with this program. If not, see . import logging import novelwriter -from PyQt5.QtCore import Qt, QT_TRANSLATE_NOOP +from PyQt5.QtCore import Qt, QT_TRANSLATE_NOOP, pyqtSignal from PyQt5.QtWidgets import ( QScrollArea, QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel ) +from novelwriter.enum import nwView from novelwriter.common import checkInt from novelwriter.constants import trConst, nwKeyWords, nwLabels @@ -46,6 +47,8 @@ class GuiOutlineDetails(QScrollArea): "H4": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Section"), } + viewChangeRequested = pyqtSignal(nwView) + def __init__(self, theParent): QScrollArea.__init__(self, theParent) @@ -329,6 +332,7 @@ class GuiOutlineDetails(QScrollArea): if len(theLink) > 0: theBits = theLink.split("=") if len(theBits) == 2: + self.viewChangeRequested.emit(nwView.PROJECT) self.theParent.docViewer.loadFromTag(theBits[1]) return diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 19fe823a..e3151ea8 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -456,20 +456,18 @@ class GuiIcons: ICON_KEYS = { # Project and GUI icons - "novelwriter", "proj_nwx", - "cls_none", "cls_novel", "cls_plot", "cls_character", "cls_world", - "cls_timeline", "cls_object", "cls_entity", "cls_custom", "cls_archive", "cls_trash", - "proj_document", "proj_title", "proj_chapter", "proj_scene", "proj_note", "proj_folder", - "status_lang", "status_time", "status_idle", "status_stats", "status_lines", - "doc_h0", "doc_h1", "doc_h2", "doc_h3", "doc_h4", - "search_case", "search_regex", "search_word", "search_loop", "search_project", - "search_cancel", "search_preserve", + "novelwriter", "cls_archive", "cls_character", "cls_custom", "cls_entity", "cls_none", + "cls_novel", "cls_object", "cls_plot", "cls_timeline", "cls_trash", "cls_world", "doc_h0", + "doc_h1", "doc_h2", "doc_h3", "doc_h4", "proj_chapter", "proj_details", "proj_document", + "proj_folder", "proj_note", "proj_nwx", "proj_scene", "proj_stats", "proj_title", + "search_cancel", "search_case", "search_loop", "search_preserve", "search_project", + "search_regex", "search_word", "status_idle", "status_lang", "status_lines", + "status_stats", "status_time", "view_editor", "view_novel", "view_outline", # General Button Icons - "delete", "close", "done", "clear", "save", "add", "remove", - "search", "search_replace", "edit", "check", "cross", "hash", - "maximise", "minimise", "refresh", "reference", "backward", - "forward", "settings", "up", "down", + "add", "backward", "check", "clear", "close", "cross", "delete", "done", "down", "edit", + "forward", "hash", "maximise", "minimise", "reference", "refresh", "remove", "save", + "search_replace", "search", "settings", "up", # Switches "sticky-on", "sticky-off", diff --git a/novelwriter/gui/viewsbar.py b/novelwriter/gui/viewsbar.py new file mode 100644 index 00000000..92244781 --- /dev/null +++ b/novelwriter/gui/viewsbar.py @@ -0,0 +1,103 @@ +""" +novelWriter – GUI Main Window Views ToolBar +=========================================== +GUI class for the main window "Views" toolbar + +File History: +Created: 2022-05-10 [1.7b1] + +This file is a part of novelWriter +Copyright 2018–2022, Veronica Berglyd Olsen + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +import logging +import novelwriter + +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) + + logger.debug("Initialising GuiViewsBar ...") + + self.mainConf = novelwriter.CONFIG + self.theParent = theParent + self.theTheme = theParent.theTheme + + # Style + iPx = self.mainConf.pxInt(22) + + lblFont = self.theTheme.guiFont + lblFont.setPointSizeF(0.65*self.theTheme.fontPointSize) + self.setFont(lblFont) + + self.setMovable(False) + self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) + self.setIconSize(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.aProject.setIcon(self.theTheme.getIcon("view_editor")) + self.aProject.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.PROJECT)) + + self.aNovel = QAction(self.tr("Novel")) + self.aNovel.setIcon(self.theTheme.getIcon("view_novel")) + self.aNovel.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL)) + + self.aOutline = QAction(self.tr("Outline")) + self.aOutline.setIcon(self.theTheme.getIcon("view_outline")) + self.aOutline.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE)) + + self.aDetails = QAction(self.tr("Details")) + self.aDetails.setIcon(self.theTheme.getIcon("proj_details")) + self.aDetails.triggered.connect(lambda: self.viewChangeRequested.emit(nwView.DETAILS)) + + self.aStats = QAction(self.tr("Stats")) + self.aStats.setIcon(self.theTheme.getIcon("proj_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.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) + + logger.debug("GuiViewsBar initialisation complete") + + return + +# END Class GuiViewsBar diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 60fe0d23..ad06cc59 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -30,17 +30,17 @@ 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 ( GuiDocEditor, GuiDocViewDetails, GuiDocViewer, GuiItemDetails, GuiMainMenu, GuiMainStatus, GuiNovelTree, GuiOutline, GuiOutlineDetails, GuiProjectTree, - GuiTheme + GuiTheme, GuiViewsBar ) from novelwriter.dialogs import ( GuiAbout, GuiDocMerge, GuiDocSplit, GuiItemEditor, GuiPreferences, @@ -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) @@ -116,6 +114,7 @@ class GuiMain(QMainWindow): self.projView = GuiOutline(self) self.projMeta = GuiOutlineDetails(self) self.mainMenu = GuiMainMenu(self) + self.viewsBar = GuiViewsBar(self) # Connect Signals Between Main Elements self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage) @@ -128,48 +127,21 @@ 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) + self.projMeta.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) @@ -190,34 +162,32 @@ class GuiMain(QMainWindow): self.splitOutline.addWidget(self.projMeta) 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) - # Splitter : Project Tree / Main Tabs self.splitMain = QSplitter(Qt.Horizontal) - self.splitMain.setContentsMargins(mPx, mPx, mPx, mPx) + self.splitMain.setContentsMargins(0, 0, mPx, 0) self.splitMain.addWidget(self.treePane) - self.splitMain.addWidget(self.mainTabs) + self.splitMain.addWidget(self.splitDocs) self.splitMain.setSizes(self.mainConf.getMainPanePos()) + # Main Stack : Editor / Outline + self.mainStack = QStackedWidget() + self.mainStack.addWidget(self.splitMain) + self.mainStack.addWidget(self.splitOutline) + self.mainStack.currentChanged.connect(self._mainStackChanged) + # Indices of Splitter Widgets self.idxTree = self.splitMain.indexOf(self.treePane) - self.idxMain = self.splitMain.indexOf(self.mainTabs) + self.idxMain = self.splitMain.indexOf(self.splitDocs) 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.idxEditorView = self.mainStack.indexOf(self.splitMain) + self.idxOutlineView = 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) @@ -236,8 +206,9 @@ class GuiMain(QMainWindow): # Set Main Window Elements self.setMenuBar(self.mainMenu) - self.setCentralWidget(self.splitMain) + self.setCentralWidget(self.mainStack) self.setStatusBar(self.statusBar) + self.addToolBar(Qt.LeftToolBarArea, self.viewsBar) # Finalise Initialisation # ======================= @@ -448,7 +419,7 @@ class GuiMain(QMainWindow): self.theIndex.clearIndex() self.clearGUI() self.hasProject = False - self.mainTabs.setCurrentWidget(self.splitDocs) + self._changeView(nwView.PROJECT) return saveOK @@ -464,7 +435,7 @@ class GuiMain(QMainWindow): return False # Switch main tab to editor view - self.mainTabs.setCurrentWidget(self.splitDocs) + self._changeView(nwView.PROJECT) # Try to open the project if not self.theProject.openProject(projFile): @@ -603,7 +574,7 @@ class GuiMain(QMainWindow): return False self.closeDocument() - self.mainTabs.setCurrentWidget(self.splitDocs) + self._changeView(nwView.EDITOR) if self.docEditor.loadText(tHandle, tLine): if changeFocus: self.docEditor.setFocus() @@ -686,7 +657,7 @@ class GuiMain(QMainWindow): return False # Make sure main tab is in Editor view - self.mainTabs.setCurrentWidget(self.splitDocs) + self._changeView(nwView.EDITOR) logger.debug("Viewing document with handle '%s'", tHandle) if self.docViewer.loadText(tHandle): @@ -871,7 +842,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 @@ -932,7 +903,7 @@ class GuiMain(QMainWindow): return False logger.verbose("Forcing a rebuild of the Project Outline") - self.mainTabs.setCurrentWidget(self.splitOutline) + self._changeView(nwView.OUTLINE) self.projView.refreshTree(overRide=True) return True @@ -1245,19 +1216,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._changeView(nwView.EDITOR) self.docEditor.setFocus() elif paneNo == nwWidget.VIEWER: - self.mainTabs.setCurrentWidget(self.splitDocs) + self._changeView(nwView.EDITOR) self.docViewer.setFocus() elif paneNo == nwWidget.OUTLINE: - self.mainTabs.setCurrentWidget(self.splitOutline) + self._changeView(nwView.OUTLINE) self.projView.setFocus() return @@ -1290,7 +1261,6 @@ class GuiMain(QMainWindow): self.mainMenu.setFocusMode(self.isFocusMode) if self.isFocusMode: logger.debug("Activating Focus Mode") - self.mainTabs.setCurrentWidget(self.splitDocs) self.switchFocus(nwWidget.EDITOR) else: logger.debug("Deactivating Focus Mode") @@ -1299,7 +1269,7 @@ class GuiMain(QMainWindow): self.treePane.setVisible(isVisible) self.statusBar.setVisible(isVisible) self.mainMenu.setVisible(isVisible) - self.mainTabs.tabBar().setVisible(isVisible) + self.viewsBar.setVisible(isVisible) hideDocFooter = self.isFocusMode and self.mainConf.hideFocusFooter self.docEditor.docFooter.setVisible(not hideDocFooter) @@ -1513,6 +1483,36 @@ class GuiMain(QMainWindow): # Slots ## + @pyqtSlot(nwView) + def _changeView(self, view): + """Handle the requested change of view from the GuiViewBar. + """ + if view == nwView.EDITOR: + # Only change the main stack, but not the project stack + self.mainStack.setCurrentWidget(self.splitMain) + + elif view == nwView.PROJECT: + self.mainStack.setCurrentWidget(self.splitMain) + self.projStack.setCurrentWidget(self.treeView) + + elif view == nwView.NOVEL: + self.mainStack.setCurrentWidget(self.splitMain) + 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. @@ -1586,7 +1586,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.idxOutlineView: logger.verbose("Novel tree changed while Outline tab active") if self.hasProject: self.treeView.flushTreeOrder() @@ -1615,12 +1615,12 @@ 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: + if tabIndex == self.idxEditorView: logger.verbose("Editor tab activated") - elif tabIndex == self.idxTabProj: + elif tabIndex == self.idxOutlineView: logger.verbose("Project outline tab activated") if self.hasProject: self.projView.refreshTree() @@ -1628,7 +1628,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 diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index 65648862..ddb4f09b 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -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) diff --git a/tests/test_gui/test_gui_noveltree.py b/tests/test_gui/test_gui_noveltree.py index f2418a87..2bf2df8a 100644 --- a/tests/test_gui/test_gui_noveltree.py +++ b/tests/test_gui/test_gui_noveltree.py @@ -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 diff --git a/tests/test_gui/test_gui_outline.py b/tests/test_gui/test_gui_outline.py index 972e7456..40c58388 100644 --- a/tests/test_gui/test_gui_outline.py +++ b/tests/test_gui/test_gui_outline.py @@ -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.idxOutlineView) assert nwGUI.projView.topLevelItemCount() > 0