From 67c2912c7f531fbef069746382a3da30d82e09bd Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Fri, 31 May 2019 18:59:53 +0200 Subject: [PATCH] Started adding timelibe view GUI --- nw/gui/mainmenu.py | 12 +++- nw/gui/timelineview.py | 127 +++++++++++++++++++++++++++++++++++++++++ nw/gui/winmain.py | 6 ++ nw/project/index.py | 38 ++++++++++++ 4 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 nw/gui/timelineview.py diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index 15a38754..a0816b36 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -311,13 +311,23 @@ class GuiMainMenu(QMenuBar): menuItem.triggered.connect(lambda : self.theParent.setFocus(2)) self.viewMenu.addAction(menuItem) - # # View > Document Pane 2 + # View > Document Pane 2 menuItem = QAction(QIcon.fromTheme("go-last"), "Right Document Pane", self) menuItem.setStatusTip("Move focus to right document pane") menuItem.setShortcut("Ctrl+3") menuItem.triggered.connect(lambda : self.theParent.setFocus(3)) self.viewMenu.addAction(menuItem) + # View > Separator + self.viewMenu.addSeparator() + + # View > Project Timeline + menuItem = QAction(QIcon.fromTheme("x-office-spreadsheet"), "Show Project Timeline", self) + menuItem.setStatusTip("Open the project timeline window") + menuItem.setShortcut("Ctrl+T") + menuItem.triggered.connect(self.theParent.showTimeLineDialog) + self.viewMenu.addAction(menuItem) + return def _buildEditMenu(self): diff --git a/nw/gui/timelineview.py b/nw/gui/timelineview.py new file mode 100644 index 00000000..a6acf870 --- /dev/null +++ b/nw/gui/timelineview.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +"""novelWriter GUI Timeline View + + novelWriter – GUI Timeline View +================================= + Class holding the timeline view window + + File History: + Created: 2019-05-30 [0.1.4] + +""" + +import logging +import nw + +from PyQt5.QtWidgets import QDialog, QVBoxLayout, QTableWidget, QTableWidgetItem, QDialogButtonBox + +logger = logging.getLogger(__name__) + +class GuiTimeLineView(QDialog): + + def __init__(self, theParent, theProject, theIndex): + QDialog.__init__(self, theParent) + + logger.debug("Initialising TimeLineView ...") + + self.mainConf = nw.CONFIG + self.theProject = theProject + self.theParent = theParent + self.theIndex = theIndex + self.theMatrix = {} + self.numRows = 0 + self.numCols = 0 + + self.outerBox = QVBoxLayout() + + self.setWindowTitle("Timeline View") + + self.mainTable = QTableWidget(1,1) + + self.setLayout(self.outerBox) + + self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close) + self.buttonBox.rejected.connect(self._doClose) + + self.outerBox.addWidget(self.mainTable) + self.outerBox.addWidget(self.buttonBox) + + self._buildMatrix() + self._buildNovelList() + + self.setMinimumSize(600,400) + + self.show() + + logger.debug("TimeLineView initialisation complete") + + return + + def _buildMatrix(self): + + self.theMatrix = { + "title" : [], # Size numRows - 1 + "depth" : [], # Size numRows - 1 + "handle" : [], # Size numRows - 1 + "line" : [], # Size numRows - 1 + "tags" : [], # Size numCols - 1 + "table" : [], # Size numRows - 1 x numCols - 1 + } + + self.numRows = 1 + self.numCols = 1 + for tHandle in self.theProject.treeOrder: + if tHandle not in self.theIndex.novelIndex: + continue + for nLine, nDepth, tTitle, tLayout in self.theIndex.novelIndex[tHandle]: + self.theMatrix["title"].append(tTitle) + self.theMatrix["depth"].append(nDepth) + self.theMatrix["handle"].append(tHandle) + self.theMatrix["line"].append(nLine) + self.numRows += 1 + + for tTag in self.theIndex.tagIndex: + self.theMatrix["tags"].append(tTag) + self.numCols += 1 + + # theTable = [[0]*(self.numCols-1)]*(self.numRows-1) + + # for i in range(self.numCols): + # for j in range(self.numRows): + + return + + def _buildNovelList(self): + + self.theIndex.buildNovelList() + self.numRows = len(self.theIndex.novelList) + 1 + + self.mainTable.setRowCount(self.numRows) + self.mainTable.setColumnCount(self.numCols) + + for n in range(self.numRows-1): + iDepth = self.theIndex.novelList[n][1] + iTitle = self.theIndex.novelList[n][2] + newItem = QTableWidgetItem(" "*iDepth + iTitle) + self.mainTable.setItem(n+1, 0, newItem) + + theTag = self.theMatrix["tags"][0] + theMap = self.theIndex.buildTagNovelMap(theTag) + newItem = QTableWidgetItem(theTag) + self.mainTable.setItem(0, 1, newItem) + for n in range(self.numRows-1): + newItem = QTableWidgetItem(str(theMap[n])) + self.mainTable.setItem(n+1, 1, newItem) + + # for n in range(self.numCols-1): + # iTag = self.theMatrix["tags"][n] + # newItem = QTableWidgetItem(iTag) + # self.mainTable.setItem(0, n+1, newItem) + + return + + def _doClose(self): + self.close() + return + +# END Class GuiItemEditor diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py index cf7592f9..31744acc 100644 --- a/nw/gui/winmain.py +++ b/nw/gui/winmain.py @@ -31,6 +31,7 @@ from nw.gui.mainmenu import GuiMainMenu from nw.gui.projecteditor import GuiProjectEditor from nw.gui.itemeditor import GuiItemEditor from nw.gui.statusbar import GuiMainStatus +from nw.gui.timelineview import GuiTimeLineView from nw.project.project import NWProject from nw.project.document import NWDoc from nw.project.item import NWItem @@ -472,6 +473,11 @@ class GuiMain(QMainWindow): self._setWindowTitle(self.theProject.projName) return True + def showTimeLineDialog(self): + dlgTLine = GuiTimeLineView(self, self.theProject, self.theIndex) + dlgTLine.exec_() + return True + def makeAlert(self, theMessage, theLevel=nwAlert.INFO): """Alert both the user and the logger at the same time. Message can be either a string or an array of strings. Severity level is 0 = info, 1 = warning, and 2 = error. diff --git a/nw/project/index.py b/nw/project/index.py index 86a3ad57..543caa31 100644 --- a/nw/project/index.py +++ b/nw/project/index.py @@ -69,6 +69,9 @@ class NWIndex(): self.noteIndex = {} self.novelIndex = {} + # Lists + self.novelList = [] + return def clearIndex(self): @@ -222,6 +225,10 @@ class NWIndex(): return True + ## + # Check @ Lines + ## + def scanThis(self, aLine): theBits = [] @@ -292,4 +299,35 @@ class NWIndex(): return isGood + ## + # Extract Data + ## + + def buildNovelList(self): + + self.novelList = [] + for tHandle in self.theProject.treeOrder: + if tHandle not in self.novelIndex: + continue + for tEntry in self.novelIndex[tHandle]: + self.novelList.append(tEntry) + + return True + + def buildTagNovelMap(self, theTag): + + tagList = [] + if theTag not in self.tagIndex: + return tagList + + try: + tagClass = nwItemClass[self.tagIndex[theTag][2]] + except: + logger.error("Could not map '%s' to nwItemClass" % self.tagIndex[theTag][2]) + return tagList + + tagList = [0]*len(self.novelList) + + return tagList + # END Class NWIndex