From b790fe7db9ba6a3be0f4ee47e7effdf7d8cbc795 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 14:27:57 +0200 Subject: [PATCH 01/11] Started adding a tabbed widget for the project settings GUI --- nw/gui/projecteditor.py | 66 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index c7638b87..1eccc5d3 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -15,15 +15,18 @@ import nw from os import path -from PyQt5.QtWidgets import QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit, QPlainTextEdit, QPushButton +from PyQt5.QtWidgets import ( + QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit, QPlainTextEdit, + QPushButton, QWidget, QTabWidget +) from PyQt5.QtSvg import QSvgWidget logger = logging.getLogger(__name__) class GuiProjectEditor(QDialog): - def __init__(self, guiParent, theProject): - QDialog.__init__(self, guiParent) + def __init__(self, theParent, theProject): + QDialog.__init__(self, theParent) logger.debug("Initialising ProjectEditor ...") @@ -37,27 +40,14 @@ class GuiProjectEditor(QDialog): self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","block.svg")) self.svgGradient = QSvgWidget(self.gradPath) self.svgGradient.setFixedWidth(80) + + # self.tabWidget = QTabWidget() + self.setLayout(self.outerBox) self.outerBox.addWidget(self.svgGradient) self.outerBox.addLayout(self.innerBox) - self.mainGroup = QGroupBox("Project Settings") - self.mainForm = QFormLayout() - - self.editName = QLineEdit() - self.editTitle = QLineEdit() - self.editAuthors = QPlainTextEdit() - - self.mainForm.addRow("Working Title", self.editName) - self.mainForm.addRow("Book Title", self.editTitle) - self.mainForm.addRow("Book Authors", self.editAuthors) - - self.editName.setText(self.theProject.projName) - self.editTitle.setText(self.theProject.bookTitle) - bookAuthors = "" - for bookAuthor in self.theProject.bookAuthors: - bookAuthors += bookAuthor+"\n" - self.editAuthors.setPlainText(bookAuthors) + self.tabSettings = GuiProjectEditMain(self.theProject) self.buttonBox = QHBoxLayout() self.closeButton = QPushButton("Close") @@ -68,8 +58,8 @@ class GuiProjectEditor(QDialog): self.buttonBox.addWidget(self.closeButton) self.buttonBox.addWidget(self.saveButton) - self.mainGroup.setLayout(self.mainForm) - self.innerBox.addWidget(self.mainGroup) + # self.mainGroup.setLayout(self.mainForm) + self.innerBox.addWidget(self.tabSettings) self.innerBox.addLayout(self.buttonBox) self.show() @@ -96,3 +86,35 @@ class GuiProjectEditor(QDialog): return # END Class GuiProjectEditor + +class GuiProjectEditMain(QGroupBox): + + def __init__(self, theProject): + QGroupBox.__init__(self) + + self.theProject = theProject + + # self.mainGroup = QGroupBox("Project Settings") + self.setTitle("Project Settings") + self.mainForm = QFormLayout() + + self.editName = QLineEdit() + self.editTitle = QLineEdit() + self.editAuthors = QPlainTextEdit() + + self.mainForm.addRow("Working Title", self.editName) + self.mainForm.addRow("Book Title", self.editTitle) + self.mainForm.addRow("Book Authors", self.editAuthors) + + self.editName.setText(self.theProject.projName) + self.editTitle.setText(self.theProject.bookTitle) + bookAuthors = "" + for bookAuthor in self.theProject.bookAuthors: + bookAuthors += bookAuthor+"\n" + self.editAuthors.setPlainText(bookAuthors) + + self.setLayout(self.mainForm) + + return + +# END Class GuiProjectEditMain From 0b98723b25e5b37a62a9d4d5b56b26700c1555fe Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 15:00:30 +0200 Subject: [PATCH 02/11] Redesigned the project settings GUI to use tabs --- nw/gui/projecteditor.py | 47 ++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index 1eccc5d3..2b1b2de3 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -17,7 +17,7 @@ from os import path from PyQt5.QtWidgets import ( QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit, QPlainTextEdit, - QPushButton, QWidget, QTabWidget + QPushButton, QWidget, QTabWidget, QDialogButtonBox ) from PyQt5.QtSvg import QSvgWidget @@ -31,6 +31,7 @@ class GuiProjectEditor(QDialog): logger.debug("Initialising ProjectEditor ...") self.mainConf = nw.CONFIG + self.theParent = theParent self.theProject = theProject self.outerBox = QHBoxLayout() self.innerBox = QVBoxLayout() @@ -41,26 +42,21 @@ class GuiProjectEditor(QDialog): self.svgGradient = QSvgWidget(self.gradPath) self.svgGradient.setFixedWidth(80) - # self.tabWidget = QTabWidget() + self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) + + self.tabWidget = QTabWidget() + self.tabWidget.addTab(self.tabMain,"Settings") self.setLayout(self.outerBox) self.outerBox.addWidget(self.svgGradient) self.outerBox.addLayout(self.innerBox) - self.tabSettings = GuiProjectEditMain(self.theProject) + self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.buttonBox.accepted.connect(self._doSave) + self.buttonBox.rejected.connect(self._doClose) - self.buttonBox = QHBoxLayout() - self.closeButton = QPushButton("Close") - self.closeButton.clicked.connect(self._doClose) - self.saveButton = QPushButton("Save") - self.saveButton.clicked.connect(self._doSave) - self.buttonBox.addStretch(1) - self.buttonBox.addWidget(self.closeButton) - self.buttonBox.addWidget(self.saveButton) - - # self.mainGroup.setLayout(self.mainForm) - self.innerBox.addWidget(self.tabSettings) - self.innerBox.addLayout(self.buttonBox) + self.innerBox.addWidget(self.tabWidget) + self.innerBox.addWidget(self.buttonBox) self.show() @@ -70,9 +66,9 @@ class GuiProjectEditor(QDialog): def _doSave(self): logger.verbose("ProjectEditor save button clicked") - projName = self.editName.text() - bookTitle = self.editTitle.text() - bookAuthors = self.editAuthors.toPlainText() + projName = self.tabMain.editName.text() + bookTitle = self.tabMain.editTitle.text() + bookAuthors = self.tabMain.editAuthors.toPlainText() self.theProject.setProjectName(projName) self.theProject.setBookTitle(bookTitle) self.theProject.setBookAuthors(bookAuthors) @@ -87,17 +83,14 @@ class GuiProjectEditor(QDialog): # END Class GuiProjectEditor -class GuiProjectEditMain(QGroupBox): +class GuiProjectEditMain(QWidget): - def __init__(self, theProject): - QGroupBox.__init__(self) - - self.theProject = theProject - - # self.mainGroup = QGroupBox("Project Settings") - self.setTitle("Project Settings") - self.mainForm = QFormLayout() + def __init__(self, theParent, theProject): + QWidget.__init__(self, theParent) + self.theParent = theParent + self.theProject = theProject + self.mainForm = QFormLayout() self.editName = QLineEdit() self.editTitle = QLineEdit() self.editAuthors = QPlainTextEdit() From 37ec8e6280402ada59def156edbaacc5394e4404 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 17:00:05 +0200 Subject: [PATCH 03/11] Added code to extend the status and importance colour lists --- nw/gui/projecteditor.py | 145 ++++++++++++++++++++++++++++++++++++++-- nw/project/project.py | 8 +++ 2 files changed, 147 insertions(+), 6 deletions(-) diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index 2b1b2de3..d4d26b6e 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -15,11 +15,13 @@ import nw from os import path -from PyQt5.QtWidgets import ( - QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit, QPlainTextEdit, - QPushButton, QWidget, QTabWidget, QDialogButtonBox -) +from PyQt5.QtGui import QIcon, QPixmap, QColor from PyQt5.QtSvg import QSvgWidget +from PyQt5.QtWidgets import ( + QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel, + QWidget, QTabWidget, QDialogButtonBox, QListWidget, QListWidgetItem, QPushButton, + QColorDialog +) logger = logging.getLogger(__name__) @@ -43,9 +45,13 @@ class GuiProjectEditor(QDialog): self.svgGradient.setFixedWidth(80) self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) + self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusCols) + self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importCols) self.tabWidget = QTabWidget() - self.tabWidget.addTab(self.tabMain,"Settings") + self.tabWidget.addTab(self.tabMain, "Settings") + self.tabWidget.addTab(self.tabStatus,"Status") + self.tabWidget.addTab(self.tabImport,"Importance") self.setLayout(self.outerBox) self.outerBox.addWidget(self.svgGradient) @@ -66,14 +72,21 @@ class GuiProjectEditor(QDialog): def _doSave(self): logger.verbose("ProjectEditor save button clicked") + projName = self.tabMain.editName.text() bookTitle = self.tabMain.editTitle.text() bookAuthors = self.tabMain.editAuthors.toPlainText() self.theProject.setProjectName(projName) self.theProject.setBookTitle(bookTitle) self.theProject.setBookAuthors(bookAuthors) - self.theProject.setProjectChanged(True) + + statusCol = self.tabStatus.getNewList() + importCol = self.tabImport.getNewList() + self.theProject.setStatusColours(statusCol) + self.theProject.setImportColours(importCol) + self.close() + return def _doClose(self): @@ -111,3 +124,123 @@ class GuiProjectEditMain(QWidget): return # END Class GuiProjectEditMain + +class GuiProjectEditStatus(QWidget): + + def __init__(self, theParent, colList): + QWidget.__init__(self, theParent) + + self.theParent = theParent + self.colList = colList.copy() + self.colChanged = False + + self.mainBox = QHBoxLayout() + self.mainForm = QVBoxLayout() + + self.listBox = QListWidget() + self.listBox.itemSelectionChanged.connect(self._selectedItem) + + for iName, iR, iG, iB in self.colList: + self._addItem(iName, iR, iG, iB) + + self.editName = QLineEdit() + self.newButton = QPushButton("New") + self.delButton = QPushButton("Delete") + self.saveButton = QPushButton("Save") + self.colPixmap = QPixmap(16,16) + self.colPixmap.fill(QColor(120,120,120)) + self.colButton = QPushButton(QIcon(self.colPixmap),"Colour") + self.colButton.setIconSize(self.colPixmap.rect().size()) + + self.newButton.clicked.connect(self._newItem) + self.saveButton.clicked.connect(self._saveItem) + self.colButton.clicked.connect(self._selectColour) + + self.mainForm.addWidget(self.newButton) + self.mainForm.addWidget(self.delButton) + self.mainForm.addStretch(1) + self.mainForm.addWidget(QLabel("Name")) + self.mainForm.addWidget(self.editName) + self.mainForm.addWidget(self.colButton) + self.mainForm.addStretch(1) + self.mainForm.addWidget(self.saveButton) + + self.mainBox.addWidget(self.listBox) + self.mainBox.addLayout(self.mainForm) + + self.setLayout(self.mainBox) + + return + + def getNewList(self): + if self.colChanged: + newList = [] + for n in range(self.listBox.count()): + nItem = self.listBox.item(n) + nName = nItem.text() + nImg = nItem.icon().pixmap(16,16).toImage() + nCol = QColor(nImg.pixel(7,7)) + newList.append((nName,nCol.red(),nCol.green(),nCol.blue())) + return newList + return self.colList + + ## + # User Actions + ## + + def _selectColour(self): + logger.verbose("Item colour button clicked") + selImg = self.colButton.icon().pixmap(16,16).toImage() + selCol = QColor(selImg.pixel(7,7)) + newCol = QColorDialog.getColor(selCol, self, "Select Colour", QColorDialog.DontUseNativeDialog) + if newCol: + colPixmap = QPixmap(16,16) + colPixmap.fill(newCol) + self.colButton.setIcon(QIcon(colPixmap)) + self.colButton.setIconSize(colPixmap.rect().size()) + return + + def _newItem(self): + self._addItem("New Item", 0, 0, 0) + return + + def _saveItem(self): + logger.verbose("Item save button clicked") + selItem = self._getSelectedItem() + if selItem is not None: + selItem.setText(self.editName.text().strip()) + selItem.setIcon(self.colButton.icon()) + self.colChanged = True + return + + def _addItem(self, iName, iR, iG, iB): + logger.verbose("New item button clicked") + newIcon = QPixmap(16,16) + newIcon.fill(QColor(iR,iG,iB)) + newItem = QListWidgetItem() + newItem.setText(iName) + newItem.setIcon(QIcon(newIcon)) + self.listBox.addItem(newItem) + return + + def _selectedItem(self): + logger.verbose("Item selected") + selItem = self._getSelectedItem() + if selItem is not None: + self.editName.setText(selItem.text()) + self.colButton.setIcon(selItem.icon()) + return + + ## + # Internal Functions + ## + + def _getSelectedItem(self): + selItem = self.listBox.selectedItems() + if len(selItem) == 0: + return None + if isinstance(selItem[0], QListWidgetItem): + return selItem[0] + return None + +# END Class GuiProjectEditStatus diff --git a/nw/project/project.py b/nw/project/project.py index a2462d4d..2236592d 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -353,6 +353,14 @@ class NWProject(): self.setProjectChanged(True) return True + def setStatusColours(self, newCols): + self.setProjectChanged(True) + return + + def setImportColours(self, newCols): + self.setProjectChanged(True) + return + def setProjectChanged(self, bValue): self.projChanged = bValue self.theParent.setProjectStatus(self.projChanged) From 540aa7fcbc0c7700c9e785354d638256345dee5d Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 19:03:59 +0200 Subject: [PATCH 04/11] Moved item status recrod keeping into a separate iterable class --- nw/enum.py | 9 ++++ nw/gui/docdetails.py | 13 +----- nw/gui/doctree.py | 13 ++---- nw/gui/itemeditor.py | 8 ++-- nw/gui/projecteditor.py | 59 ++++++++++++++++-------- nw/gui/winmain.py | 26 ++++------- nw/project/item.py | 12 +++-- nw/project/project.py | 61 +++++++++++++------------ nw/project/status.py | 78 ++++++++++++++++++++++++++++++++ sample/sampleNovel/nwProject.nwx | 30 ++++++------ 10 files changed, 200 insertions(+), 109 deletions(-) create mode 100644 nw/project/status.py diff --git a/nw/enum.py b/nw/enum.py index 61540882..5bbdb311 100644 --- a/nw/enum.py +++ b/nw/enum.py @@ -76,3 +76,12 @@ class nwAlert(Enum): BUG = 3 # END Enum nwAlert + +class nwChanged(Enum): + + NONE = 0 + DELETE = 1 + NEW = 2 + IGNORE = 3 + +# END Enum nwAlert diff --git a/nw/gui/docdetails.py b/nw/gui/docdetails.py index 1552640a..b1f91345 100644 --- a/nw/gui/docdetails.py +++ b/nw/gui/docdetails.py @@ -70,20 +70,9 @@ class GuiDocDetails(QFrame): if nwItem is None: colTwo = [""]*4 else: - itemStatus = nwItem.itemStatus - if nwItem.itemClass == nwItemClass.NOVEL: - if itemStatus < 0 or itemStatus >= len(self.theParent.statusLabels): - statusLabel = self.theParent.statusLabels[0] - else: - statusLabel = self.theParent.statusLabels[itemStatus] - else: - if itemStatus < 0 or itemStatus >= len(self.theParent.importLabels): - statusLabel = self.theParent.importLabels[0] - else: - statusLabel = self.theParent.importLabels[itemStatus] colTwo = [ nwItem.itemName, - statusLabel, + nwItem.itemStatus, nwLabels.CLASS_NAME[nwItem.itemClass], nwLabels.LAYOUT_NAME[nwItem.itemLayout], ] diff --git a/nw/gui/doctree.py b/nw/gui/doctree.py index 8844866c..e764709a 100644 --- a/nw/gui/doctree.py +++ b/nw/gui/doctree.py @@ -259,19 +259,12 @@ class GuiDocTree(QTreeWidget): tStatus = nwLabels.CLASS_FLAG[nwItem.itemClass] if nwItem.itemType == nwItemType.FILE: tStatus += "."+nwLabels.LAYOUT_FLAG[nwItem.itemLayout] - nStatus = nwItem.itemStatus if tClass == nwItemClass.NOVEL: - if nStatus < 0 or nStatus >= len(self.theParent.statusIcons): - flagIcon = self.theParent.statusIcons[0] - else: - flagIcon = self.theParent.statusIcons[nStatus] + flagIcon = self.theParent.statusIcons[nwItem.itemStatus] else: - if nStatus < 0 or nStatus >= len(self.theParent.importIcons): - flagIcon = self.theParent.importIcons[0] - else: - flagIcon = self.theParent.importIcons[nStatus] + flagIcon = self.theParent.importIcons[nwItem.itemStatus] - trItem.setText(self.C_NAME,tName) + trItem.setText(self.C_NAME, tName) trItem.setText(self.C_FLAGS,tStatus) trItem.setIcon(self.C_FLAGS,flagIcon) diff --git a/nw/gui/itemeditor.py b/nw/gui/itemeditor.py index 3cc48140..7939b8a5 100644 --- a/nw/gui/itemeditor.py +++ b/nw/gui/itemeditor.py @@ -55,14 +55,14 @@ class GuiItemEditor(QDialog): self.editLayout = QComboBox() if self.theItem.itemClass == nwItemClass.NOVEL: - for n in range(len(self.theParent.statusLabels)): + for sLabel, sCol in self.theProject.statusItems: self.editStatus.addItem( - self.theParent.statusIcons[n], self.theParent.statusLabels[n], n + self.theParent.statusIcons[sLabel], sLabel, sLabel ) else: - for n in range(len(self.theParent.statusLabels)): + for sLabel, sCol in self.theProject.importItems: self.editStatus.addItem( - self.theParent.importIcons[n], self.theParent.importLabels[n], n + self.theParent.importIcons[sLabel], sLabel, sLabel ) self.validLayouts = [] diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index d4d26b6e..640cb1a6 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -13,9 +13,9 @@ import logging import nw -from os import path +from os import path -from PyQt5.QtGui import QIcon, QPixmap, QColor +from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush from PyQt5.QtSvg import QSvgWidget from PyQt5.QtWidgets import ( QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel, @@ -23,6 +23,8 @@ from PyQt5.QtWidgets import ( QColorDialog ) +from nw.enum import nwChanged + logger = logging.getLogger(__name__) class GuiProjectEditor(QDialog): @@ -45,8 +47,8 @@ class GuiProjectEditor(QDialog): self.svgGradient.setFixedWidth(80) self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) - self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusCols) - self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importCols) + self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusItems) + self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importItems) self.tabWidget = QTabWidget() self.tabWidget.addTab(self.tabMain, "Settings") @@ -80,10 +82,10 @@ class GuiProjectEditor(QDialog): self.theProject.setBookTitle(bookTitle) self.theProject.setBookAuthors(bookAuthors) - statusCol = self.tabStatus.getNewList() - importCol = self.tabImport.getNewList() - self.theProject.setStatusColours(statusCol) - self.theProject.setImportColours(importCol) + statusCol, statusChange = self.tabStatus.getNewList() + importCol, importChange = self.tabImport.getNewList() + self.theProject.setStatusColours(statusCol, statusChange) + self.theProject.setImportColours(importCol, importChange) self.close() @@ -127,11 +129,12 @@ class GuiProjectEditMain(QWidget): class GuiProjectEditStatus(QWidget): - def __init__(self, theParent, colList): + def __init__(self, theParent, theStatus): QWidget.__init__(self, theParent) self.theParent = theParent - self.colList = colList.copy() + self.theStatus = theStatus + self.colNames = [] self.colChanged = False self.mainBox = QHBoxLayout() @@ -140,8 +143,9 @@ class GuiProjectEditStatus(QWidget): self.listBox = QListWidget() self.listBox.itemSelectionChanged.connect(self._selectedItem) - for iName, iR, iG, iB in self.colList: - self._addItem(iName, iR, iG, iB) + for iName, iCol in self.theStatus: + self._addItem(iName, iCol) + self.colNames.append(iName) self.editName = QLineEdit() self.newButton = QPushButton("New") @@ -153,6 +157,7 @@ class GuiProjectEditStatus(QWidget): self.colButton.setIconSize(self.colPixmap.rect().size()) self.newButton.clicked.connect(self._newItem) + self.delButton.clicked.connect(self._delItem) self.saveButton.clicked.connect(self._saveItem) self.colButton.clicked.connect(self._selectColour) @@ -181,8 +186,8 @@ class GuiProjectEditStatus(QWidget): nImg = nItem.icon().pixmap(16,16).toImage() nCol = QColor(nImg.pixel(7,7)) newList.append((nName,nCol.red(),nCol.green(),nCol.blue())) - return newList - return self.colList + return newList, self.colNames + return None, None ## # User Actions @@ -201,7 +206,25 @@ class GuiProjectEditStatus(QWidget): return def _newItem(self): - self._addItem("New Item", 0, 0, 0) + newItem = self._addItem("New Item", (0, 0, 0)) + newItem.setBackground(QBrush(QColor(0,255,0,80))) + self.colNames.append(None) + self.colChanged = True + return + + def _delItem(self): + selItem = self._getSelectedItem() + colDel = QBrush(QColor(255,0,0,80)) + colNone = QBrush(QColor(0,0,0,0)) + if selItem is not None: + sText = selItem.text() + iRow = self.listBox.row(selItem) + if sText == "** Delete **": + selItem.setBackground(colNone) + selItem.setText(self.colNames[iRow]) + else: + selItem.setBackground(colDel) + selItem.setText("** Delete **") return def _saveItem(self): @@ -213,15 +236,15 @@ class GuiProjectEditStatus(QWidget): self.colChanged = True return - def _addItem(self, iName, iR, iG, iB): + def _addItem(self, iName, iCol): logger.verbose("New item button clicked") newIcon = QPixmap(16,16) - newIcon.fill(QColor(iR,iG,iB)) + newIcon.fill(QColor(*iCol)) newItem = QListWidgetItem() newItem.setText(iName) newItem.setIcon(QIcon(newIcon)) self.listBox.addItem(newItem) - return + return newItem def _selectedItem(self): logger.verbose("Item selected") diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py index 6bcea030..58324e1c 100644 --- a/nw/gui/winmain.py +++ b/nw/gui/winmain.py @@ -61,10 +61,8 @@ class GuiMain(QMainWindow): self.statusBar = GuiMainStatus(self) # Minor Gui Elements - self.statusIcons = [] - self.statusLabels = [] - self.importIcons = [] - self.importLabels = [] + self.statusIcons = [] + self.importIcons = [] # Assemble Main Window self.treePane = QFrame() @@ -397,23 +395,19 @@ class GuiMain(QMainWindow): return True def _makeStatusIcons(self): - self.statusIcons = [] - self.statusLabels = [] - for sLabel, sR, sG, sB in self.theProject.statusCols: + self.statusIcons = {} + for sLabel, sCol in self.theProject.statusItems: theIcon = QPixmap(32,32) - theIcon.fill(QColor(sR,sG,sB)) - self.statusIcons.append(QIcon(theIcon)) - self.statusLabels.append(sLabel) + theIcon.fill(QColor(*sCol)) + self.statusIcons[sLabel] = QIcon(theIcon) return def _makeImportIcons(self): - self.importIcons = [] - self.importLabels = [] - for sLabel, sR, sG, sB in self.theProject.importCols: + self.importIcons = {} + for sLabel, sCol in self.theProject.importItems: theIcon = QPixmap(32,32) - theIcon.fill(QColor(sR,sG,sB)) - self.importIcons.append(QIcon(theIcon)) - self.importLabels.append(sLabel) + theIcon.fill(QColor(*sCol)) + self.importIcons[sLabel] = QIcon(theIcon) return ## diff --git a/nw/project/item.py b/nw/project/item.py index 7ea631ac..367167c8 100644 --- a/nw/project/item.py +++ b/nw/project/item.py @@ -26,7 +26,9 @@ class NWItem(): MAX_DEPTH = 8 - def __init__(self): + def __init__(self, theProject): + + self.theProject = theProject self.itemName = "" self.itemHandle = None @@ -35,7 +37,7 @@ class NWItem(): self.itemType = nwItemType.NO_TYPE self.itemClass = nwItemClass.NO_CLASS self.itemLayout = nwItemLayout.NO_LAYOUT - self.itemStatus = 0 + self.itemStatus = None self.isExpanded = False # Document Meta Data @@ -158,8 +160,10 @@ class NWItem(): return def setStatus(self, theStatus): - theStatus = checkInt(theStatus,0) - self.itemStatus = theStatus + if self.itemClass == nwItemClass.NOVEL: + self.itemStatus = self.theProject.statusItems.checkEntry(theStatus) + else: + self.itemStatus = self.theProject.importItems.checkEntry(theStatus) return def setExpanded(self, expState): diff --git a/nw/project/project.py b/nw/project/project.py index 2236592d..360ca69b 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -13,15 +13,16 @@ import logging import nw -from os import path, mkdir, listdir -from lxml import etree -from hashlib import sha256 -from datetime import datetime -from time import time +from os import path, mkdir, listdir +from lxml import etree +from hashlib import sha256 +from datetime import datetime +from time import time -from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert -from nw.common import checkString, checkBool -from nw.project.item import NWItem +from nw.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert +from nw.common import checkString, checkBool +from nw.project.item import NWItem +from nw.project.status import NWStatus logger = logging.getLogger(__name__) @@ -54,8 +55,8 @@ class NWProject(): # Project Settings self.spellCheck = False - self.statusCols = None - self.importCols = None + self.statusItems = NWStatus() + self.importItems = NWStatus() self.lastEdited = None self.lastViewed = None @@ -75,7 +76,7 @@ class NWProject(): if not self.checkRootUnique(rootClass): self.makeAlert("Duplicate root item detected!", nwAlert.ERROR) return None - newItem = NWItem() + newItem = NWItem(self) newItem.setName(rootName) newItem.setType(nwItemType.ROOT) newItem.setClass(rootClass) @@ -83,7 +84,7 @@ class NWProject(): return newItem.itemHandle def newFolder(self, folderName, folderClass, pHandle): - newItem = NWItem() + newItem = NWItem(self) newItem.setName(folderName) newItem.setType(nwItemType.FOLDER) newItem.setClass(folderClass) @@ -91,7 +92,7 @@ class NWProject(): return newItem.itemHandle def newFile(self, fileName, fileClass, pHandle): - newItem = NWItem() + newItem = NWItem(self) newItem.setName(fileName) newItem.setType(nwItemType.FILE) if fileClass == nwItemClass.NOVEL: @@ -103,7 +104,7 @@ class NWProject(): return newItem.itemHandle def addTrash(self): - newItem = NWItem() + newItem = NWItem(self) newItem.setName("Trash") newItem.setType(nwItemType.TRASH) newItem.setClass(nwItemClass.TRASH) @@ -144,18 +145,16 @@ class NWProject(): self.bookTitle = "" self.bookAuthors = [] self.spellCheck = False - self.statusCols = [ - ("New", 100,100,100), - ("Note", 200, 50, 0), - ("Draft", 200,150, 0), - ("Finished", 50,200, 0), - ] - self.importCols = [ - ("None", 100,100,100), - ("Minor", 200, 50, 0), - ("Major", 200,150, 0), - ("Main", 50,200, 0), - ] + self.statusItems = NWStatus() + self.statusItems.addEntry("New", (100,100,100)) + self.statusItems.addEntry("Note", (200, 50, 0)) + self.statusItems.addEntry("Draft", (200,150, 0)) + self.statusItems.addEntry("Finished",( 50,200, 0)) + self.importItems = NWStatus() + self.importItems.addEntry("None", (100,100,100)) + self.importItems.addEntry("Minor", (200, 50, 0)) + self.importItems.addEntry("Major", (200,150, 0)) + self.importItems.addEntry("Main", ( 50,200, 0)) return @@ -228,7 +227,7 @@ class NWProject(): pHandle = itemAttrib["parent"] else: pHandle = None - nwItem = NWItem() + nwItem = NWItem(self) for xValue in xItem: nwItem.setFromTag(xValue.tag,xValue.text) self._appendItem(tHandle,pHandle,nwItem) @@ -353,11 +352,13 @@ class NWProject(): self.setProjectChanged(True) return True - def setStatusColours(self, newCols): + def setStatusColours(self, newCols, colChanged): + print(newCols,colChanged) self.setProjectChanged(True) return - def setImportColours(self, newCols): + def setImportColours(self, newCols, colChanged): + print(newCols,colChanged) self.setProjectChanged(True) return @@ -500,7 +501,7 @@ class NWProject(): nOrph = 0 for oHandle in orphanFiles: nOrph += 1 - orItem = NWItem() + orItem = NWItem(self) orItem.setName("Orphaned File %d" % nOrph) orItem.setType(nwItemType.FILE) orItem.setClass(nwItemClass.NO_CLASS) diff --git a/nw/project/status.py b/nw/project/status.py new file mode 100644 index 00000000..7197e1da --- /dev/null +++ b/nw/project/status.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +"""novelWriter Item Status + + novelWriter – Item Status +=========================== + Class holding the project's item statuses + + File History: + Created: 2019-05-19 [0.1.3] + +""" + +import logging +import nw + +from nw.enum import nwItemClass +from nw.common import checkInt + +logger = logging.getLogger(__name__) + +class NWStatus(): + + def __init__(self): + self.theLabels = [] + self.theColours = [] + self.theMap = {} + self.theCount = 0 + self.theIndex = 0 + return + + def addEntry(self, theLabel, theColours): + theLabel = theLabel.strip() + if self.lookupEntry(theLabel) is None: + self.theLabels.append(theLabel) + self.theColours.append(theColours) + self.theMap[theLabel] = self.theCount + self.theCount += 1 + return True + + def lookupEntry(self, theLabel): + theLabel = theLabel.strip() + if theLabel in self.theMap.keys(): + return self.theMap[theLabel] + return None + + def checkEntry(self, theStatus): + theStatus = theStatus.strip() + if isinstance(theStatus, str): + if self.lookupEntry(theStatus) is not None: + return theStatus + theStatus = checkInt(theStatus, None, False) + if theStatus is None: + return None + if theStatus >= 0 and theStatus < self.theCount: + return self.theLabels[theStatus] + + ## + # Iterator Bits + ## + + def __getitem__(self, n): + if n >= 0 and n < self.theCount: + return self.theLabels[n], self.theColours[n] + return None, None + + def __iter__(self): + self.theIndex = 0 + return self + + def __next__(self): + if self.theIndex < self.theCount: + theLabel, theColour = self.__getitem__(self.theIndex) + self.theIndex += 1 + return theLabel, theColour + else: + raise StopIteration + +# END Class NWStatus diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx index 0d421f0e..89cd44e8 100644 --- a/sample/sampleNovel/nwProject.nwx +++ b/sample/sampleNovel/nwProject.nwx @@ -1,5 +1,5 @@ - + Sample Project Sample Project @@ -16,14 +16,14 @@ Novel ROOT NOVEL - 0 + New True Title Page FILE NOVEL - 2 + Draft False TITLE 23 @@ -35,14 +35,14 @@ Some Chapter FOLDER NOVEL - 1 + Note True New Scene FILE NOVEL - 2 + Draft False SCENE 2571 @@ -54,7 +54,7 @@ File With Stuff FILE NOVEL - 1 + Note False SCENE 578 @@ -66,7 +66,7 @@ New File FILE NOVEL - 0 + Note False SCENE 69 @@ -78,21 +78,21 @@ Characters ROOT CHARACTER - 0 + None True Main Characters FOLDER CHARACTER - 0 + None True John Smith FILE CHARACTER - 0 + Minor False NOTE 42 @@ -104,7 +104,7 @@ Jane Smith FILE CHARACTER - 0 + Major False NOTE 51 @@ -116,14 +116,14 @@ Locations ROOT WORLD - 0 + None True Earth FILE WORLD - 0 + None False NOTE 0 @@ -135,14 +135,14 @@ Trash TRASH TRASH - 0 + None True Orphaned File 2 FILE NO_CLASS - 0 + None False NO_LAYOUT 14 From edb6c41788080c7902cbddf6f8be3e428854054a Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 21:55:50 +0200 Subject: [PATCH 05/11] Manipulating statuses now seem to work, and update correctly. --- nw/enum.py | 9 ---- nw/gui/doctabs.py | 111 ---------------------------------------- nw/gui/doctree.py | 9 +++- nw/gui/itemeditor.py | 4 +- nw/gui/projecteditor.py | 58 +++++++++++---------- nw/gui/winmain.py | 4 +- nw/project/document.py | 3 +- nw/project/project.py | 30 +++++++++-- nw/project/status.py | 58 ++++++++++++++++----- 9 files changed, 114 insertions(+), 172 deletions(-) delete mode 100644 nw/gui/doctabs.py diff --git a/nw/enum.py b/nw/enum.py index 5bbdb311..61540882 100644 --- a/nw/enum.py +++ b/nw/enum.py @@ -76,12 +76,3 @@ class nwAlert(Enum): BUG = 3 # END Enum nwAlert - -class nwChanged(Enum): - - NONE = 0 - DELETE = 1 - NEW = 2 - IGNORE = 3 - -# END Enum nwAlert diff --git a/nw/gui/doctabs.py b/nw/gui/doctabs.py deleted file mode 100644 index b8e5c46c..00000000 --- a/nw/gui/doctabs.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- coding: utf-8 -*- -"""novelWriter GUI Document Tabs - - novelWriter – GUI Document Tabs -================================= - Class holding the document tab view - - File History: - Created: 2018-09-29 [0.0.1] - -""" - -import logging -import nw - -from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QTabWidget, QWidget, QVBoxLayout - -from nw.gui.doceditor import GuiDocEditor -from nw.gui.projecteditor import GuiProjectEditor -from nw.gui.aboutview import GuiAboutView - -logger = logging.getLogger(__name__) - -class GuiDocTabs(QTabWidget): - - def __init__(self): - QTabWidget.__init__(self) - - logger.debug("Initialising DocTabs ...") - self.mainConf = nw.CONFIG - self.tabList = [] - - self.resize(900,500) - self.setTabsClosable(True) - - self.tabBar().tabCloseRequested.connect(self._doCloseTab) - - self.createTab(None,nw.DOCTYPE_ABOUT) - - logger.debug("DocTabs initialisation complete") - - return - - def createTab(self, theName=None, tabType=None): - if tabType == nw.DOCTYPE_ABOUT: - self._createTabAbout() - return True - elif tabType == nw.DOCTYPE_PROJECT: - self._createTabProject(theName) - return True - elif tabType == nw.DOCTYPE_DOC: - self._createTabDoc(theName) - return True - return False - - # - # Internal Functions - # - - def _createTabDoc(self, docName=None): - if docName is None: - tabName = "New Document" - else: - tabName = docName - thisTab = GuiDocEditor() - self.addTab(thisTab,tabName) - self.setCurrentWidget(thisTab) - return True - - def _createTabProject(self, projectName=None): - """Display or create the project settings page. - """ - for i in range(self.count()): - thisTab = self.widget(i) - if isinstance(thisTab, GuiProjectEditor): - self.setCurrentWidget(thisTab) - return True - if projectName is None: - tabName = "New Project" - else: - tabName = projectName - thisTab = GuiProjectEditor() - self.addTab(thisTab,tabName) - self.setCurrentWidget(thisTab) - return True - - def _createTabAbout(self): - """Display or create the About tab. - """ - for i in range(self.count()): - thisTab = self.widget(i) - if isinstance(thisTab, GuiAboutView): - self.setCurrentWidget(thisTab) - return True - thisTab = GuiAboutView() - self.addTab(thisTab,"About") - self.setCurrentWidget(thisTab) - return True - - # - # Signals - # - - def _doCloseTab(self, tabIdx): - logger.verbose("User requested tab %d to be closed." % tabIdx) - self.removeTab(tabIdx) - logger.verbose("Tab %d closed." % tabIdx) - return - -# END Class GuiDocTabs diff --git a/nw/gui/doctree.py b/nw/gui/doctree.py index e764709a..e0f066ad 100644 --- a/nw/gui/doctree.py +++ b/nw/gui/doctree.py @@ -259,10 +259,15 @@ class GuiDocTree(QTreeWidget): tStatus = nwLabels.CLASS_FLAG[nwItem.itemClass] if nwItem.itemType == nwItemType.FILE: tStatus += "."+nwLabels.LAYOUT_FLAG[nwItem.itemLayout] + iStatus = nwItem.itemStatus if tClass == nwItemClass.NOVEL: - flagIcon = self.theParent.statusIcons[nwItem.itemStatus] + if iStatus is None: + iStatus = self.theProject.statusItems.checkEntry(iStatus) + flagIcon = self.theParent.statusIcons[iStatus] else: - flagIcon = self.theParent.importIcons[nwItem.itemStatus] + if iStatus is None: + iStatus = self.theProject.importItems.checkEntry(iStatus) + flagIcon = self.theParent.importIcons[iStatus] trItem.setText(self.C_NAME, tName) trItem.setText(self.C_FLAGS,tStatus) diff --git a/nw/gui/itemeditor.py b/nw/gui/itemeditor.py index 7939b8a5..06edf0fd 100644 --- a/nw/gui/itemeditor.py +++ b/nw/gui/itemeditor.py @@ -55,12 +55,12 @@ class GuiItemEditor(QDialog): self.editLayout = QComboBox() if self.theItem.itemClass == nwItemClass.NOVEL: - for sLabel, sCol in self.theProject.statusItems: + for sLabel, _, _ in self.theProject.statusItems: self.editStatus.addItem( self.theParent.statusIcons[sLabel], sLabel, sLabel ) else: - for sLabel, sCol in self.theProject.importItems: + for sLabel, _, _ in self.theProject.importItems: self.editStatus.addItem( self.theParent.importIcons[sLabel], sLabel, sLabel ) diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index 640cb1a6..6f5556a2 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -22,8 +22,7 @@ from PyQt5.QtWidgets import ( QWidget, QTabWidget, QDialogButtonBox, QListWidget, QListWidgetItem, QPushButton, QColorDialog ) - -from nw.enum import nwChanged +from nw.enum import nwAlert logger = logging.getLogger(__name__) @@ -46,6 +45,7 @@ class GuiProjectEditor(QDialog): self.svgGradient = QSvgWidget(self.gradPath) self.svgGradient.setFixedWidth(80) + self.theProject.countStatus() self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusItems) self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importItems) @@ -82,10 +82,10 @@ class GuiProjectEditor(QDialog): self.theProject.setBookTitle(bookTitle) self.theProject.setBookAuthors(bookAuthors) - statusCol, statusChange = self.tabStatus.getNewList() - importCol, importChange = self.tabImport.getNewList() - self.theProject.setStatusColours(statusCol, statusChange) - self.theProject.setImportColours(importCol, importChange) + statusCol = self.tabStatus.getNewList() + importCol = self.tabImport.getNewList() + self.theProject.setStatusColours(statusCol) + self.theProject.setImportColours(importCol) self.close() @@ -135,6 +135,7 @@ class GuiProjectEditStatus(QWidget): self.theParent = theParent self.theStatus = theStatus self.colNames = [] + self.colCounts = [] self.colChanged = False self.mainBox = QHBoxLayout() @@ -143,9 +144,10 @@ class GuiProjectEditStatus(QWidget): self.listBox = QListWidget() self.listBox.itemSelectionChanged.connect(self._selectedItem) - for iName, iCol in self.theStatus: - self._addItem(iName, iCol) + for iName, iCol, nUse in self.theStatus: + self._addItem("%s [%d]" % (iName, nUse), iCol) self.colNames.append(iName) + self.colCounts.append(nUse) self.editName = QLineEdit() self.newButton = QPushButton("New") @@ -182,12 +184,12 @@ class GuiProjectEditStatus(QWidget): newList = [] for n in range(self.listBox.count()): nItem = self.listBox.item(n) - nName = nItem.text() + nName = self._cleanLabel(nItem.text()) nImg = nItem.icon().pixmap(16,16).toImage() nCol = QColor(nImg.pixel(7,7)) - newList.append((nName,nCol.red(),nCol.green(),nCol.blue())) - return newList, self.colNames - return None, None + newList.append((nName,nCol.red(),nCol.green(),nCol.blue(),self.colNames[n])) + return newList + return None ## # User Actions @@ -206,32 +208,29 @@ class GuiProjectEditStatus(QWidget): return def _newItem(self): - newItem = self._addItem("New Item", (0, 0, 0)) + newItem = self._addItem("New Item [0]", (0, 0, 0)) newItem.setBackground(QBrush(QColor(0,255,0,80))) self.colNames.append(None) + self.colCounts.append(0) self.colChanged = True return def _delItem(self): selItem = self._getSelectedItem() - colDel = QBrush(QColor(255,0,0,80)) - colNone = QBrush(QColor(0,0,0,0)) - if selItem is not None: - sText = selItem.text() - iRow = self.listBox.row(selItem) - if sText == "** Delete **": - selItem.setBackground(colNone) - selItem.setText(self.colNames[iRow]) - else: - selItem.setBackground(colDel) - selItem.setText("** Delete **") + iRow = self.listBox.row(selItem) + if self.colCounts[iRow] == 0: + self.listBox.takeItem(iRow) + self.colChanged = True + else: + self.theParent.makeAlert("Cannot delete status item that is in use.",nwAlert.ERROR) return def _saveItem(self): logger.verbose("Item save button clicked") selItem = self._getSelectedItem() + iRow = self.listBox.row(selItem) if selItem is not None: - selItem.setText(self.editName.text().strip()) + selItem.setText("%s [%d]" % (self.editName.text().strip(), self.colCounts[iRow])) selItem.setIcon(self.colButton.icon()) self.colChanged = True return @@ -250,7 +249,7 @@ class GuiProjectEditStatus(QWidget): logger.verbose("Item selected") selItem = self._getSelectedItem() if selItem is not None: - self.editName.setText(selItem.text()) + self.editName.setText(self._cleanLabel(selItem.text())) self.colButton.setIcon(selItem.icon()) return @@ -266,4 +265,11 @@ class GuiProjectEditStatus(QWidget): return selItem[0] return None + def _cleanLabel(self, theText): + iPos = theText.rfind("[") + if iPos > 0: + return theText[:iPos-1] + else: + return theText + # END Class GuiProjectEditStatus diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py index 58324e1c..9369569a 100644 --- a/nw/gui/winmain.py +++ b/nw/gui/winmain.py @@ -396,7 +396,7 @@ class GuiMain(QMainWindow): def _makeStatusIcons(self): self.statusIcons = {} - for sLabel, sCol in self.theProject.statusItems: + for sLabel, sCol, _ in self.theProject.statusItems: theIcon = QPixmap(32,32) theIcon.fill(QColor(*sCol)) self.statusIcons[sLabel] = QIcon(theIcon) @@ -404,7 +404,7 @@ class GuiMain(QMainWindow): def _makeImportIcons(self): self.importIcons = {} - for sLabel, sCol in self.theProject.importItems: + for sLabel, sCol, _ in self.theProject.importItems: theIcon = QPixmap(32,32) theIcon.fill(QColor(*sCol)) self.importIcons[sLabel] = QIcon(theIcon) diff --git a/nw/project/document.py b/nw/project/document.py index 1d0a8af3..bb8ad4bd 100644 --- a/nw/project/document.py +++ b/nw/project/document.py @@ -15,8 +15,7 @@ import nw from os import path, mkdir, rename, unlink -from nw.tools.analyse import TextAnalysis -from nw.enum import nwAlert +from nw.enum import nwAlert logger = logging.getLogger(__name__) diff --git a/nw/project/project.py b/nw/project/project.py index 360ca69b..c607763d 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -352,13 +352,25 @@ class NWProject(): self.setProjectChanged(True) return True - def setStatusColours(self, newCols, colChanged): - print(newCols,colChanged) + def setStatusColours(self, newCols): + replaceMap = self.statusItems.setNewEntries(newCols) + if self.projTree is not None: + for nwItem in self.projTree.values(): + if nwItem.itemClass == nwItemClass.NOVEL: + if nwItem.itemStatus in replaceMap.keys(): + nwItem.setStatus(replaceMap[nwItem.itemStatus]) self.setProjectChanged(True) + print(self.statusItems.theLabels) + print(self.statusItems.theColours) return - def setImportColours(self, newCols, colChanged): - print(newCols,colChanged) + def setImportColours(self, newCols,): + replaceMap = self.importItems.setNewEntries(newCols) + if self.projTree is not None: + for nwItem in self.projTree.values(): + if nwItem.itemClass != nwItemClass.NOVEL: + if nwItem.itemStatus in replaceMap.keys(): + nwItem.setStatus(replaceMap[nwItem.itemStatus]) self.setProjectChanged(True) return @@ -435,6 +447,16 @@ class NWProject(): return False return True + def countStatus(self): + self.statusItems.resetCounts() + self.importItems.resetCounts() + for nwItem in self.projTree.values(): + if nwItem.itemClass == nwItemClass.NOVEL: + self.statusItems.countEntry(nwItem.itemStatus) + else: + self.importItems.countEntry(nwItem.itemStatus) + return + ## # Internal Functions ## diff --git a/nw/project/status.py b/nw/project/status.py index 7197e1da..0fef9eb1 100644 --- a/nw/project/status.py +++ b/nw/project/status.py @@ -23,8 +23,9 @@ class NWStatus(): def __init__(self): self.theLabels = [] self.theColours = [] + self.theCounts = [] self.theMap = {} - self.theCount = 0 + self.theLength = 0 self.theIndex = 0 return @@ -33,8 +34,9 @@ class NWStatus(): if self.lookupEntry(theLabel) is None: self.theLabels.append(theLabel) self.theColours.append(theColours) - self.theMap[theLabel] = self.theCount - self.theCount += 1 + self.theCounts.append(0) + self.theMap[theLabel] = self.theLength + self.theLength += 1 return True def lookupEntry(self, theLabel): @@ -44,34 +46,62 @@ class NWStatus(): return None def checkEntry(self, theStatus): - theStatus = theStatus.strip() if isinstance(theStatus, str): + theStatus = theStatus.strip() if self.lookupEntry(theStatus) is not None: return theStatus - theStatus = checkInt(theStatus, None, False) - if theStatus is None: - return None - if theStatus >= 0 and theStatus < self.theCount: + theStatus = checkInt(theStatus, 0, False) + if theStatus >= 0 and theStatus < self.theLength: return self.theLabels[theStatus] + def setNewEntries(self, newList): + + replaceMap = {} + + if newList is not None: + + self.theLabels = [] + self.theColours = [] + self.theCounts = [] + self.theMap = {} + self.theLength = 0 + self.theIndex = 0 + + for nName, nR, nG, nB, oName in newList: + self.addEntry(nName, (nR, nG, nB)) + if nName != oName and oName is not None: + replaceMap[oName] = nName + + return replaceMap + + def resetCounts(self): + self.theCounts = [0]*self.theLength + return + + def countEntry(self, theLabel): + theIndex = self.lookupEntry(theLabel) + if theIndex is not None: + self.theCounts[theIndex] += 1 + return + ## # Iterator Bits ## def __getitem__(self, n): - if n >= 0 and n < self.theCount: - return self.theLabels[n], self.theColours[n] - return None, None + if n >= 0 and n < self.theLength: + return self.theLabels[n], self.theColours[n], self.theCounts[n] + return None, None, None def __iter__(self): self.theIndex = 0 return self def __next__(self): - if self.theIndex < self.theCount: - theLabel, theColour = self.__getitem__(self.theIndex) + if self.theIndex < self.theLength: + theLabel, theColour, theCount = self.__getitem__(self.theIndex) self.theIndex += 1 - return theLabel, theColour + return theLabel, theColour, theCount else: raise StopIteration From fdd9c58235d02dce07a2365e954a09602f382578 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 22:20:54 +0200 Subject: [PATCH 06/11] Document tree is now refreshed when status colours change --- nw/gui/doctree.py | 8 +++----- nw/gui/projecteditor.py | 12 ++++++++---- nw/gui/winmain.py | 12 ++++++++---- nw/project/project.py | 7 +++++++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/nw/gui/doctree.py b/nw/gui/doctree.py index e0f066ad..5ff18107 100644 --- a/nw/gui/doctree.py +++ b/nw/gui/doctree.py @@ -229,7 +229,7 @@ class GuiDocTree(QTreeWidget): trItemP.takeChild(tIndex) self.clearSelection() trItemP.setSelected(True) - self.theProject.setProjectChanged(True) + self.theProject.deleteItem(tHandle) else: self.makeAlert(["Cannot delete folder.","It is not empty."], nwAlert.ERROR) return @@ -261,12 +261,10 @@ class GuiDocTree(QTreeWidget): tStatus += "."+nwLabels.LAYOUT_FLAG[nwItem.itemLayout] iStatus = nwItem.itemStatus if tClass == nwItemClass.NOVEL: - if iStatus is None: - iStatus = self.theProject.statusItems.checkEntry(iStatus) + iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's a valid index flagIcon = self.theParent.statusIcons[iStatus] else: - if iStatus is None: - iStatus = self.theProject.importItems.checkEntry(iStatus) + iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's a valid index flagIcon = self.theParent.importIcons[iStatus] trItem.setText(self.C_NAME, tName) diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index 6f5556a2..d5e41a77 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -82,10 +82,14 @@ class GuiProjectEditor(QDialog): self.theProject.setBookTitle(bookTitle) self.theProject.setBookAuthors(bookAuthors) - statusCol = self.tabStatus.getNewList() - importCol = self.tabImport.getNewList() - self.theProject.setStatusColours(statusCol) - self.theProject.setImportColours(importCol) + if self.tabStatus.colChanged: + statusCol = self.tabStatus.getNewList() + self.theProject.setStatusColours(statusCol) + if self.tabImport.colChanged: + importCol = self.tabImport.getNewList() + self.theProject.setImportColours(importCol) + if self.tabStatus.colChanged or self.tabImport.colChanged: + self.theParent.rebuildTree() self.close() diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py index 9369569a..20a0aa50 100644 --- a/nw/gui/winmain.py +++ b/nw/gui/winmain.py @@ -184,12 +184,9 @@ class GuiMain(QMainWindow): projFile = self.openProjectDialog() if projFile is None: return False - self.treeView.clearTree() self.theProject.openProject(projFile) - self.treeView.buildTree() self._setWindowTitle(self.theProject.projName) - self._makeStatusIcons() - self._makeImportIcons() + self.rebuildTree() self.docEditor.setPwl(path.join(self.theProject.projMeta,"wordlist.txt")) self.docEditor.setSpellCheck(self.theProject.spellCheck) self.mainMenu.updateMenu() @@ -300,6 +297,13 @@ class GuiMain(QMainWindow): return + def rebuildTree(self): + self._makeStatusIcons() + self._makeImportIcons() + self.treeView.clearTree() + self.treeView.buildTree() + return + ## # Main Dialogs ## diff --git a/nw/project/project.py b/nw/project/project.py index c607763d..2d75f1b7 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -430,6 +430,13 @@ class NWProject(): # Class Methods ## + def deleteItem(self, tHandle): + """This only removed the item from the order list, but not from the project tree. + """ + self.treeOrder.remove(tHandle) + self.setProjectChanged(True) + return True + def findRootItem(self, theClass): for aRoot in self.treeRoots: if theClass == self.projTree[aRoot].itemClass: From 823426f4f8ee7ccdcd3fd3be2ed37f7716725737 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Sun, 19 May 2019 22:49:24 +0200 Subject: [PATCH 07/11] Loading and saving of status and importance now works --- nw/project/project.py | 15 ++++++++--- nw/project/status.py | 46 ++++++++++++++++++++++++++++++++ sample/sampleNovel/nwProject.nwx | 29 +++++++++++++++----- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/nw/project/project.py b/nw/project/project.py index 2d75f1b7..aece184c 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -55,8 +55,8 @@ class NWProject(): # Project Settings self.spellCheck = False - self.statusItems = NWStatus() - self.importItems = NWStatus() + self.statusItems = None + self.importItems = None self.lastEdited = None self.lastViewed = None @@ -214,6 +214,10 @@ class NWProject(): self.lastEdited = checkString(xItem.text,None,True) if xItem.tag == "lastViewed": self.lastViewed = checkString(xItem.text,None,True) + if xItem.tag == "status": + self.statusItems.unpackEntries(xItem) + if xItem.tag == "importance": + self.importItems.unpackEntries(xItem) elif xChild.tag == "content": logger.debug("Found project content") for xItem in xChild: @@ -275,6 +279,11 @@ class NWProject(): self._saveProjectValue(xSettings,"lastEdited",self.lastEdited) self._saveProjectValue(xSettings,"lastViewed",self.lastViewed) + xStatus = etree.SubElement(xSettings,"status") + self.statusItems.packEntries(xStatus) + xStatus = etree.SubElement(xSettings,"importance") + self.importItems.packEntries(xStatus) + # Save Tree Content logger.debug("Writing project content") xContent = etree.SubElement(nwXML,"content",attrib={"count":str(len(self.treeOrder))}) @@ -360,8 +369,6 @@ class NWProject(): if nwItem.itemStatus in replaceMap.keys(): nwItem.setStatus(replaceMap[nwItem.itemStatus]) self.setProjectChanged(True) - print(self.statusItems.theLabels) - print(self.statusItems.theColours) return def setImportColours(self, newCols,): diff --git a/nw/project/status.py b/nw/project/status.py index 0fef9eb1..1d19bf34 100644 --- a/nw/project/status.py +++ b/nw/project/status.py @@ -13,6 +13,8 @@ import logging import nw +from lxml import etree + from nw.enum import nwItemClass from nw.common import checkInt @@ -84,6 +86,50 @@ class NWStatus(): self.theCounts[theIndex] += 1 return + def packEntries(self, xParent): + for n in range(self.theLength): + xSub = etree.SubElement(xParent,"entry",attrib={ + "red" : str(self.theColours[n][0]), + "green" : str(self.theColours[n][1]), + "blue" : str(self.theColours[n][2]), + }) + xSub.text = self.theLabels[n] + return True + + def unpackEntries(self, xParent): + + theLabels = [] + theColours = [] + + for xChild in xParent: + theLabels.append(xChild.text) + if "red" in xChild.attrib: + cR = checkInt(xChild.attrib["red"],0,False) + else: + cR = 0 + if "green" in xChild.attrib: + cG = checkInt(xChild.attrib["green"],0,False) + else: + cG = 0 + if "blue" in xChild.attrib: + cB = checkInt(xChild.attrib["blue"],0,False) + else: + cB = 0 + theColours.append((cR,cG,cB)) + + if len(theLabels) > 0: + self.theLabels = [] + self.theColours = [] + self.theCounts = [] + self.theMap = {} + self.theLength = 0 + self.theIndex = 0 + + for n in range(len(theLabels)): + self.addEntry(theLabels[n], theColours[n]) + + return True + ## # Iterator Bits ## diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx index 89cd44e8..c68ec5b0 100644 --- a/sample/sampleNovel/nwProject.nwx +++ b/sample/sampleNovel/nwProject.nwx @@ -1,5 +1,5 @@ - + Sample Project Sample Project @@ -8,8 +8,23 @@ True - 4cd0bd12b087d + 636b6aa9b697b 636b6aa9b697b + + New + Notes + Started + 1st Draft + 2nd Draft + 3rd Draft + Finished + + + None + Minor + Major + Main + @@ -23,7 +38,7 @@ Title Page FILE NOVEL - Draft + Started False TITLE 23 @@ -35,14 +50,14 @@ Some Chapter FOLDER NOVEL - Note + Notes True New Scene FILE NOVEL - Draft + Started False SCENE 2571 @@ -54,7 +69,7 @@ File With Stuff FILE NOVEL - Note + Notes False SCENE 578 @@ -66,7 +81,7 @@ New File FILE NOVEL - Note + Notes False SCENE 69 From 20418f79ca1229703e18714cb0a5fc9e3be09237 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Wed, 22 May 2019 21:21:02 +0200 Subject: [PATCH 08/11] Fix the GUI tests --- nw/project/project.py | 7 +++-- tests/reference/gui/1_nwProject.nwx | 44 ++++++++++++++++++---------- tests/reference/gui/2_nwProject.nwx | 26 +++++++++++----- tests/reference/gui/3_nwProject.nwx | 26 +++++++++++----- tests/reference/proj/1_nwProject.nwx | 26 +++++++++++----- tests/reference/proj/2_nwProject.nwx | 34 ++++++++++++++------- tests/test_gui.py | 28 ++++++++++-------- 7 files changed, 129 insertions(+), 62 deletions(-) diff --git a/nw/project/project.py b/nw/project/project.py index aece184c..c8d04db6 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -80,6 +80,7 @@ class NWProject(): newItem.setName(rootName) newItem.setType(nwItemType.ROOT) newItem.setClass(rootClass) + newItem.setStatus(0) self._appendItem(None,None,newItem) return newItem.itemHandle @@ -88,6 +89,7 @@ class NWProject(): newItem.setName(folderName) newItem.setType(nwItemType.FOLDER) newItem.setClass(folderClass) + newItem.setStatus(0) self._appendItem(None,pHandle,newItem) return newItem.itemHandle @@ -100,6 +102,7 @@ class NWProject(): else: newItem.setLayout(nwItemLayout.NOTE) newItem.setClass(fileClass) + newItem.setStatus(0) self._appendItem(None,pHandle,newItem) return newItem.itemHandle @@ -151,7 +154,7 @@ class NWProject(): self.statusItems.addEntry("Draft", (200,150, 0)) self.statusItems.addEntry("Finished",( 50,200, 0)) self.importItems = NWStatus() - self.importItems.addEntry("None", (100,100,100)) + self.importItems.addEntry("New", (100,100,100)) self.importItems.addEntry("Minor", (200, 50, 0)) self.importItems.addEntry("Major", (200,150, 0)) self.importItems.addEntry("Main", ( 50,200, 0)) @@ -438,7 +441,7 @@ class NWProject(): ## def deleteItem(self, tHandle): - """This only removed the item from the order list, but not from the project tree. + """This only removes the item from the order list, but not from the project tree. """ self.treeOrder.remove(tHandle) self.setProjectChanged(True) diff --git a/tests/reference/gui/1_nwProject.nwx b/tests/reference/gui/1_nwProject.nwx index cf0b0f54..971954a6 100644 --- a/tests/reference/gui/1_nwProject.nwx +++ b/tests/reference/gui/1_nwProject.nwx @@ -1,60 +1,72 @@ - + - False - None - None + True + 31489056e0916 + 31489056e0916 + + New + Note + Draft + Finished + + + New + Minor + Major + Main + Novel ROOT NOVEL - 0 - False + New + True New Chapter FOLDER NOVEL - 0 - False + New + True New Scene FILE NOVEL - 0 + New False SCENE - 0 - 0 - 0 - 0 + 377 + 69 + 2 + 443 Characters ROOT CHARACTER - 0 + New False Plot ROOT PLOT - 0 + New False World ROOT WORLD - 0 + New False diff --git a/tests/reference/gui/2_nwProject.nwx b/tests/reference/gui/2_nwProject.nwx index 33070870..1e41ce6e 100644 --- a/tests/reference/gui/2_nwProject.nwx +++ b/tests/reference/gui/2_nwProject.nwx @@ -1,5 +1,5 @@ - + Project Name Project Title @@ -10,27 +10,39 @@ False None None + + New + Note + Draft + Finished + + + New + Minor + Major + Main + Novel ROOT NOVEL - 0 + New False New Chapter FOLDER NOVEL - 0 + New False New Scene FILE NOVEL - 0 + New False SCENE 0 @@ -42,21 +54,21 @@ Characters ROOT CHARACTER - 0 + New False Plot ROOT PLOT - 0 + New False World ROOT WORLD - 0 + New False diff --git a/tests/reference/gui/3_nwProject.nwx b/tests/reference/gui/3_nwProject.nwx index ecc54350..510192ff 100644 --- a/tests/reference/gui/3_nwProject.nwx +++ b/tests/reference/gui/3_nwProject.nwx @@ -1,5 +1,5 @@ - + @@ -8,27 +8,39 @@ False None None + + New + Note + Draft + Finished + + + New + Minor + Major + Main + Novel ROOT NOVEL - 0 + New False New Chapter FOLDER NOVEL - 0 + New False Just a Page FILE NOVEL - 1 + Note False PAGE 0 @@ -40,21 +52,21 @@ Characters ROOT CHARACTER - 0 + New False Plot ROOT PLOT - 0 + New False World ROOT WORLD - 0 + New False diff --git a/tests/reference/proj/1_nwProject.nwx b/tests/reference/proj/1_nwProject.nwx index 181e1166..e9ff11f5 100644 --- a/tests/reference/proj/1_nwProject.nwx +++ b/tests/reference/proj/1_nwProject.nwx @@ -1,5 +1,5 @@ - + @@ -8,48 +8,60 @@ False None None + + New + Note + Draft + Finished + + + New + Minor + Major + Main + Novel ROOT NOVEL - 0 + New False Characters ROOT CHARACTER - 0 + New False Plot ROOT PLOT - 0 + New False World ROOT WORLD - 0 + New False New Chapter FOLDER NOVEL - 0 + New False New Scene FILE NOVEL - 0 + New False SCENE 0 diff --git a/tests/reference/proj/2_nwProject.nwx b/tests/reference/proj/2_nwProject.nwx index f9dbdef1..8c68bc42 100644 --- a/tests/reference/proj/2_nwProject.nwx +++ b/tests/reference/proj/2_nwProject.nwx @@ -1,5 +1,5 @@ - + @@ -8,48 +8,60 @@ False None None + + New + Note + Draft + Finished + + + New + Minor + Major + Main + Novel ROOT NOVEL - 0 + New False Characters ROOT CHARACTER - 0 + New False Plot ROOT PLOT - 0 + New False World ROOT WORLD - 0 + New False New Chapter FOLDER NOVEL - 0 + New False New Scene FILE NOVEL - 0 + New False SCENE 0 @@ -61,28 +73,28 @@ Timeline ROOT TIMELINE - 0 + New False Object ROOT OBJECT - 0 + New False Custom1 ROOT CUSTOM - 0 + New False Custom2 ROOT CUSTOM - 0 + New False diff --git a/tests/test_gui.py b/tests/test_gui.py index 681c2116..cf3593fe 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -99,15 +99,19 @@ def testMainWindows(qtbot, nwTempGUI, nwRef): qtbot.wait(stepDelay) nwGUI.docEditor.wCounter.run() qtbot.wait(stepDelay) + nwGUI.docEditor._updateCounts() # Save the document assert nwGUI.docEditor.docChanged assert nwGUI.saveDocument() + assert not nwGUI.docEditor.docChanged qtbot.wait(stepDelay) # Open and view the edited document assert nwGUI.openDocument("31489056e0916") assert nwGUI.viewDocument("31489056e0916") + qtbot.wait(stepDelay) + assert nwGUI.saveProject() # Check the files projFile = path.join(nwTempGUI,"nwProject.nwx") @@ -135,27 +139,27 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef): qtbot.addWidget(projEdit) for c in "Project Name": - qtbot.keyClick(projEdit.editName, c, delay=keyDelay) + qtbot.keyClick(projEdit.tabMain.editName, c, delay=keyDelay) for c in "Project Title": - qtbot.keyClick(projEdit.editTitle, c, delay=keyDelay) + qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=keyDelay) for c in "Jane Doe": - qtbot.keyClick(projEdit.editAuthors, c, delay=keyDelay) - qtbot.keyClick(projEdit.editAuthors, Qt.Key_Return, delay=keyDelay) + qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay) + qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay) for c in "John Doh": - qtbot.keyClick(projEdit.editAuthors, c, delay=keyDelay) + qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay) - qtbot.mouseClick(projEdit.saveButton, Qt.LeftButton) + projEdit._doSave() projEdit = GuiProjectEditor(nwGUI, nwGUI.theProject) qtbot.addWidget(projEdit) - assert projEdit.editName.text() == "Project Name" - assert projEdit.editTitle.text() == "Project Title" - theAuth = projEdit.editAuthors.toPlainText().strip().splitlines() + assert projEdit.tabMain.editName.text() == "Project Name" + assert projEdit.tabMain.editTitle.text() == "Project Title" + theAuth = projEdit.tabMain.editAuthors.toPlainText().strip().splitlines() assert len(theAuth) == 2 assert theAuth[0] == "Jane Doe" assert theAuth[1] == "John Doh" - qtbot.mouseClick(projEdit.closeButton, Qt.LeftButton) + projEdit._doClose() qtbot.wait(stepDelay) assert nwGUI.saveProject() @@ -185,7 +189,7 @@ def testItemEditor(qtbot, nwTempGUI, nwRef): qtbot.addWidget(itemEdit) assert itemEdit.editName.text() == "New Scene" - assert itemEdit.editStatus.currentData() == 0 + assert itemEdit.editStatus.currentData() == "New" assert itemEdit.editLayout.currentData() == nwItemLayout.SCENE for c in "Just a Page": @@ -199,7 +203,7 @@ def testItemEditor(qtbot, nwTempGUI, nwRef): itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "31489056e0916") qtbot.addWidget(itemEdit) assert itemEdit.editName.text() == "Just a Page" - assert itemEdit.editStatus.currentData() == 1 + assert itemEdit.editStatus.currentData() == "Note" assert itemEdit.editLayout.currentData() == nwItemLayout.PAGE qtbot.mouseClick(itemEdit.closeButton, Qt.LeftButton) From 07ed0e2523c9af352561fa3f9178b3530476e9b9 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Wed, 22 May 2019 21:39:08 +0200 Subject: [PATCH 09/11] Update the gui test to cover more of the project editor. --- tests/reference/gui/2_nwProject.nwx | 4 ++-- tests/test_gui.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/reference/gui/2_nwProject.nwx b/tests/reference/gui/2_nwProject.nwx index 1e41ce6e..02f3c384 100644 --- a/tests/reference/gui/2_nwProject.nwx +++ b/tests/reference/gui/2_nwProject.nwx @@ -1,5 +1,5 @@ - + Project Name Project Title @@ -13,8 +13,8 @@ New Note - Draft Finished + Final New diff --git a/tests/test_gui.py b/tests/test_gui.py index cf3593fe..ac47fdd2 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -148,8 +148,21 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef): for c in "John Doh": qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay) + #Test Status Tab + projEdit.tabWidget.setCurrentWidget(projEdit.tabStatus) + projEdit.tabStatus.listBox.item(2).setSelected(True) + qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton) + qtbot.mouseClick(projEdit.tabStatus.newButton, Qt.LeftButton) + projEdit.tabStatus.listBox.item(3).setSelected(True) + for n in range(8): + qtbot.keyClick(projEdit.tabStatus.editName, Qt.Key_Backspace, delay=keyDelay) + for c in "Final": + qtbot.keyClick(projEdit.tabStatus.editName, c, delay=keyDelay) + qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton) + projEdit._doSave() + # Open again, and check project settings projEdit = GuiProjectEditor(nwGUI, nwGUI.theProject) qtbot.addWidget(projEdit) assert projEdit.tabMain.editName.text() == "Project Name" From 08c74b254128ee61acb61cf305cf35f3775e105d Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Wed, 22 May 2019 21:58:42 +0200 Subject: [PATCH 10/11] Updated sample project --- sample/sampleNovel/data_6/36b6aa9b697b_main.nwd | 2 +- sample/sampleNovel/nwProject.nwx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sample/sampleNovel/data_6/36b6aa9b697b_main.nwd b/sample/sampleNovel/data_6/36b6aa9b697b_main.nwd index c74aae3f..72d112c6 100644 --- a/sample/sampleNovel/data_6/36b6aa9b697b_main.nwd +++ b/sample/sampleNovel/data_6/36b6aa9b697b_main.nwd @@ -15,6 +15,6 @@ So, this is some __text__ that we’ve been adding to this document. It is utter This paragraph is also meaningless. At least a bit. It’s also very short. -This one is a bit longer. “It also has some dialogue in it” she said, before she moved on to check if the spelllchecker worked. It did. “Cool,” she concluded. +This one is a bit longer. “It also has some dialogue in it” she said, before she moved on to check if the spellchecker worked. It did. “Cool,” she concluded. diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx index c68ec5b0..f358fe07 100644 --- a/sample/sampleNovel/nwProject.nwx +++ b/sample/sampleNovel/nwProject.nwx @@ -1,5 +1,5 @@ - + Sample Project Sample Project @@ -21,9 +21,9 @@ None - Minor - Major - Main + Minor + Major + Main @@ -72,10 +72,10 @@ Notes False SCENE - 578 + 577 104 5 - 658 + 603 New File From 4ae32f32698c7f6db061541700d779774ec86a15 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" Date: Wed, 22 May 2019 23:29:55 +0200 Subject: [PATCH 11/11] Rewritten how status items are changed, using a data storage instead of passing colours back and forth from icons --- nw/gui/projecteditor.py | 93 ++++++++++++++++++-------------- sample/sampleNovel/nwProject.nwx | 2 +- 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/nw/gui/projecteditor.py b/nw/gui/projecteditor.py index d5e41a77..0fdb1fb8 100644 --- a/nw/gui/projecteditor.py +++ b/nw/gui/projecteditor.py @@ -15,12 +15,13 @@ import nw from os import path +from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush from PyQt5.QtSvg import QSvgWidget from PyQt5.QtWidgets import ( QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QLabel, QWidget, QTabWidget, QDialogButtonBox, QListWidget, QListWidgetItem, QPushButton, - QColorDialog + QColorDialog, QAbstractItemView ) from nw.enum import nwAlert @@ -138,20 +139,21 @@ class GuiProjectEditStatus(QWidget): self.theParent = theParent self.theStatus = theStatus - self.colNames = [] + self.colData = [] self.colCounts = [] self.colChanged = False + self.selColour = None self.mainBox = QHBoxLayout() self.mainForm = QVBoxLayout() self.listBox = QListWidget() + self.listBox.setDragDropMode(QAbstractItemView.InternalMove) self.listBox.itemSelectionChanged.connect(self._selectedItem) + self.listBox.model().rowsMoved.connect(self._rowsMoved) for iName, iCol, nUse in self.theStatus: - self._addItem("%s [%d]" % (iName, nUse), iCol) - self.colNames.append(iName) - self.colCounts.append(nUse) + self._addItem(iName, iCol, iName, nUse) self.editName = QLineEdit() self.newButton = QPushButton("New") @@ -188,10 +190,8 @@ class GuiProjectEditStatus(QWidget): newList = [] for n in range(self.listBox.count()): nItem = self.listBox.item(n) - nName = self._cleanLabel(nItem.text()) - nImg = nItem.icon().pixmap(16,16).toImage() - nCol = QColor(nImg.pixel(7,7)) - newList.append((nName,nCol.red(),nCol.green(),nCol.blue(),self.colNames[n])) + nIdx = nItem.data(Qt.UserRole) + newList.append(self.colData[nIdx]) return newList return None @@ -201,60 +201,77 @@ class GuiProjectEditStatus(QWidget): def _selectColour(self): logger.verbose("Item colour button clicked") - selImg = self.colButton.icon().pixmap(16,16).toImage() - selCol = QColor(selImg.pixel(7,7)) - newCol = QColorDialog.getColor(selCol, self, "Select Colour", QColorDialog.DontUseNativeDialog) - if newCol: - colPixmap = QPixmap(16,16) - colPixmap.fill(newCol) - self.colButton.setIcon(QIcon(colPixmap)) - self.colButton.setIconSize(colPixmap.rect().size()) + if self.selColour is not None: + newCol = QColorDialog.getColor(self.selColour, self, "Select Colour", QColorDialog.DontUseNativeDialog) + if newCol: + self.selColour = newCol + colPixmap = QPixmap(16,16) + colPixmap.fill(newCol) + self.colButton.setIcon(QIcon(colPixmap)) + self.colButton.setIconSize(colPixmap.rect().size()) return def _newItem(self): - newItem = self._addItem("New Item [0]", (0, 0, 0)) + logger.verbose("New item button clicked") + newItem = self._addItem("New Item", (0, 0, 0), None, 0) newItem.setBackground(QBrush(QColor(0,255,0,80))) - self.colNames.append(None) - self.colCounts.append(0) self.colChanged = True return def _delItem(self): + logger.verbose("Delete item button clicked") selItem = self._getSelectedItem() - iRow = self.listBox.row(selItem) - if self.colCounts[iRow] == 0: - self.listBox.takeItem(iRow) - self.colChanged = True - else: - self.theParent.makeAlert("Cannot delete status item that is in use.",nwAlert.ERROR) + if selItem is not None: + iRow = self.listBox.row(selItem) + selIdx = selItem.data(Qt.UserRole) + if self.colCounts[selIdx] == 0: + self.listBox.takeItem(iRow) + self.colChanged = True + else: + self.theParent.makeAlert("Cannot delete status item that is in use.",nwAlert.ERROR) return def _saveItem(self): - logger.verbose("Item save button clicked") + logger.verbose("Save item button clicked") selItem = self._getSelectedItem() iRow = self.listBox.row(selItem) if selItem is not None: - selItem.setText("%s [%d]" % (self.editName.text().strip(), self.colCounts[iRow])) + selIdx = selItem.data(Qt.UserRole) + self.colData[selIdx] = ( + self.editName.text().strip(), + self.selColour.red(), + self.selColour.green(), + self.selColour.blue(), + self.colData[selIdx][4] + ) + selItem.setText("%s [%d]" % (self.colData[selIdx][0], self.colCounts[selIdx])) selItem.setIcon(self.colButton.icon()) self.colChanged = True return - def _addItem(self, iName, iCol): - logger.verbose("New item button clicked") + def _addItem(self, iName, iCol, oName, nUse): newIcon = QPixmap(16,16) newIcon.fill(QColor(*iCol)) newItem = QListWidgetItem() - newItem.setText(iName) + newItem.setText("%s [%d]" % (iName, nUse)) newItem.setIcon(QIcon(newIcon)) + newItem.setData(Qt.UserRole, len(self.colData)) self.listBox.addItem(newItem) + self.colData.append((iName,*iCol,oName)) + self.colCounts.append(nUse) return newItem def _selectedItem(self): logger.verbose("Item selected") selItem = self._getSelectedItem() if selItem is not None: - self.editName.setText(self._cleanLabel(selItem.text())) - self.colButton.setIcon(selItem.icon()) + selIdx = selItem.data(Qt.UserRole) + selVal = self.colData[selIdx] + self.selColour = QColor(selVal[1],selVal[2],selVal[3]) + newIcon = QPixmap(16,16) + newIcon.fill(self.selColour) + self.editName.setText(selVal[0]) + self.colButton.setIcon(QIcon(newIcon)) return ## @@ -269,11 +286,9 @@ class GuiProjectEditStatus(QWidget): return selItem[0] return None - def _cleanLabel(self, theText): - iPos = theText.rfind("[") - if iPos > 0: - return theText[:iPos-1] - else: - return theText + def _rowsMoved(self): + logger.verbose("A drag move event occurred") + self.colChanged = True + return # END Class GuiProjectEditStatus diff --git a/sample/sampleNovel/nwProject.nwx b/sample/sampleNovel/nwProject.nwx index f358fe07..769c4a83 100644 --- a/sample/sampleNovel/nwProject.nwx +++ b/sample/sampleNovel/nwProject.nwx @@ -1,5 +1,5 @@ - + Sample Project Sample Project