Update Project Settings dialog (#1668)
This commit is contained in:
@@ -131,7 +131,7 @@ def main(sysArgs: list | None = None):
|
|||||||
elif inOpt == "--debug":
|
elif inOpt == "--debug":
|
||||||
CONFIG.isDebug = True
|
CONFIG.isDebug = True
|
||||||
logLevel = logging.DEBUG
|
logLevel = logging.DEBUG
|
||||||
logFormat = "[{asctime:}] {filename:>17}:{lineno:<4d} {levelname:8} {message:}"
|
logFormat = "[{asctime:}] {filename:>18}:{lineno:<4d} {levelname:8} {message:}"
|
||||||
elif inOpt == "--style":
|
elif inOpt == "--style":
|
||||||
qtStyle = inArg
|
qtStyle = inArg
|
||||||
elif inOpt == "--config":
|
elif inOpt == "--config":
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ class GuiPreferences(QDialog):
|
|||||||
|
|
||||||
# Title
|
# Title
|
||||||
self.titleLabel = NColourLabel(
|
self.titleLabel = NColourLabel(
|
||||||
self.tr("Preferences"), SHARED.theme.helpText, parent=self, scale=1.25
|
self.tr("Preferences"), SHARED.theme.helpText,
|
||||||
|
parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
||||||
)
|
)
|
||||||
self.titleLabel.setIndent(CONFIG.pxInt(4))
|
|
||||||
|
|
||||||
# Search Box
|
# Search Box
|
||||||
self.searchText = QLineEdit(self)
|
self.searchText = QLineEdit(self)
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ novelWriter – GUI Project Settings
|
|||||||
==================================
|
==================================
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2018-09-29 [0.0.1] GuiProjectSettings
|
Created: 2018-09-29 [0.0.1] GuiProjectSettings
|
||||||
|
Rewritten: 2024-01-26 [2.3b1] GuiProjectSettings
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2024, Veronica Berglyd Olsen
|
Copyright 2018–2024, Veronica Berglyd Olsen
|
||||||
@@ -25,75 +26,101 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap
|
||||||
|
|
||||||
from PyQt5.QtGui import QCloseEvent, QIcon, QPixmap, QColor
|
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QColorDialog, QComboBox, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit,
|
QColorDialog, QComboBox, QDialog, QDialogButtonBox, QHBoxLayout, QLineEdit,
|
||||||
QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget, qApp
|
QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
||||||
|
QWidget, qApp
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.common import simplified
|
from novelwriter.common import simplified
|
||||||
from novelwriter.extensions.switch import NSwitch
|
from novelwriter.extensions.switch import NSwitch
|
||||||
from novelwriter.extensions.pageddialog import NPagedDialog
|
from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm
|
||||||
from novelwriter.extensions.configlayout import NConfigLayout
|
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma: no cover
|
|
||||||
from novelwriter.guimain import GuiMain
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class GuiProjectSettings(NPagedDialog):
|
class GuiProjectSettings(QDialog):
|
||||||
|
|
||||||
TAB_MAIN = 0
|
PAGE_SETTINGS = 0
|
||||||
TAB_STATUS = 1
|
PAGE_STATUS = 1
|
||||||
TAB_IMPORT = 2
|
PAGE_IMPORT = 2
|
||||||
TAB_REPLACE = 3
|
PAGE_REPLACE = 3
|
||||||
|
|
||||||
newProjectSettingsReady = pyqtSignal()
|
newProjectSettingsReady = pyqtSignal(bool)
|
||||||
|
|
||||||
def __init__(self, mainGui: GuiMain, focusTab: int = TAB_MAIN) -> None:
|
def __init__(self, parent: QWidget, gotoPage: int = PAGE_SETTINGS) -> None:
|
||||||
super().__init__(parent=mainGui)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
logger.debug("Create: GuiProjectSettings")
|
logger.debug("Create: GuiProjectSettings")
|
||||||
self.setObjectName("GuiProjectSettings")
|
self.setObjectName("GuiProjectSettings")
|
||||||
|
|
||||||
self.mainGui = mainGui
|
|
||||||
SHARED.project.countStatus()
|
|
||||||
self.setWindowTitle(self.tr("Project Settings"))
|
self.setWindowTitle(self.tr("Project Settings"))
|
||||||
|
|
||||||
wW = CONFIG.pxInt(570)
|
options = SHARED.project.options
|
||||||
wH = CONFIG.pxInt(375)
|
self.setMinimumSize(CONFIG.pxInt(500), CONFIG.pxInt(400))
|
||||||
pOptions = SHARED.project.options
|
|
||||||
|
|
||||||
self.setMinimumWidth(wW)
|
|
||||||
self.setMinimumHeight(wH)
|
|
||||||
self.resize(
|
self.resize(
|
||||||
CONFIG.pxInt(pOptions.getInt("GuiProjectSettings", "winWidth", wW)),
|
CONFIG.pxInt(options.getInt("GuiProjectSettings", "winWidth", CONFIG.pxInt(650))),
|
||||||
CONFIG.pxInt(pOptions.getInt("GuiProjectSettings", "winHeight", wH))
|
CONFIG.pxInt(options.getInt("GuiProjectSettings", "winHeight", CONFIG.pxInt(500)))
|
||||||
)
|
)
|
||||||
|
|
||||||
self.tabMain = GuiProjectEditMain(self)
|
# Title
|
||||||
self.tabStatus = GuiProjectEditStatus(self, True)
|
self.titleLabel = NColourLabel(
|
||||||
self.tabImport = GuiProjectEditStatus(self, False)
|
self.tr("Project Settings"), SHARED.theme.helpText,
|
||||||
self.tabReplace = GuiProjectEditReplace(self)
|
parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
||||||
|
)
|
||||||
|
|
||||||
self.addTab(self.tabMain, self.tr("Settings"))
|
# SideBar
|
||||||
self.addTab(self.tabStatus, self.tr("Status"))
|
self.sidebar = NPagedSideBar(self)
|
||||||
self.addTab(self.tabImport, self.tr("Importance"))
|
self.sidebar.setLabelColor(SHARED.theme.helpText)
|
||||||
self.addTab(self.tabReplace, self.tr("Auto-Replace"))
|
self.sidebar.addButton(self.tr("Settings"), self.PAGE_SETTINGS)
|
||||||
|
self.sidebar.addButton(self.tr("Status"), self.PAGE_STATUS)
|
||||||
|
self.sidebar.addButton(self.tr("Importance"), self.PAGE_IMPORT)
|
||||||
|
self.sidebar.addButton(self.tr("Auto-Replace"), self.PAGE_REPLACE)
|
||||||
|
self.sidebar.setSelected(gotoPage)
|
||||||
|
self.sidebar.buttonClicked.connect(self._sidebarClicked)
|
||||||
|
|
||||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
# Buttons
|
||||||
|
self.buttonBox = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Save | QDialogButtonBox.StandardButton.Cancel
|
||||||
|
)
|
||||||
self.buttonBox.accepted.connect(self._doSave)
|
self.buttonBox.accepted.connect(self._doSave)
|
||||||
self.buttonBox.rejected.connect(self.close)
|
self.buttonBox.rejected.connect(self.close)
|
||||||
self.rejected.connect(self.close)
|
|
||||||
self.addControls(self.buttonBox)
|
|
||||||
|
|
||||||
# Focus Tab
|
# Content
|
||||||
self._focusTab(focusTab)
|
SHARED.project.countStatus()
|
||||||
|
|
||||||
|
self.settingsPage = _SettingsPage(self)
|
||||||
|
self.statusPage = _StatusPage(self, True)
|
||||||
|
self.importPage = _StatusPage(self, False)
|
||||||
|
self.replacePage = _ReplacePage(self)
|
||||||
|
|
||||||
|
self.mainStack = QStackedWidget(self)
|
||||||
|
self.mainStack.addWidget(self.settingsPage)
|
||||||
|
self.mainStack.addWidget(self.statusPage)
|
||||||
|
self.mainStack.addWidget(self.importPage)
|
||||||
|
self.mainStack.addWidget(self.replacePage)
|
||||||
|
|
||||||
|
# Assemble
|
||||||
|
self.topBox = QHBoxLayout()
|
||||||
|
self.topBox.addWidget(self.titleLabel)
|
||||||
|
self.topBox.addStretch(1)
|
||||||
|
|
||||||
|
self.mainBox = QHBoxLayout()
|
||||||
|
self.mainBox.addWidget(self.sidebar)
|
||||||
|
self.mainBox.addWidget(self.mainStack)
|
||||||
|
self.mainBox.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
|
self.outerBox = QVBoxLayout()
|
||||||
|
self.outerBox.addLayout(self.topBox)
|
||||||
|
self.outerBox.addLayout(self.mainBox)
|
||||||
|
self.outerBox.addWidget(self.buttonBox)
|
||||||
|
self.outerBox.setSpacing(CONFIG.pxInt(8))
|
||||||
|
|
||||||
|
self.setLayout(self.outerBox)
|
||||||
|
self.setSizeGripEnabled(True)
|
||||||
|
|
||||||
logger.debug("Ready: GuiProjectSettings")
|
logger.debug("Ready: GuiProjectSettings")
|
||||||
|
|
||||||
@@ -103,9 +130,13 @@ class GuiProjectSettings(NPagedDialog):
|
|||||||
logger.debug("Delete: GuiProjectSettings")
|
logger.debug("Delete: GuiProjectSettings")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Events
|
||||||
|
##
|
||||||
|
|
||||||
def closeEvent(self, event: QCloseEvent) -> None:
|
def closeEvent(self, event: QCloseEvent) -> None:
|
||||||
"""Capture the close event and perform cleanup."""
|
"""Capture the user closing the window and save settings."""
|
||||||
self._saveGuiSettings()
|
self._saveSettings()
|
||||||
event.accept()
|
event.accept()
|
||||||
self.deleteLater()
|
self.deleteLater()
|
||||||
return
|
return
|
||||||
@@ -114,40 +145,52 @@ class GuiProjectSettings(NPagedDialog):
|
|||||||
# Private Slots
|
# Private Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
|
@pyqtSlot(int)
|
||||||
|
def _sidebarClicked(self, pageId: int) -> None:
|
||||||
|
"""Process a user request to switch page."""
|
||||||
|
if pageId == self.PAGE_SETTINGS:
|
||||||
|
self.mainStack.setCurrentWidget(self.settingsPage)
|
||||||
|
elif pageId == self.PAGE_STATUS:
|
||||||
|
self.mainStack.setCurrentWidget(self.statusPage)
|
||||||
|
elif pageId == self.PAGE_IMPORT:
|
||||||
|
self.mainStack.setCurrentWidget(self.importPage)
|
||||||
|
elif pageId == self.PAGE_REPLACE:
|
||||||
|
self.mainStack.setCurrentWidget(self.replacePage)
|
||||||
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _doSave(self) -> None:
|
def _doSave(self) -> None:
|
||||||
"""Save settings and close dialog."""
|
"""Save settings and close dialog."""
|
||||||
project = SHARED.project
|
project = SHARED.project
|
||||||
projName = self.tabMain.editName.text()
|
projName = self.settingsPage.projName.text()
|
||||||
bookTitle = self.tabMain.editTitle.text()
|
projAuthor = self.settingsPage.projAuthor.text()
|
||||||
bookAuthor = self.tabMain.editAuthor.text()
|
projLang = self.settingsPage.projLang.currentData()
|
||||||
projLang = self.tabMain.projLang.currentData()
|
spellLang = self.settingsPage.spellLang.currentData()
|
||||||
spellLang = self.tabMain.spellLang.currentData()
|
doBackup = not self.settingsPage.doBackup.isChecked()
|
||||||
doBackup = not self.tabMain.doBackup.isChecked()
|
|
||||||
|
|
||||||
project.data.setName(projName)
|
project.data.setName(projName)
|
||||||
project.data.setTitle(bookTitle)
|
project.data.setAuthor(projAuthor)
|
||||||
project.data.setAuthor(bookAuthor)
|
|
||||||
project.data.setDoBackup(doBackup)
|
project.data.setDoBackup(doBackup)
|
||||||
project.data.setSpellLang(spellLang)
|
project.data.setSpellLang(spellLang)
|
||||||
project.setProjectLang(projLang)
|
project.setProjectLang(projLang)
|
||||||
|
|
||||||
if self.tabStatus.colChanged:
|
rebuildTrees = False
|
||||||
newList, delList = self.tabStatus.getNewList()
|
|
||||||
|
if self.statusPage.wasChanged:
|
||||||
|
newList, delList = self.statusPage.getNewList()
|
||||||
project.setStatusColours(newList, delList)
|
project.setStatusColours(newList, delList)
|
||||||
|
rebuildTrees = True
|
||||||
|
|
||||||
if self.tabImport.colChanged:
|
if self.importPage.wasChanged:
|
||||||
newList, delList = self.tabImport.getNewList()
|
newList, delList = self.importPage.getNewList()
|
||||||
project.setImportColours(newList, delList)
|
project.setImportColours(newList, delList)
|
||||||
|
rebuildTrees = True
|
||||||
|
|
||||||
if self.tabStatus.colChanged or self.tabImport.colChanged:
|
if self.replacePage.wasChanged:
|
||||||
self.mainGui.rebuildTrees()
|
newList = self.replacePage.getNewList()
|
||||||
|
|
||||||
if self.tabReplace.arChanged:
|
|
||||||
newList = self.tabReplace.getNewList()
|
|
||||||
project.data.setAutoReplace(newList)
|
project.data.setAutoReplace(newList)
|
||||||
|
|
||||||
self.newProjectSettingsReady.emit()
|
self.newProjectSettingsReady.emit(rebuildTrees)
|
||||||
qApp.processEvents()
|
qApp.processEvents()
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
@@ -157,134 +200,103 @@ class GuiProjectSettings(NPagedDialog):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _focusTab(self, tab: int) -> None:
|
def _saveSettings(self) -> None:
|
||||||
"""Change which is the focused tab."""
|
|
||||||
if tab == self.TAB_MAIN:
|
|
||||||
self.setCurrentWidget(self.tabMain)
|
|
||||||
elif tab == self.TAB_STATUS:
|
|
||||||
self.setCurrentWidget(self.tabStatus)
|
|
||||||
elif tab == self.TAB_IMPORT:
|
|
||||||
self.setCurrentWidget(self.tabImport)
|
|
||||||
elif tab == self.TAB_REPLACE:
|
|
||||||
self.setCurrentWidget(self.tabReplace)
|
|
||||||
return
|
|
||||||
|
|
||||||
def _saveGuiSettings(self) -> None:
|
|
||||||
"""Save GUI settings."""
|
"""Save GUI settings."""
|
||||||
winWidth = CONFIG.rpxInt(self.width())
|
winWidth = CONFIG.rpxInt(self.width())
|
||||||
winHeight = CONFIG.rpxInt(self.height())
|
winHeight = CONFIG.rpxInt(self.height())
|
||||||
replaceColW = CONFIG.rpxInt(self.tabReplace.listBox.columnWidth(0))
|
statusColW = CONFIG.rpxInt(self.statusPage.columnWidth())
|
||||||
statusColW = CONFIG.rpxInt(self.tabStatus.listBox.columnWidth(0))
|
importColW = CONFIG.rpxInt(self.importPage.columnWidth())
|
||||||
importColW = CONFIG.rpxInt(self.tabImport.listBox.columnWidth(0))
|
replaceColW = CONFIG.rpxInt(self.replacePage.columnWidth())
|
||||||
|
|
||||||
logger.debug("Saving State: GuiProjectSettings")
|
logger.debug("Saving State: GuiProjectSettings")
|
||||||
pOptions = SHARED.project.options
|
options = SHARED.project.options
|
||||||
pOptions.setValue("GuiProjectSettings", "winWidth", winWidth)
|
options.setValue("GuiProjectSettings", "winWidth", winWidth)
|
||||||
pOptions.setValue("GuiProjectSettings", "winHeight", winHeight)
|
options.setValue("GuiProjectSettings", "winHeight", winHeight)
|
||||||
pOptions.setValue("GuiProjectSettings", "replaceColW", replaceColW)
|
options.setValue("GuiProjectSettings", "statusColW", statusColW)
|
||||||
pOptions.setValue("GuiProjectSettings", "statusColW", statusColW)
|
options.setValue("GuiProjectSettings", "importColW", importColW)
|
||||||
pOptions.setValue("GuiProjectSettings", "importColW", importColW)
|
options.setValue("GuiProjectSettings", "replaceColW", replaceColW)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiProjectSettings
|
# END Class GuiProjectSettings
|
||||||
|
|
||||||
|
|
||||||
class GuiProjectEditMain(QWidget):
|
class _SettingsPage(NScrollableForm):
|
||||||
|
|
||||||
def __init__(self, parent: QWidget) -> None:
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
# The Form
|
xW = CONFIG.pxInt(200)
|
||||||
self.mainForm = NConfigLayout()
|
data = SHARED.project.data
|
||||||
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
self.setHelpTextStyle(SHARED.theme.helpText)
|
||||||
self.setLayout(self.mainForm)
|
self.setRowIndent(0)
|
||||||
|
|
||||||
self.mainForm.addGroupLabel(self.tr("Project Settings"))
|
# Project Name
|
||||||
|
self.projName = QLineEdit(self)
|
||||||
xW = CONFIG.pxInt(250)
|
self.projName.setMaxLength(200)
|
||||||
pData = SHARED.project.data
|
self.projName.setMinimumWidth(xW)
|
||||||
|
self.projName.setText(data.name)
|
||||||
self.editName = QLineEdit()
|
self.addRow(
|
||||||
self.editName.setMaxLength(200)
|
self.tr("Project name"), self.projName,
|
||||||
self.editName.setMaximumWidth(xW)
|
self.tr("Changing this will affect the backup path."),
|
||||||
self.editName.setText(pData.name)
|
stretch=(3, 2)
|
||||||
self.mainForm.addRow(
|
|
||||||
self.tr("Project name"),
|
|
||||||
self.editName,
|
|
||||||
self.tr("Should be set only once.")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.editTitle = QLineEdit()
|
# Project Author
|
||||||
self.editTitle.setMaxLength(200)
|
self.projAuthor = QLineEdit(self)
|
||||||
self.editTitle.setMaximumWidth(xW)
|
self.projAuthor.setMaxLength(200)
|
||||||
self.editTitle.setText(pData.title)
|
self.projAuthor.setMinimumWidth(xW)
|
||||||
self.mainForm.addRow(
|
self.projAuthor.setText(data.author)
|
||||||
self.tr("Novel title"),
|
self.addRow(
|
||||||
self.editTitle,
|
self.tr("Author(s)"), self.projAuthor,
|
||||||
self.tr("Change whenever you want!")
|
self.tr("Only used when building the manuscript."),
|
||||||
)
|
stretch=(3, 2)
|
||||||
|
|
||||||
self.editAuthor = QLineEdit()
|
|
||||||
self.editAuthor.setMaxLength(200)
|
|
||||||
self.editAuthor.setMaximumWidth(xW)
|
|
||||||
self.editAuthor.setText(pData.author)
|
|
||||||
self.mainForm.addRow(
|
|
||||||
self.tr("Author(s)"),
|
|
||||||
self.editAuthor,
|
|
||||||
self.tr("Change whenever you want!")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Project Language
|
||||||
self.projLang = QComboBox(self)
|
self.projLang = QComboBox(self)
|
||||||
self.projLang.setMaximumWidth(xW)
|
self.projLang.setMinimumWidth(xW)
|
||||||
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
|
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
|
||||||
self.projLang.addItem(language, tag)
|
self.projLang.addItem(language, tag)
|
||||||
self.mainForm.addRow(
|
self.addRow(
|
||||||
self.tr("Project language"),
|
self.tr("Project language"), self.projLang,
|
||||||
self.projLang,
|
self.tr("Only used when building the manuscript."),
|
||||||
self.tr("Used when building the manuscript.")
|
stretch=(3, 2)
|
||||||
)
|
)
|
||||||
|
if (idx := self.projLang.findData(data.language)) != -1:
|
||||||
|
self.projLang.setCurrentIndex(idx)
|
||||||
|
|
||||||
langIdx = 0
|
# Spell Check Language
|
||||||
if pData.language is not None:
|
|
||||||
langIdx = self.projLang.findData(pData.language)
|
|
||||||
if langIdx == -1:
|
|
||||||
langIdx = self.projLang.findData("en_GB")
|
|
||||||
if langIdx != -1:
|
|
||||||
self.projLang.setCurrentIndex(langIdx)
|
|
||||||
|
|
||||||
self.spellLang = QComboBox(self)
|
self.spellLang = QComboBox(self)
|
||||||
self.spellLang.setMaximumWidth(xW)
|
self.spellLang.setMinimumWidth(xW)
|
||||||
self.spellLang.addItem(self.tr("Default"), "None")
|
self.spellLang.addItem(self.tr("Default"), "None")
|
||||||
if CONFIG.hasEnchant:
|
if CONFIG.hasEnchant:
|
||||||
for tag, language in SHARED.spelling.listDictionaries():
|
for tag, language in SHARED.spelling.listDictionaries():
|
||||||
self.spellLang.addItem(language, tag)
|
self.spellLang.addItem(language, tag)
|
||||||
self.mainForm.addRow(
|
self.addRow(
|
||||||
self.tr("Spell check language"),
|
self.tr("Spell check language"), self.spellLang,
|
||||||
self.spellLang,
|
self.tr("Overrides main preferences."),
|
||||||
self.tr("Overrides main preferences.")
|
stretch=(3, 2)
|
||||||
)
|
)
|
||||||
|
if (idx := self.spellLang.findData(data.spellLang)) != -1:
|
||||||
|
self.spellLang.setCurrentIndex(idx)
|
||||||
|
|
||||||
langIdx = 0
|
# Backup on Close
|
||||||
if pData.spellLang is not None:
|
|
||||||
langIdx = self.spellLang.findData(pData.spellLang)
|
|
||||||
if langIdx != -1:
|
|
||||||
self.spellLang.setCurrentIndex(langIdx)
|
|
||||||
|
|
||||||
self.doBackup = NSwitch(self)
|
self.doBackup = NSwitch(self)
|
||||||
self.doBackup.setChecked(not pData.doBackup)
|
self.doBackup.setChecked(not data.doBackup)
|
||||||
self.mainForm.addRow(
|
self.addRow(
|
||||||
self.tr("No backup on close"),
|
self.tr("Disable backup on close"), self.doBackup,
|
||||||
self.doBackup,
|
|
||||||
self.tr("Overrides main preferences.")
|
self.tr("Overrides main preferences.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.finalise()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiProjectEditMain
|
# END Class _SettingsPage
|
||||||
|
|
||||||
|
|
||||||
class GuiProjectEditStatus(QWidget):
|
class _StatusPage(NFixedPage):
|
||||||
|
|
||||||
COL_LABEL = 0
|
COL_LABEL = 0
|
||||||
COL_USAGE = 1
|
COL_USAGE = 1
|
||||||
@@ -297,56 +309,54 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
if isStatus:
|
if isStatus:
|
||||||
self.theStatus = SHARED.project.data.itemStatus
|
status = SHARED.project.data.itemStatus
|
||||||
pageLabel = self.tr("Novel File Status Levels")
|
pageLabel = self.tr("Novel Document Status Levels")
|
||||||
colSetting = "statusColW"
|
colSetting = "statusColW"
|
||||||
else:
|
else:
|
||||||
self.theStatus = SHARED.project.data.itemImport
|
status = SHARED.project.data.itemImport
|
||||||
pageLabel = self.tr("Note File Importance Levels")
|
pageLabel = self.tr("Project Note Importance Levels")
|
||||||
colSetting = "importColW"
|
colSetting = "importColW"
|
||||||
|
|
||||||
wCol0 = CONFIG.pxInt(
|
wCol0 = CONFIG.pxInt(
|
||||||
SHARED.project.options.getInt("GuiProjectSettings", colSetting, 130)
|
SHARED.project.options.getInt("GuiProjectSettings", colSetting, 130)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.colDeleted = []
|
self._changed = False
|
||||||
self.colChanged = False
|
self._colDeleted = []
|
||||||
self.selColour = QColor(100, 100, 100)
|
self._selColour = QColor(100, 100, 100)
|
||||||
|
|
||||||
self.iPx = SHARED.theme.baseIconSize
|
self.iPx = SHARED.theme.baseIconSize
|
||||||
|
|
||||||
# The List
|
# Title
|
||||||
# ========
|
self.pageTitle = NColourLabel(
|
||||||
|
pageLabel, SHARED.theme.helpText, parent=self,
|
||||||
|
scale=NColourLabel.HEADER_SCALE
|
||||||
|
)
|
||||||
|
|
||||||
self.listBox = QTreeWidget()
|
# List Box
|
||||||
self.listBox.setHeaderLabels([
|
self.listBox = QTreeWidget(self)
|
||||||
self.tr("Label"), self.tr("Usage"),
|
self.listBox.setHeaderLabels([self.tr("Label"), self.tr("Usage")])
|
||||||
])
|
|
||||||
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
||||||
self.listBox.setColumnWidth(self.COL_LABEL, wCol0)
|
self.listBox.setColumnWidth(self.COL_LABEL, wCol0)
|
||||||
self.listBox.setIndentation(0)
|
self.listBox.setIndentation(0)
|
||||||
|
|
||||||
for key, entry in self.theStatus.items():
|
for key, entry in status.items():
|
||||||
self._addItem(key, entry["name"], entry["cols"], entry["count"])
|
self._addItem(key, entry["name"], entry["cols"], entry["count"])
|
||||||
|
|
||||||
# List Controls
|
# List Controls
|
||||||
# =============
|
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "", self)
|
||||||
|
|
||||||
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
|
|
||||||
self.addButton.clicked.connect(self._newItem)
|
self.addButton.clicked.connect(self._newItem)
|
||||||
|
|
||||||
self.delButton = QPushButton(SHARED.theme.getIcon("remove"), "")
|
self.delButton = QPushButton(SHARED.theme.getIcon("remove"), "", self)
|
||||||
self.delButton.clicked.connect(self._delItem)
|
self.delButton.clicked.connect(self._delItem)
|
||||||
|
|
||||||
self.upButton = QPushButton(SHARED.theme.getIcon("up"), "")
|
self.upButton = QPushButton(SHARED.theme.getIcon("up"), "", self)
|
||||||
self.upButton.clicked.connect(lambda: self._moveItem(-1))
|
self.upButton.clicked.connect(lambda: self._moveItem(-1))
|
||||||
|
|
||||||
self.dnButton = QPushButton(SHARED.theme.getIcon("down"), "")
|
self.dnButton = QPushButton(SHARED.theme.getIcon("down"), "", self)
|
||||||
self.dnButton.clicked.connect(lambda: self._moveItem(1))
|
self.dnButton.clicked.connect(lambda: self._moveItem(1))
|
||||||
|
|
||||||
# Edit Form
|
# Edit Form
|
||||||
# =========
|
|
||||||
|
|
||||||
self.editName = QLineEdit()
|
self.editName = QLineEdit()
|
||||||
self.editName.setMaxLength(40)
|
self.editName.setMaxLength(40)
|
||||||
self.editName.setPlaceholderText(self.tr("Select item to edit"))
|
self.editName.setPlaceholderText(self.tr("Select item to edit"))
|
||||||
@@ -364,8 +374,6 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
self.saveButton.clicked.connect(self._saveItem)
|
self.saveButton.clicked.connect(self._saveItem)
|
||||||
|
|
||||||
# Assemble
|
# Assemble
|
||||||
# ========
|
|
||||||
|
|
||||||
self.listControls = QVBoxLayout()
|
self.listControls = QVBoxLayout()
|
||||||
self.listControls.addWidget(self.addButton)
|
self.listControls.addWidget(self.addButton)
|
||||||
self.listControls.addWidget(self.delButton)
|
self.listControls.addWidget(self.delButton)
|
||||||
@@ -387,16 +395,25 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
self.innerBox.addLayout(self.listControls)
|
self.innerBox.addLayout(self.listControls)
|
||||||
|
|
||||||
self.outerBox = QVBoxLayout()
|
self.outerBox = QVBoxLayout()
|
||||||
self.outerBox.addWidget(QLabel("<b>%s</b>" % pageLabel))
|
self.outerBox.addWidget(self.pageTitle)
|
||||||
self.outerBox.addLayout(self.innerBox)
|
self.outerBox.addLayout(self.innerBox)
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setCentralLayout(self.outerBox)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wasChanged(self) -> bool:
|
||||||
|
"""The user changed these settings."""
|
||||||
|
return self._changed
|
||||||
|
|
||||||
|
##
|
||||||
|
# Methods
|
||||||
|
##
|
||||||
|
|
||||||
def getNewList(self) -> tuple[list, list]:
|
def getNewList(self) -> tuple[list, list]:
|
||||||
"""Return list of entries."""
|
"""Return list of entries."""
|
||||||
if self.colChanged:
|
if self._changed:
|
||||||
newList = []
|
newList = []
|
||||||
for n in range(self.listBox.topLevelItemCount()):
|
for n in range(self.listBox.topLevelItemCount()):
|
||||||
item = self.listBox.topLevelItem(n)
|
item = self.listBox.topLevelItem(n)
|
||||||
@@ -406,10 +423,13 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
"name": item.text(self.COL_LABEL),
|
"name": item.text(self.COL_LABEL),
|
||||||
"cols": item.data(self.COL_LABEL, self.COL_ROLE),
|
"cols": item.data(self.COL_LABEL, self.COL_ROLE),
|
||||||
})
|
})
|
||||||
return newList, self.colDeleted
|
return newList, self._colDeleted
|
||||||
|
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
|
def columnWidth(self) -> int:
|
||||||
|
"""Return the size of the header column."""
|
||||||
|
return self.listBox.columnWidth(0)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Private Slots
|
# Private Slots
|
||||||
##
|
##
|
||||||
@@ -417,12 +437,12 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _selectColour(self) -> None:
|
def _selectColour(self) -> None:
|
||||||
"""Open a dialog to select the status icon colour."""
|
"""Open a dialog to select the status icon colour."""
|
||||||
if self.selColour is not None:
|
if self._selColour is not None:
|
||||||
newCol = QColorDialog.getColor(
|
newCol = QColorDialog.getColor(
|
||||||
self.selColour, self, self.tr("Select Colour")
|
self._selColour, self, self.tr("Select Colour")
|
||||||
)
|
)
|
||||||
if newCol.isValid():
|
if newCol.isValid():
|
||||||
self.selColour = newCol
|
self._selColour = newCol
|
||||||
pixmap = QPixmap(self.iPx, self.iPx)
|
pixmap = QPixmap(self.iPx, self.iPx)
|
||||||
pixmap.fill(newCol)
|
pixmap.fill(newCol)
|
||||||
self.colButton.setIcon(QIcon(pixmap))
|
self.colButton.setIcon(QIcon(pixmap))
|
||||||
@@ -433,7 +453,7 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
def _newItem(self) -> None:
|
def _newItem(self) -> None:
|
||||||
"""Create a new status item."""
|
"""Create a new status item."""
|
||||||
self._addItem(None, self.tr("New Item"), (100, 100, 100), 0)
|
self._addItem(None, self.tr("New Item"), (100, 100, 100), 0)
|
||||||
self.colChanged = True
|
self._changed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -446,8 +466,8 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
SHARED.error(self.tr("Cannot delete a status item that is in use."))
|
SHARED.error(self.tr("Cannot delete a status item that is in use."))
|
||||||
else:
|
else:
|
||||||
self.listBox.takeTopLevelItem(iRow)
|
self.listBox.takeTopLevelItem(iRow)
|
||||||
self.colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
|
self._colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
|
||||||
self.colChanged = True
|
self._changed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -458,9 +478,9 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
selItem.setText(self.COL_LABEL, simplified(self.editName.text()))
|
selItem.setText(self.COL_LABEL, simplified(self.editName.text()))
|
||||||
selItem.setIcon(self.COL_LABEL, self.colButton.icon())
|
selItem.setIcon(self.COL_LABEL, self.colButton.icon())
|
||||||
selItem.setData(self.COL_LABEL, self.COL_ROLE, (
|
selItem.setData(self.COL_LABEL, self.COL_ROLE, (
|
||||||
self.selColour.red(), self.selColour.green(), self.selColour.blue()
|
self._selColour.red(), self._selColour.green(), self._selColour.blue()
|
||||||
))
|
))
|
||||||
self.colChanged = True
|
self._changed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -474,7 +494,7 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
name = selItem.text(self.COL_LABEL)
|
name = selItem.text(self.COL_LABEL)
|
||||||
pixmap = QPixmap(self.iPx, self.iPx)
|
pixmap = QPixmap(self.iPx, self.iPx)
|
||||||
pixmap.fill(QColor(*cols))
|
pixmap.fill(QColor(*cols))
|
||||||
self.selColour = QColor(*cols)
|
self._selColour = QColor(*cols)
|
||||||
self.editName.setText(name)
|
self.editName.setText(name)
|
||||||
self.colButton.setIcon(QIcon(pixmap))
|
self.colButton.setIcon(QIcon(pixmap))
|
||||||
self.editName.selectAll()
|
self.editName.selectAll()
|
||||||
@@ -485,7 +505,7 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
else:
|
else:
|
||||||
pixmap = QPixmap(self.iPx, self.iPx)
|
pixmap = QPixmap(self.iPx, self.iPx)
|
||||||
pixmap.fill(QColor(100, 100, 100))
|
pixmap.fill(QColor(100, 100, 100))
|
||||||
self.selColour = QColor(100, 100, 100)
|
self._selColour = QColor(100, 100, 100)
|
||||||
self.editName.setText("")
|
self.editName.setText("")
|
||||||
self.colButton.setIcon(QIcon(pixmap))
|
self.colButton.setIcon(QIcon(pixmap))
|
||||||
self.editName.setEnabled(False)
|
self.editName.setEnabled(False)
|
||||||
@@ -498,16 +518,16 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _addItem(self, key: str | None, name: str,
|
def _addItem(self, key: str | None, name: str,
|
||||||
cols: tuple[int, int, int], count: int) -> None:
|
colour: tuple[int, int, int], count: int) -> None:
|
||||||
"""Add a status item to the list."""
|
"""Add a status item to the list."""
|
||||||
pixmap = QPixmap(self.iPx, self.iPx)
|
pixmap = QPixmap(self.iPx, self.iPx)
|
||||||
pixmap.fill(QColor(*cols))
|
pixmap.fill(QColor(*colour))
|
||||||
|
|
||||||
item = QTreeWidgetItem()
|
item = QTreeWidgetItem()
|
||||||
item.setText(self.COL_LABEL, name)
|
item.setText(self.COL_LABEL, name)
|
||||||
item.setIcon(self.COL_LABEL, QIcon(pixmap))
|
item.setIcon(self.COL_LABEL, QIcon(pixmap))
|
||||||
item.setData(self.COL_LABEL, self.KEY_ROLE, key)
|
item.setData(self.COL_LABEL, self.KEY_ROLE, key)
|
||||||
item.setData(self.COL_LABEL, self.COL_ROLE, cols)
|
item.setData(self.COL_LABEL, self.COL_ROLE, colour)
|
||||||
item.setData(self.COL_LABEL, self.NUM_ROLE, count)
|
item.setData(self.COL_LABEL, self.NUM_ROLE, count)
|
||||||
item.setText(self.COL_USAGE, self._usageString(count))
|
item.setText(self.COL_USAGE, self._usageString(count))
|
||||||
|
|
||||||
@@ -533,30 +553,29 @@ class GuiProjectEditStatus(QWidget):
|
|||||||
|
|
||||||
if cItem is not None:
|
if cItem is not None:
|
||||||
cItem.setSelected(True)
|
cItem.setSelected(True)
|
||||||
self.colChanged = True
|
self._changed = True
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _getSelectedItem(self) -> QTreeWidgetItem | None:
|
def _getSelectedItem(self) -> QTreeWidgetItem | None:
|
||||||
"""Get the currently selected item."""
|
"""Get the currently selected item."""
|
||||||
selItem = self.listBox.selectedItems()
|
if items := self.listBox.selectedItems():
|
||||||
if len(selItem) > 0:
|
return items[0]
|
||||||
return selItem[0]
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _usageString(self, nUse: int) -> str:
|
def _usageString(self, count: int) -> str:
|
||||||
"""Generate usage string."""
|
"""Generate usage string."""
|
||||||
if nUse == 0:
|
if count == 0:
|
||||||
return self.tr("Not in use")
|
return self.tr("Not in use")
|
||||||
elif nUse == 1:
|
elif count == 1:
|
||||||
return self.tr("Used once")
|
return self.tr("Used once")
|
||||||
else:
|
else:
|
||||||
return self.tr("Used by {0} items").format(nUse)
|
return self.tr("Used by {0} items").format(count)
|
||||||
|
|
||||||
# END Class GuiProjectEditStatus
|
# END Class _StatusPage
|
||||||
|
|
||||||
|
|
||||||
class GuiProjectEditReplace(QWidget):
|
class _ReplacePage(NFixedPage):
|
||||||
|
|
||||||
COL_KEY = 0
|
COL_KEY = 0
|
||||||
COL_REPL = 1
|
COL_REPL = 1
|
||||||
@@ -564,24 +583,24 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
def __init__(self, parent: QWidget) -> None:
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
self.arChanged = False
|
self._changed = False
|
||||||
|
|
||||||
wCol0 = CONFIG.pxInt(
|
wCol0 = CONFIG.pxInt(
|
||||||
SHARED.project.options.getInt("GuiProjectSettings", "replaceColW", 130)
|
SHARED.project.options.getInt("GuiProjectSettings", "replaceColW", 130)
|
||||||
)
|
)
|
||||||
pageLabel = self.tr("Text Replace List for Preview and Export")
|
|
||||||
|
# Title
|
||||||
|
self.pageTitle = NColourLabel(
|
||||||
|
self.tr("Text Auto-Replace for Preview and Build"),
|
||||||
|
SHARED.theme.helpText, parent=self, scale=NColourLabel.HEADER_SCALE
|
||||||
|
)
|
||||||
|
|
||||||
# List Box
|
# List Box
|
||||||
# ========
|
|
||||||
|
|
||||||
self.listBox = QTreeWidget()
|
self.listBox = QTreeWidget()
|
||||||
self.listBox.setHeaderLabels([
|
self.listBox.setHeaderLabels([self.tr("Keyword"), self.tr("Replace With")])
|
||||||
self.tr("Keyword"),
|
|
||||||
self.tr("Replace With"),
|
|
||||||
])
|
|
||||||
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
|
||||||
self.listBox.setColumnWidth(self.COL_KEY, wCol0)
|
self.listBox.setColumnWidth(self.COL_KEY, wCol0)
|
||||||
self.listBox.setIndentation(0)
|
self.listBox.setIndentation(0)
|
||||||
|
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
||||||
|
|
||||||
for aKey, aVal in SHARED.project.data.autoReplace.items():
|
for aKey, aVal in SHARED.project.data.autoReplace.items():
|
||||||
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
|
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
|
||||||
@@ -591,8 +610,6 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
self.listBox.setSortingEnabled(True)
|
self.listBox.setSortingEnabled(True)
|
||||||
|
|
||||||
# List Controls
|
# List Controls
|
||||||
# =============
|
|
||||||
|
|
||||||
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
|
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
|
||||||
self.addButton.clicked.connect(self._addEntry)
|
self.addButton.clicked.connect(self._addEntry)
|
||||||
|
|
||||||
@@ -600,8 +617,6 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
self.delButton.clicked.connect(self._delEntry)
|
self.delButton.clicked.connect(self._delEntry)
|
||||||
|
|
||||||
# Edit Form
|
# Edit Form
|
||||||
# =========
|
|
||||||
|
|
||||||
self.editKey = QLineEdit()
|
self.editKey = QLineEdit()
|
||||||
self.editKey.setPlaceholderText(self.tr("Select item to edit"))
|
self.editKey.setPlaceholderText(self.tr("Select item to edit"))
|
||||||
self.editKey.setEnabled(False)
|
self.editKey.setEnabled(False)
|
||||||
@@ -615,8 +630,6 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
self.saveButton.clicked.connect(self._saveEntry)
|
self.saveButton.clicked.connect(self._saveEntry)
|
||||||
|
|
||||||
# Assemble
|
# Assemble
|
||||||
# ========
|
|
||||||
|
|
||||||
self.listControls = QVBoxLayout()
|
self.listControls = QVBoxLayout()
|
||||||
self.listControls.addWidget(self.addButton)
|
self.listControls.addWidget(self.addButton)
|
||||||
self.listControls.addWidget(self.delButton)
|
self.listControls.addWidget(self.delButton)
|
||||||
@@ -636,50 +649,61 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
self.innerBox.addLayout(self.listControls)
|
self.innerBox.addLayout(self.listControls)
|
||||||
|
|
||||||
self.outerBox = QVBoxLayout()
|
self.outerBox = QVBoxLayout()
|
||||||
self.outerBox.addWidget(QLabel("<b>%s</b>" % pageLabel))
|
self.outerBox.addWidget(self.pageTitle)
|
||||||
self.outerBox.addLayout(self.innerBox)
|
self.outerBox.addLayout(self.innerBox)
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setCentralLayout(self.outerBox)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wasChanged(self) -> bool:
|
||||||
|
"""The user changed these settings."""
|
||||||
|
return self._changed
|
||||||
|
|
||||||
|
##
|
||||||
|
# Methods
|
||||||
|
##
|
||||||
|
|
||||||
def getNewList(self) -> dict:
|
def getNewList(self) -> dict:
|
||||||
"""Extract the list from the widget."""
|
"""Extract the list from the widget."""
|
||||||
new = {}
|
new = {}
|
||||||
for n in range(self.listBox.topLevelItemCount()):
|
for n in range(self.listBox.topLevelItemCount()):
|
||||||
tItem = self.listBox.topLevelItem(n)
|
if tItem := self.listBox.topLevelItem(n):
|
||||||
if tItem is not None:
|
|
||||||
aKey = self._stripNotAllowed(tItem.text(0))
|
aKey = self._stripNotAllowed(tItem.text(0))
|
||||||
aVal = tItem.text(1)
|
aVal = tItem.text(1)
|
||||||
if len(aKey) > 0:
|
if len(aKey) > 0:
|
||||||
new[aKey] = aVal
|
new[aKey] = aVal
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
def columnWidth(self) -> int:
|
||||||
|
"""Return the size of the header column."""
|
||||||
|
return self.listBox.columnWidth(0)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Private Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
def _selectedItem(self) -> bool:
|
@pyqtSlot()
|
||||||
|
def _selectedItem(self) -> None:
|
||||||
"""Extract the details from the selected item and populate the
|
"""Extract the details from the selected item and populate the
|
||||||
edit form.
|
edit form.
|
||||||
"""
|
"""
|
||||||
selItem = self._getSelectedItem()
|
if selItem := self._getSelectedItem():
|
||||||
if selItem is None:
|
editKey = self._stripNotAllowed(selItem.text(0))
|
||||||
return False
|
editVal = selItem.text(1)
|
||||||
editKey = self._stripNotAllowed(selItem.text(0))
|
self.editKey.setText(editKey)
|
||||||
editVal = selItem.text(1)
|
self.editValue.setText(editVal)
|
||||||
self.editKey.setText(editKey)
|
self.editKey.setEnabled(True)
|
||||||
self.editValue.setText(editVal)
|
self.editValue.setEnabled(True)
|
||||||
self.editKey.setEnabled(True)
|
self.editKey.selectAll()
|
||||||
self.editValue.setEnabled(True)
|
self.editKey.setFocus()
|
||||||
self.editKey.selectAll()
|
return
|
||||||
self.editKey.setFocus()
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
def _saveEntry(self) -> None:
|
def _saveEntry(self) -> None:
|
||||||
"""Save the form data into the list widget."""
|
"""Save the form data into the list widget."""
|
||||||
selItem = self._getSelectedItem()
|
if selItem := self._getSelectedItem():
|
||||||
if selItem:
|
|
||||||
newKey = self.editKey.text()
|
newKey = self.editKey.text()
|
||||||
newVal = self.editValue.text()
|
newVal = self.editValue.text()
|
||||||
saveKey = self._stripNotAllowed(newKey)
|
saveKey = self._stripNotAllowed(newKey)
|
||||||
@@ -691,38 +715,36 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
self.editKey.setEnabled(False)
|
self.editKey.setEnabled(False)
|
||||||
self.editValue.setEnabled(False)
|
self.editValue.setEnabled(False)
|
||||||
self.listBox.clearSelection()
|
self.listBox.clearSelection()
|
||||||
self.arChanged = True
|
self._changed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
def _addEntry(self) -> None:
|
def _addEntry(self) -> None:
|
||||||
"""Add a new list entry."""
|
"""Add a new list entry."""
|
||||||
saveKey = "<keyword%d>" % (self.listBox.topLevelItemCount() + 1)
|
saveKey = "<keyword%d>" % (self.listBox.topLevelItemCount() + 1)
|
||||||
newVal = ""
|
self.listBox.addTopLevelItem(QTreeWidgetItem([saveKey, ""]))
|
||||||
newItem = QTreeWidgetItem([saveKey, newVal])
|
|
||||||
self.listBox.addTopLevelItem(newItem)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
def _delEntry(self) -> None:
|
def _delEntry(self) -> None:
|
||||||
"""Delete the selected entry."""
|
"""Delete the selected entry."""
|
||||||
selItem = self._getSelectedItem()
|
if selItem := self._getSelectedItem():
|
||||||
if selItem:
|
|
||||||
self.listBox.takeTopLevelItem(self.listBox.indexOfTopLevelItem(selItem))
|
self.listBox.takeTopLevelItem(self.listBox.indexOfTopLevelItem(selItem))
|
||||||
self.arChanged = True
|
self._changed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
def _getSelectedItem(self) -> QTreeWidgetItem | None:
|
def _getSelectedItem(self) -> QTreeWidgetItem | None:
|
||||||
"""Extract the currently selected item."""
|
"""Extract the currently selected item."""
|
||||||
selItem = self.listBox.selectedItems()
|
if items := self.listBox.selectedItems():
|
||||||
if len(selItem) == 0:
|
return items[0]
|
||||||
return None
|
return None
|
||||||
return selItem[0]
|
|
||||||
|
|
||||||
def _stripNotAllowed(self, key: str) -> str:
|
def _stripNotAllowed(self, key: str) -> str:
|
||||||
"""Clean up the replace key string."""
|
"""Clean up the replace key string."""
|
||||||
result = ""
|
return "".join(c for c in key if c.isalnum())
|
||||||
for c in key:
|
|
||||||
if c.isalnum():
|
|
||||||
result += c
|
|
||||||
return result
|
|
||||||
|
|
||||||
# END Class GuiProjectEditReplace
|
# END Class _ReplacePage
|
||||||
@@ -6,6 +6,8 @@ File History:
|
|||||||
Created: 2020-05-03 [0.4.5] NConfigLayout, NColourLabel
|
Created: 2020-05-03 [0.4.5] NConfigLayout, NColourLabel
|
||||||
Created: 2023-05-23 [2.1b1] NSimpleLayout
|
Created: 2023-05-23 [2.1b1] NSimpleLayout
|
||||||
Created: 2024-01-08 [2.3b1] NScrollableForm
|
Created: 2024-01-08 [2.3b1] NScrollableForm
|
||||||
|
Created: 2024-01-26 [2.3b1] NScrollablePage
|
||||||
|
Created: 2024-01-26 [2.3b1] NFixedPage
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2024, Veronica Berglyd Olsen
|
Copyright 2018–2024, Veronica Berglyd Olsen
|
||||||
@@ -28,17 +30,59 @@ from __future__ import annotations
|
|||||||
from PyQt5.QtGui import QColor, QPalette
|
from PyQt5.QtGui import QColor, QPalette
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractButton, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QScrollArea, QSizePolicy,
|
QAbstractButton, QFrame, QGridLayout, QHBoxLayout, QLabel, QLayout,
|
||||||
QVBoxLayout, QWidget
|
QScrollArea, QSizePolicy, QVBoxLayout, QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
|
|
||||||
FONT_SCALE = 0.9
|
DEFAULT_SCALE = 0.9
|
||||||
RIGHT_TOP = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
|
RIGHT_TOP = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
|
||||||
LEFT_TOP = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop
|
LEFT_TOP = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop
|
||||||
|
|
||||||
|
|
||||||
|
class NFixedPage(QFrame):
|
||||||
|
"""Extension: Fixed Page Widget
|
||||||
|
|
||||||
|
A custom widget that holds a layout. This is just a wrapper around a
|
||||||
|
QFrame that sets the same frame style as the other Page widgets.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, parent: QWidget) -> None:
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self.setFrameShadow(QFrame.Shadow.Sunken)
|
||||||
|
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||||
|
self.setCentralLayout = self.setLayout
|
||||||
|
return
|
||||||
|
|
||||||
|
# END Class NFixedPage
|
||||||
|
|
||||||
|
|
||||||
|
class NScrollablePage(QScrollArea):
|
||||||
|
"""Extension: Scrollable Page Widget
|
||||||
|
|
||||||
|
A custom widget that holds a layout within a scrollable area.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, parent: QWidget) -> None:
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self._widget = QWidget(self)
|
||||||
|
self.setWidget(self._widget)
|
||||||
|
self.setWidgetResizable(True)
|
||||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
|
self.setFrameShadow(QFrame.Shadow.Sunken)
|
||||||
|
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setCentralLayout(self, layout: QLayout) -> None:
|
||||||
|
"""Set the central layout of the scroll page."""
|
||||||
|
self._widget.setLayout(layout)
|
||||||
|
return
|
||||||
|
|
||||||
|
# END Class NScrollablePage
|
||||||
|
|
||||||
|
|
||||||
class NScrollableForm(QScrollArea):
|
class NScrollableForm(QScrollArea):
|
||||||
"""Extension: Scrollable Form Widget
|
"""Extension: Scrollable Form Widget
|
||||||
|
|
||||||
@@ -48,8 +92,9 @@ class NScrollableForm(QScrollArea):
|
|||||||
def __init__(self, parent: QWidget) -> None:
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self._helpCol = QColor(0, 0, 0)
|
self._helpCol = QColor(0, 0, 0)
|
||||||
self._fontScale = FONT_SCALE
|
self._fontScale = DEFAULT_SCALE
|
||||||
self._first = True
|
self._first = True
|
||||||
|
self._indent = CONFIG.pxInt(12)
|
||||||
|
|
||||||
self._sections: dict[int, QLabel] = {}
|
self._sections: dict[int, QLabel] = {}
|
||||||
self._editable: dict[str, NColourLabel] = {}
|
self._editable: dict[str, NColourLabel] = {}
|
||||||
@@ -65,6 +110,8 @@ class NScrollableForm(QScrollArea):
|
|||||||
self.setWidgetResizable(True)
|
self.setWidgetResizable(True)
|
||||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
|
self.setFrameShadow(QFrame.Shadow.Sunken)
|
||||||
|
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -80,7 +127,7 @@ class NScrollableForm(QScrollArea):
|
|||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
|
|
||||||
def setHelpTextStyle(self, color: QColor, scale: float = FONT_SCALE) -> None:
|
def setHelpTextStyle(self, color: QColor, scale: float = DEFAULT_SCALE) -> None:
|
||||||
"""Set the text color for the help text."""
|
"""Set the text color for the help text."""
|
||||||
self._helpCol = color
|
self._helpCol = color
|
||||||
self._fontScale = scale
|
self._fontScale = scale
|
||||||
@@ -92,6 +139,11 @@ class NScrollableForm(QScrollArea):
|
|||||||
qHelp.setText(text)
|
qHelp.setText(text)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def setRowIndent(self, indent: int) -> None:
|
||||||
|
"""Set the indentation of each row."""
|
||||||
|
self._indent = max(indent, 0)
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Methods
|
# Methods
|
||||||
##
|
##
|
||||||
@@ -123,37 +175,43 @@ class NScrollableForm(QScrollArea):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def addRow(self, label: str, widget: QWidget, helpText: str = "", unit: str | None = None,
|
def addRow(self, label: str, widget: QWidget, helpText: str = "", unit: str | None = None,
|
||||||
button: QWidget | None = None, editable: str | None = None) -> None:
|
button: QWidget | None = None, editable: str | None = None,
|
||||||
|
stretch: tuple[int, int] = (0, 0)) -> None:
|
||||||
"""Add a label and a widget as a new row of the form."""
|
"""Add a label and a widget as a new row of the form."""
|
||||||
row = QHBoxLayout()
|
row = QHBoxLayout()
|
||||||
row.setSpacing(CONFIG.pxInt(4))
|
row.setSpacing(CONFIG.pxInt(12))
|
||||||
|
|
||||||
mPx = CONFIG.pxInt(12)
|
|
||||||
qLabel = QLabel(label, self)
|
qLabel = QLabel(label, self)
|
||||||
qLabel.setIndent(mPx)
|
qLabel.setIndent(self._indent)
|
||||||
qLabel.setBuddy(widget)
|
qLabel.setBuddy(widget)
|
||||||
|
|
||||||
if helpText:
|
if helpText:
|
||||||
qHelp = NColourLabel(str(helpText), self._helpCol, scale=self._fontScale, wrap=True)
|
qHelp = NColourLabel(
|
||||||
qHelp.setIndent(mPx)
|
str(helpText), self._helpCol, parent=self,
|
||||||
|
scale=self._fontScale, wrap=True, indent=self._indent
|
||||||
|
)
|
||||||
labelBox = QVBoxLayout()
|
labelBox = QVBoxLayout()
|
||||||
labelBox.addWidget(qLabel)
|
labelBox.addWidget(qLabel)
|
||||||
labelBox.addWidget(qHelp)
|
labelBox.addWidget(qHelp)
|
||||||
labelBox.setSpacing(0)
|
labelBox.setSpacing(0)
|
||||||
labelBox.addStretch(1)
|
row.addLayout(labelBox, stretch[0])
|
||||||
row.addLayout(labelBox)
|
|
||||||
if editable:
|
if editable:
|
||||||
self._editable[editable] = qHelp
|
self._editable[editable] = qHelp
|
||||||
else:
|
else:
|
||||||
row.addWidget(qLabel)
|
row.addWidget(qLabel, stretch[0])
|
||||||
|
|
||||||
row.addSpacing(mPx)
|
|
||||||
row.addWidget(widget)
|
|
||||||
|
|
||||||
if isinstance(unit, str):
|
if isinstance(unit, str):
|
||||||
row.addWidget(QLabel(unit, self))
|
box = QHBoxLayout()
|
||||||
|
box.addWidget(widget)
|
||||||
|
box.addWidget(QLabel(unit, self))
|
||||||
|
row.addLayout(box, stretch[1])
|
||||||
elif isinstance(button, QAbstractButton):
|
elif isinstance(button, QAbstractButton):
|
||||||
row.addWidget(button)
|
box = QHBoxLayout()
|
||||||
|
box.addWidget(widget)
|
||||||
|
box.addWidget(button)
|
||||||
|
row.addLayout(box, stretch[1])
|
||||||
|
else:
|
||||||
|
row.addWidget(widget, stretch[1])
|
||||||
|
|
||||||
self._layout.addLayout(row)
|
self._layout.addLayout(row)
|
||||||
self._index[label.strip()] = widget
|
self._index[label.strip()] = widget
|
||||||
@@ -177,7 +235,7 @@ class NConfigLayout(QGridLayout):
|
|||||||
|
|
||||||
self._nextRow = 0
|
self._nextRow = 0
|
||||||
self._helpCol = QColor(0, 0, 0)
|
self._helpCol = QColor(0, 0, 0)
|
||||||
self._fontScale = FONT_SCALE
|
self._fontScale = DEFAULT_SCALE
|
||||||
self._itemMap = {}
|
self._itemMap = {}
|
||||||
|
|
||||||
wSp = CONFIG.pxInt(8)
|
wSp = CONFIG.pxInt(8)
|
||||||
@@ -187,16 +245,6 @@ class NConfigLayout(QGridLayout):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
|
||||||
# Getters and Setters
|
|
||||||
##
|
|
||||||
|
|
||||||
def setHelpTextStyle(self, color: QColor, scale: float = FONT_SCALE) -> None:
|
|
||||||
"""Set the text color for the help text."""
|
|
||||||
self._helpCol = color if isinstance(color, QColor) else QColor(*color)
|
|
||||||
self._fontScale = scale
|
|
||||||
return
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Class Methods
|
# Class Methods
|
||||||
##
|
##
|
||||||
@@ -212,8 +260,8 @@ class NConfigLayout(QGridLayout):
|
|||||||
self._nextRow += 1
|
self._nextRow += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
def addRow(self, label: str, widget: QWidget, helpText: str | None = None,
|
def addRow(self, label: str, widget: QWidget, unit: str | None = None,
|
||||||
unit: str | None = None, button: QWidget | None = None) -> int:
|
button: QWidget | None = None) -> int:
|
||||||
"""Add a label and a widget as a new row of the grid."""
|
"""Add a label and a widget as a new row of the grid."""
|
||||||
wSp = CONFIG.pxInt(8)
|
wSp = CONFIG.pxInt(8)
|
||||||
qLabel = QLabel(label)
|
qLabel = QLabel(label)
|
||||||
@@ -221,17 +269,7 @@ class NConfigLayout(QGridLayout):
|
|||||||
qLabel.setBuddy(widget)
|
qLabel.setBuddy(widget)
|
||||||
|
|
||||||
qHelp = None
|
qHelp = None
|
||||||
if helpText is not None:
|
self.addWidget(qLabel, self._nextRow, 0, 1, 1, LEFT_TOP)
|
||||||
qHelp = NColourLabel(str(helpText), self._helpCol, scale=self._fontScale, wrap=True)
|
|
||||||
qHelp.setIndent(wSp)
|
|
||||||
labelBox = QVBoxLayout()
|
|
||||||
labelBox.addWidget(qLabel)
|
|
||||||
labelBox.addWidget(qHelp)
|
|
||||||
labelBox.setSpacing(0)
|
|
||||||
labelBox.addStretch(1)
|
|
||||||
self.addLayout(labelBox, self._nextRow, 0, 1, 1, LEFT_TOP)
|
|
||||||
else:
|
|
||||||
self.addWidget(qLabel, self._nextRow, 0, 1, 1, LEFT_TOP)
|
|
||||||
|
|
||||||
if isinstance(unit, str):
|
if isinstance(unit, str):
|
||||||
controlBox = QHBoxLayout()
|
controlBox = QHBoxLayout()
|
||||||
@@ -248,12 +286,7 @@ class NConfigLayout(QGridLayout):
|
|||||||
self.addLayout(controlBox, self._nextRow, 1, 1, 1, RIGHT_TOP)
|
self.addLayout(controlBox, self._nextRow, 1, 1, 1, RIGHT_TOP)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if isinstance(widget, QLineEdit):
|
self.addWidget(widget, self._nextRow, 1, 1, 1, RIGHT_TOP)
|
||||||
qLayout = QHBoxLayout()
|
|
||||||
qLayout.addWidget(widget)
|
|
||||||
self.addLayout(qLayout, self._nextRow, 1, 1, 1, RIGHT_TOP)
|
|
||||||
else:
|
|
||||||
self.addWidget(widget, self._nextRow, 1, 1, 1, RIGHT_TOP)
|
|
||||||
|
|
||||||
self.setRowStretch(self._nextRow, 0)
|
self.setRowStretch(self._nextRow, 0)
|
||||||
self.setRowStretch(self._nextRow+1, 1)
|
self.setRowStretch(self._nextRow+1, 1)
|
||||||
@@ -321,17 +354,21 @@ class NColourLabel(QLabel):
|
|||||||
optionally at a specific size, and word wrapped.
|
optionally at a specific size, and word wrapped.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
HELP_SCALE = DEFAULT_SCALE
|
||||||
|
HEADER_SCALE = 1.25
|
||||||
|
|
||||||
def __init__(self, text: str, color: QColor, parent: QWidget | None = None,
|
def __init__(self, text: str, color: QColor, parent: QWidget | None = None,
|
||||||
scale: float = FONT_SCALE, wrap: bool = False) -> None:
|
scale: float = HELP_SCALE, wrap: bool = False, indent: int = 0) -> None:
|
||||||
super().__init__(text, parent=parent)
|
super().__init__(text, parent=parent)
|
||||||
|
|
||||||
lblCol = self.palette()
|
font = self.font()
|
||||||
lblCol.setColor(QPalette.WindowText, color)
|
font.setPointSizeF(scale*font.pointSizeF())
|
||||||
self.setPalette(lblCol)
|
colour = self.palette()
|
||||||
|
colour.setColor(QPalette.WindowText, color)
|
||||||
|
|
||||||
lblFont = self.font()
|
self.setPalette(colour)
|
||||||
lblFont.setPointSizeF(scale*lblFont.pointSizeF())
|
self.setFont(font)
|
||||||
self.setFont(lblFont)
|
self.setIndent(indent)
|
||||||
|
|
||||||
if wrap:
|
if wrap:
|
||||||
self.setWordWrap(True)
|
self.setWordWrap(True)
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
"""
|
|
||||||
novelWriter – Custom Widget: Paged Dialog
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
File History:
|
|
||||||
Created: 2020-05-17 [0.5.1]
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright 2018–2024, Veronica Berglyd Olsen
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from PyQt5.QtGui import QPaintEvent
|
|
||||||
from PyQt5.QtCore import QRect, QPoint, QSize
|
|
||||||
from PyQt5.QtWidgets import (
|
|
||||||
QDialog, QHBoxLayout, QStyle, QStyleOptionTab, QStylePainter, QTabBar,
|
|
||||||
QTabWidget, QVBoxLayout, QWidget
|
|
||||||
)
|
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
|
||||||
|
|
||||||
|
|
||||||
class NPagedDialog(QDialog):
|
|
||||||
|
|
||||||
def __init__(self, parent: QWidget) -> None:
|
|
||||||
super().__init__(parent=parent)
|
|
||||||
|
|
||||||
self._tabBar = NVerticalTabBar(self)
|
|
||||||
self._tabBar.setExpanding(False)
|
|
||||||
|
|
||||||
self._tabBox = QTabWidget(self)
|
|
||||||
self._tabBox.setTabBar(self._tabBar)
|
|
||||||
self._tabBox.setTabPosition(QTabWidget.West)
|
|
||||||
|
|
||||||
self._buttonBox = QHBoxLayout()
|
|
||||||
|
|
||||||
self._outerBox = QVBoxLayout()
|
|
||||||
self._outerBox.addWidget(self._tabBox)
|
|
||||||
self._outerBox.addLayout(self._buttonBox)
|
|
||||||
|
|
||||||
# Default Margins
|
|
||||||
thisStyle = self.style()
|
|
||||||
mL = thisStyle.pixelMetric(QStyle.PM_LayoutLeftMargin)
|
|
||||||
mR = thisStyle.pixelMetric(QStyle.PM_LayoutRightMargin)
|
|
||||||
mT = thisStyle.pixelMetric(QStyle.PM_LayoutLeftMargin)
|
|
||||||
mB = thisStyle.pixelMetric(QStyle.PM_LayoutBottomMargin)
|
|
||||||
|
|
||||||
# Set Margins
|
|
||||||
self.setContentsMargins(0, 0, 0, 0)
|
|
||||||
self._outerBox.setContentsMargins(0, 0, 0, mB)
|
|
||||||
self._buttonBox.setContentsMargins(mL, 0, mR, 0)
|
|
||||||
self._outerBox.setSpacing(mT)
|
|
||||||
|
|
||||||
self.setLayout(self._outerBox)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def addTab(self, widget: QWidget, label: str) -> None:
|
|
||||||
"""Forward the adding of tabs to the QTabWidget."""
|
|
||||||
self._tabBox.addTab(widget, label)
|
|
||||||
return
|
|
||||||
|
|
||||||
def addControls(self, buttonBar: QWidget) -> None:
|
|
||||||
"""Add a button bar to the dialog."""
|
|
||||||
self._buttonBox.addWidget(buttonBar)
|
|
||||||
return
|
|
||||||
|
|
||||||
def setCurrentWidget(self, widget: QWidget) -> None:
|
|
||||||
"""Forward the changing of tab to the QTabWidget."""
|
|
||||||
self._tabBox.setCurrentWidget(widget)
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class NPagedDialog
|
|
||||||
|
|
||||||
|
|
||||||
class NVerticalTabBar(QTabBar):
|
|
||||||
|
|
||||||
def __init__(self, parent: QWidget) -> None:
|
|
||||||
super().__init__(parent=parent)
|
|
||||||
self._mW = CONFIG.pxInt(150)
|
|
||||||
return
|
|
||||||
|
|
||||||
def tabSizeHint(self, index: int) -> QSize:
|
|
||||||
"""Return a transposed size hint for the rotated bar."""
|
|
||||||
tSize = super().tabSizeHint(index)
|
|
||||||
tSize.transpose()
|
|
||||||
tSize.setWidth(min(tSize.width(), self._mW))
|
|
||||||
return tSize
|
|
||||||
|
|
||||||
def paintEvent(self, event: QPaintEvent) -> None:
|
|
||||||
"""Custom implementation of the label painter that rotates the
|
|
||||||
label 90 degrees.
|
|
||||||
"""
|
|
||||||
pObj = QStylePainter(self)
|
|
||||||
oObj = QStyleOptionTab()
|
|
||||||
|
|
||||||
for i in range(self.count()):
|
|
||||||
self.initStyleOption(oObj, i)
|
|
||||||
pObj.drawControl(QStyle.CE_TabBarTabShape, oObj)
|
|
||||||
pObj.save()
|
|
||||||
|
|
||||||
oSize = oObj.rect.size()
|
|
||||||
oSize.transpose()
|
|
||||||
oRect = QRect(QPoint(), oSize)
|
|
||||||
oRect.moveCenter(oObj.rect.center())
|
|
||||||
oObj.rect = oRect
|
|
||||||
|
|
||||||
oCenter = self.tabRect(i).center()
|
|
||||||
pObj.translate(oCenter)
|
|
||||||
pObj.rotate(90)
|
|
||||||
pObj.translate(-oCenter)
|
|
||||||
pObj.drawControl(QStyle.CE_TabBarTabLabel, oObj)
|
|
||||||
pObj.restore()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class NVerticalTabBar
|
|
||||||
@@ -48,7 +48,7 @@ from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter
|
|||||||
from novelwriter.dialogs.docmerge import GuiDocMerge
|
from novelwriter.dialogs.docmerge import GuiDocMerge
|
||||||
from novelwriter.dialogs.docsplit import GuiDocSplit
|
from novelwriter.dialogs.docsplit import GuiDocSplit
|
||||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
from novelwriter.dialogs.projectsettings import GuiProjectSettings
|
||||||
from novelwriter.enum import (
|
from novelwriter.enum import (
|
||||||
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
|
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
|
||||||
)
|
)
|
||||||
@@ -1748,7 +1748,7 @@ class _TreeContextMenu(QMenu):
|
|||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
action = menu.addAction(self.tr("Manage Labels ..."))
|
action = menu.addAction(self.tr("Manage Labels ..."))
|
||||||
action.triggered.connect(
|
action.triggered.connect(
|
||||||
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_STATUS)
|
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.PAGE_STATUS)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
menu = self.addMenu(self.tr("Set Importance to ..."))
|
menu = self.addMenu(self.tr("Set Importance to ..."))
|
||||||
@@ -1765,7 +1765,7 @@ class _TreeContextMenu(QMenu):
|
|||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
action = menu.addAction(self.tr("Manage Labels ..."))
|
action = menu.addAction(self.tr("Manage Labels ..."))
|
||||||
action.triggered.connect(
|
action.triggered.connect(
|
||||||
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_IMPORT)
|
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.PAGE_IMPORT)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ from novelwriter.dialogs.about import GuiAbout
|
|||||||
from novelwriter.dialogs.updates import GuiUpdates
|
from novelwriter.dialogs.updates import GuiUpdates
|
||||||
from novelwriter.dialogs.wordlist import GuiWordList
|
from novelwriter.dialogs.wordlist import GuiWordList
|
||||||
from novelwriter.dialogs.preferences import GuiPreferences
|
from novelwriter.dialogs.preferences import GuiPreferences
|
||||||
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
from novelwriter.dialogs.projectsettings import GuiProjectSettings
|
||||||
from novelwriter.tools.welcome import GuiWelcome
|
from novelwriter.tools.welcome import GuiWelcome
|
||||||
from novelwriter.tools.manuscript import GuiManuscript
|
from novelwriter.tools.manuscript import GuiManuscript
|
||||||
from novelwriter.tools.dictionaries import GuiDictionaries
|
from novelwriter.tools.dictionaries import GuiDictionaries
|
||||||
@@ -809,10 +809,10 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def showProjectSettingsDialog(self, focusTab: int = GuiProjectSettings.TAB_MAIN) -> None:
|
def showProjectSettingsDialog(self, focusTab: int = GuiProjectSettings.PAGE_SETTINGS) -> None:
|
||||||
"""Open the project settings dialog."""
|
"""Open the project settings dialog."""
|
||||||
if SHARED.hasProject:
|
if SHARED.hasProject:
|
||||||
dialog = GuiProjectSettings(self, focusTab=focusTab)
|
dialog = GuiProjectSettings(self, gotoPage=focusTab)
|
||||||
dialog.newProjectSettingsReady.connect(self._processProjectSettingsChanges)
|
dialog.newProjectSettingsReady.connect(self._processProjectSettingsChanges)
|
||||||
dialog.exec_()
|
dialog.exec_()
|
||||||
return
|
return
|
||||||
@@ -1111,13 +1111,15 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot(bool)
|
||||||
def _processProjectSettingsChanges(self) -> None:
|
def _processProjectSettingsChanges(self, rebuildTrees: bool) -> None:
|
||||||
"""Refresh data dependent on project settings."""
|
"""Refresh data dependent on project settings."""
|
||||||
logger.debug("Applying new project settings")
|
logger.debug("Applying new project settings")
|
||||||
SHARED.updateSpellCheckLanguage()
|
SHARED.updateSpellCheckLanguage()
|
||||||
self.itemDetails.refreshDetails()
|
self.itemDetails.refreshDetails()
|
||||||
self._updateWindowTitle(SHARED.project.data.name)
|
self._updateWindowTitle(SHARED.project.data.name)
|
||||||
|
if rebuildTrees:
|
||||||
|
self.rebuildTrees()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
|||||||
@@ -38,14 +38,12 @@ from novelwriter import CONFIG, SHARED
|
|||||||
from novelwriter.common import formatTime, numberToRoman
|
from novelwriter.common import formatTime, numberToRoman
|
||||||
from novelwriter.constants import nwUnicode
|
from novelwriter.constants import nwUnicode
|
||||||
from novelwriter.extensions.switch import NSwitch
|
from novelwriter.extensions.switch import NSwitch
|
||||||
from novelwriter.extensions.configlayout import NColourLabel
|
from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage
|
||||||
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
||||||
from novelwriter.extensions.novelselector import NovelSelector
|
from novelwriter.extensions.novelselector import NovelSelector
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
HEADER_SIZE = 1.4
|
|
||||||
|
|
||||||
|
|
||||||
class GuiNovelDetails(QDialog):
|
class GuiNovelDetails(QDialog):
|
||||||
|
|
||||||
@@ -59,21 +57,18 @@ class GuiNovelDetails(QDialog):
|
|||||||
self.setObjectName("GuiNovelDetails")
|
self.setObjectName("GuiNovelDetails")
|
||||||
self.setWindowTitle(self.tr("Novel Details"))
|
self.setWindowTitle(self.tr("Novel Details"))
|
||||||
|
|
||||||
wW = CONFIG.pxInt(500)
|
|
||||||
wH = CONFIG.pxInt(400)
|
|
||||||
options = SHARED.project.options
|
options = SHARED.project.options
|
||||||
|
self.setMinimumSize(CONFIG.pxInt(500), CONFIG.pxInt(400))
|
||||||
self.setMinimumSize(wW, wH)
|
|
||||||
self.resize(
|
self.resize(
|
||||||
CONFIG.pxInt(options.getInt("GuiNovelDetails", "winWidth", wW)),
|
CONFIG.pxInt(options.getInt("GuiNovelDetails", "winWidth", CONFIG.pxInt(650))),
|
||||||
CONFIG.pxInt(options.getInt("GuiNovelDetails", "winHeight", wH))
|
CONFIG.pxInt(options.getInt("GuiNovelDetails", "winHeight", CONFIG.pxInt(500)))
|
||||||
)
|
)
|
||||||
|
|
||||||
# Title
|
# Title
|
||||||
self.titleLabel = NColourLabel(
|
self.titleLabel = NColourLabel(
|
||||||
self.tr("Novel Details"), SHARED.theme.helpText, parent=self, scale=1.25
|
self.tr("Novel Details"), SHARED.theme.helpText,
|
||||||
|
parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
||||||
)
|
)
|
||||||
self.titleLabel.setIndent(CONFIG.pxInt(4))
|
|
||||||
|
|
||||||
# Novel Selector
|
# Novel Selector
|
||||||
self.novelSelector = NovelSelector(self)
|
self.novelSelector = NovelSelector(self)
|
||||||
@@ -192,7 +187,7 @@ class GuiNovelDetails(QDialog):
|
|||||||
# END Class GuiNovelDetails
|
# END Class GuiNovelDetails
|
||||||
|
|
||||||
|
|
||||||
class _OverviewPage(QWidget):
|
class _OverviewPage(NScrollablePage):
|
||||||
|
|
||||||
def __init__(self, parent: QWidget) -> None:
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@@ -204,7 +199,8 @@ class _OverviewPage(QWidget):
|
|||||||
|
|
||||||
# Project Info
|
# Project Info
|
||||||
self.projLabel = NColourLabel(
|
self.projLabel = NColourLabel(
|
||||||
self.tr("Project"), SHARED.theme.helpText, parent=self, scale=HEADER_SIZE
|
self.tr("Project"), SHARED.theme.helpText,
|
||||||
|
parent=self, scale=NColourLabel.HEADER_SCALE
|
||||||
)
|
)
|
||||||
|
|
||||||
self.projName = QLabel("", self)
|
self.projName = QLabel("", self)
|
||||||
@@ -227,7 +223,8 @@ class _OverviewPage(QWidget):
|
|||||||
|
|
||||||
# Novel Info
|
# Novel Info
|
||||||
self.novelLabel = NColourLabel(
|
self.novelLabel = NColourLabel(
|
||||||
self.tr("Selected Novel"), SHARED.theme.helpText, parent=self, scale=HEADER_SIZE
|
self.tr("Selected Novel"), SHARED.theme.helpText,
|
||||||
|
parent=self, scale=NColourLabel.HEADER_SCALE
|
||||||
)
|
)
|
||||||
|
|
||||||
self.novelName = QLabel("", self)
|
self.novelName = QLabel("", self)
|
||||||
@@ -250,11 +247,10 @@ class _OverviewPage(QWidget):
|
|||||||
self.outerBox.addLayout(self.projForm)
|
self.outerBox.addLayout(self.projForm)
|
||||||
self.outerBox.addWidget(self.novelLabel)
|
self.outerBox.addWidget(self.novelLabel)
|
||||||
self.outerBox.addLayout(self.novelForm)
|
self.outerBox.addLayout(self.novelForm)
|
||||||
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
|
||||||
self.outerBox.setSpacing(sPx)
|
self.outerBox.setSpacing(sPx)
|
||||||
self.outerBox.addStretch(1)
|
self.outerBox.addStretch(1)
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setCentralLayout(self.outerBox)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -299,7 +295,7 @@ class _OverviewPage(QWidget):
|
|||||||
# END Class _OverviewPage
|
# END Class _OverviewPage
|
||||||
|
|
||||||
|
|
||||||
class _ContentsPage(QWidget):
|
class _ContentsPage(NFixedPage):
|
||||||
|
|
||||||
C_TITLE = 0
|
C_TITLE = 0
|
||||||
C_WORDS = 1
|
C_WORDS = 1
|
||||||
@@ -320,7 +316,8 @@ class _ContentsPage(QWidget):
|
|||||||
|
|
||||||
# Title
|
# Title
|
||||||
self.contentLabel = NColourLabel(
|
self.contentLabel = NColourLabel(
|
||||||
self.tr("Table of Contents"), SHARED.theme.helpText, parent=self, scale=HEADER_SIZE
|
self.tr("Table of Contents"), SHARED.theme.helpText,
|
||||||
|
parent=self, scale=NColourLabel.HEADER_SCALE
|
||||||
)
|
)
|
||||||
|
|
||||||
# Contents Tree
|
# Contents Tree
|
||||||
@@ -407,20 +404,25 @@ class _ContentsPage(QWidget):
|
|||||||
self.outerBox.addWidget(self.contentLabel)
|
self.outerBox.addWidget(self.contentLabel)
|
||||||
self.outerBox.addWidget(self.tocTree)
|
self.outerBox.addWidget(self.tocTree)
|
||||||
self.outerBox.addLayout(self.optionsBox)
|
self.outerBox.addLayout(self.optionsBox)
|
||||||
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setCentralLayout(self.outerBox)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def saveSettings(self) -> None:
|
def saveSettings(self) -> None:
|
||||||
"""Save the user GUI settings."""
|
"""Save the user GUI settings."""
|
||||||
|
widthCol0 = CONFIG.rpxInt(self.tocTree.columnWidth(0))
|
||||||
|
widthCol1 = CONFIG.rpxInt(self.tocTree.columnWidth(1))
|
||||||
|
widthCol2 = CONFIG.rpxInt(self.tocTree.columnWidth(2))
|
||||||
|
widthCol3 = CONFIG.rpxInt(self.tocTree.columnWidth(3))
|
||||||
|
widthCol4 = CONFIG.rpxInt(self.tocTree.columnWidth(4))
|
||||||
|
|
||||||
options = SHARED.project.options
|
options = SHARED.project.options
|
||||||
options.setValue("GuiNovelDetails", "widthCol0", self.tocTree.columnWidth(0))
|
options.setValue("GuiNovelDetails", "widthCol0", widthCol0)
|
||||||
options.setValue("GuiNovelDetails", "widthCol1", self.tocTree.columnWidth(1))
|
options.setValue("GuiNovelDetails", "widthCol1", widthCol1)
|
||||||
options.setValue("GuiNovelDetails", "widthCol2", self.tocTree.columnWidth(2))
|
options.setValue("GuiNovelDetails", "widthCol2", widthCol2)
|
||||||
options.setValue("GuiNovelDetails", "widthCol3", self.tocTree.columnWidth(3))
|
options.setValue("GuiNovelDetails", "widthCol3", widthCol3)
|
||||||
options.setValue("GuiNovelDetails", "widthCol4", self.tocTree.columnWidth(4))
|
options.setValue("GuiNovelDetails", "widthCol4", widthCol4)
|
||||||
options.setValue("GuiNovelDetails", "wordsPerPage", self.wpValue.value())
|
options.setValue("GuiNovelDetails", "wordsPerPage", self.wpValue.value())
|
||||||
options.setValue("GuiNovelDetails", "countFrom", self.poValue.value())
|
options.setValue("GuiNovelDetails", "countFrom", self.poValue.value())
|
||||||
options.setValue("GuiNovelDetails", "clearDouble", self.dblValue.isChecked())
|
options.setValue("GuiNovelDetails", "clearDouble", self.dblValue.isChecked())
|
||||||
|
|||||||
+135
-150
@@ -31,7 +31,7 @@ from PyQt5.QtWidgets import QDialog, QAction, QColorDialog
|
|||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.enum import nwItemType
|
from novelwriter.enum import nwItemType
|
||||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
from novelwriter.dialogs.projectsettings import GuiProjectSettings
|
||||||
|
|
||||||
KEY_DELAY = 1
|
KEY_DELAY = 1
|
||||||
|
|
||||||
@@ -63,17 +63,17 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
|
|||||||
qtbot.addWidget(projSettings)
|
qtbot.addWidget(projSettings)
|
||||||
|
|
||||||
# Switch Tabs
|
# Switch Tabs
|
||||||
projSettings._focusTab(GuiProjectSettings.TAB_REPLACE)
|
projSettings.sidebar.button(GuiProjectSettings.PAGE_SETTINGS).click()
|
||||||
assert projSettings._tabBox.currentWidget() == projSettings.tabReplace
|
assert projSettings.mainStack.currentWidget() == projSettings.settingsPage
|
||||||
|
|
||||||
projSettings._focusTab(GuiProjectSettings.TAB_IMPORT)
|
projSettings.sidebar.button(GuiProjectSettings.PAGE_STATUS).click()
|
||||||
assert projSettings._tabBox.currentWidget() == projSettings.tabImport
|
assert projSettings.mainStack.currentWidget() == projSettings.statusPage
|
||||||
|
|
||||||
projSettings._focusTab(GuiProjectSettings.TAB_STATUS)
|
projSettings.sidebar.button(GuiProjectSettings.PAGE_IMPORT).click()
|
||||||
assert projSettings._tabBox.currentWidget() == projSettings.tabStatus
|
assert projSettings.mainStack.currentWidget() == projSettings.importPage
|
||||||
|
|
||||||
projSettings._focusTab(GuiProjectSettings.TAB_MAIN)
|
projSettings.sidebar.button(GuiProjectSettings.PAGE_REPLACE).click()
|
||||||
assert projSettings._tabBox.currentWidget() == projSettings.tabMain
|
assert projSettings.mainStack.currentWidget() == projSettings.replacePage
|
||||||
|
|
||||||
# Clean Up
|
# Clean Up
|
||||||
projSettings.close()
|
projSettings.close()
|
||||||
@@ -83,9 +83,11 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
def testDlgProjSettings_SettingsPage(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
||||||
"""Test the main tab of the project settings dialog."""
|
"""Test the settings page of the dialog."""
|
||||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
|
languages = [("en", "English"), ("de", "German")]
|
||||||
|
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda *a: languages)
|
||||||
|
monkeypatch.setattr(CONFIG, "listLanguages", lambda *a: languages)
|
||||||
|
|
||||||
# Create new project
|
# Create new project
|
||||||
buildTestProject(nwGUI, projPath)
|
buildTestProject(nwGUI, projPath)
|
||||||
@@ -94,72 +96,57 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockR
|
|||||||
|
|
||||||
# Set some values
|
# Set some values
|
||||||
project = SHARED.project
|
project = SHARED.project
|
||||||
|
project.data.setLanguage("en")
|
||||||
project.data.setSpellLang("en")
|
project.data.setSpellLang("en")
|
||||||
project.data.setAuthor("Jane Smith")
|
project.data.setAuthor("Jane Smith")
|
||||||
project.data.setAutoReplace({"A": "B", "C": "D"})
|
project.data.setAutoReplace({"A": "B", "C": "D"})
|
||||||
|
|
||||||
# Create Dialog
|
# Create Dialog
|
||||||
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_MAIN)
|
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_SETTINGS)
|
||||||
projSettings.show()
|
projSettings.show()
|
||||||
qtbot.addWidget(projSettings)
|
qtbot.addWidget(projSettings)
|
||||||
|
|
||||||
# Settings Tab
|
# Settings Tab
|
||||||
# ============
|
settings = projSettings.settingsPage
|
||||||
|
|
||||||
tabMain = projSettings.tabMain
|
assert settings.projName.text() == "New Project"
|
||||||
|
assert settings.projAuthor.text() == "Jane Smith"
|
||||||
|
assert settings.projLang.currentData() == "en"
|
||||||
|
assert settings.spellLang.currentData() == "en"
|
||||||
|
assert settings.doBackup.isChecked() is False
|
||||||
|
|
||||||
assert tabMain.editName.text() == "New Project"
|
settings.projName.setText("Project Name")
|
||||||
assert tabMain.editTitle.text() == "New Novel"
|
settings.projAuthor.setText("Jane Doe")
|
||||||
assert tabMain.editAuthor.text() == "Jane Smith"
|
settings.projLang.setCurrentIndex(settings.projLang.findData("de"))
|
||||||
assert tabMain.spellLang.currentData() == "en"
|
settings.spellLang.setCurrentIndex(settings.spellLang.findData("de"))
|
||||||
assert tabMain.doBackup.isChecked() is False
|
settings.doBackup.setChecked(True)
|
||||||
|
|
||||||
tabMain.editName.setText("")
|
|
||||||
for c in "Project Name":
|
|
||||||
qtbot.keyClick(tabMain.editName, c, delay=KEY_DELAY)
|
|
||||||
tabMain.editTitle.setText("")
|
|
||||||
for c in "Project Title":
|
|
||||||
qtbot.keyClick(tabMain.editTitle, c, delay=KEY_DELAY)
|
|
||||||
|
|
||||||
tabMain.editAuthor.clear()
|
|
||||||
for c in "Jane Doe":
|
|
||||||
qtbot.keyClick(tabMain.editAuthor, c, delay=KEY_DELAY)
|
|
||||||
|
|
||||||
assert tabMain.editName.text() == "Project Name"
|
|
||||||
assert tabMain.editTitle.text() == "Project Title"
|
|
||||||
assert tabMain.editAuthor.text() == "Jane Doe"
|
|
||||||
|
|
||||||
projSettings._doSave()
|
projSettings._doSave()
|
||||||
assert project.data.name == "Project Name"
|
assert project.data.name == "Project Name"
|
||||||
assert project.data.title == "Project Title"
|
|
||||||
assert project.data.author == "Jane Doe"
|
assert project.data.author == "Jane Doe"
|
||||||
|
assert project.data.language == "de"
|
||||||
|
assert project.data.spellLang == "de"
|
||||||
|
assert project.data.doBackup is False
|
||||||
|
|
||||||
nwGUI._processProjectSettingsChanges()
|
nwGUI._processProjectSettingsChanges(False)
|
||||||
assert nwGUI.windowTitle() == "novelWriter - Project Name"
|
assert nwGUI.windowTitle() == "novelWriter - Project Name"
|
||||||
|
|
||||||
# qtbot.stop()
|
# qtbot.stop()
|
||||||
|
|
||||||
# END Test testDlgProjSettings_Main
|
# END Test testDlgProjSettings_SettingsPage
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||||
"""Test the status and importance tabs of the project settings
|
"""Test the status and importance pages of the dialog."""
|
||||||
dialog.
|
|
||||||
"""
|
|
||||||
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
|
|
||||||
|
|
||||||
# Create new project
|
|
||||||
mockRnd.reset()
|
|
||||||
buildTestProject(nwGUI, projPath)
|
buildTestProject(nwGUI, projPath)
|
||||||
CONFIG.setBackupPath(fncPath)
|
|
||||||
|
|
||||||
# Set some values
|
# Set some values
|
||||||
theProject = SHARED.project
|
project = SHARED.project
|
||||||
theProject.tree[C.hTitlePage].setStatus(C.sFinished) # type: ignore
|
project.tree[C.hTitlePage].setStatus(C.sFinished) # type: ignore
|
||||||
theProject.tree[C.hChapterDoc].setStatus(C.sDraft) # type: ignore
|
project.tree[C.hChapterDoc].setStatus(C.sDraft) # type: ignore
|
||||||
theProject.tree[C.hSceneDoc].setStatus(C.sDraft) # type: ignore
|
project.tree[C.hSceneDoc].setStatus(C.sDraft) # type: ignore
|
||||||
|
|
||||||
nwGUI.projView.projTree.setSelectedHandle(C.hPlotRoot)
|
nwGUI.projView.projTree.setSelectedHandle(C.hPlotRoot)
|
||||||
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
|
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
|
||||||
@@ -172,51 +159,54 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
|||||||
hCharNote = "0000000000011"
|
hCharNote = "0000000000011"
|
||||||
hWorldNote = "0000000000012"
|
hWorldNote = "0000000000012"
|
||||||
|
|
||||||
theProject.tree[hPlotNote].setImport(C.iMajor) # type: ignore
|
project.tree[hPlotNote].setImport(C.iMajor) # type: ignore
|
||||||
theProject.tree[hCharNote].setImport(C.iMajor) # type: ignore
|
project.tree[hCharNote].setImport(C.iMajor) # type: ignore
|
||||||
theProject.tree[hWorldNote].setImport(C.iMain) # type: ignore
|
project.tree[hWorldNote].setImport(C.iMain) # type: ignore
|
||||||
|
|
||||||
|
nwGUI.rebuildTrees()
|
||||||
|
project.countStatus()
|
||||||
|
|
||||||
|
assert [e["count"] for _, e in project.data.itemStatus.items()] == [2, 0, 2, 1]
|
||||||
|
assert [e["count"] for _, e in project.data.itemImport.items()] == [3, 0, 2, 1]
|
||||||
|
|
||||||
# Create Dialog
|
# Create Dialog
|
||||||
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_STATUS)
|
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_STATUS)
|
||||||
projSettings.show()
|
projSettings.show()
|
||||||
qtbot.addWidget(projSettings)
|
qtbot.addWidget(projSettings)
|
||||||
|
|
||||||
# Status Tab
|
# Status Tab
|
||||||
# ==========
|
# ==========
|
||||||
|
|
||||||
tabStatus = projSettings.tabStatus
|
status = projSettings.statusPage
|
||||||
|
|
||||||
assert tabStatus.colChanged is False
|
assert status.wasChanged is False
|
||||||
assert tabStatus.getNewList() == ([], [])
|
assert status.getNewList() == ([], [])
|
||||||
assert tabStatus.listBox.topLevelItemCount() == 4
|
assert status.listBox.topLevelItemCount() == 4
|
||||||
|
|
||||||
# Can't delete the first item (it's in use)
|
# Can't delete the first item (it's in use)
|
||||||
tabStatus.listBox.clearSelection()
|
status.listBox.clearSelection()
|
||||||
tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(0))
|
status.listBox.setCurrentItem(status.listBox.topLevelItem(0))
|
||||||
qtbot.mouseClick(tabStatus.delButton, Qt.LeftButton)
|
qtbot.mouseClick(status.delButton, Qt.LeftButton)
|
||||||
assert tabStatus.listBox.topLevelItemCount() == 4
|
assert status.listBox.topLevelItemCount() == 4
|
||||||
|
|
||||||
# Can delete the second item
|
# Can delete the second item
|
||||||
tabStatus.listBox.clearSelection()
|
status.listBox.clearSelection()
|
||||||
tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(1))
|
status.listBox.setCurrentItem(status.listBox.topLevelItem(1))
|
||||||
qtbot.mouseClick(tabStatus.delButton, Qt.LeftButton)
|
qtbot.mouseClick(status.delButton, Qt.LeftButton)
|
||||||
assert tabStatus.listBox.topLevelItemCount() == 3
|
assert status.listBox.topLevelItemCount() == 3
|
||||||
|
|
||||||
# Add a new item
|
# Add a new item
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
|
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
|
||||||
qtbot.mouseClick(tabStatus.addButton, Qt.LeftButton)
|
status.addButton.click()
|
||||||
tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(3))
|
status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
|
||||||
for _ in range(8):
|
status.editName.setText("Final")
|
||||||
qtbot.keyClick(tabStatus.editName, Qt.Key_Backspace, delay=KEY_DELAY)
|
status.colButton.click()
|
||||||
for c in "Final":
|
status.saveButton.click()
|
||||||
qtbot.keyClick(tabStatus.editName, c, delay=KEY_DELAY)
|
assert status.listBox.topLevelItemCount() == 4
|
||||||
qtbot.mouseClick(tabStatus.colButton, Qt.LeftButton)
|
|
||||||
qtbot.mouseClick(tabStatus.saveButton, Qt.LeftButton)
|
|
||||||
assert tabStatus.listBox.topLevelItemCount() == 4
|
|
||||||
|
|
||||||
assert tabStatus.colChanged is True
|
assert status.wasChanged is True
|
||||||
assert tabStatus.getNewList() == (
|
assert status.getNewList() == (
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"key": C.sNew,
|
"key": C.sNew,
|
||||||
@@ -241,62 +231,62 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Move items, none selected -> no change
|
# Move items, none selected -> no change
|
||||||
tabStatus.listBox.clearSelection()
|
status.listBox.clearSelection()
|
||||||
tabStatus._moveItem(1)
|
status._moveItem(1)
|
||||||
assert [x["key"] for x in tabStatus.getNewList()[0]] == [
|
assert [x["key"] for x in status.getNewList()[0]] == [
|
||||||
C.sNew, C.sDraft, C.sFinished, None
|
C.sNew, C.sDraft, C.sFinished, None
|
||||||
]
|
]
|
||||||
|
|
||||||
# Move items, first selected, move up -> no change
|
# Move items, first selected, move up -> no change
|
||||||
tabStatus.listBox.clearSelection()
|
status.listBox.clearSelection()
|
||||||
tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(0))
|
status.listBox.setCurrentItem(status.listBox.topLevelItem(0))
|
||||||
tabStatus._moveItem(-1)
|
status._moveItem(-1)
|
||||||
assert [x["key"] for x in tabStatus.getNewList()[0]] == [
|
assert [x["key"] for x in status.getNewList()[0]] == [
|
||||||
C.sNew, C.sDraft, C.sFinished, None
|
C.sNew, C.sDraft, C.sFinished, None
|
||||||
]
|
]
|
||||||
|
|
||||||
# Move items, last selected, move up -> allowed
|
# Move items, last selected, move up -> allowed
|
||||||
tabStatus.listBox.clearSelection()
|
status.listBox.clearSelection()
|
||||||
tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(3))
|
status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
|
||||||
tabStatus._moveItem(-1)
|
status._moveItem(-1)
|
||||||
assert [x["key"] for x in tabStatus.getNewList()[0]] == [
|
assert [x["key"] for x in status.getNewList()[0]] == [
|
||||||
C.sNew, C.sDraft, None, C.sFinished
|
C.sNew, C.sDraft, None, C.sFinished
|
||||||
]
|
]
|
||||||
|
|
||||||
# Move items, same selected, move down -> allowed
|
# Move items, same selected, move down -> allowed
|
||||||
tabStatus._moveItem(1)
|
status._moveItem(1)
|
||||||
assert [x["key"] for x in tabStatus.getNewList()[0]] == [
|
assert [x["key"] for x in status.getNewList()[0]] == [
|
||||||
C.sNew, C.sDraft, C.sFinished, None
|
C.sNew, C.sDraft, C.sFinished, None
|
||||||
]
|
]
|
||||||
|
|
||||||
# Importance Tab
|
# Importance Tab
|
||||||
# ==============
|
# ==============
|
||||||
|
|
||||||
tabImport = projSettings.tabImport
|
importance = projSettings.importPage
|
||||||
projSettings._focusTab(GuiProjectSettings.TAB_IMPORT)
|
projSettings._sidebarClicked(GuiProjectSettings.PAGE_IMPORT)
|
||||||
|
|
||||||
# Delete unused entry
|
# Delete unused entry
|
||||||
tabImport.listBox.clearSelection()
|
importance.listBox.clearSelection()
|
||||||
tabImport.listBox.setCurrentItem(tabImport.listBox.topLevelItem(1))
|
importance.listBox.setCurrentItem(importance.listBox.topLevelItem(1))
|
||||||
qtbot.mouseClick(tabImport.delButton, Qt.LeftButton)
|
qtbot.mouseClick(importance.delButton, Qt.LeftButton)
|
||||||
assert tabImport.listBox.topLevelItemCount() == 3
|
assert importance.listBox.topLevelItemCount() == 3
|
||||||
|
|
||||||
# Add a new entry
|
# Add a new entry
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
|
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
|
||||||
qtbot.mouseClick(tabImport.addButton, Qt.LeftButton)
|
qtbot.mouseClick(importance.addButton, Qt.LeftButton)
|
||||||
tabImport.listBox.clearSelection()
|
importance.listBox.clearSelection()
|
||||||
tabImport.listBox.setCurrentItem(tabImport.listBox.topLevelItem(3))
|
importance.listBox.setCurrentItem(importance.listBox.topLevelItem(3))
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
qtbot.keyClick(tabImport.editName, Qt.Key_Backspace, delay=KEY_DELAY)
|
qtbot.keyClick(importance.editName, Qt.Key_Backspace, delay=KEY_DELAY)
|
||||||
for c in "Final":
|
for c in "Final":
|
||||||
qtbot.keyClick(tabImport.editName, c, delay=KEY_DELAY)
|
qtbot.keyClick(importance.editName, c, delay=KEY_DELAY)
|
||||||
qtbot.mouseClick(tabImport.colButton, Qt.LeftButton)
|
qtbot.mouseClick(importance.colButton, Qt.LeftButton)
|
||||||
qtbot.mouseClick(tabImport.saveButton, Qt.LeftButton)
|
qtbot.mouseClick(importance.saveButton, Qt.LeftButton)
|
||||||
assert tabImport.listBox.topLevelItemCount() == 4
|
assert importance.listBox.topLevelItemCount() == 4
|
||||||
|
|
||||||
assert tabImport.colChanged is True
|
assert importance.wasChanged is True
|
||||||
assert tabImport.getNewList() == (
|
assert importance.getNewList() == (
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"key": C.iNew,
|
"key": C.iNew,
|
||||||
@@ -323,13 +313,13 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
|||||||
# Check Project
|
# Check Project
|
||||||
projSettings._doSave()
|
projSettings._doSave()
|
||||||
|
|
||||||
statusItems = dict(theProject.data.itemStatus.items())
|
statusItems = dict(project.data.itemStatus.items())
|
||||||
assert statusItems[C.sNew]["name"] == "New"
|
assert statusItems[C.sNew]["name"] == "New"
|
||||||
assert statusItems[C.sDraft]["name"] == "Draft"
|
assert statusItems[C.sDraft]["name"] == "Draft"
|
||||||
assert statusItems[C.sFinished]["name"] == "Finished"
|
assert statusItems[C.sFinished]["name"] == "Finished"
|
||||||
assert statusItems["s000013"]["name"] == "Final"
|
assert statusItems["s000013"]["name"] == "Final"
|
||||||
|
|
||||||
importItems = dict(theProject.data.itemImport.items())
|
importItems = dict(project.data.itemImport.items())
|
||||||
assert importItems[C.iNew]["name"] == "New"
|
assert importItems[C.iNew]["name"] == "New"
|
||||||
assert importItems[C.iMajor]["name"] == "Major"
|
assert importItems[C.iMajor]["name"] == "Major"
|
||||||
assert importItems[C.iMain]["name"] == "Main"
|
assert importItems[C.iMain]["name"] == "Main"
|
||||||
@@ -341,83 +331,78 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||||
"""Test the auto-replace tab of the project settings dialog."""
|
"""Test the auto-replace page of the dialog."""
|
||||||
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
|
|
||||||
|
|
||||||
# Create new project
|
|
||||||
mockRnd.reset()
|
|
||||||
buildTestProject(nwGUI, projPath)
|
buildTestProject(nwGUI, projPath)
|
||||||
CONFIG.setBackupPath(fncPath)
|
|
||||||
|
|
||||||
# Set some values
|
# Set some values
|
||||||
theProject = SHARED.project
|
project = SHARED.project
|
||||||
theProject.data.setAutoReplace({
|
project.data.setAutoReplace({
|
||||||
"A": "B", "C": "D"
|
"A": "B", "C": "D"
|
||||||
})
|
})
|
||||||
|
|
||||||
# Create Dialog
|
# Create Dialog
|
||||||
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_REPLACE)
|
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_REPLACE)
|
||||||
projSettings.show()
|
projSettings.show()
|
||||||
qtbot.addWidget(projSettings)
|
qtbot.addWidget(projSettings)
|
||||||
|
|
||||||
# Auto-Replace Tab
|
# Auto-Replace Tab
|
||||||
# ================
|
# ================
|
||||||
|
|
||||||
tabReplace = projSettings.tabReplace
|
replace = projSettings.replacePage
|
||||||
|
|
||||||
assert tabReplace.listBox.topLevelItem(0).text(0) == "<A>" # type: ignore
|
assert replace.listBox.topLevelItem(0).text(0) == "<A>" # type: ignore
|
||||||
assert tabReplace.listBox.topLevelItem(0).text(1) == "B" # type: ignore
|
assert replace.listBox.topLevelItem(0).text(1) == "B" # type: ignore
|
||||||
assert tabReplace.listBox.topLevelItem(1).text(0) == "<C>" # type: ignore
|
assert replace.listBox.topLevelItem(1).text(0) == "<C>" # type: ignore
|
||||||
assert tabReplace.listBox.topLevelItem(1).text(1) == "D" # type: ignore
|
assert replace.listBox.topLevelItem(1).text(1) == "D" # type: ignore
|
||||||
assert tabReplace.listBox.topLevelItemCount() == 2
|
assert replace.listBox.topLevelItemCount() == 2
|
||||||
|
|
||||||
# Nothing to save or delete
|
# Nothing to save or delete
|
||||||
tabReplace.listBox.clearSelection()
|
replace.listBox.clearSelection()
|
||||||
tabReplace._saveEntry()
|
replace._saveEntry()
|
||||||
tabReplace._delEntry()
|
replace._delEntry()
|
||||||
assert tabReplace.listBox.topLevelItemCount() == 2
|
assert replace.listBox.topLevelItemCount() == 2
|
||||||
|
|
||||||
# Create a new entry
|
# Create a new entry
|
||||||
qtbot.mouseClick(tabReplace.addButton, Qt.LeftButton)
|
qtbot.mouseClick(replace.addButton, Qt.LeftButton)
|
||||||
assert tabReplace.listBox.topLevelItemCount() == 3
|
assert replace.listBox.topLevelItemCount() == 3
|
||||||
assert tabReplace.listBox.topLevelItem(2).text(0) == "<keyword3>" # type: ignore
|
assert replace.listBox.topLevelItem(2).text(0) == "<keyword3>" # type: ignore
|
||||||
assert tabReplace.listBox.topLevelItem(2).text(1) == "" # type: ignore
|
assert replace.listBox.topLevelItem(2).text(1) == "" # type: ignore
|
||||||
|
|
||||||
# Edit the entry
|
# Edit the entry
|
||||||
tabReplace.listBox.setCurrentItem(tabReplace.listBox.topLevelItem(2))
|
replace.listBox.setCurrentItem(replace.listBox.topLevelItem(2))
|
||||||
tabReplace.editKey.setText("")
|
replace.editKey.setText("")
|
||||||
for c in "Th is ":
|
for c in "Th is ":
|
||||||
qtbot.keyClick(tabReplace.editKey, c, delay=KEY_DELAY)
|
qtbot.keyClick(replace.editKey, c, delay=KEY_DELAY)
|
||||||
tabReplace.editValue.setText("")
|
replace.editValue.setText("")
|
||||||
for c in "With This Stuff ":
|
for c in "With This Stuff ":
|
||||||
qtbot.keyClick(tabReplace.editValue, c, delay=KEY_DELAY)
|
qtbot.keyClick(replace.editValue, c, delay=KEY_DELAY)
|
||||||
qtbot.mouseClick(tabReplace.saveButton, Qt.LeftButton)
|
qtbot.mouseClick(replace.saveButton, Qt.LeftButton)
|
||||||
assert tabReplace.listBox.topLevelItem(2).text(0) == "<This>" # type: ignore
|
assert replace.listBox.topLevelItem(2).text(0) == "<This>" # type: ignore
|
||||||
assert tabReplace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore
|
assert replace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore
|
||||||
|
|
||||||
# Create a new entry again
|
# Create a new entry again
|
||||||
tabReplace.listBox.clearSelection()
|
replace.listBox.clearSelection()
|
||||||
qtbot.mouseClick(tabReplace.addButton, Qt.LeftButton)
|
qtbot.mouseClick(replace.addButton, Qt.LeftButton)
|
||||||
assert tabReplace.listBox.topLevelItemCount() == 4
|
assert replace.listBox.topLevelItemCount() == 4
|
||||||
|
|
||||||
# The list is sorted, so we must find it
|
# The list is sorted, so we must find it
|
||||||
newIdx = -1
|
newIdx = -1
|
||||||
for i in range(tabReplace.listBox.topLevelItemCount()):
|
for i in range(replace.listBox.topLevelItemCount()):
|
||||||
if tabReplace.listBox.topLevelItem(i).text(0) == "<keyword4>": # type: ignore
|
if replace.listBox.topLevelItem(i).text(0) == "<keyword4>": # type: ignore
|
||||||
newIdx = i
|
newIdx = i
|
||||||
break
|
break
|
||||||
assert newIdx >= 0
|
assert newIdx >= 0
|
||||||
|
|
||||||
# Then delete the new item
|
# Then delete the new item
|
||||||
tabReplace.listBox.setCurrentItem(tabReplace.listBox.topLevelItem(newIdx))
|
replace.listBox.setCurrentItem(replace.listBox.topLevelItem(newIdx))
|
||||||
qtbot.mouseClick(tabReplace.delButton, Qt.LeftButton)
|
qtbot.mouseClick(replace.delButton, Qt.LeftButton)
|
||||||
assert tabReplace.listBox.topLevelItemCount() == 3
|
assert replace.listBox.topLevelItemCount() == 3
|
||||||
|
|
||||||
# Check Project
|
# Check Project
|
||||||
projSettings._doSave()
|
projSettings._doSave()
|
||||||
assert theProject.data.autoReplace == {
|
assert project.data.autoReplace == {
|
||||||
"A": "B", "C": "D", "This": "With This Stuff"
|
"A": "B", "C": "D", "This": "With This Stuff"
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user