From c42b0caf0fb3879f02f203a61864443886d7b53e Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Tue, 23 Feb 2021 23:29:18 +0100 Subject: [PATCH 1/9] Clean up the Project Settings classes --- i18n/nw_nb_NO.ts | 4 +- i18n/nw_pt.ts | 2 +- nw/gui/projsettings.py | 96 +++++++++++++++++++++++++++--------------- 3 files changed, 65 insertions(+), 37 deletions(-) diff --git a/i18n/nw_nb_NO.ts b/i18n/nw_nb_NO.ts index c29ad4b3..8d47c2ce 100644 --- a/i18n/nw_nb_NO.ts +++ b/i18n/nw_nb_NO.ts @@ -3675,8 +3675,8 @@ - Cannot delete status item that is in use. - Kan ikke slette statusnivåer som er i bruk. + Cannot delete a status item that is in use. + Kan ikke slette et statusnivå som er i bruk. diff --git a/i18n/nw_pt.ts b/i18n/nw_pt.ts index 26a47379..12b94e47 100644 --- a/i18n/nw_pt.ts +++ b/i18n/nw_pt.ts @@ -3675,7 +3675,7 @@ - Cannot delete status item that is in use. + Cannot delete a status item that is in use. Não é possível remover um item de status que estja em uso. diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index dca62040..75779cc8 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -244,10 +244,13 @@ class GuiProjectEditStatus(QWidget): self.theParent = theParent self.theProject = theProject self.theTheme = theParent.theTheme + if isStatus: self.theStatus = self.theProject.statusItems + pageLabel = self.tr("Novel File Status Levels") else: self.theStatus = self.theProject.importItems + pageLabel = self.tr("Note File Importance Levels") self.colData = [] self.colCounts = [] @@ -256,9 +259,8 @@ class GuiProjectEditStatus(QWidget): self.iPx = self.theTheme.baseIconSize - self.outerBox = QVBoxLayout() - self.mainBox = QHBoxLayout() - self.mainForm = QVBoxLayout() + # The List + # ======== self.listBox = QListWidget() self.listBox.setDragDropMode(QAbstractItemView.InternalMove) @@ -268,22 +270,33 @@ class GuiProjectEditStatus(QWidget): for iName, iCol, nUse in self.theStatus: self._addItem(iName, iCol, iName, nUse) + # The Controls + # ============ + + self.newButton = QPushButton(self.tr("New")) + self.newButton.clicked.connect(self._newItem) + + self.delButton = QPushButton(self.tr("Delete")) + self.delButton.clicked.connect(self._delItem) + self.editName = QLineEdit() self.editName.setMaxLength(40) self.editName.setEnabled(False) - self.newButton = QPushButton(self.tr("New")) - self.delButton = QPushButton(self.tr("Delete")) - self.saveButton = QPushButton(self.tr("Save")) - self.colPixmap = QPixmap(self.iPx, self.iPx) - self.colPixmap.fill(QColor(120, 120, 120)) - self.colButton = QPushButton(QIcon(self.colPixmap), self.tr("Colour")) - self.colButton.setIconSize(self.colPixmap.rect().size()) + self.editName.setPlaceholderText(self.tr("Select item to edit")) - self.newButton.clicked.connect(self._newItem) - self.delButton.clicked.connect(self._delItem) - self.saveButton.clicked.connect(self._saveItem) + self.colPixmap = QPixmap(self.iPx, self.iPx) + self.colPixmap.fill(QColor(120, 120, 120)) + self.colButton = QPushButton(QIcon(self.colPixmap), self.tr("Colour")) + self.colButton.setIconSize(self.colPixmap.rect().size()) self.colButton.clicked.connect(self._selectColour) + self.saveButton = QPushButton(self.tr("Save")) + self.saveButton.clicked.connect(self._saveItem) + + # Assemble + # ======== + + self.mainForm = QVBoxLayout() self.mainForm.addWidget(self.newButton) self.mainForm.addWidget(self.delButton) self.mainForm.addStretch(1) @@ -293,13 +306,12 @@ class GuiProjectEditStatus(QWidget): self.mainForm.addStretch(1) self.mainForm.addWidget(self.saveButton) + self.mainBox = QHBoxLayout() self.mainBox.addWidget(self.listBox) self.mainBox.addLayout(self.mainForm) - if isStatus: - self.outerBox.addWidget(QLabel("%s" % self.tr("Novel File Status Levels"))) - else: - self.outerBox.addWidget(QLabel("%s" % self.tr("Note File Importance Levels"))) + self.outerBox = QVBoxLayout() + self.outerBox.addWidget(QLabel("%s" % pageLabel)) self.outerBox.addLayout(self.mainBox) self.setLayout(self.outerBox) @@ -307,6 +319,8 @@ class GuiProjectEditStatus(QWidget): return def getNewList(self): + """Return list of entries. + """ if self.colChanged: newList = [] for n in range(self.listBox.count()): @@ -314,6 +328,7 @@ class GuiProjectEditStatus(QWidget): nIdx = nItem.data(Qt.UserRole) newList.append(self.colData[nIdx]) return newList + return None ## @@ -355,7 +370,7 @@ class GuiProjectEditStatus(QWidget): self.colChanged = True else: self.theParent.makeAlert( - self.tr("Cannot delete status item that is in use."), nwAlert.ERROR + self.tr("Cannot delete a status item that is in use."), nwAlert.ERROR ) return @@ -410,6 +425,7 @@ class GuiProjectEditStatus(QWidget): self.editName.setEnabled(True) self.editName.selectAll() self.editName.setFocus() + return ## @@ -425,9 +441,8 @@ class GuiProjectEditStatus(QWidget): return None def _rowsMoved(self): - """A row has been moved, so sett the changed flag. + """A row has been moved, so set the changed flag. """ - logger.verbose("A drag move event occurred") self.colChanged = True return @@ -445,12 +460,14 @@ class GuiProjectEditReplace(QWidget): self.optState = theProject.optState self.arChanged = False - self.outerBox = QVBoxLayout() - self.bottomBox = QHBoxLayout() - wCol0 = self.mainConf.pxInt( self.optState.getInt("GuiProjectSettings", "replaceColW", 100) ) + pageLabel = self.tr("Text Replace List for Preview and Export") + + # List Box + # ======== + self.listBox = QTreeWidget() self.listBox.setHeaderLabels([ self.tr("Keyword"), @@ -467,35 +484,45 @@ class GuiProjectEditReplace(QWidget): self.listBox.sortByColumn(0, Qt.AscendingOrder) self.listBox.setSortingEnabled(True) - self.editKey = QLineEdit() - self.editValue = QLineEdit() - self.saveButton = QPushButton(self.theTheme.getIcon("done"), "") - self.addButton = QPushButton(self.theTheme.getIcon("add"), "") - self.delButton = QPushButton(self.theTheme.getIcon("remove"), "") - self.saveButton.setToolTip(self.tr("Save entry")) - self.addButton.setToolTip(self.tr("Add new entry")) - self.delButton.setToolTip(self.tr("Delete selected entry")) + # Controls + # ======== + self.editKey = QLineEdit() + self.editKey.setPlaceholderText(self.tr("Select item to edit")) self.editKey.setEnabled(False) self.editKey.setMaxLength(40) + + self.editValue = QLineEdit() self.editValue.setEnabled(False) self.editValue.setMaxLength(80) + self.saveButton = QPushButton(self.theTheme.getIcon("done"), "") + self.saveButton.setToolTip(self.tr("Save entry")) self.saveButton.clicked.connect(self._saveEntry) + + self.addButton = QPushButton(self.theTheme.getIcon("add"), "") + self.addButton.setToolTip(self.tr("Add new entry")) self.addButton.clicked.connect(self._addEntry) + + self.delButton = QPushButton(self.theTheme.getIcon("remove"), "") + self.delButton.setToolTip(self.tr("Delete selected entry")) self.delButton.clicked.connect(self._delEntry) + # Assemble + # ======== + + self.bottomBox = QHBoxLayout() self.bottomBox.addWidget(self.editKey, 2) self.bottomBox.addWidget(self.editValue, 3) self.bottomBox.addWidget(self.saveButton) self.bottomBox.addWidget(self.addButton) self.bottomBox.addWidget(self.delButton) - self.outerBox.addWidget( - QLabel("%s" % self.tr("Text Replace List for Preview and Export")) - ) + self.outerBox = QVBoxLayout() + self.outerBox.addWidget(QLabel("%s" % pageLabel)) self.outerBox.addWidget(self.listBox) self.outerBox.addLayout(self.bottomBox) + self.setLayout(self.outerBox) return @@ -510,6 +537,7 @@ class GuiProjectEditReplace(QWidget): aVal = tItem.text(1) if len(aKey) > 0: newList[aKey] = aVal + return newList ## From b383142c1402b0d785d4a137722ece64fcb0af6b Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:47:49 +0100 Subject: [PATCH 2/9] Set maximum height for author box on project settings --- nw/gui/projsettings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index 75779cc8..3612e55e 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -169,7 +169,7 @@ class GuiProjectEditMain(QWidget): self.mainForm.addGroupLabel(self.tr("Project Settings")) xW = self.mainConf.pxInt(250) - xH = self.mainConf.pxInt(80) + xH = round(4.8*self.theParent.theTheme.fontPixelSize) self.editName = QLineEdit() self.editName.setMaxLength(200) @@ -192,7 +192,7 @@ class GuiProjectEditMain(QWidget): ) self.editAuthors = QPlainTextEdit() - self.editAuthors.setMinimumHeight(xH) + self.editAuthors.setMaximumHeight(xH) self.editAuthors.setMaximumWidth(xW) self.editAuthors.setPlainText("\n".join(self.theProject.bookAuthors)) self.mainForm.addRow( From 2fd2c18dfcf711756c5d771438c5707197b47e63 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 16:06:24 +0100 Subject: [PATCH 3/9] Remove the colour range function as it will not be used --- nw/common.py | 30 ----------------------------- tests/test_base/test_base_common.py | 30 +---------------------------- 2 files changed, 1 insertion(+), 59 deletions(-) diff --git a/nw/common.py b/nw/common.py index 6d609f6e..1cf4e9a9 100644 --- a/nw/common.py +++ b/nw/common.py @@ -150,36 +150,6 @@ def hexToInt(value, default=0): return default return default -def colRange(rgbStart, rgbEnd, nStep): - """Generate a range of colours from one RGB value to another. - """ - if len(rgbStart) != 3 and len(rgbEnd) != 3 and nStep < 1: - logger.error("Cannot create colour range from given parameters") - return None - - if nStep == 1: - return rgbStart - elif nStep == 2: - return [rgbStart, rgbEnd] - - dC = [0, 0, 0] - for c in range(3): - cA = rgbStart[c] - cB = rgbEnd[c] - dC[c] = (cB-cA)/(nStep-1) - - retCol = [rgbStart] - for n in range(nStep): - if n > 0 and n < nStep: - retCol.append([ - int(retCol[n-1][0] + dC[0]), - int(retCol[n-1][1] + dC[1]), - int(retCol[n-1][2] + dC[2]), - ]) - retCol[-1] = rgbEnd - - return retCol - def formatInt(theInt): """Formats an integer with k, M, G etc. """ diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index 03c408cd..695fb66a 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -24,7 +24,7 @@ import time import pytest from nw.common import ( - checkString, checkBool, checkInt, colRange, formatInt, transferCase, + checkString, checkBool, checkInt, formatInt, transferCase, fuzzyTime, checkHandle, formatTimeStamp, formatTime, hexToInt, makeFileNameSafe, isHandle, isTitleTag, isItemClass, isItemType, isItemLayout, numberToRoman @@ -191,34 +191,6 @@ def testBaseCommon_HexToInt(): # END Test testBaseCommon_HexToInt -@pytest.mark.base -def testBaseCommon_ColRange(): - """Test the colRange function. - """ - assert colRange([0, 0], [0, 0], 0) is None - assert cmpList( - colRange([200, 50, 0], [50, 200, 0], 1), - [200, 50, 0] - ) - assert cmpList( - colRange([200, 50, 0], [50, 200, 0], 2), - [[200, 50, 0], [50, 200, 0]] - ) - assert cmpList( - colRange([200, 50, 0], [50, 200, 0], 3), - [[200, 50, 0], [125, 125, 0], [50, 200, 0]] - ) - assert cmpList( - colRange([200, 50, 0], [50, 200, 0], 4), - [[200, 50, 0], [150, 100, 0], [100, 150, 0], [50, 200, 0]] - ) - assert cmpList( - colRange([200, 50, 0], [50, 200, 0], 5), - [[200, 50, 0], [162, 87, 0], [124, 124, 0], [86, 161, 0], [50, 200, 0]] - ) - -# END Test testBaseCommon_ColRange - @pytest.mark.base def testBaseCommon_FormatTimeStamp(): """Test the formatTimeStamp function. From 4136328a36bf93b2181494d482f640c943fdbe48 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 16:21:03 +0100 Subject: [PATCH 4/9] Improve the layout of Project Settings > Auto-Replace --- nw/gui/projsettings.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index 3612e55e..ff21309d 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -392,7 +392,9 @@ class GuiProjectEditStatus(QWidget): ) selItem.setIcon(self.colButton.icon()) self.editName.setEnabled(False) + self.editName.setText("") self.colChanged = True + return def _addItem(self, iName, iCol, oName, nUse): @@ -496,7 +498,7 @@ class GuiProjectEditReplace(QWidget): self.editValue.setEnabled(False) self.editValue.setMaxLength(80) - self.saveButton = QPushButton(self.theTheme.getIcon("done"), "") + self.saveButton = QPushButton("Save") self.saveButton.setToolTip(self.tr("Save entry")) self.saveButton.clicked.connect(self._saveEntry) @@ -511,17 +513,27 @@ class GuiProjectEditReplace(QWidget): # Assemble # ======== - self.bottomBox = QHBoxLayout() - self.bottomBox.addWidget(self.editKey, 2) - self.bottomBox.addWidget(self.editValue, 3) - self.bottomBox.addWidget(self.saveButton) - self.bottomBox.addWidget(self.addButton) - self.bottomBox.addWidget(self.delButton) + self.listControls = QVBoxLayout() + self.listControls.addWidget(self.addButton) + self.listControls.addWidget(self.delButton) + self.listControls.addStretch(1) + + self.editBox = QHBoxLayout() + self.editBox.addWidget(self.editKey, 4) + self.editBox.addWidget(self.editValue, 5) + self.editBox.addWidget(self.saveButton, 0) + + self.mainBox = QVBoxLayout() + self.mainBox.addWidget(self.listBox) + self.mainBox.addLayout(self.editBox) + + self.innerBox = QHBoxLayout() + self.innerBox.addLayout(self.mainBox) + self.innerBox.addLayout(self.listControls) self.outerBox = QVBoxLayout() self.outerBox.addWidget(QLabel("%s" % pageLabel)) - self.outerBox.addWidget(self.listBox) - self.outerBox.addLayout(self.bottomBox) + self.outerBox.addLayout(self.innerBox) self.setLayout(self.outerBox) From bfa8f97e7e33d48fe1519361c6a7615c860085a7 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 16:49:54 +0100 Subject: [PATCH 5/9] Make the Importance and Status tabs look consistent with Auto-Replace --- nw/core/options.py | 2 + nw/gui/projsettings.py | 139 ++++++++++++++++++---------- tests/test_base/test_base_common.py | 1 - tests/tools.py | 12 --- 4 files changed, 90 insertions(+), 64 deletions(-) diff --git a/nw/core/options.py b/nw/core/options.py index 51fba3b6..e9de1af3 100644 --- a/nw/core/options.py +++ b/nw/core/options.py @@ -91,6 +91,8 @@ class OptionState(): "winWidth", "winHeight", "replaceColW", + "statusColW", + "importColW", }, "GuiProjectDetails": { "winWidth", diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index ff21309d..3755a5b8 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -31,8 +31,8 @@ from PyQt5.QtCore import Qt, QLocale from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush from PyQt5.QtWidgets import ( QHBoxLayout, QVBoxLayout, QLineEdit, QPlainTextEdit, QLabel, QWidget, - QDialogButtonBox, QListWidget, QPushButton, QListWidgetItem, QColorDialog, - QAbstractItemView, QTreeWidget, QTreeWidgetItem, QComboBox + QDialogButtonBox, QPushButton, QColorDialog, QTreeWidget, QTreeWidgetItem, + QComboBox ) from nw.constants import nwAlert @@ -143,10 +143,14 @@ class GuiProjectSettings(PagedDialog): winWidth = self.mainConf.rpxInt(self.width()) winHeight = self.mainConf.rpxInt(self.height()) replaceColW = self.mainConf.rpxInt(self.tabReplace.listBox.columnWidth(0)) + statusColW = self.mainConf.rpxInt(self.tabStatus.listBox.columnWidth(0)) + importColW = self.mainConf.rpxInt(self.tabImport.listBox.columnWidth(0)) self.optState.setValue("GuiProjectSettings", "winWidth", winWidth) self.optState.setValue("GuiProjectSettings", "winHeight", winHeight) self.optState.setValue("GuiProjectSettings", "replaceColW", replaceColW) + self.optState.setValue("GuiProjectSettings", "statusColW", statusColW) + self.optState.setValue("GuiProjectSettings", "importColW", importColW) return @@ -243,14 +247,21 @@ class GuiProjectEditStatus(QWidget): self.mainConf = nw.CONFIG self.theParent = theParent self.theProject = theProject + self.optState = theProject.optState self.theTheme = theParent.theTheme if isStatus: self.theStatus = self.theProject.statusItems pageLabel = self.tr("Novel File Status Levels") + colSetting = "statusColW" else: self.theStatus = self.theProject.importItems pageLabel = self.tr("Note File Importance Levels") + colSetting = "importColW" + + wCol0 = self.mainConf.pxInt( + self.optState.getInt("GuiProjectSettings", colSetting, 130) + ) self.colData = [] self.colCounts = [] @@ -262,23 +273,32 @@ class GuiProjectEditStatus(QWidget): # The List # ======== - self.listBox = QListWidget() - self.listBox.setDragDropMode(QAbstractItemView.InternalMove) + self.listBox = QTreeWidget() + self.listBox.setHeaderLabels([ + self.tr("Label"), + self.tr("Usage"), + ]) self.listBox.itemSelectionChanged.connect(self._selectedItem) - self.listBox.model().rowsMoved.connect(self._rowsMoved) + self.listBox.setColumnWidth(0, wCol0) + self.listBox.setIndentation(0) for iName, iCol, nUse in self.theStatus: self._addItem(iName, iCol, iName, nUse) - # The Controls - # ============ + # List Controls + # ============= - self.newButton = QPushButton(self.tr("New")) - self.newButton.clicked.connect(self._newItem) + self.addButton = QPushButton(self.theTheme.getIcon("add"), "") + self.addButton.setToolTip(self.tr("Add new entry")) + self.addButton.clicked.connect(self._newItem) - self.delButton = QPushButton(self.tr("Delete")) + self.delButton = QPushButton(self.theTheme.getIcon("remove"), "") + self.delButton.setToolTip(self.tr("Delete selected entry")) self.delButton.clicked.connect(self._delItem) + # Edit Form + # ========= + self.editName = QLineEdit() self.editName.setMaxLength(40) self.editName.setEnabled(False) @@ -296,23 +316,27 @@ class GuiProjectEditStatus(QWidget): # Assemble # ======== - self.mainForm = QVBoxLayout() - self.mainForm.addWidget(self.newButton) - self.mainForm.addWidget(self.delButton) - self.mainForm.addStretch(1) - self.mainForm.addWidget(QLabel("%s" % self.tr("Name"))) - self.mainForm.addWidget(self.editName) - self.mainForm.addWidget(self.colButton) - self.mainForm.addStretch(1) - self.mainForm.addWidget(self.saveButton) + self.listControls = QVBoxLayout() + self.listControls.addWidget(self.addButton) + self.listControls.addWidget(self.delButton) + self.listControls.addStretch(1) - self.mainBox = QHBoxLayout() + self.editBox = QHBoxLayout() + self.editBox.addWidget(self.editName) + self.editBox.addWidget(self.colButton) + self.editBox.addWidget(self.saveButton) + + self.mainBox = QVBoxLayout() self.mainBox.addWidget(self.listBox) - self.mainBox.addLayout(self.mainForm) + self.mainBox.addLayout(self.editBox) + + self.innerBox = QHBoxLayout() + self.innerBox.addLayout(self.mainBox) + self.innerBox.addLayout(self.listControls) self.outerBox = QVBoxLayout() self.outerBox.addWidget(QLabel("%s" % pageLabel)) - self.outerBox.addLayout(self.mainBox) + self.outerBox.addLayout(self.innerBox) self.setLayout(self.outerBox) @@ -323,9 +347,9 @@ class GuiProjectEditStatus(QWidget): """ if self.colChanged: newList = [] - for n in range(self.listBox.count()): - nItem = self.listBox.item(n) - nIdx = nItem.data(Qt.UserRole) + for n in range(self.listBox.topLevelItemCount()): + nItem = self.listBox.topLevelItem(n) + nIdx = nItem.data(0, Qt.UserRole) newList.append(self.colData[nIdx]) return newList @@ -354,7 +378,8 @@ class GuiProjectEditStatus(QWidget): """Create a new status item. """ newItem = self._addItem(self.tr("New Item"), (0, 0, 0), None, 0) - newItem.setBackground(QBrush(QColor(0, 255, 0, 80))) + newItem.setBackground(0, QBrush(QColor(0, 255, 0, 70))) + newItem.setBackground(1, QBrush(QColor(0, 255, 0, 70))) self.colChanged = True return @@ -363,8 +388,8 @@ class GuiProjectEditStatus(QWidget): """ selItem = self._getSelectedItem() if selItem is not None: - iRow = self.listBox.row(selItem) - selIdx = selItem.data(Qt.UserRole) + iRow = self.listBox.indexFromItem(selItem) + selIdx = selItem.data(0, Qt.UserRole) if self.colCounts[selIdx] == 0: self.listBox.takeItem(iRow) self.colChanged = True @@ -379,7 +404,7 @@ class GuiProjectEditStatus(QWidget): """ selItem = self._getSelectedItem() if selItem is not None: - selIdx = selItem.data(Qt.UserRole) + selIdx = selItem.data(0, Qt.UserRole) self.colData[selIdx] = ( self.editName.text().strip(), self.selColour.red(), @@ -387,12 +412,10 @@ class GuiProjectEditStatus(QWidget): self.selColour.blue(), self.colData[selIdx][4] ) - selItem.setText(self.tr("{0} [{1}]").format( - self.colData[selIdx][0], self.colCounts[selIdx]) - ) - selItem.setIcon(self.colButton.icon()) + selItem.setText(0, self.colData[selIdx][0]) + selItem.setText(1, self._usageString(self.colCounts[selIdx])) + selItem.setIcon(0, self.colButton.icon()) self.editName.setEnabled(False) - self.editName.setText("") self.colChanged = True return @@ -402,11 +425,12 @@ class GuiProjectEditStatus(QWidget): """ newIcon = QPixmap(self.iPx, self.iPx) newIcon.fill(QColor(*iCol)) - newItem = QListWidgetItem() - newItem.setText(self.tr("{0} [{1}]").format(iName, nUse)) - newItem.setIcon(QIcon(newIcon)) - newItem.setData(Qt.UserRole, len(self.colData)) - self.listBox.addItem(newItem) + newItem = QTreeWidgetItem() + newItem.setText(0, iName) + newItem.setText(1, self._usageString(nUse)) + newItem.setIcon(0, QIcon(newIcon)) + newItem.setData(0, Qt.UserRole, len(self.colData)) + self.listBox.addTopLevelItem(newItem) self.colData.append((iName, iCol[0], iCol[1], iCol[2], oName)) self.colCounts.append(nUse) return newItem @@ -417,7 +441,7 @@ class GuiProjectEditStatus(QWidget): """ selItem = self._getSelectedItem() if selItem is not None: - selIdx = selItem.data(Qt.UserRole) + selIdx = selItem.data(0, Qt.UserRole) selVal = self.colData[selIdx] self.selColour = QColor(selVal[1], selVal[2], selVal[3]) newIcon = QPixmap(self.iPx, self.iPx) @@ -448,6 +472,16 @@ class GuiProjectEditStatus(QWidget): self.colChanged = True return + def _usageString(self, nUse): + """Generate usage string. + """ + if nUse == 0: + return self.tr("Not in use") + elif nUse == 1: + return self.tr("Used once") + else: + return self.tr("Used by {0} items").format(nUse) + # END Class GuiProjectEditStatus class GuiProjectEditReplace(QWidget): @@ -463,7 +497,7 @@ class GuiProjectEditReplace(QWidget): self.arChanged = False wCol0 = self.mainConf.pxInt( - self.optState.getInt("GuiProjectSettings", "replaceColW", 100) + self.optState.getInt("GuiProjectSettings", "replaceColW", 130) ) pageLabel = self.tr("Text Replace List for Preview and Export") @@ -486,8 +520,19 @@ class GuiProjectEditReplace(QWidget): self.listBox.sortByColumn(0, Qt.AscendingOrder) self.listBox.setSortingEnabled(True) - # Controls - # ======== + # List Controls + # ============= + + self.addButton = QPushButton(self.theTheme.getIcon("add"), "") + self.addButton.setToolTip(self.tr("Add new entry")) + self.addButton.clicked.connect(self._addEntry) + + self.delButton = QPushButton(self.theTheme.getIcon("remove"), "") + self.delButton.setToolTip(self.tr("Delete selected entry")) + self.delButton.clicked.connect(self._delEntry) + + # Edit Form + # ========= self.editKey = QLineEdit() self.editKey.setPlaceholderText(self.tr("Select item to edit")) @@ -502,14 +547,6 @@ class GuiProjectEditReplace(QWidget): self.saveButton.setToolTip(self.tr("Save entry")) self.saveButton.clicked.connect(self._saveEntry) - self.addButton = QPushButton(self.theTheme.getIcon("add"), "") - self.addButton.setToolTip(self.tr("Add new entry")) - self.addButton.clicked.connect(self._addEntry) - - self.delButton = QPushButton(self.theTheme.getIcon("remove"), "") - self.delButton.setToolTip(self.tr("Delete selected entry")) - self.delButton.clicked.connect(self._delEntry) - # Assemble # ======== diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index 695fb66a..a5698685 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -29,7 +29,6 @@ from nw.common import ( makeFileNameSafe, isHandle, isTitleTag, isItemClass, isItemType, isItemLayout, numberToRoman ) -from tools import cmpList @pytest.mark.base def testBaseCommon_CheckString(): diff --git a/tests/tools.py b/tests/tools.py index 1b688f1e..65128cc9 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -72,18 +72,6 @@ def cmpFiles(fileOne, fileTwo, ignoreLines=None): return not diffFound -def cmpList(listOne, listTwo): - """Compare two iterable objects. - """ - flatOne = list(chain.from_iterable([listOne])) - flatTwo = list(chain.from_iterable([listTwo])) - if len(flatOne) != len(flatTwo): - return False - for i in range(len(flatOne)): - if flatOne[i] != flatTwo[i]: - return False - return True - def getGuiItem(theName): """Returns a QtWidget based on its objectName. """ From d3eabd8d8f26aba23b22594f2a70b87f27cf0726 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 17:00:17 +0100 Subject: [PATCH 6/9] Fix test and revealed bug in main code --- nw/gui/projsettings.py | 4 ++-- tests/test_gui/test_gui_projsettings.py | 32 ++++++++++++++----------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index 3755a5b8..5b4d6e3c 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -388,10 +388,10 @@ class GuiProjectEditStatus(QWidget): """ selItem = self._getSelectedItem() if selItem is not None: - iRow = self.listBox.indexFromItem(selItem) + iRow = self.listBox.indexOfTopLevelItem(selItem) selIdx = selItem.data(0, Qt.UserRole) if self.colCounts[selIdx] == 0: - self.listBox.takeItem(iRow) + self.listBox.takeTopLevelItem(iRow) self.colChanged = True else: self.theParent.makeAlert( diff --git a/tests/test_gui/test_gui_projsettings.py b/tests/test_gui/test_gui_projsettings.py index cb2e5b70..3f2f8653 100644 --- a/tests/test_gui/test_gui_projsettings.py +++ b/tests/test_gui/test_gui_projsettings.py @@ -29,7 +29,7 @@ from tools import cmpFiles, getGuiItem from PyQt5.QtGui import QColor from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( - QDialog, QAction, QMessageBox, QColorDialog, QListWidgetItem + QDialog, QAction, QMessageBox, QColorDialog, QTreeWidgetItem ) from nw.gui import GuiProjectSettings @@ -110,7 +110,7 @@ def testGuiProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi assert projEdit.tabStatus.colChanged is False assert projEdit.tabStatus.getNewList() is None - assert projEdit.tabStatus.listBox.count() == 4 + assert projEdit.tabStatus.listBox.topLevelItemCount() == 4 # Fake drag'n'drop should change changed status projEdit.tabStatus._rowsMoved() @@ -119,30 +119,32 @@ def testGuiProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi projEdit.tabStatus.listBox.clearSelection() assert projEdit.tabStatus._getSelectedItem() is None - projEdit.tabStatus.listBox.item(0).setSelected(True) - assert isinstance(projEdit.tabStatus._getSelectedItem(), QListWidgetItem) + projEdit.tabStatus.listBox.topLevelItem(0).setSelected(True) + assert isinstance(projEdit.tabStatus._getSelectedItem(), QTreeWidgetItem) # Can't delete the first item (it's in use) - projEdit.tabStatus.listBox.item(0).setSelected(True) + projEdit.tabStatus.listBox.clearSelection() + projEdit.tabStatus.listBox.topLevelItem(0).setSelected(True) qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton) - assert projEdit.tabStatus.listBox.count() == 4 + assert projEdit.tabStatus.listBox.topLevelItemCount() == 4 # Can delete the third item - projEdit.tabStatus.listBox.item(2).setSelected(True) + projEdit.tabStatus.listBox.clearSelection() + projEdit.tabStatus.listBox.topLevelItem(2).setSelected(True) qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton) - assert projEdit.tabStatus.listBox.count() == 3 + assert projEdit.tabStatus.listBox.topLevelItemCount() == 3 # Add a new item monkeypatch.setattr(QColorDialog, "getColor", lambda *args: QColor(20, 30, 40)) - qtbot.mouseClick(projEdit.tabStatus.newButton, Qt.LeftButton) - projEdit.tabStatus.listBox.item(3).setSelected(True) + qtbot.mouseClick(projEdit.tabStatus.addButton, Qt.LeftButton) + projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True) for n in range(8): qtbot.keyClick(projEdit.tabStatus.editName, Qt.Key_Backspace, delay=typeDelay) for c in "Final": qtbot.keyClick(projEdit.tabStatus.editName, c, delay=typeDelay) qtbot.mouseClick(projEdit.tabStatus.colButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton) - assert projEdit.tabStatus.listBox.count() == 4 + assert projEdit.tabStatus.listBox.topLevelItemCount() == 4 qtbot.wait(stepDelay) assert projEdit.tabStatus.colChanged is True @@ -157,10 +159,12 @@ def testGuiProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi # ============== projEdit._tabBox.setCurrentWidget(projEdit.tabImport) - projEdit.tabImport.listBox.item(3).setSelected(True) + projEdit.tabStatus.listBox.clearSelection() + projEdit.tabImport.listBox.topLevelItem(3).setSelected(True) qtbot.mouseClick(projEdit.tabImport.delButton, Qt.LeftButton) - qtbot.mouseClick(projEdit.tabImport.newButton, Qt.LeftButton) - projEdit.tabImport.listBox.item(3).setSelected(True) + qtbot.mouseClick(projEdit.tabImport.addButton, Qt.LeftButton) + projEdit.tabStatus.listBox.clearSelection() + projEdit.tabImport.listBox.topLevelItem(3).setSelected(True) for n in range(8): qtbot.keyClick(projEdit.tabImport.editName, Qt.Key_Backspace, delay=typeDelay) for c in "Final": From 9c3e063635d2bb0ae6c89743e10289f293d90f26 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 17:08:28 +0100 Subject: [PATCH 7/9] Update en_US and nb_NO translations --- i18n/nw_en_US.ts | 140 ++++++++++++++++++++++++++------------------- i18n/nw_nb_NO.ts | 144 ++++++++++++++++++++++++++++------------------- 2 files changed, 168 insertions(+), 116 deletions(-) diff --git a/i18n/nw_en_US.ts b/i18n/nw_en_US.ts index b39a715c..d9188d2f 100644 --- a/i18n/nw_en_US.ts +++ b/i18n/nw_en_US.ts @@ -1,74 +1,75 @@ - + + Common - + in the future - + just now - + a minute ago - + {0} minutes ago - + an hour ago - + {0} hours ago - + a day ago - + {0} days ago - + a week ago - + {0} weeks ago - + a month ago - + {0} months ago - + a year ago - + {0} years ago @@ -3537,57 +3538,57 @@ GuiProjectEditMain - + Project Settings - + Working title - + Should be set only once. - + Novel title - + Change whenever you want! - + Author(s) - + One name per line. - + Default - + Spell check language - + Overrides main preferences. - + No backup on close @@ -3595,91 +3596,116 @@ GuiProjectEditReplace - + Keyword - + Replace With - + Save entry - + Add new entry - + Delete selected entry - + Text Replace List for Preview and Export + + + Select item to edit + + GuiProjectEditStatus - - New - - - - - Delete - - - - + Save - + Colour Color - - Name - - - - + Novel File Status Levels - + Note File Importance Levels - + Select Colour Select Color - + New Item - - Cannot delete status item that is in use. + + Label - - {0} [{1}] + + Usage + + + + + Add new entry + + + + + Delete selected entry + + + + + Select item to edit + + + + + Cannot delete a status item that is in use. + + + + + Not in use + + + + + Used once + + + + + Used by {0} items diff --git a/i18n/nw_nb_NO.ts b/i18n/nw_nb_NO.ts index 8ccf7747..679c46b0 100644 --- a/i18n/nw_nb_NO.ts +++ b/i18n/nw_nb_NO.ts @@ -1,74 +1,75 @@ - + + Common - + just now nå nettopp - + a minute ago for et minutt siden - + an hour ago for en time siden - + a day ago for en dag siden - + a week ago for en uke siden - + a month ago for en måned siden - + a year ago for et år siden - + {0} minutes ago for {0} minutter siden - + {0} hours ago for {0} timer siden - + {0} days ago for {0} dager siden - + {0} weeks ago for {0} uker siden - + {0} months ago for {0} måneder siden - + {0} years ago for {0} år siden - + in the future i fremtiden @@ -3537,57 +3538,57 @@ GuiProjectEditMain - + Project Settings Prosjektinnstillinger - + Working title Arbeidstittel - + Should be set only once. Bør bare settes én gang. - + Novel title Bokens tittel - + Change whenever you want! Kan endres når som helst! - + Author(s) Forfatter(e) - + One name per line. Ett navn per linje. - + Default Ingen valg - + Spell check language Språk for stavekontroll - + Overrides main preferences. Overstyrer valg i innstillinger. - + No backup on close Slå av sikkerhetskopi @@ -3595,92 +3596,117 @@ GuiProjectEditReplace - + Keyword Kodeord - + Replace With Erstatt med - + Save entry Lagre tekst - + Add new entry Legg til ny - + Delete selected entry Slett valgte element - + Text Replace List for Preview and Export Erstatningsliste for forhåndsvisning og eksport + + + Select item to edit + Velg enhet å redigere + GuiProjectEditStatus - - New - Ny - - - - Delete - Slett - - - + Save Lagre - + Colour Farge - - Name - Navn - - - + Novel File Status Levels Statusnivåer i roman-filer - + Note File Importance Levels Viktighetsnivåer i notatfiler - + Select Colour Velg farge - + New Item Legg til - - Cannot delete status item that is in use. - Kan ikke slette statusnivåer som er i bruk. + + Label + Navn - - {0} [{1}] - + + Usage + Bruk + + + + Add new entry + Legg til ny + + + + Delete selected entry + Slett valgte element + + + + Select item to edit + Velg enhet å redigere + + + + Cannot delete a status item that is in use. + Kan ikke slette status som er i bruk. + + + + Not in use + Ikke i bruk + + + + Used once + Brukt ett sted + + + + Used by {0} items + Brukt {0} steder From 12d39550a8bdafac36fb6cf935553e6a4a357c7b Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 17:18:30 +0100 Subject: [PATCH 8/9] Use constants for column indices --- nw/gui/projsettings.py | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py index 5b4d6e3c..44ae65e4 100644 --- a/nw/gui/projsettings.py +++ b/nw/gui/projsettings.py @@ -241,6 +241,9 @@ class GuiProjectEditMain(QWidget): class GuiProjectEditStatus(QWidget): + COL_LABEL = 0 + COL_USAGE = 1 + def __init__(self, theParent, theProject, isStatus): QWidget.__init__(self, theParent) @@ -279,7 +282,7 @@ class GuiProjectEditStatus(QWidget): self.tr("Usage"), ]) self.listBox.itemSelectionChanged.connect(self._selectedItem) - self.listBox.setColumnWidth(0, wCol0) + self.listBox.setColumnWidth(self.COL_LABEL, wCol0) self.listBox.setIndentation(0) for iName, iCol, nUse in self.theStatus: @@ -349,7 +352,7 @@ class GuiProjectEditStatus(QWidget): newList = [] for n in range(self.listBox.topLevelItemCount()): nItem = self.listBox.topLevelItem(n) - nIdx = nItem.data(0, Qt.UserRole) + nIdx = nItem.data(self.COL_LABEL, Qt.UserRole) newList.append(self.colData[nIdx]) return newList @@ -378,8 +381,8 @@ class GuiProjectEditStatus(QWidget): """Create a new status item. """ newItem = self._addItem(self.tr("New Item"), (0, 0, 0), None, 0) - newItem.setBackground(0, QBrush(QColor(0, 255, 0, 70))) - newItem.setBackground(1, QBrush(QColor(0, 255, 0, 70))) + newItem.setBackground(self.COL_LABEL, QBrush(QColor(0, 255, 0, 70))) + newItem.setBackground(self.COL_USAGE, QBrush(QColor(0, 255, 0, 70))) self.colChanged = True return @@ -389,7 +392,7 @@ class GuiProjectEditStatus(QWidget): selItem = self._getSelectedItem() if selItem is not None: iRow = self.listBox.indexOfTopLevelItem(selItem) - selIdx = selItem.data(0, Qt.UserRole) + selIdx = selItem.data(self.COL_LABEL, Qt.UserRole) if self.colCounts[selIdx] == 0: self.listBox.takeTopLevelItem(iRow) self.colChanged = True @@ -404,7 +407,7 @@ class GuiProjectEditStatus(QWidget): """ selItem = self._getSelectedItem() if selItem is not None: - selIdx = selItem.data(0, Qt.UserRole) + selIdx = selItem.data(self.COL_LABEL, Qt.UserRole) self.colData[selIdx] = ( self.editName.text().strip(), self.selColour.red(), @@ -412,9 +415,9 @@ class GuiProjectEditStatus(QWidget): self.selColour.blue(), self.colData[selIdx][4] ) - selItem.setText(0, self.colData[selIdx][0]) - selItem.setText(1, self._usageString(self.colCounts[selIdx])) - selItem.setIcon(0, self.colButton.icon()) + selItem.setText(self.COL_LABEL, self.colData[selIdx][0]) + selItem.setText(self.COL_USAGE, self._usageString(self.colCounts[selIdx])) + selItem.setIcon(self.COL_LABEL, self.colButton.icon()) self.editName.setEnabled(False) self.colChanged = True @@ -426,10 +429,10 @@ class GuiProjectEditStatus(QWidget): newIcon = QPixmap(self.iPx, self.iPx) newIcon.fill(QColor(*iCol)) newItem = QTreeWidgetItem() - newItem.setText(0, iName) - newItem.setText(1, self._usageString(nUse)) - newItem.setIcon(0, QIcon(newIcon)) - newItem.setData(0, Qt.UserRole, len(self.colData)) + newItem.setText(self.COL_LABEL, iName) + newItem.setText(self.COL_USAGE, self._usageString(nUse)) + newItem.setIcon(self.COL_LABEL, QIcon(newIcon)) + newItem.setData(self.COL_LABEL, Qt.UserRole, len(self.colData)) self.listBox.addTopLevelItem(newItem) self.colData.append((iName, iCol[0], iCol[1], iCol[2], oName)) self.colCounts.append(nUse) @@ -441,7 +444,7 @@ class GuiProjectEditStatus(QWidget): """ selItem = self._getSelectedItem() if selItem is not None: - selIdx = selItem.data(0, Qt.UserRole) + selIdx = selItem.data(self.COL_LABEL, Qt.UserRole) selVal = self.colData[selIdx] self.selColour = QColor(selVal[1], selVal[2], selVal[3]) newIcon = QPixmap(self.iPx, self.iPx) @@ -486,6 +489,9 @@ class GuiProjectEditStatus(QWidget): class GuiProjectEditReplace(QWidget): + COL_KEY = 0 + COL_REPL = 1 + def __init__(self, theParent, theProject): QWidget.__init__(self, theParent) @@ -510,14 +516,14 @@ class GuiProjectEditReplace(QWidget): self.tr("Replace With"), ]) self.listBox.itemSelectionChanged.connect(self._selectedItem) - self.listBox.setColumnWidth(0, wCol0) + self.listBox.setColumnWidth(self.COL_KEY, wCol0) self.listBox.setIndentation(0) for aKey, aVal in self.theProject.autoReplace.items(): newItem = QTreeWidgetItem(["<%s>" % aKey, aVal]) self.listBox.addTopLevelItem(newItem) - self.listBox.sortByColumn(0, Qt.AscendingOrder) + self.listBox.sortByColumn(self.COL_KEY, Qt.AscendingOrder) self.listBox.setSortingEnabled(True) # List Controls @@ -622,8 +628,8 @@ class GuiProjectEditReplace(QWidget): saveKey = self._stripNotAllowed(newKey) if len(saveKey) > 0 and len(newVal) > 0: - selItem.setText(0, "<%s>" % saveKey) - selItem.setText(1, newVal) + selItem.setText(self.COL_KEY, "<%s>" % saveKey) + selItem.setText(self.COL_REPL, newVal) self.editKey.clear() self.editValue.clear() self.editKey.setEnabled(False) From cf99b4f8b9456c7f6a01e192ceb5778be023b51c Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 27 Feb 2021 17:19:39 +0100 Subject: [PATCH 9/9] Fix flake8 error --- tests/tools.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/tools.py b/tests/tools.py index 65128cc9..b375f671 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -23,8 +23,6 @@ along with this program. If not, see . import os import shutil -from itertools import chain - from PyQt5.QtWidgets import qApp def cmpFiles(fileOne, fileTwo, ignoreLines=None):