diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py index b8196cc2..4c215058 100644 --- a/nw/gui/__init__.py +++ b/nw/gui/__init__.py @@ -20,6 +20,7 @@ from nw.gui.elements.doceditor import GuiDocEditor from nw.gui.elements.doctree import GuiDocTree from nw.gui.elements.docviewer import GuiDocViewer from nw.gui.elements.noticebar import GuiNoticeBar +from nw.gui.elements.outline import GuiProjectOutline from nw.gui.elements.searchbar import GuiSearchBar from nw.gui.elements.viewdetails import GuiDocViewDetails @@ -43,6 +44,7 @@ __all__ = [ "GuiDocTree", "GuiDocViewer", "GuiNoticeBar", + "GuiProjectOutline", "GuiSearchBar", "GuiDocViewDetails", "GuiDocHighlighter", diff --git a/nw/gui/elements/__init__.py b/nw/gui/elements/__init__.py index 572473ee..1d885de0 100644 --- a/nw/gui/elements/__init__.py +++ b/nw/gui/elements/__init__.py @@ -5,6 +5,7 @@ from nw.gui.elements.doceditor import GuiDocEditor from nw.gui.elements.doctree import GuiDocTree from nw.gui.elements.docviewer import GuiDocViewer from nw.gui.elements.noticebar import GuiNoticeBar +from nw.gui.elements.outline import GuiProjectOutline from nw.gui.elements.searchbar import GuiSearchBar from nw.gui.elements.viewdetails import GuiDocViewDetails @@ -14,6 +15,7 @@ __all__ = [ "GuiDocTree", "GuiDocViewer", "GuiNoticeBar", + "GuiProjectOutline", "GuiSearchBar", "GuiDocViewDetails", ] diff --git a/nw/gui/elements/outline.py b/nw/gui/elements/outline.py new file mode 100644 index 00000000..166d6fef --- /dev/null +++ b/nw/gui/elements/outline.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +"""novelWriter GUI Project Outline + + novelWriter – GUI Project Outline +=================================== + Class holding the project outline view + + File History: + Created: 2019-11-16 [0.4.1] + +""" + +import logging +import nw + +from os import path + +from PyQt5.QtWidgets import ( + QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem +) + +from nw.constants import nwItemLayout + +logger = logging.getLogger(__name__) + +class GuiProjectOutline(QWidget): + + def __init__(self, theParent, theProject): + QWidget.__init__(self, theParent) + + logger.debug("Initialising ProjectOutline ...") + + self.mainConf = nw.CONFIG + self.theParent = theParent + self.theProject = theProject + self.theIndex = self.theParent.theIndex + + self.showWords = True + self.showSynopsis = True + self.showFilePath = False + + self.outerBox = QVBoxLayout() + self.mainTree = QTreeWidget() + + self.outerBox.addWidget(self.mainTree) + self.outerBox.setContentsMargins(0,0,0,0) + self.setLayout(self.outerBox) + + logger.debug("ProjectOutline initialisation complete") + + return + + def populateTree(self): + + self.mainTree.clear() + self.mainTree.setHeaderLabels(["Title","Level","Document","Line"]) + + currTitle = None + currChapter = None + currScene = None + + for tHandle in self.theProject.treeOrder: + + if tHandle not in self.theIndex.novelIndex: + continue + + nwItem = self.theProject.getItem(tHandle) + if nwItem.itemLayout == nwItemLayout.NOTE: + continue + + for tEntry in self.theIndex.novelIndex[tHandle]: + newItem = QTreeWidgetItem([""]*4) + newItem.setText(0, tEntry[2]) + newItem.setText(1, str(tEntry[1])) + newItem.setText(2, nwItem.itemName) + newItem.setText(3, str(tEntry[0])) + + if tEntry[1] == 1: + currTitle = newItem + self.mainTree.addTopLevelItem(newItem) + elif tEntry[1] == 2: + if currTitle is None: + self.mainTree.addTopLevelItem(newItem) + else: + currTitle.addChild(newItem) + currChapter = newItem + elif tEntry[1] == 3: + if currChapter is None: + if currTitle is None: + self.mainTree.addTopLevelItem(newItem) + else: + currTitle.addChild(newItem) + else: + currChapter.addChild(newItem) + currScene = newItem + elif tEntry[1] == 4: + if currScene is None: + if currChapter is None: + if currTitle is None: + self.mainTree.addTopLevelItem(newItem) + else: + currTitle.addChild(newItem) + else: + currChapter.addChild(newItem) + else: + currScene.addChild(newItem) + + newItem.setExpanded(True) + + return + +# END Class GuiProjectOutline diff --git a/nw/guimain.py b/nw/guimain.py index 0156877e..74f41f91 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -20,14 +20,14 @@ from PyQt5.QtCore import Qt, QTimer from PyQt5.QtGui import QIcon, QPixmap, QColor from PyQt5.QtWidgets import ( qApp, QMainWindow, QVBoxLayout, QFrame, QSplitter, QFileDialog, QShortcut, - QMessageBox, QProgressDialog, QDialog + QMessageBox, QProgressDialog, QDialog, QTabWidget ) from nw.gui import ( GuiMainMenu, GuiMainStatus, GuiTheme, GuiDocTree, GuiDocEditor, GuiDocViewer, GuiDocDetails, GuiSearchBar, GuiNoticeBar, GuiDocViewDetails, GuiConfigEditor, GuiProjectEditor, GuiExport, - GuiItemEditor, GuiTimeLineView, GuiSessionLogView + GuiItemEditor, GuiTimeLineView, GuiSessionLogView, GuiProjectOutline ) from nw.project import NWProject, NWDoc, NWItem, NWIndex, NWBackup from nw.tools import countWords @@ -75,6 +75,7 @@ class GuiMain(QMainWindow): self.searchBar = GuiSearchBar(self) self.treeMeta = GuiDocDetails(self, self.theProject) self.treeView = GuiDocTree(self, self.theProject) + self.projView = GuiProjectOutline(self, self.theProject) self.mainMenu = GuiMainMenu(self, self.theProject) # Minor Gui Elements @@ -109,19 +110,29 @@ class GuiMain(QMainWindow): self.splitView.addWidget(self.editPane) self.splitView.addWidget(self.viewPane) + self.tabWidget = QTabWidget() + self.tabWidget.setTabPosition(QTabWidget.East) + self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}") + self.tabWidget.addTab(self.splitView, "Editor") + self.tabWidget.addTab(self.projView, "Outline") + self.tabWidget.currentChanged.connect(self._mainTabChanged) + self.splitMain = QSplitter(Qt.Horizontal) self.splitMain.setContentsMargins(4,4,4,4) self.splitMain.addWidget(self.treePane) - self.splitMain.addWidget(self.splitView) + self.splitMain.addWidget(self.tabWidget) self.splitMain.setSizes(self.mainConf.mainPanePos) self.setCentralWidget(self.splitMain) self.idxTree = self.splitMain.indexOf(self.treePane) - self.idxMain = self.splitMain.indexOf(self.splitView) + self.idxMain = self.splitMain.indexOf(self.tabWidget) self.idxEditor = self.splitView.indexOf(self.editPane) self.idxViewer = self.splitView.indexOf(self.viewPane) + self.idxTabEdit = self.tabWidget.indexOf(self.splitView) + self.idxTabProj = self.tabWidget.indexOf(self.projView) + self.splitMain.setCollapsible(self.idxTree, False) self.splitMain.setCollapsible(self.idxMain, False) self.splitView.setCollapsible(self.idxEditor, False) @@ -876,4 +887,15 @@ class GuiMain(QMainWindow): self.toggleZenMode() return + def _mainTabChanged(self, tabIndex): + """Activated when the main window tab is changed. + """ + if tabIndex == self.idxTabEdit: + logger.verbose("Editor tab activated") + elif tabIndex == self.idxTabProj: + logger.verbose("Project outline tab activated") + if self.hasProject: + self.projView.populateTree() + return + # END Class GuiMain