Improve build settings dialog (#1499)
This commit is contained in:
@@ -21,7 +21,7 @@ backward = typ_chevron-left.svg
|
|||||||
bookmark = typ_bookmark.svg
|
bookmark = typ_bookmark.svg
|
||||||
browse = typ_folder-open.svg
|
browse = typ_folder-open.svg
|
||||||
build_excluded = typ_cancel.svg
|
build_excluded = typ_cancel.svg
|
||||||
build_filtered = typ_filter.svg
|
build_filtered = typ_arrow-forward.svg
|
||||||
build_included = typ_pin.svg
|
build_included = typ_pin.svg
|
||||||
bullet-off = typ_media-record-outline.svg
|
bullet-off = typ_media-record-outline.svg
|
||||||
bullet-on = typ_media-record.svg
|
bullet-on = typ_media-record.svg
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m13.25 3.5625c-0.32 0-0.64 0.12125-0.88375 0.365-0.24375 0.245-0.36625 0.565-0.36625 0.885v3.1988c-5.625 0.6225-10 5.3862-10 11.176v1.25c2.8062-4.2788 6.5625-4.9 10-4.9862v3.1112c0 0.31875 0.1225 0.64 0.36625 0.88375s0.56375 0.36625 0.88375 0.36625 0.64-0.1225 0.88375-0.36625l7.8662-7.7588-7.8662-7.76c-0.24375-0.24375-0.56375-0.365-0.88375-0.365z" fill="#9c9" stroke-width="1.25"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 538 B |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="24" height="24" version="1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="m20.694 2h-17.387c-1.3661 0-1.7387 0.85714-0.74516 2l5.2161 6c0.99354 1.1429 1.7387 3.2857 1.7387 4.8571v7.1429l4.9677-2.8571v-5c0-1.1429 0.74516-3 1.7387-4.1429l5.2161-6c0.99354-1.1429 0.62096-2-0.74516-2z" fill="#f99157" stroke-width="1.332"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 398 B |
@@ -21,7 +21,7 @@ backward = typ_chevron-left.svg
|
|||||||
bookmark = typ_bookmark.svg
|
bookmark = typ_bookmark.svg
|
||||||
browse = typ_folder-open.svg
|
browse = typ_folder-open.svg
|
||||||
build_excluded = typ_cancel.svg
|
build_excluded = typ_cancel.svg
|
||||||
build_filtered = typ_filter.svg
|
build_filtered = typ_arrow-forward.svg
|
||||||
build_included = typ_pin.svg
|
build_included = typ_pin.svg
|
||||||
bullet-off = typ_media-record-outline.svg
|
bullet-off = typ_media-record-outline.svg
|
||||||
bullet-on = typ_media-record.svg
|
bullet-on = typ_media-record.svg
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m13.25 3.5625c-0.32 0-0.64 0.12125-0.88375 0.365-0.24375 0.245-0.36625 0.565-0.36625 0.885v3.1988c-5.625 0.6225-10 5.3862-10 11.176v1.25c2.8062-4.2788 6.5625-4.9 10-4.9862v3.1112c0 0.31875 0.1225 0.64 0.36625 0.88375s0.56375 0.36625 0.88375 0.36625 0.64-0.1225 0.88375-0.36625l7.8662-7.7588-7.8662-7.76c-0.24375-0.24375-0.56375-0.365-0.88375-0.365z" fill="#718c00" stroke-width="1.25"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 541 B |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="24" height="24" version="1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="m20.694 2h-17.387c-1.3661 0-1.7387 0.85714-0.74516 2l5.2161 6c0.99354 1.1429 1.7387 3.2857 1.7387 4.8571v7.1429l4.9677-2.8571v-5c0-1.1429 0.74516-3 1.7387-4.1429l5.2161-6c0.99354-1.1429 0.62096-2-0.74516-2z" fill="#f5871f" stroke-width="1.332"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 398 B |
@@ -257,6 +257,7 @@ class nwLabels:
|
|||||||
|
|
||||||
class nwHeadFmt:
|
class nwHeadFmt:
|
||||||
|
|
||||||
|
BR = "{BR}"
|
||||||
TITLE = "{Title}"
|
TITLE = "{Title}"
|
||||||
CH_NUM = "{Chapter}"
|
CH_NUM = "{Chapter}"
|
||||||
CH_WORD = "{Chapter:Word}"
|
CH_WORD = "{Chapter:Word}"
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ SETTINGS_TEMPLATE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SETTINGS_LABELS = {
|
SETTINGS_LABELS = {
|
||||||
"filter": QT_TRANSLATE_NOOP("Builds", "Document Types"),
|
"filter": QT_TRANSLATE_NOOP("Builds", "Document Filters"),
|
||||||
"filter.includeNovel": QT_TRANSLATE_NOOP("Builds", "Novel Documents"),
|
"filter.includeNovel": QT_TRANSLATE_NOOP("Builds", "Novel Documents"),
|
||||||
"filter.includeNotes": QT_TRANSLATE_NOOP("Builds", "Project Notes"),
|
"filter.includeNotes": QT_TRANSLATE_NOOP("Builds", "Project Notes"),
|
||||||
"filter.includeInactive": QT_TRANSLATE_NOOP("Builds", "Inactive Documents"),
|
"filter.includeInactive": QT_TRANSLATE_NOOP("Builds", "Inactive Documents"),
|
||||||
@@ -125,10 +125,10 @@ SETTINGS_LABELS = {
|
|||||||
"format.leftMargin": QT_TRANSLATE_NOOP("Builds", "Left Margin"),
|
"format.leftMargin": QT_TRANSLATE_NOOP("Builds", "Left Margin"),
|
||||||
"format.rightMargin": QT_TRANSLATE_NOOP("Builds", "Right Margin"),
|
"format.rightMargin": QT_TRANSLATE_NOOP("Builds", "Right Margin"),
|
||||||
|
|
||||||
"odt": QT_TRANSLATE_NOOP("Builds", "Open Document"),
|
"odt": QT_TRANSLATE_NOOP("Builds", "Open Document (.odt)"),
|
||||||
"odt.addColours": QT_TRANSLATE_NOOP("Builds", "Add Highlight Colours"),
|
"odt.addColours": QT_TRANSLATE_NOOP("Builds", "Add Highlight Colours"),
|
||||||
|
|
||||||
"html": QT_TRANSLATE_NOOP("Builds", "HTML"),
|
"html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"),
|
||||||
"html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
|
"html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from novelwriter import CONFIG
|
from novelwriter import CONFIG
|
||||||
from novelwriter.common import formatTimeStamp
|
from novelwriter.common import formatTimeStamp
|
||||||
from novelwriter.constants import nwKeyWords, nwLabels, nwHtmlUnicode
|
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwHtmlUnicode
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.core.tokenizer import Tokenizer, stripEscape
|
from novelwriter.core.tokenizer import Tokenizer, stripEscape
|
||||||
|
|
||||||
@@ -244,27 +244,27 @@ class ToHtml(Tokenizer):
|
|||||||
parStyle = None
|
parStyle = None
|
||||||
|
|
||||||
elif tType == self.T_TITLE:
|
elif tType == self.T_TITLE:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
|
||||||
tmpResult.append(f"<h1 class='title'{hStyle}>{aNm}{tHead}</h1>\n")
|
tmpResult.append(f"<h1 class='title'{hStyle}>{aNm}{tHead}</h1>\n")
|
||||||
|
|
||||||
elif tType == self.T_UNNUM:
|
elif tType == self.T_UNNUM:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
|
||||||
tmpResult.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
|
tmpResult.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD1:
|
elif tType == self.T_HEAD1:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
|
||||||
tmpResult.append(f"<{h1}{h1Cl}{hStyle}>{aNm}{tHead}</{h1}>\n")
|
tmpResult.append(f"<{h1}{h1Cl}{hStyle}>{aNm}{tHead}</{h1}>\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tType == self.T_HEAD2:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
|
||||||
tmpResult.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
|
tmpResult.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
|
||||||
tmpResult.append(f"<{h3}{hStyle}>{aNm}{tHead}</{h3}>\n")
|
tmpResult.append(f"<{h3}{hStyle}>{aNm}{tHead}</{h3}>\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4:
|
||||||
tHead = tText.replace(r"\\", "<br/>")
|
tHead = tText.replace(nwHeadFmt.BR, "<br/>")
|
||||||
tmpResult.append(f"<{h4}{hStyle}>{aNm}{tHead}</{h4}>\n")
|
tmpResult.append(f"<{h4}{hStyle}>{aNm}{tHead}</{h4}>\n")
|
||||||
|
|
||||||
elif tType == self.T_SEP:
|
elif tType == self.T_SEP:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import logging
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter.constants import nwLabels
|
from novelwriter.constants import nwHeadFmt, nwLabels
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.core.tokenizer import Tokenizer
|
from novelwriter.core.tokenizer import Tokenizer
|
||||||
|
|
||||||
@@ -122,27 +122,27 @@ class ToMarkdown(Tokenizer):
|
|||||||
thisPar = []
|
thisPar = []
|
||||||
|
|
||||||
elif tType == self.T_TITLE:
|
elif tType == self.T_TITLE:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
tmpResult.append(f"# {tHead}\n\n")
|
tmpResult.append(f"# {tHead}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_UNNUM:
|
elif tType == self.T_UNNUM:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
tmpResult.append(f"## {tHead}\n\n")
|
tmpResult.append(f"## {tHead}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD1:
|
elif tType == self.T_HEAD1:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
tmpResult.append(f"# {tHead}\n\n")
|
tmpResult.append(f"# {tHead}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tType == self.T_HEAD2:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
tmpResult.append(f"## {tHead}\n\n")
|
tmpResult.append(f"## {tHead}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
tmpResult.append(f"### {tHead}\n\n")
|
tmpResult.append(f"### {tHead}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
tmpResult.append(f"#### {tHead}\n\n")
|
tmpResult.append(f"#### {tHead}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_SEP:
|
elif tType == self.T_SEP:
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
from novelwriter import __version__
|
from novelwriter import __version__
|
||||||
from novelwriter.common import xmlIndent
|
from novelwriter.common import xmlIndent
|
||||||
from novelwriter.constants import nwKeyWords, nwLabels
|
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.core.tokenizer import Tokenizer, stripEscape
|
from novelwriter.core.tokenizer import Tokenizer, stripEscape
|
||||||
|
|
||||||
@@ -445,27 +445,27 @@ class ToOdt(Tokenizer):
|
|||||||
parStyle = None
|
parStyle = None
|
||||||
|
|
||||||
elif tType == self.T_TITLE:
|
elif tType == self.T_TITLE:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
self._addTextPar("Title", oStyle, tHead, isHead=False) # Title must be text:p
|
self._addTextPar("Title", oStyle, tHead, isHead=False) # Title must be text:p
|
||||||
|
|
||||||
elif tType == self.T_UNNUM:
|
elif tType == self.T_UNNUM:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
|
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
|
||||||
|
|
||||||
elif tType == self.T_HEAD1:
|
elif tType == self.T_HEAD1:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
self._addTextPar("Heading_20_1", oStyle, tHead, isHead=True, oLevel="1")
|
self._addTextPar("Heading_20_1", oStyle, tHead, isHead=True, oLevel="1")
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tType == self.T_HEAD2:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
|
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
self._addTextPar("Heading_20_3", oStyle, tHead, isHead=True, oLevel="3")
|
self._addTextPar("Heading_20_3", oStyle, tHead, isHead=True, oLevel="3")
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4:
|
||||||
tHead = tText.replace(r"\\", "\n")
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
||||||
self._addTextPar("Heading_20_4", oStyle, tHead, isHead=True, oLevel="4")
|
self._addTextPar("Heading_20_4", oStyle, tHead, isHead=True, oLevel="4")
|
||||||
|
|
||||||
elif tType == self.T_SEP:
|
elif tType == self.T_SEP:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
novelWriter – Custom Widget: Paged SideBar
|
novelWriter – Custom Widget: Paged SideBar
|
||||||
==========================================
|
==========================================
|
||||||
A custom widget for making a sidebar for flipping through pages
|
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2023-02-21 [2.1b1] NPagedSideBar
|
Created: 2023-02-21 [2.1b1] NPagedSideBar
|
||||||
@@ -24,20 +23,26 @@ General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from PyQt5.QtGui import QColor, QPainter
|
from PyQt5.QtGui import QColor, QPaintEvent, QPainter, QPolygon
|
||||||
from PyQt5.QtCore import QRectF, Qt, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import QPoint, QRectF, Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QButtonGroup, QLabel, QSizePolicy, QStyle, QStyleOptionToolButton, QToolBar,
|
QAbstractButton, QAction, QButtonGroup, QLabel, QSizePolicy, QStyle,
|
||||||
QToolButton, QWidget
|
QStyleOptionToolButton, QToolBar, QToolButton, QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class NPagedSideBar(QToolBar):
|
class NPagedSideBar(QToolBar):
|
||||||
|
"""Extensions: Paged Side Bar
|
||||||
|
|
||||||
|
A side bar widget that holds buttons that mimic tabs. It is designed
|
||||||
|
to be used in combination with a QStackedWidget for options panels.
|
||||||
|
"""
|
||||||
|
|
||||||
buttonClicked = pyqtSignal(int)
|
buttonClicked = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
self._buttons = []
|
self._buttons = []
|
||||||
@@ -58,7 +63,7 @@ class NPagedSideBar(QToolBar):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def setLabelColor(self, color):
|
def setLabelColor(self, color: list | QColor) -> None:
|
||||||
"""Set the text color for the labels."""
|
"""Set the text color for the labels."""
|
||||||
if isinstance(color, list):
|
if isinstance(color, list):
|
||||||
self._labelCol = QColor(*color)
|
self._labelCol = QColor(*color)
|
||||||
@@ -66,7 +71,7 @@ class NPagedSideBar(QToolBar):
|
|||||||
self._labelCol = color
|
self._labelCol = color
|
||||||
return
|
return
|
||||||
|
|
||||||
def addSeparator(self):
|
def addSeparator(self) -> None:
|
||||||
"""Add a spacer widget."""
|
"""Add a spacer widget."""
|
||||||
spacer = QWidget(self)
|
spacer = QWidget(self)
|
||||||
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||||
@@ -74,16 +79,16 @@ class NPagedSideBar(QToolBar):
|
|||||||
self.insertWidget(self._stretchAction, spacer)
|
self.insertWidget(self._stretchAction, spacer)
|
||||||
return
|
return
|
||||||
|
|
||||||
def addLabel(self, text):
|
def addLabel(self, text: str) -> None:
|
||||||
"""Add a new label to the toolbar."""
|
"""Add a new label to the toolbar."""
|
||||||
label = NPagedToolLabel(self, self._labelCol)
|
label = _NPagedToolLabel(self, self._labelCol)
|
||||||
label.setText(text)
|
label.setText(text)
|
||||||
self.insertWidget(self._stretchAction, label)
|
self.insertWidget(self._stretchAction, label)
|
||||||
return
|
return
|
||||||
|
|
||||||
def addButton(self, text, buttonId=-1):
|
def addButton(self, text: str, buttonId: int = -1) -> QAction:
|
||||||
"""Add a new button to the toolbar."""
|
"""Add a new button to the toolbar."""
|
||||||
button = NPagedToolButton(self)
|
button = _NPagedToolButton(self)
|
||||||
button.setText(text)
|
button.setText(text)
|
||||||
|
|
||||||
action = self.insertWidget(self._stretchAction, button)
|
action = self.insertWidget(self._stretchAction, button)
|
||||||
@@ -94,7 +99,7 @@ class NPagedSideBar(QToolBar):
|
|||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def setSelected(self, buttonId):
|
def setSelected(self, buttonId: int) -> None:
|
||||||
"""Set the selected button."""
|
"""Set the selected button."""
|
||||||
self._group.button(buttonId).setChecked(True)
|
self._group.button(buttonId).setChecked(True)
|
||||||
return
|
return
|
||||||
@@ -104,7 +109,7 @@ class NPagedSideBar(QToolBar):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot("QAbstractButton*")
|
@pyqtSlot("QAbstractButton*")
|
||||||
def _buttonClicked(self, button):
|
def _buttonClicked(self, button: QAbstractButton) -> None:
|
||||||
"""A button was clicked in the group, emit its id."""
|
"""A button was clicked in the group, emit its id."""
|
||||||
buttonId = self._group.id(button)
|
buttonId = self._group.id(button)
|
||||||
if buttonId != -1:
|
if buttonId != -1:
|
||||||
@@ -114,11 +119,11 @@ class NPagedSideBar(QToolBar):
|
|||||||
# END Class NPagedSideBar
|
# END Class NPagedSideBar
|
||||||
|
|
||||||
|
|
||||||
class NPagedToolButton(QToolButton):
|
class _NPagedToolButton(QToolButton):
|
||||||
|
|
||||||
__slots__ = ("_bH", "_tM", "_lM", "_cR")
|
__slots__ = ("_bH", "_tM", "_lM", "_cR", "_aH")
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||||
@@ -126,14 +131,15 @@ class NPagedToolButton(QToolButton):
|
|||||||
|
|
||||||
fH = self.fontMetrics().height()
|
fH = self.fontMetrics().height()
|
||||||
self._bH = round(fH * 1.7)
|
self._bH = round(fH * 1.7)
|
||||||
self._tM = (self._bH - fH) // 2
|
self._tM = (self._bH - fH)//2
|
||||||
self._lM = self.style().pixelMetric(QStyle.PM_ButtonMargin)
|
self._lM = 3*self.style().pixelMetric(QStyle.PM_ButtonMargin)//2
|
||||||
self._cR = self._lM // 2
|
self._cR = self._lM//2
|
||||||
|
self._aH = 2*fH//7
|
||||||
self.setFixedHeight(self._bH)
|
self.setFixedHeight(self._bH)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event: QPaintEvent) -> None:
|
||||||
"""Overload the paint event to draw a simple, left aligned text
|
"""Overload the paint event to draw a simple, left aligned text
|
||||||
label, with a highlight when selected and a transparent base
|
label, with a highlight when selected and a transparent base
|
||||||
colour when hovered.
|
colour when hovered.
|
||||||
@@ -144,6 +150,7 @@ class NPagedToolButton(QToolButton):
|
|||||||
paint = QPainter(self)
|
paint = QPainter(self)
|
||||||
paint.setRenderHint(QPainter.Antialiasing, True)
|
paint.setRenderHint(QPainter.Antialiasing, True)
|
||||||
paint.setPen(Qt.NoPen)
|
paint.setPen(Qt.NoPen)
|
||||||
|
paint.setBrush(Qt.NoBrush)
|
||||||
|
|
||||||
width = self.width()
|
width = self.width()
|
||||||
height = self.height()
|
height = self.height()
|
||||||
@@ -171,31 +178,41 @@ class NPagedToolButton(QToolButton):
|
|||||||
paint.setOpacity(1.0)
|
paint.setOpacity(1.0)
|
||||||
paint.drawText(QRectF(self._lM, self._tM, tW, tH), Qt.AlignLeft, self.text())
|
paint.drawText(QRectF(self._lM, self._tM, tW, tH), Qt.AlignLeft, self.text())
|
||||||
|
|
||||||
|
tC = self.height()//2
|
||||||
|
tW = self.width() - self._aH - self._lM
|
||||||
|
if self.isChecked():
|
||||||
|
paint.setBrush(textCol)
|
||||||
|
paint.drawPolygon(QPolygon([
|
||||||
|
QPoint(tW, tC - self._aH),
|
||||||
|
QPoint(tW + self._aH, tC),
|
||||||
|
QPoint(tW, tC + self._aH),
|
||||||
|
]))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class NPagedToolButton
|
# END Class _NPagedToolButton
|
||||||
|
|
||||||
|
|
||||||
class NPagedToolLabel(QLabel):
|
class _NPagedToolLabel(QLabel):
|
||||||
|
|
||||||
__slots__ = ("_bH", "_tM", "_lM", "_textCol")
|
__slots__ = ("_bH", "_tM", "_lM", "_textCol")
|
||||||
|
|
||||||
def __init__(self, parent, textColor=None):
|
def __init__(self, parent: QWidget, textColor: QColor | None = None) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||||
|
|
||||||
fH = self.fontMetrics().height()
|
fH = self.fontMetrics().height()
|
||||||
self._bH = round(fH * 1.7)
|
self._bH = round(fH * 1.7)
|
||||||
self._tM = (self._bH - fH) // 2
|
self._tM = (self._bH - fH)//2
|
||||||
self._lM = self.style().pixelMetric(QStyle.PM_ButtonMargin)
|
self._lM = self.style().pixelMetric(QStyle.PM_ButtonMargin)//2
|
||||||
self.setFixedHeight(self._bH)
|
self.setFixedHeight(self._bH)
|
||||||
|
|
||||||
self._textCol = textColor or self.palette().text().color()
|
self._textCol = textColor or self.palette().text().color()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event: QPaintEvent) -> None:
|
||||||
"""Overload the paint event to draw a simple, left aligned text
|
"""Overload the paint event to draw a simple, left aligned text
|
||||||
label that matches the button style.
|
label that matches the button style.
|
||||||
"""
|
"""
|
||||||
@@ -215,4 +232,4 @@ class NPagedToolLabel(QLabel):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class NPagedToolLabel
|
# END Class _NPagedToolLabel
|
||||||
|
|||||||
@@ -1202,6 +1202,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
open a context menu in-place.
|
open a context menu in-place.
|
||||||
"""
|
"""
|
||||||
tItem = None
|
tItem = None
|
||||||
|
tHandle = None
|
||||||
hasChild = False
|
hasChild = False
|
||||||
selItem = self.itemAt(clickPos)
|
selItem = self.itemAt(clickPos)
|
||||||
if isinstance(selItem, QTreeWidgetItem):
|
if isinstance(selItem, QTreeWidgetItem):
|
||||||
@@ -1209,7 +1210,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
tItem = self.theProject.tree[tHandle]
|
tItem = self.theProject.tree[tHandle]
|
||||||
hasChild = selItem.childCount() > 0
|
hasChild = selItem.childCount() > 0
|
||||||
|
|
||||||
if tItem is None:
|
if tItem is None or tHandle is None:
|
||||||
logger.debug("No item found")
|
logger.debug("No item found")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ from time import time
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from PyQt5.QtGui import QColor, QCursor, QFont, QPalette, QResizeEvent
|
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
|
||||||
from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
|
from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog, QGridLayout, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton,
|
QDialog, QGridLayout, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton,
|
||||||
@@ -231,13 +231,13 @@ class GuiManuscript(QDialog):
|
|||||||
# Events
|
# Events
|
||||||
##
|
##
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event: QCloseEvent):
|
||||||
"""Capture the user closing the window so we can save GUI
|
"""Capture the user closing the window so we can save GUI
|
||||||
settings. We also check that we don't have a build settings
|
settings. We also check that we don't have a build settings
|
||||||
dialog open.
|
dialog open.
|
||||||
"""
|
"""
|
||||||
self._saveSettings()
|
self._saveSettings()
|
||||||
for obj in self.children():
|
for obj in self.mainGui.children():
|
||||||
# Make sure we don't have any settings windows open
|
# Make sure we don't have any settings windows open
|
||||||
if isinstance(obj, GuiBuildSettings) and obj.isVisible():
|
if isinstance(obj, GuiBuildSettings) and obj.isVisible():
|
||||||
obj.close()
|
obj.close()
|
||||||
@@ -330,15 +330,13 @@ class GuiManuscript(QDialog):
|
|||||||
def _buildManuscript(self):
|
def _buildManuscript(self):
|
||||||
"""Open the build dialog and build the manuscript."""
|
"""Open the build dialog and build the manuscript."""
|
||||||
build = self._getSelectedBuild()
|
build = self._getSelectedBuild()
|
||||||
if build is None:
|
if isinstance(build, BuildSettings):
|
||||||
return
|
dlgBuild = GuiManuscriptBuild(self, self.mainGui, build)
|
||||||
|
dlgBuild.exec_()
|
||||||
|
|
||||||
dlgBuild = GuiManuscriptBuild(self, self.mainGui, build)
|
# After the build is done, save build settings changes
|
||||||
dlgBuild.exec_()
|
if build.changed:
|
||||||
|
self._builds.setBuild(build)
|
||||||
# After the build is done, save build settings changes
|
|
||||||
if build.changed:
|
|
||||||
self._builds.setBuild(build)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -376,10 +374,13 @@ class GuiManuscript(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _getSelectedBuild(self) -> BuildSettings | None:
|
def _getSelectedBuild(self) -> BuildSettings | None:
|
||||||
"""Get the currently selected build."""
|
"""Get the currently selected build. If none are selected,
|
||||||
bItems = self.buildList.selectedItems()
|
automatically select the first one.
|
||||||
if bItems:
|
"""
|
||||||
build = self._builds.getBuild(bItems[0].data(self.D_KEY))
|
items = self.buildList.selectedItems()
|
||||||
|
item = items[0] if items else self.buildList.item(0)
|
||||||
|
if item:
|
||||||
|
build = self._builds.getBuild(item.data(self.D_KEY))
|
||||||
if isinstance(build, BuildSettings):
|
if isinstance(build, BuildSettings):
|
||||||
return build
|
return build
|
||||||
return None
|
return None
|
||||||
@@ -406,13 +407,23 @@ class GuiManuscript(QDialog):
|
|||||||
|
|
||||||
def _openSettingsDialog(self, build: BuildSettings):
|
def _openSettingsDialog(self, build: BuildSettings):
|
||||||
"""Open the build settings dialog."""
|
"""Open the build settings dialog."""
|
||||||
dlgSettings = GuiBuildSettings(self, self.mainGui, build)
|
for obj in self.mainGui.children():
|
||||||
|
# Don't open a second dialog if one exists
|
||||||
|
if isinstance(obj, GuiBuildSettings):
|
||||||
|
if obj.buildID == build.buildID:
|
||||||
|
logger.debug("Found instance of GuiBuildSettings")
|
||||||
|
obj.show()
|
||||||
|
obj.raise_()
|
||||||
|
return
|
||||||
|
|
||||||
|
dlgSettings = GuiBuildSettings(self.mainGui, build)
|
||||||
dlgSettings.setModal(False)
|
dlgSettings.setModal(False)
|
||||||
dlgSettings.show()
|
dlgSettings.show()
|
||||||
dlgSettings.raise_()
|
dlgSettings.raise_()
|
||||||
qApp.processEvents()
|
qApp.processEvents()
|
||||||
dlgSettings.loadContent()
|
dlgSettings.loadContent()
|
||||||
dlgSettings.newSettingsReady.connect(self._processNewSettings)
|
dlgSettings.newSettingsReady.connect(self._processNewSettings)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _updateBuildsList(self):
|
def _updateBuildsList(self):
|
||||||
@@ -634,7 +645,7 @@ class _PreviewWidget(QTextBrowser):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
strBuildTime = self.tr("Unknown")
|
strBuildTime = self.tr("Unknown")
|
||||||
text = "{0} {1}".format(self.tr("Built"), strBuildTime)
|
text = "{0}: {1}".format(self.tr("Built"), strBuildTime)
|
||||||
if self._buildName:
|
if self._buildName:
|
||||||
text = "<b>{0}</b><br>{1}".format(self._buildName, text)
|
text = "<b>{0}</b><br>{1}".format(self._buildName, text)
|
||||||
self.ageLabel.setText(text)
|
self.ageLabel.setText(text)
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ class GuiBuildSettings(QDialog):
|
|||||||
|
|
||||||
newSettingsReady = pyqtSignal(BuildSettings)
|
newSettingsReady = pyqtSignal(BuildSettings)
|
||||||
|
|
||||||
def __init__(self, parent: QWidget, mainGui: GuiMain, build: BuildSettings):
|
def __init__(self, mainGui: GuiMain, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=mainGui)
|
||||||
|
|
||||||
logger.debug("Create: GuiBuildSettings")
|
logger.debug("Create: GuiBuildSettings")
|
||||||
self.setObjectName("GuiBuildSettings")
|
self.setObjectName("GuiBuildSettings")
|
||||||
@@ -106,7 +106,7 @@ class GuiBuildSettings(QDialog):
|
|||||||
self.optSideBar.setLabelColor(self.mainTheme.helpText)
|
self.optSideBar.setLabelColor(self.mainTheme.helpText)
|
||||||
|
|
||||||
self.optSideBar.addLabel(self.tr("Options"))
|
self.optSideBar.addLabel(self.tr("Options"))
|
||||||
self.optSideBar.addButton(self.tr("Filters"), self.OPT_FILTERS)
|
self.optSideBar.addButton(self.tr("Selection"), self.OPT_FILTERS)
|
||||||
self.optSideBar.addButton(self.tr("Headings"), self.OPT_HEADINGS)
|
self.optSideBar.addButton(self.tr("Headings"), self.OPT_HEADINGS)
|
||||||
self.optSideBar.addButton(self.tr("Content"), self.OPT_CONTENT)
|
self.optSideBar.addButton(self.tr("Content"), self.OPT_CONTENT)
|
||||||
self.optSideBar.addButton(self.tr("Format"), self.OPT_FORMAT)
|
self.optSideBar.addButton(self.tr("Format"), self.OPT_FORMAT)
|
||||||
@@ -169,10 +169,11 @@ class GuiBuildSettings(QDialog):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def __del__(self): # pragma: no cover
|
def __del__(self) -> None: # pragma: no cover
|
||||||
logger.debug("Delete: GuiBuildSettings")
|
logger.debug("Delete: GuiBuildSettings")
|
||||||
|
return
|
||||||
|
|
||||||
def loadContent(self):
|
def loadContent(self) -> None:
|
||||||
"""Populate the child widgets."""
|
"""Populate the child widgets."""
|
||||||
self.editBuildName.setText(self._build.name)
|
self.editBuildName.setText(self._build.name)
|
||||||
self.optTabSelect.loadContent()
|
self.optTabSelect.loadContent()
|
||||||
@@ -182,12 +183,21 @@ class GuiBuildSettings(QDialog):
|
|||||||
self.optTabOutput.loadContent()
|
self.optTabOutput.loadContent()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Properties
|
||||||
|
##
|
||||||
|
|
||||||
|
@property
|
||||||
|
def buildID(self) -> str:
|
||||||
|
"""The build ID of the build of the dialog."""
|
||||||
|
return self._build.buildID
|
||||||
|
|
||||||
##
|
##
|
||||||
# Private Slots
|
# Private Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def _stackPageSelected(self, pageId: int):
|
def _stackPageSelected(self, pageId: int) -> None:
|
||||||
"""Process a user request to switch page."""
|
"""Process a user request to switch page."""
|
||||||
if pageId == self.OPT_FILTERS:
|
if pageId == self.OPT_FILTERS:
|
||||||
self.toolStack.setCurrentWidget(self.optTabSelect)
|
self.toolStack.setCurrentWidget(self.optTabSelect)
|
||||||
@@ -202,7 +212,7 @@ class GuiBuildSettings(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot("QAbstractButton*")
|
@pyqtSlot("QAbstractButton*")
|
||||||
def _dialogButtonClicked(self, button: QAbstractButton):
|
def _dialogButtonClicked(self, button: QAbstractButton) -> None:
|
||||||
"""Handle button clicks from the dialog button box."""
|
"""Handle button clicks from the dialog button box."""
|
||||||
role = self.dlgButtons.buttonRole(button)
|
role = self.dlgButtons.buttonRole(button)
|
||||||
if role == QDialogButtonBox.ApplyRole:
|
if role == QDialogButtonBox.ApplyRole:
|
||||||
@@ -218,7 +228,7 @@ class GuiBuildSettings(QDialog):
|
|||||||
# Events
|
# Events
|
||||||
##
|
##
|
||||||
|
|
||||||
def closeEvent(self, event: QEvent):
|
def closeEvent(self, event: QEvent) -> None:
|
||||||
"""Capture the user closing the window so we can save
|
"""Capture the user closing the window so we can save
|
||||||
settings.
|
settings.
|
||||||
"""
|
"""
|
||||||
@@ -233,7 +243,7 @@ class GuiBuildSettings(QDialog):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _askToSaveBuild(self):
|
def _askToSaveBuild(self) -> None:
|
||||||
"""Check if there are unsaved changes, and if there are, ask if
|
"""Check if there are unsaved changes, and if there are, ask if
|
||||||
it's ok to reject them.
|
it's ok to reject them.
|
||||||
"""
|
"""
|
||||||
@@ -247,7 +257,7 @@ class GuiBuildSettings(QDialog):
|
|||||||
self._build.resetChangedState()
|
self._build.resetChangedState()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _saveSettings(self):
|
def _saveSettings(self) -> None:
|
||||||
"""Save the various user settings."""
|
"""Save the various user settings."""
|
||||||
logger.debug("Saving GuiBuildSettings settings")
|
logger.debug("Saving GuiBuildSettings settings")
|
||||||
|
|
||||||
@@ -265,7 +275,7 @@ class GuiBuildSettings(QDialog):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _emitBuildData(self):
|
def _emitBuildData(self) -> None:
|
||||||
"""Assemble the build data and emit the signal."""
|
"""Assemble the build data and emit the signal."""
|
||||||
self._build.setName(self.editBuildName.text())
|
self._build.setName(self.editBuildName.text())
|
||||||
self.optTabHeadings.saveContent()
|
self.optTabHeadings.saveContent()
|
||||||
@@ -294,23 +304,26 @@ class _FilterTab(QWidget):
|
|||||||
F_INCLUDED = 2
|
F_INCLUDED = 2
|
||||||
F_EXCLUDED = 3
|
F_EXCLUDED = 3
|
||||||
|
|
||||||
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
|
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=buildMain)
|
super().__init__(parent=buildMain)
|
||||||
|
|
||||||
self.mainGui = buildMain.mainGui
|
self.mainGui = buildMain.mainGui
|
||||||
self.mainTheme = buildMain.mainGui.mainTheme
|
self.mainTheme = buildMain.mainGui.mainTheme
|
||||||
self.theProject = buildMain.mainGui.theProject
|
self.theProject = buildMain.mainGui.theProject
|
||||||
|
|
||||||
self._treeMap = {}
|
self._treeMap: dict[str, QTreeWidgetItem] = {}
|
||||||
self._build = build
|
self._build = build
|
||||||
|
|
||||||
self._statusFlags = {
|
self._statusFlags: dict[int, QIcon] = {
|
||||||
self.F_NONE: ("", QIcon()),
|
self.F_NONE: QIcon(),
|
||||||
self.F_FILTERED: (self.tr("Filtered"), self.mainTheme.getIcon("build_filtered")),
|
self.F_FILTERED: self.mainTheme.getIcon("build_filtered"),
|
||||||
self.F_INCLUDED: (self.tr("Included"), self.mainTheme.getIcon("build_included")),
|
self.F_INCLUDED: self.mainTheme.getIcon("build_included"),
|
||||||
self.F_EXCLUDED: (self.tr("Excluded"), self.mainTheme.getIcon("build_excluded")),
|
self.F_EXCLUDED: self.mainTheme.getIcon("build_excluded"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self._trIncluded = self.tr("Included in manuscript")
|
||||||
|
self._trExcluded = self.tr("Excluded from manuscript")
|
||||||
|
|
||||||
# Project Tree
|
# Project Tree
|
||||||
# ============
|
# ============
|
||||||
|
|
||||||
@@ -341,27 +354,28 @@ class _FilterTab(QWidget):
|
|||||||
# Filters
|
# Filters
|
||||||
# =======
|
# =======
|
||||||
|
|
||||||
self.filteredButton = QToolButton(self)
|
|
||||||
self.filteredButton.setToolTip(self._statusFlags[self.F_FILTERED][0])
|
|
||||||
self.filteredButton.setIcon(self._statusFlags[self.F_FILTERED][1])
|
|
||||||
self.filteredButton.clicked.connect(lambda: self._setSelectedMode(self.F_FILTERED))
|
|
||||||
|
|
||||||
self.includedButton = QToolButton(self)
|
self.includedButton = QToolButton(self)
|
||||||
self.includedButton.setToolTip(self._statusFlags[self.F_INCLUDED][0])
|
self.includedButton.setToolTip(self.tr("Always included"))
|
||||||
self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED][1])
|
self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED])
|
||||||
self.includedButton.clicked.connect(lambda: self._setSelectedMode(self.F_INCLUDED))
|
self.includedButton.clicked.connect(lambda: self._setSelectedMode(self.F_INCLUDED))
|
||||||
|
|
||||||
self.excludedButton = QToolButton(self)
|
self.excludedButton = QToolButton(self)
|
||||||
self.excludedButton.setToolTip(self._statusFlags[self.F_EXCLUDED][0])
|
self.excludedButton.setToolTip(self.tr("Always excluded"))
|
||||||
self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED][1])
|
self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED])
|
||||||
self.excludedButton.clicked.connect(lambda: self._setSelectedMode(self.F_EXCLUDED))
|
self.excludedButton.clicked.connect(lambda: self._setSelectedMode(self.F_EXCLUDED))
|
||||||
|
|
||||||
|
self.resetButton = QToolButton(self)
|
||||||
|
self.resetButton.setToolTip(self.tr("Reset to default"))
|
||||||
|
self.resetButton.setIcon(self.mainTheme.getIcon("revert"))
|
||||||
|
self.resetButton.clicked.connect(lambda: self._setSelectedMode(self.F_FILTERED))
|
||||||
|
|
||||||
self.modeBox = QHBoxLayout()
|
self.modeBox = QHBoxLayout()
|
||||||
self.modeBox.addWidget(QLabel(self.tr("Mark selection as")))
|
self.modeBox.addWidget(QLabel(self.tr("Mark selection as")))
|
||||||
self.modeBox.addStretch(1)
|
self.modeBox.addStretch(1)
|
||||||
self.modeBox.addWidget(self.filteredButton)
|
|
||||||
self.modeBox.addWidget(self.includedButton)
|
self.modeBox.addWidget(self.includedButton)
|
||||||
self.modeBox.addWidget(self.excludedButton)
|
self.modeBox.addWidget(self.excludedButton)
|
||||||
|
self.modeBox.addWidget(self.resetButton)
|
||||||
|
self.modeBox.setSpacing(CONFIG.pxInt(4))
|
||||||
|
|
||||||
# Filer Options
|
# Filer Options
|
||||||
self.filterOpt = NSwitchBox(self, iPx)
|
self.filterOpt = NSwitchBox(self, iPx)
|
||||||
@@ -401,7 +415,7 @@ class _FilterTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadContent(self):
|
def loadContent(self) -> None:
|
||||||
"""Populate the widgets."""
|
"""Populate the widgets."""
|
||||||
self._populateTree()
|
self._populateTree()
|
||||||
self._populateFilters()
|
self._populateFilters()
|
||||||
@@ -418,7 +432,7 @@ class _FilterTab(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot(str, bool)
|
@pyqtSlot(str, bool)
|
||||||
def _applyFilterSwitch(self, key: str, state: bool):
|
def _applyFilterSwitch(self, key: str, state: bool) -> None:
|
||||||
"""Apply filter switch and update the settings."""
|
"""Apply filter switch and update the settings."""
|
||||||
if key.startswith("doc:"):
|
if key.startswith("doc:"):
|
||||||
self._build.setValue(key[4:], state)
|
self._build.setValue(key[4:], state)
|
||||||
@@ -432,7 +446,7 @@ class _FilterTab(QWidget):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _populateTree(self):
|
def _populateTree(self) -> None:
|
||||||
"""Build the tree of project items."""
|
"""Build the tree of project items."""
|
||||||
logger.debug("Building project tree")
|
logger.debug("Building project tree")
|
||||||
self._treeMap = {}
|
self._treeMap = {}
|
||||||
@@ -486,7 +500,7 @@ class _FilterTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _populateFilters(self):
|
def _populateFilters(self) -> None:
|
||||||
"""Populate the filter options switches."""
|
"""Populate the filter options switches."""
|
||||||
self.filterOpt.clear()
|
self.filterOpt.clear()
|
||||||
self.filterOpt.addLabel(self._build.getLabel("filter"))
|
self.filterOpt.addLabel(self._build.getLabel("filter"))
|
||||||
@@ -512,7 +526,7 @@ class _FilterTab(QWidget):
|
|||||||
self.filterOpt.addSeparator()
|
self.filterOpt.addSeparator()
|
||||||
|
|
||||||
# Root Classes
|
# Root Classes
|
||||||
self.filterOpt.addLabel(self.tr("Root Folders"))
|
self.filterOpt.addLabel(self.tr("Select Root Folders"))
|
||||||
for tHandle, nwItem in self.theProject.tree.iterRoots(None):
|
for tHandle, nwItem in self.theProject.tree.iterRoots(None):
|
||||||
if not nwItem.isInactiveClass():
|
if not nwItem.isInactiveClass():
|
||||||
itemIcon = self.mainTheme.getItemIcon(
|
itemIcon = self.mainTheme.getItemIcon(
|
||||||
@@ -525,9 +539,13 @@ class _FilterTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _setSelectedMode(self, mode: int):
|
def _setSelectedMode(self, mode: int) -> None:
|
||||||
"""Set the mode for the selected items."""
|
"""Set the mode for the selected items."""
|
||||||
for item in self.optTree.selectedItems():
|
items = self.optTree.selectedItems()
|
||||||
|
if len(items) == 1 and isinstance(items[0], QTreeWidgetItem):
|
||||||
|
items = self._scanChildren(items[0], [])
|
||||||
|
|
||||||
|
for item in items:
|
||||||
if isinstance(item, QTreeWidgetItem):
|
if isinstance(item, QTreeWidgetItem):
|
||||||
tHandle = item.data(self.C_DATA, self.D_HANDLE)
|
tHandle = item.data(self.C_DATA, self.D_HANDLE)
|
||||||
isFile = item.data(self.C_DATA, self.D_FILE)
|
isFile = item.data(self.C_DATA, self.D_FILE)
|
||||||
@@ -543,21 +561,34 @@ class _FilterTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _setTreeItemMode(self):
|
def _setTreeItemMode(self) -> None:
|
||||||
"""Update the filtered mode icon on all items."""
|
"""Update the filtered mode icon on all items."""
|
||||||
filtered = self._build.buildItemFilter(self.theProject)
|
filtered = self._build.buildItemFilter(self.theProject)
|
||||||
for tHandle, item in self._treeMap.items():
|
for tHandle, item in self._treeMap.items():
|
||||||
allow, mode = filtered.get(tHandle, (False, FilterMode.UNKNOWN))
|
allow, mode = filtered.get(tHandle, (False, FilterMode.UNKNOWN))
|
||||||
if mode == FilterMode.INCLUDED:
|
if mode == FilterMode.INCLUDED:
|
||||||
item.setIcon(self.C_STATUS, self._statusFlags[self.F_INCLUDED][1])
|
item.setIcon(self.C_STATUS, self._statusFlags[self.F_INCLUDED])
|
||||||
|
item.setToolTip(self.C_STATUS, self._trIncluded)
|
||||||
elif mode == FilterMode.EXCLUDED:
|
elif mode == FilterMode.EXCLUDED:
|
||||||
item.setIcon(self.C_STATUS, self._statusFlags[self.F_EXCLUDED][1])
|
item.setIcon(self.C_STATUS, self._statusFlags[self.F_EXCLUDED])
|
||||||
|
item.setToolTip(self.C_STATUS, self._trExcluded)
|
||||||
elif mode == FilterMode.FILTERED and allow:
|
elif mode == FilterMode.FILTERED and allow:
|
||||||
item.setIcon(self.C_STATUS, self._statusFlags[self.F_FILTERED][1])
|
item.setIcon(self.C_STATUS, self._statusFlags[self.F_FILTERED])
|
||||||
|
item.setToolTip(self.C_STATUS, self._trIncluded)
|
||||||
else:
|
else:
|
||||||
item.setIcon(self.C_STATUS, self._statusFlags[self.F_NONE][1])
|
item.setIcon(self.C_STATUS, self._statusFlags[self.F_NONE])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _scanChildren(self, item: QTreeWidgetItem | None, items: list) -> list[QTreeWidgetItem]:
|
||||||
|
"""This is a recursive function returning all items in a tree
|
||||||
|
starting at a given QTreeWidgetItem.
|
||||||
|
"""
|
||||||
|
if isinstance(item, QTreeWidgetItem):
|
||||||
|
items.append(item)
|
||||||
|
for i in range(item.childCount()):
|
||||||
|
self._scanChildren(item.child(i), items)
|
||||||
|
return items
|
||||||
|
|
||||||
# END Class _FilterTab
|
# END Class _FilterTab
|
||||||
|
|
||||||
|
|
||||||
@@ -569,7 +600,7 @@ class _HeadingsTab(QWidget):
|
|||||||
EDIT_SCENE = 4
|
EDIT_SCENE = 4
|
||||||
EDIT_SECTION = 5
|
EDIT_SECTION = 5
|
||||||
|
|
||||||
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
|
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=buildMain)
|
super().__init__(parent=buildMain)
|
||||||
|
|
||||||
self.mainGui = buildMain.mainGui
|
self.mainGui = buildMain.mainGui
|
||||||
@@ -747,7 +778,7 @@ class _HeadingsTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadContent(self):
|
def loadContent(self) -> None:
|
||||||
"""Populate the widgets."""
|
"""Populate the widgets."""
|
||||||
self.fmtTitle.setText(self._build.getStr("headings.fmtTitle"))
|
self.fmtTitle.setText(self._build.getStr("headings.fmtTitle"))
|
||||||
self.fmtChapter.setText(self._build.getStr("headings.fmtChapter"))
|
self.fmtChapter.setText(self._build.getStr("headings.fmtChapter"))
|
||||||
@@ -758,7 +789,7 @@ class _HeadingsTab(QWidget):
|
|||||||
self.swtSection.setChecked(self._build.getBool("headings.hideSection"))
|
self.swtSection.setChecked(self._build.getBool("headings.hideSection"))
|
||||||
return
|
return
|
||||||
|
|
||||||
def saveContent(self):
|
def saveContent(self) -> None:
|
||||||
"""Save choices back into build object."""
|
"""Save choices back into build object."""
|
||||||
self._build.setValue("headings.hideScene", self.swtScene.isChecked())
|
self._build.setValue("headings.hideScene", self.swtScene.isChecked())
|
||||||
self._build.setValue("headings.hideSection", self.swtSection.isChecked())
|
self._build.setValue("headings.hideSection", self.swtSection.isChecked())
|
||||||
@@ -768,7 +799,7 @@ class _HeadingsTab(QWidget):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _insertIntoForm(self, text: str):
|
def _insertIntoForm(self, text: str) -> None:
|
||||||
"""Insert formatting text from the dropdown menu."""
|
"""Insert formatting text from the dropdown menu."""
|
||||||
if self._editing > 0:
|
if self._editing > 0:
|
||||||
cursor = self.editTextBox.textCursor()
|
cursor = self.editTextBox.textCursor()
|
||||||
@@ -776,7 +807,7 @@ class _HeadingsTab(QWidget):
|
|||||||
self.editTextBox.setFocus()
|
self.editTextBox.setFocus()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _editHeading(self, heading: int):
|
def _editHeading(self, heading: int) -> None:
|
||||||
"""Populate the form with a specific heading format."""
|
"""Populate the form with a specific heading format."""
|
||||||
self._editing = heading
|
self._editing = heading
|
||||||
self.editTextBox.setEnabled(True)
|
self.editTextBox.setEnabled(True)
|
||||||
@@ -801,7 +832,7 @@ class _HeadingsTab(QWidget):
|
|||||||
text = ""
|
text = ""
|
||||||
label = self.tr("None")
|
label = self.tr("None")
|
||||||
|
|
||||||
self.editTextBox.setPlainText(text.replace("//", "\n"))
|
self.editTextBox.setPlainText(text.replace(nwHeadFmt.BR, "\n"))
|
||||||
self.lblEditForm.setText(self.tr("Editing: {0}").format(label))
|
self.lblEditForm.setText(self.tr("Editing: {0}").format(label))
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -810,10 +841,10 @@ class _HeadingsTab(QWidget):
|
|||||||
# Private Slots
|
# Private Slots
|
||||||
##
|
##
|
||||||
|
|
||||||
def _saveFormat(self):
|
def _saveFormat(self) -> None:
|
||||||
"""Save the format from the edit text box."""
|
"""Save the format from the edit text box."""
|
||||||
heading = self._editing
|
heading = self._editing
|
||||||
text = self.editTextBox.toPlainText().strip().replace("\n", "//")
|
text = self.editTextBox.toPlainText().strip().replace("\n", nwHeadFmt.BR)
|
||||||
if heading == self.EDIT_TITLE:
|
if heading == self.EDIT_TITLE:
|
||||||
self.fmtTitle.setText(text)
|
self.fmtTitle.setText(text)
|
||||||
self._build.setValue("headings.fmtTitle", text)
|
self._build.setValue("headings.fmtTitle", text)
|
||||||
@@ -842,7 +873,7 @@ class _HeadingsTab(QWidget):
|
|||||||
|
|
||||||
class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
|
class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
|
||||||
|
|
||||||
def __init__(self, document: QTextDocument, mainTheme: GuiTheme):
|
def __init__(self, document: QTextDocument, mainTheme: GuiTheme) -> None:
|
||||||
super().__init__(document)
|
super().__init__(document)
|
||||||
self._fmtSymbol = QTextCharFormat()
|
self._fmtSymbol = QTextCharFormat()
|
||||||
self._fmtSymbol.setForeground(QColor(*mainTheme.colHead))
|
self._fmtSymbol.setForeground(QColor(*mainTheme.colHead))
|
||||||
@@ -850,7 +881,7 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
|
|||||||
self._fmtFormat.setForeground(QColor(*mainTheme.colEmph))
|
self._fmtFormat.setForeground(QColor(*mainTheme.colEmph))
|
||||||
return
|
return
|
||||||
|
|
||||||
def highlightBlock(self, text: str):
|
def highlightBlock(self, text: str) -> None:
|
||||||
"""Add syntax highlighting to the text block."""
|
"""Add syntax highlighting to the text block."""
|
||||||
for heading in nwHeadFmt.ALL:
|
for heading in nwHeadFmt.ALL:
|
||||||
pos = text.find(heading)
|
pos = text.find(heading)
|
||||||
@@ -868,7 +899,7 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
class _ContentTab(QWidget):
|
class _ContentTab(QWidget):
|
||||||
|
|
||||||
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
|
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=buildMain)
|
super().__init__(parent=buildMain)
|
||||||
|
|
||||||
self.mainGui = buildMain.mainGui
|
self.mainGui = buildMain.mainGui
|
||||||
@@ -917,7 +948,7 @@ class _ContentTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadContent(self):
|
def loadContent(self) -> None:
|
||||||
"""Populate the widgets."""
|
"""Populate the widgets."""
|
||||||
self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
|
self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
|
||||||
self.incComments.setChecked(self._build.getBool("text.includeComments"))
|
self.incComments.setChecked(self._build.getBool("text.includeComments"))
|
||||||
@@ -926,7 +957,7 @@ class _ContentTab(QWidget):
|
|||||||
self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
|
self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
|
||||||
return
|
return
|
||||||
|
|
||||||
def saveContent(self):
|
def saveContent(self) -> None:
|
||||||
"""Save choices back into build object."""
|
"""Save choices back into build object."""
|
||||||
self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
|
self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
|
||||||
self._build.setValue("text.includeComments", self.incComments.isChecked())
|
self._build.setValue("text.includeComments", self.incComments.isChecked())
|
||||||
@@ -940,7 +971,7 @@ class _ContentTab(QWidget):
|
|||||||
|
|
||||||
class _FormatTab(QWidget):
|
class _FormatTab(QWidget):
|
||||||
|
|
||||||
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
|
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=buildMain)
|
super().__init__(parent=buildMain)
|
||||||
|
|
||||||
self.buildMain = buildMain
|
self.buildMain = buildMain
|
||||||
@@ -1033,10 +1064,12 @@ class _FormatTab(QWidget):
|
|||||||
self.pageWidth = QDoubleSpinBox(self)
|
self.pageWidth = QDoubleSpinBox(self)
|
||||||
self.pageWidth.setFixedWidth(dbW)
|
self.pageWidth.setFixedWidth(dbW)
|
||||||
self.pageWidth.setMaximum(500.0)
|
self.pageWidth.setMaximum(500.0)
|
||||||
|
self.pageWidth.valueChanged.connect(self._pageSizeValueChanged)
|
||||||
|
|
||||||
self.pageHeight = QDoubleSpinBox(self)
|
self.pageHeight = QDoubleSpinBox(self)
|
||||||
self.pageHeight.setFixedWidth(dbW)
|
self.pageHeight.setFixedWidth(dbW)
|
||||||
self.pageHeight.setMaximum(500.0)
|
self.pageHeight.setMaximum(500.0)
|
||||||
|
self.pageHeight.valueChanged.connect(self._pageSizeValueChanged)
|
||||||
|
|
||||||
self.topMargin = QDoubleSpinBox(self)
|
self.topMargin = QDoubleSpinBox(self)
|
||||||
self.topMargin.setFixedWidth(dbW)
|
self.topMargin.setFixedWidth(dbW)
|
||||||
@@ -1085,7 +1118,7 @@ class _FormatTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadContent(self):
|
def loadContent(self) -> None:
|
||||||
"""Populate the widgets."""
|
"""Populate the widgets."""
|
||||||
langIdx = self.buildLang.findData(self._build.getStr("format.buildLang"))
|
langIdx = self.buildLang.findData(self._build.getStr("format.buildLang"))
|
||||||
if langIdx != -1:
|
if langIdx != -1:
|
||||||
@@ -1128,7 +1161,7 @@ class _FormatTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def saveContent(self):
|
def saveContent(self) -> None:
|
||||||
"""Save choices back into build object."""
|
"""Save choices back into build object."""
|
||||||
self._build.setValue("format.buildLang", str(self.buildLang.currentData()))
|
self._build.setValue("format.buildLang", str(self.buildLang.currentData()))
|
||||||
self._build.setValue("format.textFont", self.textFont.text())
|
self._build.setValue("format.textFont", self.textFont.text())
|
||||||
@@ -1154,7 +1187,7 @@ class _FormatTab(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _selectFont(self):
|
def _selectFont(self) -> None:
|
||||||
"""Open the QFontDialog and set a font for the font style."""
|
"""Open the QFontDialog and set a font for the font style."""
|
||||||
currFont = QFont()
|
currFont = QFont()
|
||||||
currFont.setFamily(self.textFont.text())
|
currFont.setFamily(self.textFont.text())
|
||||||
@@ -1166,7 +1199,7 @@ class _FormatTab(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def _changeUnit(self, index: int):
|
def _changeUnit(self, index: int) -> None:
|
||||||
"""The current unit change, so recalculate sizes."""
|
"""The current unit change, so recalculate sizes."""
|
||||||
newUnit = self.pageUnit.itemData(index)
|
newUnit = self.pageUnit.itemData(index)
|
||||||
newScale = nwLabels.UNIT_SCALE.get(newUnit, 1.0)
|
newScale = nwLabels.UNIT_SCALE.get(newUnit, 1.0)
|
||||||
@@ -1185,15 +1218,19 @@ class _FormatTab(QWidget):
|
|||||||
pMax = 500.0 if isMM else 50.0
|
pMax = 500.0 if isMM else 50.0
|
||||||
mMax = 150.0 if isMM else 15.0
|
mMax = 150.0 if isMM else 15.0
|
||||||
|
|
||||||
|
self.pageWidth.blockSignals(True)
|
||||||
self.pageWidth.setDecimals(nDec)
|
self.pageWidth.setDecimals(nDec)
|
||||||
self.pageWidth.setSingleStep(nStep)
|
self.pageWidth.setSingleStep(nStep)
|
||||||
self.pageWidth.setMaximum(pMax)
|
self.pageWidth.setMaximum(pMax)
|
||||||
self.pageWidth.setValue(pageWidth)
|
self.pageWidth.setValue(pageWidth)
|
||||||
|
self.pageWidth.blockSignals(False)
|
||||||
|
|
||||||
|
self.pageHeight.blockSignals(True)
|
||||||
self.pageHeight.setDecimals(nDec)
|
self.pageHeight.setDecimals(nDec)
|
||||||
self.pageHeight.setSingleStep(nStep)
|
self.pageHeight.setSingleStep(nStep)
|
||||||
self.pageHeight.setMaximum(pMax)
|
self.pageHeight.setMaximum(pMax)
|
||||||
self.pageHeight.setValue(pageHeight)
|
self.pageHeight.setValue(pageHeight)
|
||||||
|
self.pageHeight.blockSignals(False)
|
||||||
|
|
||||||
self.topMargin.setDecimals(nDec)
|
self.topMargin.setDecimals(nDec)
|
||||||
self.topMargin.setSingleStep(nStep)
|
self.topMargin.setSingleStep(nStep)
|
||||||
@@ -1216,22 +1253,31 @@ class _FormatTab(QWidget):
|
|||||||
self.rightMargin.setValue(rightMargin)
|
self.rightMargin.setValue(rightMargin)
|
||||||
|
|
||||||
self._unitScale = newScale
|
self._unitScale = newScale
|
||||||
|
self._changePageSize(self.pageSize.currentIndex())
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def _changePageSize(self, index: int):
|
def _changePageSize(self, index: int) -> None:
|
||||||
"""The page size has changed."""
|
"""The page size has changed."""
|
||||||
self.pageWidth.setEnabled(True)
|
|
||||||
self.pageHeight.setEnabled(True)
|
|
||||||
|
|
||||||
w, h = nwLabels.PAPER_SIZE[self.pageSize.itemData(index)] if index >= 0 else (-1.0, -1.0)
|
w, h = nwLabels.PAPER_SIZE[self.pageSize.itemData(index)] if index >= 0 else (-1.0, -1.0)
|
||||||
if w > 0.0 and h > 0.0:
|
if w > 0.0 and h > 0.0:
|
||||||
self.pageWidth.setEnabled(False)
|
self.pageWidth.blockSignals(True)
|
||||||
self.pageHeight.setEnabled(False)
|
|
||||||
self.pageWidth.setValue(w/self._unitScale)
|
self.pageWidth.setValue(w/self._unitScale)
|
||||||
|
self.pageWidth.blockSignals(False)
|
||||||
|
self.pageHeight.blockSignals(True)
|
||||||
self.pageHeight.setValue(h/self._unitScale)
|
self.pageHeight.setValue(h/self._unitScale)
|
||||||
|
self.pageHeight.blockSignals(False)
|
||||||
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _pageSizeValueChanged(self):
|
||||||
|
"""The user has changed the page size spin boxes, so we flip
|
||||||
|
the page size box to Custom.
|
||||||
|
"""
|
||||||
|
index = self.pageSize.findData("Custom")
|
||||||
|
if index >= 0:
|
||||||
|
self.pageSize.setCurrentIndex(index)
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class _FormatTab
|
# END Class _FormatTab
|
||||||
@@ -1239,7 +1285,7 @@ class _FormatTab(QWidget):
|
|||||||
|
|
||||||
class _OutputTab(QWidget):
|
class _OutputTab(QWidget):
|
||||||
|
|
||||||
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings):
|
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=buildMain)
|
super().__init__(parent=buildMain)
|
||||||
|
|
||||||
self.mainGui = buildMain.mainGui
|
self.mainGui = buildMain.mainGui
|
||||||
@@ -1282,13 +1328,13 @@ class _OutputTab(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadContent(self):
|
def loadContent(self) -> None:
|
||||||
"""Populate the widgets."""
|
"""Populate the widgets."""
|
||||||
self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
|
self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
|
||||||
self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
|
self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
|
||||||
return
|
return
|
||||||
|
|
||||||
def saveContent(self):
|
def saveContent(self) -> None:
|
||||||
"""Save choices back into build object."""
|
"""Save choices back into build object."""
|
||||||
self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
|
self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
|
||||||
self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
|
self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
|
||||||
|
|||||||
@@ -168,11 +168,12 @@ def testManuscript_Features(monkeypatch, qtbot: QtBot, nwGUI: GuiMain, projPath:
|
|||||||
# ========
|
# ========
|
||||||
|
|
||||||
# No build selected
|
# No build selected
|
||||||
manus.buildList.clearSelection()
|
manus.buildList.clear()
|
||||||
manus.btnPreview.click()
|
manus.btnPreview.click()
|
||||||
qtbot.wait(200) # Should be enough to run the build
|
qtbot.wait(200) # Should be enough to run the build
|
||||||
assert manus.docPreview.toPlainText().strip() == ""
|
assert manus.docPreview.toPlainText().strip() == ""
|
||||||
assert cacheFile.exists() is False
|
assert cacheFile.exists() is False
|
||||||
|
manus._updateBuildsList()
|
||||||
|
|
||||||
# Preview the first, but fail to save cache
|
# Preview the first, but fail to save cache
|
||||||
manus.buildList.setCurrentRow(0)
|
manus.buildList.setCurrentRow(0)
|
||||||
@@ -207,12 +208,6 @@ def testManuscript_Features(monkeypatch, qtbot: QtBot, nwGUI: GuiMain, projPath:
|
|||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("novelwriter.tools.manusbuild.GuiManuscriptBuild.exec_", lambda *a: None)
|
mp.setattr("novelwriter.tools.manusbuild.GuiManuscriptBuild.exec_", lambda *a: None)
|
||||||
|
|
||||||
# With no selection, no dialog should be created
|
|
||||||
manus.btnBuild.click()
|
|
||||||
for obj in manus.children():
|
|
||||||
assert not isinstance(obj, GuiManuscriptBuild)
|
|
||||||
|
|
||||||
# With a selection, there should be one
|
|
||||||
manus.buildList.setCurrentRow(0)
|
manus.buildList.setCurrentRow(0)
|
||||||
manus.btnBuild.click()
|
manus.btnBuild.click()
|
||||||
for obj in manus.children():
|
for obj in manus.children():
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd
|
|||||||
build = BuildSettings()
|
build = BuildSettings()
|
||||||
|
|
||||||
# Create the dialog and populate it
|
# Create the dialog and populate it
|
||||||
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
|
bSettings = GuiBuildSettings(nwGUI, build)
|
||||||
bSettings.show()
|
bSettings.show()
|
||||||
bSettings.loadContent()
|
bSettings.loadContent()
|
||||||
|
|
||||||
@@ -132,10 +132,10 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
|
|||||||
hCharDoc = nwGUI.theProject.newFile("Jane Doe", C.hCharRoot)
|
hCharDoc = nwGUI.theProject.newFile("Jane Doe", C.hCharRoot)
|
||||||
nwGUI.projView.projTree.revealNewTreeItem(hPlotDoc)
|
nwGUI.projView.projTree.revealNewTreeItem(hPlotDoc)
|
||||||
nwGUI.projView.projTree.revealNewTreeItem(hCharDoc)
|
nwGUI.projView.projTree.revealNewTreeItem(hCharDoc)
|
||||||
nwGUI.theProject.tree[hPlotDoc].setActive(False)
|
nwGUI.theProject.tree[hPlotDoc].setActive(False) # type: ignore
|
||||||
|
|
||||||
# Create the dialog and populate it
|
# Create the dialog and populate it
|
||||||
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
|
bSettings = GuiBuildSettings(nwGUI, build)
|
||||||
bSettings.show()
|
bSettings.show()
|
||||||
bSettings.loadContent()
|
bSettings.loadContent()
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
|
|||||||
assert filterTab.optTree.topLevelItemCount() == 4 # The 4 root folders
|
assert filterTab.optTree.topLevelItemCount() == 4 # The 4 root folders
|
||||||
assert filterTab.filterOpt._index == 10 # 2 headers, 1 sep, 3 opt and 4 roots
|
assert filterTab.filterOpt._index == 10 # 2 headers, 1 sep, 3 opt and 4 roots
|
||||||
|
|
||||||
# Untoggle note folders
|
# Un-toggle note folders
|
||||||
filterTab.filterOpt._widgets[switchMap["worldRoot"]].setChecked(False) # World Root
|
filterTab.filterOpt._widgets[switchMap["worldRoot"]].setChecked(False) # World Root
|
||||||
assert filterTab.optTree.topLevelItemCount() == 3
|
assert filterTab.optTree.topLevelItemCount() == 3
|
||||||
assert C.hWorldRoot in build._skipRoot
|
assert C.hWorldRoot in build._skipRoot
|
||||||
@@ -229,8 +229,8 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
|
|||||||
|
|
||||||
# Set char and plot docs to excluded
|
# Set char and plot docs to excluded
|
||||||
filterTab.optTree.clearSelection()
|
filterTab.optTree.clearSelection()
|
||||||
filterTab._treeMap[hPlotDoc].setSelected(True)
|
filterTab._treeMap[hPlotDoc].setSelected(True) # type: ignore
|
||||||
filterTab._treeMap[hCharDoc].setSelected(True)
|
filterTab._treeMap[hCharDoc].setSelected(True) # type: ignore
|
||||||
filterTab.excludedButton.click()
|
filterTab.excludedButton.click()
|
||||||
assert build.buildItemFilter(nwGUI.theProject) == {
|
assert build.buildItemFilter(nwGUI.theProject) == {
|
||||||
C.hNovelRoot: (False, FilterMode.SKIPPED),
|
C.hNovelRoot: (False, FilterMode.SKIPPED),
|
||||||
@@ -260,13 +260,30 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
|
|||||||
C.hWorldRoot: (False, FilterMode.SKIPPED),
|
C.hWorldRoot: (False, FilterMode.SKIPPED),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Selecting only novel root should iterate through all children
|
||||||
|
filterTab.optTree.clearSelection()
|
||||||
|
filterTab._treeMap[C.hNovelRoot].setSelected(True)
|
||||||
|
filterTab.resetButton.click()
|
||||||
|
assert build.buildItemFilter(nwGUI.theProject) == {
|
||||||
|
C.hNovelRoot: (False, FilterMode.SKIPPED),
|
||||||
|
C.hTitlePage: (True, FilterMode.FILTERED),
|
||||||
|
C.hChapterDir: (False, FilterMode.SKIPPED),
|
||||||
|
C.hChapterDoc: (True, FilterMode.FILTERED),
|
||||||
|
C.hSceneDoc: (True, FilterMode.FILTERED),
|
||||||
|
C.hPlotRoot: (False, FilterMode.SKIPPED),
|
||||||
|
hPlotDoc: (False, FilterMode.EXCLUDED),
|
||||||
|
C.hCharRoot: (False, FilterMode.SKIPPED),
|
||||||
|
hCharDoc: (False, FilterMode.EXCLUDED),
|
||||||
|
C.hWorldRoot: (False, FilterMode.SKIPPED),
|
||||||
|
}
|
||||||
|
|
||||||
# Set everything back to filtered
|
# Set everything back to filtered
|
||||||
filterTab.optTree.clearSelection()
|
filterTab.optTree.clearSelection()
|
||||||
filterTab._treeMap[C.hChapterDoc].setSelected(True)
|
filterTab._treeMap[C.hNovelRoot].setSelected(True)
|
||||||
filterTab._treeMap[C.hSceneDoc].setSelected(True)
|
filterTab._treeMap[C.hSceneDoc].setSelected(True)
|
||||||
filterTab._treeMap[hPlotDoc].setSelected(True)
|
filterTab._treeMap[hPlotDoc].setSelected(True) # type: ignore
|
||||||
filterTab._treeMap[hCharDoc].setSelected(True)
|
filterTab._treeMap[hCharDoc].setSelected(True) # type: ignore
|
||||||
filterTab.filteredButton.click()
|
filterTab.resetButton.click()
|
||||||
assert build.buildItemFilter(nwGUI.theProject) == {
|
assert build.buildItemFilter(nwGUI.theProject) == {
|
||||||
C.hNovelRoot: (False, FilterMode.SKIPPED),
|
C.hNovelRoot: (False, FilterMode.SKIPPED),
|
||||||
C.hTitlePage: (True, FilterMode.FILTERED),
|
C.hTitlePage: (True, FilterMode.FILTERED),
|
||||||
@@ -285,8 +302,8 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR
|
|||||||
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
|
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
|
||||||
C.hPlotRoot, hPlotDoc, C.hCharRoot, hCharDoc,
|
C.hPlotRoot, hPlotDoc, C.hCharRoot, hCharDoc,
|
||||||
]
|
]
|
||||||
nwGUI.theProject.tree[hCharDoc].setRoot(None) # Char doc has no root handle
|
nwGUI.theProject.tree[hCharDoc].setRoot(None) # type: ignore
|
||||||
nwGUI.theProject.tree[hPlotDoc].setParent(None) # Plot doc has no parent handle
|
nwGUI.theProject.tree[hPlotDoc].setParent(None) # type: ignore
|
||||||
filterTab._populateTree()
|
filterTab._populateTree()
|
||||||
assert list(filterTab._treeMap.keys()) == [
|
assert list(filterTab._treeMap.keys()) == [
|
||||||
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
|
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
|
||||||
@@ -320,7 +337,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
|
|||||||
build.setValue("headings.hideSection", False)
|
build.setValue("headings.hideSection", False)
|
||||||
|
|
||||||
# Create the dialog and populate it
|
# Create the dialog and populate it
|
||||||
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
|
bSettings = GuiBuildSettings(nwGUI, build)
|
||||||
bSettings.show()
|
bSettings.show()
|
||||||
bSettings.loadContent()
|
bSettings.loadContent()
|
||||||
|
|
||||||
@@ -412,7 +429,9 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
|
|||||||
headTab.btnChapter.click()
|
headTab.btnChapter.click()
|
||||||
headTab.editTextBox.setPlainText(f"Chapter {nwHeadFmt.CH_NUM}\n{nwHeadFmt.TITLE}\n")
|
headTab.editTextBox.setPlainText(f"Chapter {nwHeadFmt.CH_NUM}\n{nwHeadFmt.TITLE}\n")
|
||||||
headTab.btnApply.click()
|
headTab.btnApply.click()
|
||||||
assert build.getStr("headings.fmtChapter") == f"Chapter {nwHeadFmt.CH_NUM}//{nwHeadFmt.TITLE}"
|
assert build.getStr("headings.fmtChapter") == (
|
||||||
|
f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}"
|
||||||
|
)
|
||||||
|
|
||||||
# Set all to plain title
|
# Set all to plain title
|
||||||
headTab.btnTitle.click()
|
headTab.btnTitle.click()
|
||||||
@@ -467,7 +486,7 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
|
|||||||
build.setValue("text.addNoteHeadings", False)
|
build.setValue("text.addNoteHeadings", False)
|
||||||
|
|
||||||
# Create the dialog and populate it
|
# Create the dialog and populate it
|
||||||
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
|
bSettings = GuiBuildSettings(nwGUI, build)
|
||||||
bSettings.show()
|
bSettings.show()
|
||||||
bSettings.loadContent()
|
bSettings.loadContent()
|
||||||
|
|
||||||
@@ -534,7 +553,7 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain):
|
|||||||
build.setValue("format.rightMargin", 15.0)
|
build.setValue("format.rightMargin", 15.0)
|
||||||
|
|
||||||
# Create the dialog and populate it
|
# Create the dialog and populate it
|
||||||
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
|
bSettings = GuiBuildSettings(nwGUI, build)
|
||||||
bSettings.show()
|
bSettings.show()
|
||||||
bSettings.loadContent()
|
bSettings.loadContent()
|
||||||
|
|
||||||
@@ -622,7 +641,7 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain):
|
|||||||
build.setValue("html.addStyles", False)
|
build.setValue("html.addStyles", False)
|
||||||
|
|
||||||
# Create the dialog and populate it
|
# Create the dialog and populate it
|
||||||
bSettings = GuiBuildSettings(nwGUI, nwGUI, build)
|
bSettings = GuiBuildSettings(nwGUI, build)
|
||||||
bSettings.show()
|
bSettings.show()
|
||||||
bSettings.loadContent()
|
bSettings.loadContent()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user