From 7a60d8d8670e47fd13dad6d4f0c5804e6a28078f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 21 Feb 2023 16:06:41 +0100 Subject: [PATCH] Add a custom widgets subpackage --- novelwriter/custom.py | 475 ---------------------------- novelwriter/custom/__init__.py | 3 + novelwriter/custom/configlayout.py | 214 +++++++++++++ novelwriter/custom/pageddialog.py | 136 ++++++++ novelwriter/custom/pagedsidebar.py | 62 ++++ novelwriter/custom/switch.py | 176 +++++++++++ novelwriter/dialogs/docmerge.py | 7 +- novelwriter/dialogs/docsplit.py | 11 +- novelwriter/dialogs/preferences.py | 70 ++-- novelwriter/dialogs/projdetails.py | 7 +- novelwriter/dialogs/projsettings.py | 10 +- novelwriter/gui/sidebar.py | 2 +- novelwriter/tools/build.py | 30 +- novelwriter/tools/lipsum.py | 4 +- novelwriter/tools/projwizard.py | 10 +- novelwriter/tools/writingstats.py | 14 +- 16 files changed, 677 insertions(+), 554 deletions(-) delete mode 100644 novelwriter/custom.py create mode 100644 novelwriter/custom/__init__.py create mode 100644 novelwriter/custom/configlayout.py create mode 100644 novelwriter/custom/pageddialog.py create mode 100644 novelwriter/custom/pagedsidebar.py create mode 100644 novelwriter/custom/switch.py diff --git a/novelwriter/custom.py b/novelwriter/custom.py deleted file mode 100644 index 8c766733..00000000 --- a/novelwriter/custom.py +++ /dev/null @@ -1,475 +0,0 @@ -""" -novelWriter – Custom Widgets and Layouts -======================================== -Various custom widget and layout classes - -File History: -Created: 2020-05-03 [0.4.5] QConfigLayout -Created: 2020-05-03 [0.4.5] QSwitch -Created: 2020-05-17 [0.5.1] PagedDialog - -This file is a part of novelWriter -Copyright 2018–2023, 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 . -""" - -import logging -import novelwriter - -from PyQt5.QtGui import QColor, QPalette, QPainter -from PyQt5.QtCore import ( - Qt, QRect, QPoint, QRectF, QPropertyAnimation, pyqtProperty -) -from PyQt5.QtWidgets import ( - QGridLayout, QLabel, QWidget, QVBoxLayout, QHBoxLayout, QSizePolicy, - QAbstractButton, QDialog, QTabWidget, QTabBar, QStyle, QStylePainter, - QStyleOptionTab, QLineEdit -) - -from novelwriter.constants import nwUnicode - -logger = logging.getLogger(__name__) - - -# =============================================================================================== # -# Config Form Layout -# =============================================================================================== # - -class QConfigLayout(QGridLayout): - - def __init__(self): - super().__init__() - - self._nextRow = 0 - self._helpCol = QColor(0, 0, 0) - self._fontScale = 0.9 - - self._itemMap = {} - - wSp = novelwriter.CONFIG.pxInt(8) - self.setHorizontalSpacing(wSp) - self.setVerticalSpacing(wSp) - self.setColumnStretch(0, 1) - - return - - ## - # Getters and Setters - ## - - def setHelpTextStyle(self, helpCol, fontScale=0.9): - """Set the text color for the help text. - """ - if isinstance(helpCol, QColor): - self._helpCol = helpCol - else: - self._helpCol = QColor(*helpCol) - self._fontScale = fontScale - return - - def setHelpText(self, intRow, theText): - """Set the text for the help label. - """ - if intRow in self._itemMap: - self._itemMap[intRow]["help"].setText(theText) - return - - def setLabelText(self, intRow, theText): - """Set the text for the main label. - """ - if intRow in self._itemMap: - self._itemMap[intRow]["label"].setText(theText) - return - - ## - # Class Methods - ## - - def addGroupLabel(self, theLabel): - """Adds a text label to separate groups of settings. - """ - if isinstance(theLabel, QLabel): - qLabel = theLabel - elif isinstance(theLabel, str): - qLabel = QLabel("%s" % theLabel) - else: - qLabel = None - raise ValueError("theLabel must be a QLabel") - - hM = novelwriter.CONFIG.pxInt(4) - qLabel.setContentsMargins(0, hM, 0, hM) - self.addWidget(qLabel, self._nextRow, 0, 1, 2, Qt.AlignLeft) - - self.setRowStretch(self._nextRow, 0) - self.setRowStretch(self._nextRow + 1, 1) - - self._nextRow += 1 - - return - - def addRow(self, theLabel, theWidget, helpText=None, theUnit=None, theButton=None): - """Add a label and a widget as a new row of the grid. - """ - thisEntry = { - "label": None, - "help": None, - "widget": None, - } - - if isinstance(theLabel, QLabel): - qLabel = theLabel - elif isinstance(theLabel, str): - qLabel = QLabel(theLabel) - else: - qLabel = None - raise ValueError("theLabel must be a QLabel") - - if isinstance(theWidget, QWidget): - qWidget = theWidget - else: - qWidget = None - raise ValueError("theWidget must be a QWidget") - - wSp = novelwriter.CONFIG.pxInt(8) - qLabel.setIndent(wSp) - if helpText is not None: - qHelp = QHelpLabel(str(helpText), self._helpCol, self._fontScale) - qHelp.setIndent(wSp) - - labelBox = QVBoxLayout() - labelBox.addWidget(qLabel) - labelBox.addWidget(qHelp) - labelBox.setSpacing(0) - labelBox.addStretch(1) - - thisEntry["help"] = qHelp - self.addLayout(labelBox, self._nextRow, 0, 1, 1, Qt.AlignLeft | Qt.AlignTop) - - else: - self.addWidget(qLabel, self._nextRow, 0, 1, 1, Qt.AlignLeft | Qt.AlignTop) - - if theUnit is not None: - controlBox = QHBoxLayout() - controlBox.addWidget(qWidget, 0, Qt.AlignVCenter) - controlBox.addWidget(QLabel(theUnit), 0, Qt.AlignVCenter) - controlBox.setSpacing(wSp) - self.addLayout(controlBox, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) - - elif theButton is not None: - controlBox = QHBoxLayout() - controlBox.addWidget(qWidget, 0, Qt.AlignVCenter) - controlBox.addWidget(theButton, 0, Qt.AlignVCenter) - controlBox.setSpacing(wSp) - self.addLayout(controlBox, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) - - else: - if isinstance(theWidget, QLineEdit): - qLayout = QHBoxLayout() - qLayout.addWidget(theWidget) - self.addLayout(qLayout, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) - else: - self.addWidget(qWidget, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) - - qLabel.setBuddy(qWidget) - - self.setRowStretch(self._nextRow, 0) - self.setRowStretch(self._nextRow+1, 1) - - thisEntry["label"] = qLabel - thisEntry["widget"] = qWidget - - self._itemMap[self._nextRow] = thisEntry - - self._nextRow += 1 - - return self._nextRow - 1 - -# END Class QConfigLayout - - -class QHelpLabel(QLabel): - - def __init__(self, theText, textCol, fontSize=0.9): - super().__init__(theText) - - if isinstance(textCol, QColor): - qCol = textCol - else: - qCol = QColor(*textCol) - - lblCol = self.palette() - lblCol.setColor(QPalette.WindowText, qCol) - self.setPalette(lblCol) - - lblFont = self.font() - lblFont.setPointSizeF(fontSize*lblFont.pointSizeF()) - self.setFont(lblFont) - - self.setWordWrap(True) - self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - - return - -# END Class QHelpLabel - - -# =============================================================================================== # -# Switch Widget -# =============================================================================================== # - -class QSwitch(QAbstractButton): - - def __init__(self, parent=None, width=None, height=None): - super().__init__(parent=parent) - - if width is None: - self._xW = novelwriter.CONFIG.pxInt(40) - else: - self._xW = width - - if height is None: - self._xH = novelwriter.CONFIG.pxInt(20) - else: - self._xH = height - - self._xR = int(self._xH*0.5) - self._xT = int(self._xH*0.6) - self._rB = int(novelwriter.CONFIG.guiScale*2) - self._rH = self._xH - 2*self._rB - self._rR = self._xR - self._rB - - self.setCheckable(True) - self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) - self.setFixedWidth(self._xW) - self.setFixedHeight(self._xH) - self._offset = self._xR - - return - - ## - # Properties - ## - - @pyqtProperty(int) - def offset(self): - return self._offset - - @offset.setter - def offset(self, offset): - self._offset = offset - self.update() - return - - ## - # Getters and Setters - ## - - def setChecked(self, checked): - """Overload setChecked to also alter the offset. - """ - super().setChecked(checked) - if checked: - self.offset = self._xW - self._xR - else: - self.offset = self._xR - return - - ## - # Events - ## - - def resizeEvent(self, event): - """Overload resize to ensure correct offset. - """ - super().resizeEvent(event) - if self.isChecked(): - self.offset = self._xW - self._xR - else: - self.offset = self._xR - return - - def paintEvent(self, event): - """Drawing the switch itself. - """ - qPaint = QPainter(self) - qPaint.setRenderHint(QPainter.Antialiasing, True) - qPaint.setPen(Qt.NoPen) - - qPalette = self.palette() - if self.isChecked(): - trackBrush = qPalette.highlight() - thumbBrush = qPalette.highlightedText() - textColor = qPalette.highlight().color() - thumbText = nwUnicode.U_CHECK - else: - trackBrush = qPalette.dark() - thumbBrush = qPalette.light() - textColor = qPalette.dark().color() - thumbText = nwUnicode.U_CROSS - - if self.isEnabled(): - trackOpacity = 1.0 - else: - trackOpacity = 0.6 - trackBrush = qPalette.shadow() - thumbBrush = qPalette.mid() - textColor = qPalette.shadow().color() - - qPaint.setBrush(trackBrush) - qPaint.setOpacity(trackOpacity) - qPaint.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR) - - qPaint.setBrush(thumbBrush) - qPaint.drawEllipse(self.offset - self._rR, self._rB, self._rH, self._rH) - - theFont = qPaint.font() - theFont.setPixelSize(self._xT) - qPaint.setPen(textColor) - qPaint.setFont(theFont) - qPaint.drawText( - QRectF(self.offset - self._rR, self._rB, self._rH, self._rH), - Qt.AlignCenter, thumbText - ) - - return - - def mouseReleaseEvent(self, event): - """Animate the switch on mouse release. - """ - super().mouseReleaseEvent(event) - if event.button() == Qt.LeftButton: - doAnim = QPropertyAnimation(self, b"offset", self) - doAnim.setDuration(120) - doAnim.setStartValue(self.offset) - if self.isChecked(): - doAnim.setEndValue(self._xW - self._xR) - else: - doAnim.setEndValue(self._xR) - doAnim.start() - return - - def enterEvent(self, event): - """Change the cursor when hovering the button. - """ - self.setCursor(Qt.PointingHandCursor) - super().enterEvent(event) - return - -# END Class QSwitch - - -# =============================================================================================== # -# Paged Dialog w/Custom TabWidget -# =============================================================================================== # - -class PagedDialog(QDialog): - - def __init__(self, parent=None): - super().__init__(parent=parent) - - self._tabBar = VerticalTabBar(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, label): - """Forward the adding of tabs to the QTabWidget. - """ - self._tabBox.addTab(widget, label) - return - - def addControls(self, buttonBar): - """Add a button bar to the dialog. - """ - self._buttonBox.addWidget(buttonBar) - return - - def setCurrentWidget(self, widget): - """Forward the changing of tab to the QTabWidget. - """ - self._tabBox.setCurrentWidget(widget) - return - -# END Class PagedDialog - - -class VerticalTabBar(QTabBar): - - def __init__(self, parent=None): - super().__init__(parent=parent) - self._mW = novelwriter.CONFIG.pxInt(150) - return - - def tabSizeHint(self, index): - """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): - """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 VerticalTabBar diff --git a/novelwriter/custom/__init__.py b/novelwriter/custom/__init__.py new file mode 100644 index 00000000..6e4c5a4e --- /dev/null +++ b/novelwriter/custom/__init__.py @@ -0,0 +1,3 @@ +""" +novelWriter – Custom Layouts and Widgets +""" diff --git a/novelwriter/custom/configlayout.py b/novelwriter/custom/configlayout.py new file mode 100644 index 00000000..8eadae62 --- /dev/null +++ b/novelwriter/custom/configlayout.py @@ -0,0 +1,214 @@ +""" +novelWriter – Custom Widget: Config Layout +========================================== +A custom grid layout for config pages + +File History: +Created: 2020-05-03 [0.4.5] + +This file is a part of novelWriter +Copyright 2018–2023, 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 . +""" + +import logging +import novelwriter + +from PyQt5.QtGui import QColor, QPalette +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import ( + QGridLayout, QHBoxLayout, QLabel, QLineEdit, QSizePolicy, QVBoxLayout, + QWidget +) + +logger = logging.getLogger(__name__) + + +class NConfigLayout(QGridLayout): + + def __init__(self): + super().__init__() + + self._nextRow = 0 + self._helpCol = QColor(0, 0, 0) + self._fontScale = 0.9 + + self._itemMap = {} + + wSp = novelwriter.CONFIG.pxInt(8) + self.setHorizontalSpacing(wSp) + self.setVerticalSpacing(wSp) + self.setColumnStretch(0, 1) + + return + + ## + # Getters and Setters + ## + + def setHelpTextStyle(self, helpCol, fontScale=0.9): + """Set the text color for the help text. + """ + if isinstance(helpCol, QColor): + self._helpCol = helpCol + else: + self._helpCol = QColor(*helpCol) + self._fontScale = fontScale + return + + def setHelpText(self, intRow, theText): + """Set the text for the help label. + """ + if intRow in self._itemMap: + self._itemMap[intRow]["help"].setText(theText) + return + + def setLabelText(self, intRow, theText): + """Set the text for the main label. + """ + if intRow in self._itemMap: + self._itemMap[intRow]["label"].setText(theText) + return + + ## + # Class Methods + ## + + def addGroupLabel(self, theLabel): + """Adds a text label to separate groups of settings. + """ + if isinstance(theLabel, QLabel): + qLabel = theLabel + elif isinstance(theLabel, str): + qLabel = QLabel("%s" % theLabel) + else: + qLabel = None + raise ValueError("theLabel must be a QLabel") + + hM = novelwriter.CONFIG.pxInt(4) + qLabel.setContentsMargins(0, hM, 0, hM) + self.addWidget(qLabel, self._nextRow, 0, 1, 2, Qt.AlignLeft) + + self.setRowStretch(self._nextRow, 0) + self.setRowStretch(self._nextRow + 1, 1) + + self._nextRow += 1 + + return + + def addRow(self, theLabel, theWidget, helpText=None, theUnit=None, theButton=None): + """Add a label and a widget as a new row of the grid. + """ + thisEntry = { + "label": None, + "help": None, + "widget": None, + } + + if isinstance(theLabel, QLabel): + qLabel = theLabel + elif isinstance(theLabel, str): + qLabel = QLabel(theLabel) + else: + qLabel = None + raise ValueError("theLabel must be a QLabel") + + if isinstance(theWidget, QWidget): + qWidget = theWidget + else: + qWidget = None + raise ValueError("theWidget must be a QWidget") + + wSp = novelwriter.CONFIG.pxInt(8) + qLabel.setIndent(wSp) + if helpText is not None: + qHelp = NHelpLabel(str(helpText), self._helpCol, self._fontScale) + qHelp.setIndent(wSp) + + labelBox = QVBoxLayout() + labelBox.addWidget(qLabel) + labelBox.addWidget(qHelp) + labelBox.setSpacing(0) + labelBox.addStretch(1) + + thisEntry["help"] = qHelp + self.addLayout(labelBox, self._nextRow, 0, 1, 1, Qt.AlignLeft | Qt.AlignTop) + + else: + self.addWidget(qLabel, self._nextRow, 0, 1, 1, Qt.AlignLeft | Qt.AlignTop) + + if theUnit is not None: + controlBox = QHBoxLayout() + controlBox.addWidget(qWidget, 0, Qt.AlignVCenter) + controlBox.addWidget(QLabel(theUnit), 0, Qt.AlignVCenter) + controlBox.setSpacing(wSp) + self.addLayout(controlBox, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) + + elif theButton is not None: + controlBox = QHBoxLayout() + controlBox.addWidget(qWidget, 0, Qt.AlignVCenter) + controlBox.addWidget(theButton, 0, Qt.AlignVCenter) + controlBox.setSpacing(wSp) + self.addLayout(controlBox, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) + + else: + if isinstance(theWidget, QLineEdit): + qLayout = QHBoxLayout() + qLayout.addWidget(theWidget) + self.addLayout(qLayout, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) + else: + self.addWidget(qWidget, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignTop) + + qLabel.setBuddy(qWidget) + + self.setRowStretch(self._nextRow, 0) + self.setRowStretch(self._nextRow+1, 1) + + thisEntry["label"] = qLabel + thisEntry["widget"] = qWidget + + self._itemMap[self._nextRow] = thisEntry + + self._nextRow += 1 + + return self._nextRow - 1 + +# END Class NConfigLayout + + +class NHelpLabel(QLabel): + + def __init__(self, theText, textCol, fontSize=0.9): + super().__init__(theText) + + if isinstance(textCol, QColor): + qCol = textCol + else: + qCol = QColor(*textCol) + + lblCol = self.palette() + lblCol.setColor(QPalette.WindowText, qCol) + self.setPalette(lblCol) + + lblFont = self.font() + lblFont.setPointSizeF(fontSize*lblFont.pointSizeF()) + self.setFont(lblFont) + + self.setWordWrap(True) + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + + return + +# END Class NHelpLabel diff --git a/novelwriter/custom/pageddialog.py b/novelwriter/custom/pageddialog.py new file mode 100644 index 00000000..47f957fb --- /dev/null +++ b/novelwriter/custom/pageddialog.py @@ -0,0 +1,136 @@ +""" +novelWriter – Custom Widget: Paged Dialog +========================================= +A custom dialog with tabs and a vertical tab bar + +File History: +Created: 2020-05-17 [0.5.1] + +This file is a part of novelWriter +Copyright 2018–2023, 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 . +""" + +import logging +import novelwriter + +from PyQt5.QtCore import QRect, QPoint +from PyQt5.QtWidgets import ( + QDialog, QHBoxLayout, QStyle, QStyleOptionTab, QStylePainter, QTabBar, + QTabWidget, QVBoxLayout +) + +logger = logging.getLogger(__name__) + + +class NPagedDialog(QDialog): + + def __init__(self, parent=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, label): + """Forward the adding of tabs to the QTabWidget. + """ + self._tabBox.addTab(widget, label) + return + + def addControls(self, buttonBar): + """Add a button bar to the dialog. + """ + self._buttonBox.addWidget(buttonBar) + return + + def setCurrentWidget(self, widget): + """Forward the changing of tab to the QTabWidget. + """ + self._tabBox.setCurrentWidget(widget) + return + +# END Class NPagedDialog + + +class NVerticalTabBar(QTabBar): + + def __init__(self, parent=None): + super().__init__(parent=parent) + self._mW = novelwriter.CONFIG.pxInt(150) + return + + def tabSizeHint(self, index): + """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): + """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 diff --git a/novelwriter/custom/pagedsidebar.py b/novelwriter/custom/pagedsidebar.py new file mode 100644 index 00000000..485d71a7 --- /dev/null +++ b/novelwriter/custom/pagedsidebar.py @@ -0,0 +1,62 @@ +""" +novelWriter – Custom Widget: Paged SideBar +========================================== +A custom widget for making a sidebar for flipping through pages + +File History: +Created: 2023-02-21 [2.1b1] NPagedSideBar +Created: 2023-02-21 [2.1b1] NToolLabelButton + +This file is a part of novelWriter +Copyright 2018–2023, 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 . +""" + +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QToolBar, QToolButton + + +class NPagedSideBar(QToolBar): + + def __init__(self, parent): + super().__init__(parent=parent) + + self._buttons = [] + + self.setMovable(False) + self.setOrientation(Qt.Vertical) + + return + + def addLabel(self, text): + """Add a new label to the toolbar. + """ + return + + def addButton(self, text): + """Add a new button to the toolbar. + """ + return + +# END Class NPagedSideBar + + +class NToolLabelButton(QToolButton): + + def __init__(self, parent): + super().__init__(parent=parent) + return + +# END Class NToolLabelButton diff --git a/novelwriter/custom/switch.py b/novelwriter/custom/switch.py new file mode 100644 index 00000000..d57f07b2 --- /dev/null +++ b/novelwriter/custom/switch.py @@ -0,0 +1,176 @@ +""" +novelWriter – Custom Widget: Switch +=================================== +A custom switch widget + +File History: +Created: 2020-05-03 [0.4.5] + +This file is a part of novelWriter +Copyright 2018–2023, 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 . +""" + +import logging +import novelwriter + +from PyQt5.QtGui import QPainter +from PyQt5.QtCore import Qt, QRectF, QPropertyAnimation, pyqtProperty +from PyQt5.QtWidgets import QSizePolicy, QAbstractButton + +from novelwriter.constants import nwUnicode + +logger = logging.getLogger(__name__) + + +class NSwitch(QAbstractButton): + + def __init__(self, parent=None, width=None, height=None): + super().__init__(parent=parent) + + if width is None: + self._xW = novelwriter.CONFIG.pxInt(40) + else: + self._xW = width + + if height is None: + self._xH = novelwriter.CONFIG.pxInt(20) + else: + self._xH = height + + self._xR = int(self._xH*0.5) + self._xT = int(self._xH*0.6) + self._rB = int(novelwriter.CONFIG.guiScale*2) + self._rH = self._xH - 2*self._rB + self._rR = self._xR - self._rB + + self.setCheckable(True) + self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.setFixedWidth(self._xW) + self.setFixedHeight(self._xH) + self._offset = self._xR + + return + + ## + # Properties + ## + + @pyqtProperty(int) + def offset(self): + return self._offset + + @offset.setter + def offset(self, offset): + self._offset = offset + self.update() + return + + ## + # Getters and Setters + ## + + def setChecked(self, checked): + """Overload setChecked to also alter the offset. + """ + super().setChecked(checked) + if checked: + self.offset = self._xW - self._xR + else: + self.offset = self._xR + return + + ## + # Events + ## + + def resizeEvent(self, event): + """Overload resize to ensure correct offset. + """ + super().resizeEvent(event) + if self.isChecked(): + self.offset = self._xW - self._xR + else: + self.offset = self._xR + return + + def paintEvent(self, event): + """Drawing the switch itself. + """ + qPaint = QPainter(self) + qPaint.setRenderHint(QPainter.Antialiasing, True) + qPaint.setPen(Qt.NoPen) + + qPalette = self.palette() + if self.isChecked(): + trackBrush = qPalette.highlight() + thumbBrush = qPalette.highlightedText() + textColor = qPalette.highlight().color() + thumbText = nwUnicode.U_CHECK + else: + trackBrush = qPalette.dark() + thumbBrush = qPalette.light() + textColor = qPalette.dark().color() + thumbText = nwUnicode.U_CROSS + + if self.isEnabled(): + trackOpacity = 1.0 + else: + trackOpacity = 0.6 + trackBrush = qPalette.shadow() + thumbBrush = qPalette.mid() + textColor = qPalette.shadow().color() + + qPaint.setBrush(trackBrush) + qPaint.setOpacity(trackOpacity) + qPaint.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR) + + qPaint.setBrush(thumbBrush) + qPaint.drawEllipse(self.offset - self._rR, self._rB, self._rH, self._rH) + + theFont = qPaint.font() + theFont.setPixelSize(self._xT) + qPaint.setPen(textColor) + qPaint.setFont(theFont) + qPaint.drawText( + QRectF(self.offset - self._rR, self._rB, self._rH, self._rH), + Qt.AlignCenter, thumbText + ) + + return + + def mouseReleaseEvent(self, event): + """Animate the switch on mouse release. + """ + super().mouseReleaseEvent(event) + if event.button() == Qt.LeftButton: + doAnim = QPropertyAnimation(self, b"offset", self) + doAnim.setDuration(120) + doAnim.setStartValue(self.offset) + if self.isChecked(): + doAnim.setEndValue(self._xW - self._xR) + else: + doAnim.setEndValue(self._xR) + doAnim.start() + return + + def enterEvent(self, event): + """Change the cursor when hovering the button. + """ + self.setCursor(Qt.PointingHandCursor) + super().enterEvent(event) + return + +# END Class NSwitch diff --git a/novelwriter/dialogs/docmerge.py b/novelwriter/dialogs/docmerge.py index 25c8676f..30e42345 100644 --- a/novelwriter/dialogs/docmerge.py +++ b/novelwriter/dialogs/docmerge.py @@ -33,7 +33,8 @@ from PyQt5.QtWidgets import ( QListWidget, QListWidgetItem, QVBoxLayout, ) -from novelwriter.custom import QHelpLabel, QSwitch +from novelwriter.custom.switch import NSwitch +from novelwriter.custom.configlayout import NHelpLabel logger = logging.getLogger(__name__) @@ -56,7 +57,7 @@ class GuiDocMerge(QDialog): self.setWindowTitle(self.tr("Merge Documents")) self.headLabel = QLabel("{0}".format(self.tr("Documents to Merge"))) - self.helpLabel = QHelpLabel(self.tr( + self.helpLabel = NHelpLabel(self.tr( "Drag and drop items to change the order, or uncheck to exclude." ), self.mainTheme.helpText) @@ -75,7 +76,7 @@ class GuiDocMerge(QDialog): # Merge Options self.trashLabel = QLabel(self.tr("Move merged items to Trash")) - self.trashSwitch = QSwitch(width=2*iPx, height=iPx) + self.trashSwitch = NSwitch(width=2*iPx, height=iPx) self.optBox = QGridLayout() self.optBox.addWidget(self.trashLabel, 0, 0) diff --git a/novelwriter/dialogs/docsplit.py b/novelwriter/dialogs/docsplit.py index 0db6d6c2..6e534390 100644 --- a/novelwriter/dialogs/docsplit.py +++ b/novelwriter/dialogs/docsplit.py @@ -33,7 +33,8 @@ from PyQt5.QtWidgets import ( QListWidgetItem, QDialogButtonBox, QLabel, QGridLayout ) -from novelwriter.custom import QHelpLabel, QSwitch +from novelwriter.custom.switch import NSwitch +from novelwriter.custom.configlayout import NHelpLabel logger = logging.getLogger(__name__) @@ -61,7 +62,7 @@ class GuiDocSplit(QDialog): self.setWindowTitle(self.tr("Split Document")) self.headLabel = QLabel("{0}".format(self.tr("Document Headers"))) - self.helpLabel = QHelpLabel( + self.helpLabel = NHelpLabel( self.tr("Select the maximum level to split into files."), self.mainGui.mainTheme.helpText ) @@ -95,15 +96,15 @@ class GuiDocSplit(QDialog): # Split Options self.folderLabel = QLabel(self.tr("Split into a new folder")) - self.folderSwitch = QSwitch(width=2*iPx, height=iPx) + self.folderSwitch = NSwitch(width=2*iPx, height=iPx) self.folderSwitch.setChecked(intoFolder) self.hierarchyLabel = QLabel(self.tr("Create document hierarchy")) - self.hierarchySwitch = QSwitch(width=2*iPx, height=iPx) + self.hierarchySwitch = NSwitch(width=2*iPx, height=iPx) self.hierarchySwitch.setChecked(docHierarchy) self.trashLabel = QLabel(self.tr("Move split document to Trash")) - self.trashSwitch = QSwitch(width=2*iPx, height=iPx) + self.trashSwitch = NSwitch(width=2*iPx, height=iPx) self.optBox = QGridLayout() self.optBox.addWidget(self.folderLabel, 0, 0) diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index 41f4a032..fff952ad 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -33,13 +33,15 @@ from PyQt5.QtWidgets import ( QLineEdit, QFileDialog, QFontDialog, QDoubleSpinBox ) -from novelwriter.custom import QSwitch, QConfigLayout, PagedDialog +from novelwriter.custom.switch import NSwitch +from novelwriter.custom.pageddialog import NPagedDialog +from novelwriter.custom.configlayout import NConfigLayout from novelwriter.dialogs.quotes import GuiQuoteSelect logger = logging.getLogger(__name__) -class GuiPreferences(PagedDialog): +class GuiPreferences(NPagedDialog): def __init__(self, mainGui): super().__init__(parent=mainGui) @@ -161,7 +163,7 @@ class GuiPreferencesGeneral(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) @@ -250,7 +252,7 @@ class GuiPreferencesGeneral(QWidget): # ============ self.mainForm.addGroupLabel(self.tr("GUI Settings")) - self.emphLabels = QSwitch() + self.emphLabels = NSwitch() self.emphLabels.setChecked(self.mainConf.emphLabels) self.mainForm.addRow( self.tr("Emphasise partition and chapter labels"), @@ -258,7 +260,7 @@ class GuiPreferencesGeneral(QWidget): self.tr("Makes them stand out in the project tree."), ) - self.showFullPath = QSwitch() + self.showFullPath = NSwitch() self.showFullPath.setChecked(self.mainConf.showFullPath) self.mainForm.addRow( self.tr("Show full path in document header"), @@ -266,7 +268,7 @@ class GuiPreferencesGeneral(QWidget): self.tr("Add the parent folder names to the header.") ) - self.hideVScroll = QSwitch() + self.hideVScroll = NSwitch() self.hideVScroll.setChecked(self.mainConf.hideVScroll) self.mainForm.addRow( self.tr("Hide vertical scroll bars in main windows"), @@ -274,7 +276,7 @@ class GuiPreferencesGeneral(QWidget): self.tr("Scrolling available with mouse wheel and keys only.") ) - self.hideHScroll = QSwitch() + self.hideHScroll = NSwitch() self.hideHScroll.setChecked(self.mainConf.hideHScroll) self.mainForm.addRow( self.tr("Hide horizontal scroll bars in main windows"), @@ -343,7 +345,7 @@ class GuiPreferencesProjects(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) @@ -392,7 +394,7 @@ class GuiPreferencesProjects(QWidget): ) # Run when closing - self.backupOnClose = QSwitch() + self.backupOnClose = NSwitch() self.backupOnClose.setChecked(self.mainConf.backupOnClose) self.backupOnClose.toggled.connect(self._toggledBackupOnClose) self.mainForm.addRow( @@ -403,7 +405,7 @@ class GuiPreferencesProjects(QWidget): # Ask before backup # Only enabled when "Run when closing" is checked - self.askBeforeBackup = QSwitch() + self.askBeforeBackup = NSwitch() self.askBeforeBackup.setChecked(self.mainConf.askBeforeBackup) self.askBeforeBackup.setEnabled(self.mainConf.backupOnClose) self.mainForm.addRow( @@ -417,7 +419,7 @@ class GuiPreferencesProjects(QWidget): self.mainForm.addGroupLabel(self.tr("Session Timer")) # Pause when idle - self.stopWhenIdle = QSwitch() + self.stopWhenIdle = NSwitch() self.stopWhenIdle.setChecked(self.mainConf.stopWhenIdle) self.mainForm.addRow( self.tr("Pause the session timer when not writing"), @@ -499,7 +501,7 @@ class GuiPreferencesDocuments(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) @@ -566,7 +568,7 @@ class GuiPreferencesDocuments(QWidget): ) # Focus Mode Footer - self.hideFocusFooter = QSwitch() + self.hideFocusFooter = NSwitch() self.hideFocusFooter.setChecked(self.mainConf.hideFocusFooter) self.mainForm.addRow( self.tr("Hide document footer in \"Focus Mode\""), @@ -575,7 +577,7 @@ class GuiPreferencesDocuments(QWidget): ) # Justify Text - self.doJustify = QSwitch() + self.doJustify = NSwitch() self.doJustify.setChecked(self.mainConf.doJustify) self.mainForm.addRow( self.tr("Justify the text margins"), @@ -658,7 +660,7 @@ class GuiPreferencesEditor(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) @@ -727,7 +729,7 @@ class GuiPreferencesEditor(QWidget): ) # Include Notes in Word Count - self.incNotesWCount = QSwitch() + self.incNotesWCount = NSwitch() self.incNotesWCount.setChecked(self.mainConf.incNotesWCount) self.mainForm.addRow( self.tr("Include project notes in status bar word count"), @@ -739,7 +741,7 @@ class GuiPreferencesEditor(QWidget): self.mainForm.addGroupLabel(self.tr("Writing Guides")) # Show Tabs and Spaces - self.showTabsNSpaces = QSwitch() + self.showTabsNSpaces = NSwitch() self.showTabsNSpaces.setChecked(self.mainConf.showTabsNSpaces) self.mainForm.addRow( self.tr("Show tabs and spaces"), @@ -747,7 +749,7 @@ class GuiPreferencesEditor(QWidget): ) # Show Line Endings - self.showLineEndings = QSwitch() + self.showLineEndings = NSwitch() self.showLineEndings.setChecked(self.mainConf.showLineEndings) self.mainForm.addRow( self.tr("Show line endings"), @@ -772,7 +774,7 @@ class GuiPreferencesEditor(QWidget): ) # Typewriter Scrolling - self.autoScroll = QSwitch() + self.autoScroll = NSwitch() self.autoScroll.setChecked(self.mainConf.autoScroll) self.mainForm.addRow( self.tr("Typewriter style scrolling when you type"), @@ -831,7 +833,7 @@ class GuiPreferencesSyntax(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) @@ -839,7 +841,7 @@ class GuiPreferencesSyntax(QWidget): # ================= self.mainForm.addGroupLabel(self.tr("Quotes & Dialogue")) - self.highlightQuotes = QSwitch() + self.highlightQuotes = NSwitch() self.highlightQuotes.setChecked(self.mainConf.highlightQuotes) self.highlightQuotes.toggled.connect(self._toggleHighlightQuotes) self.mainForm.addRow( @@ -848,7 +850,7 @@ class GuiPreferencesSyntax(QWidget): self.tr("Applies to the document editor only.") ) - self.allowOpenSQuote = QSwitch() + self.allowOpenSQuote = NSwitch() self.allowOpenSQuote.setChecked(self.mainConf.allowOpenSQuote) self.mainForm.addRow( self.tr("Allow open-ended single quotes"), @@ -856,7 +858,7 @@ class GuiPreferencesSyntax(QWidget): self.tr("Highlight single-quoted line with no closing quote.") ) - self.allowOpenDQuote = QSwitch() + self.allowOpenDQuote = NSwitch() self.allowOpenDQuote.setChecked(self.mainConf.allowOpenDQuote) self.mainForm.addRow( self.tr("Allow open-ended double quotes"), @@ -868,7 +870,7 @@ class GuiPreferencesSyntax(QWidget): # ============= self.mainForm.addGroupLabel(self.tr("Text Emphasis")) - self.highlightEmph = QSwitch() + self.highlightEmph = NSwitch() self.highlightEmph.setChecked(self.mainConf.highlightEmph) self.mainForm.addRow( self.tr("Add highlight colour to emphasised text"), @@ -881,7 +883,7 @@ class GuiPreferencesSyntax(QWidget): self.mainForm.addGroupLabel(self.tr("Text Errors")) - self.showMultiSpaces = QSwitch() + self.showMultiSpaces = NSwitch() self.showMultiSpaces.setChecked(self.mainConf.showMultiSpaces) self.mainForm.addRow( self.tr("Highlight multiple or trailing spaces"), @@ -937,7 +939,7 @@ class GuiPreferencesAutomation(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) @@ -946,7 +948,7 @@ class GuiPreferencesAutomation(QWidget): self.mainForm.addGroupLabel(self.tr("Automatic Features")) # Auto-Select Word Under Cursor - self.autoSelect = QSwitch() + self.autoSelect = NSwitch() self.autoSelect.setChecked(self.mainConf.autoSelect) self.mainForm.addRow( self.tr("Auto-select word under cursor"), @@ -955,7 +957,7 @@ class GuiPreferencesAutomation(QWidget): ) # Auto-Replace as You Type Main Switch - self.doReplace = QSwitch() + self.doReplace = NSwitch() self.doReplace.setChecked(self.mainConf.doReplace) self.doReplace.toggled.connect(self._toggleAutoReplaceMain) self.mainForm.addRow( @@ -969,7 +971,7 @@ class GuiPreferencesAutomation(QWidget): self.mainForm.addGroupLabel(self.tr("Replace as You Type")) # Auto-Replace Single Quotes - self.doReplaceSQuote = QSwitch() + self.doReplaceSQuote = NSwitch() self.doReplaceSQuote.setChecked(self.mainConf.doReplaceSQuote) self.doReplaceSQuote.setEnabled(self.mainConf.doReplace) self.mainForm.addRow( @@ -979,7 +981,7 @@ class GuiPreferencesAutomation(QWidget): ) # Auto-Replace Double Quotes - self.doReplaceDQuote = QSwitch() + self.doReplaceDQuote = NSwitch() self.doReplaceDQuote.setChecked(self.mainConf.doReplaceDQuote) self.doReplaceDQuote.setEnabled(self.mainConf.doReplace) self.mainForm.addRow( @@ -989,7 +991,7 @@ class GuiPreferencesAutomation(QWidget): ) # Auto-Replace Hyphens - self.doReplaceDash = QSwitch() + self.doReplaceDash = NSwitch() self.doReplaceDash.setChecked(self.mainConf.doReplaceDash) self.doReplaceDash.setEnabled(self.mainConf.doReplace) self.mainForm.addRow( @@ -999,7 +1001,7 @@ class GuiPreferencesAutomation(QWidget): ) # Auto-Replace Dots - self.doReplaceDots = QSwitch() + self.doReplaceDots = NSwitch() self.doReplaceDots.setChecked(self.mainConf.doReplaceDots) self.doReplaceDots.setEnabled(self.mainConf.doReplace) self.mainForm.addRow( @@ -1033,7 +1035,7 @@ class GuiPreferencesAutomation(QWidget): ) # Use Thin Space - self.fmtPadThin = QSwitch() + self.fmtPadThin = NSwitch() self.fmtPadThin.setChecked(self.mainConf.fmtPadThin) self.fmtPadThin.setEnabled(self.mainConf.doReplace) self.mainForm.addRow( @@ -1092,7 +1094,7 @@ class GuiPreferencesQuotes(QWidget): self.mainTheme = prefsGui.mainGui.mainTheme # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainTheme.helpText) self.setLayout(self.mainForm) diff --git a/novelwriter/dialogs/projdetails.py b/novelwriter/dialogs/projdetails.py index 35d52345..02a31478 100644 --- a/novelwriter/dialogs/projdetails.py +++ b/novelwriter/dialogs/projdetails.py @@ -35,14 +35,15 @@ from PyQt5.QtWidgets import ( ) from novelwriter.common import formatTime, numberToRoman -from novelwriter.custom import PagedDialog, QSwitch from novelwriter.constants import nwUnicode +from novelwriter.custom.switch import NSwitch +from novelwriter.custom.pageddialog import NPagedDialog from novelwriter.gui.components import NovelSelector logger = logging.getLogger(__name__) -class GuiProjectDetails(PagedDialog): +class GuiProjectDetails(NPagedDialog): def __init__(self, mainGui): super().__init__(parent=mainGui) @@ -386,7 +387,7 @@ class GuiProjectDetailsContents(QWidget): self.dblLabel = QLabel(self.tr("Clear double pages")) self.dblLabel.setToolTip(dblHelp) - self.dblValue = QSwitch(self, 2*iPx, iPx) + self.dblValue = NSwitch(self, 2*iPx, iPx) self.dblValue.setChecked(clearDouble) self.dblValue.setToolTip(dblHelp) self.dblValue.clicked.connect(self._populateTree) diff --git a/novelwriter/dialogs/projsettings.py b/novelwriter/dialogs/projsettings.py index 23fb28c5..b406701f 100644 --- a/novelwriter/dialogs/projsettings.py +++ b/novelwriter/dialogs/projsettings.py @@ -35,12 +35,14 @@ from PyQt5.QtWidgets import ( from novelwriter.enum import nwAlert from novelwriter.common import simplified -from novelwriter.custom import QSwitch, PagedDialog, QConfigLayout +from novelwriter.custom.switch import NSwitch +from novelwriter.custom.pageddialog import NPagedDialog +from novelwriter.custom.configlayout import NConfigLayout logger = logging.getLogger(__name__) -class GuiProjectSettings(PagedDialog): +class GuiProjectSettings(NPagedDialog): TAB_MAIN = 0 TAB_STATUS = 1 @@ -196,7 +198,7 @@ class GuiProjectEditMain(QWidget): self.theProject = projGui.theProject # The Form - self.mainForm = QConfigLayout() + self.mainForm = NConfigLayout() self.mainForm.setHelpTextStyle(self.mainGui.mainTheme.helpText) self.setLayout(self.mainForm) @@ -255,7 +257,7 @@ class GuiProjectEditMain(QWidget): if spellIdx != -1: self.spellLang.setCurrentIndex(spellIdx) - self.doBackup = QSwitch(self) + self.doBackup = NSwitch(self) self.doBackup.setChecked(not self.theProject.data.doBackup) self.mainForm.addRow( self.tr("No backup on close"), diff --git a/novelwriter/gui/sidebar.py b/novelwriter/gui/sidebar.py index c27c8311..79ea27af 100644 --- a/novelwriter/gui/sidebar.py +++ b/novelwriter/gui/sidebar.py @@ -1,6 +1,6 @@ """ novelWriter – GUI Main Window SideBar -=========================================== +===================================== GUI class for the main window side bar File History: diff --git a/novelwriter/tools/build.py b/novelwriter/tools/build.py index f6f9ccd8..c1cdf291 100644 --- a/novelwriter/tools/build.py +++ b/novelwriter/tools/build.py @@ -46,11 +46,11 @@ from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog from novelwriter.enum import nwAlert, nwItemType, nwItemLayout, nwItemClass from novelwriter.error import formatException, logException from novelwriter.common import fuzzyTime, makeFileNameSafe -from novelwriter.custom import QSwitch from novelwriter.constants import nwConst, nwFiles from novelwriter.core.tomd import ToMarkdown from novelwriter.core.toodt import ToOdt from novelwriter.core.tohtml import ToHtml +from novelwriter.custom.switch import NSwitch logger = logging.getLogger(__name__) @@ -174,12 +174,12 @@ class GuiBuildNovel(QDialog): if langIdx != -1: self.buildLang.setCurrentIndex(langIdx) - self.hideScene = QSwitch(width=wS, height=hS) + self.hideScene = NSwitch(width=wS, height=hS) self.hideScene.setChecked( pOptions.getBool("GuiBuildNovel", "hideScene", False) ) - self.hideSection = QSwitch(width=wS, height=hS) + self.hideSection = NSwitch(width=wS, height=hS) self.hideSection.setChecked( pOptions.getBool("GuiBuildNovel", "hideSection", True) ) @@ -291,12 +291,12 @@ class GuiBuildNovel(QDialog): self.styleForm = QGridLayout(self) self.styleGroup.setLayout(self.styleForm) - self.justifyText = QSwitch(width=wS, height=hS) + self.justifyText = NSwitch(width=wS, height=hS) self.justifyText.setChecked( pOptions.getBool("GuiBuildNovel", "justifyText", False) ) - self.noStyling = QSwitch(width=wS, height=hS) + self.noStyling = NSwitch(width=wS, height=hS) self.noStyling.setChecked( pOptions.getBool("GuiBuildNovel", "noStyling", False) ) @@ -316,22 +316,22 @@ class GuiBuildNovel(QDialog): self.textForm = QGridLayout(self) self.textGroup.setLayout(self.textForm) - self.includeSynopsis = QSwitch(width=wS, height=hS) + self.includeSynopsis = NSwitch(width=wS, height=hS) self.includeSynopsis.setChecked( pOptions.getBool("GuiBuildNovel", "incSynopsis", False) ) - self.includeComments = QSwitch(width=wS, height=hS) + self.includeComments = NSwitch(width=wS, height=hS) self.includeComments.setChecked( pOptions.getBool("GuiBuildNovel", "incComments", False) ) - self.includeKeywords = QSwitch(width=wS, height=hS) + self.includeKeywords = NSwitch(width=wS, height=hS) self.includeKeywords.setChecked( pOptions.getBool("GuiBuildNovel", "incKeywords", False) ) - self.includeBody = QSwitch(width=wS, height=hS) + self.includeBody = NSwitch(width=wS, height=hS) self.includeBody.setChecked( pOptions.getBool("GuiBuildNovel", "incBodyText", True) ) @@ -371,7 +371,7 @@ class GuiBuildNovel(QDialog): rootLabel = QLabel(nwItem.itemName) rootLabel.setWordWrap(True) - rootValue = QSwitch(width=wS, height=hS) + rootValue = NSwitch(width=wS, height=hS) rootValue.setChecked(tHandle not in rootFilter) self.rootSelection[tHandle] = rootValue @@ -390,17 +390,17 @@ class GuiBuildNovel(QDialog): self.fileForm = QGridLayout(self) self.fileGroup.setLayout(self.fileForm) - self.novelFiles = QSwitch(width=wS, height=hS) + self.novelFiles = NSwitch(width=wS, height=hS) self.novelFiles.setChecked( pOptions.getBool("GuiBuildNovel", "addNovel", True) ) - self.noteFiles = QSwitch(width=wS, height=hS) + self.noteFiles = NSwitch(width=wS, height=hS) self.noteFiles.setChecked( pOptions.getBool("GuiBuildNovel", "addNotes", False) ) - self.ignoreFlag = QSwitch(width=wS, height=hS) + self.ignoreFlag = NSwitch(width=wS, height=hS) self.ignoreFlag.setChecked( pOptions.getBool("GuiBuildNovel", "ignoreFlag", False) ) @@ -426,12 +426,12 @@ class GuiBuildNovel(QDialog): self.exportForm = QGridLayout(self) self.exportGroup.setLayout(self.exportForm) - self.replaceTabs = QSwitch(width=wS, height=hS) + self.replaceTabs = NSwitch(width=wS, height=hS) self.replaceTabs.setChecked( pOptions.getBool("GuiBuildNovel", "replaceTabs", False) ) - self.replaceUCode = QSwitch(width=wS, height=hS) + self.replaceUCode = NSwitch(width=wS, height=hS) self.replaceUCode.setChecked( pOptions.getBool("GuiBuildNovel", "replaceUCode", False) ) diff --git a/novelwriter/tools/lipsum.py b/novelwriter/tools/lipsum.py index 9f0679c4..e4db9f66 100644 --- a/novelwriter/tools/lipsum.py +++ b/novelwriter/tools/lipsum.py @@ -34,7 +34,7 @@ from PyQt5.QtWidgets import ( ) from novelwriter.common import readTextFile -from novelwriter.custom import QSwitch +from novelwriter.custom.switch import NSwitch logger = logging.getLogger(__name__) @@ -78,7 +78,7 @@ class GuiLipsum(QDialog): self.paraCount.setValue(5) self.randLabel = QLabel(self.tr("Randomise order")) - self.randSwitch = QSwitch() + self.randSwitch = NSwitch() self.formBox = QGridLayout() self.formBox.addWidget(self.headLabel, 0, 0, 1, 2, Qt.AlignLeft) diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py index 3dee4861..8fdf2c8c 100644 --- a/novelwriter/tools/projwizard.py +++ b/novelwriter/tools/projwizard.py @@ -34,7 +34,7 @@ from PyQt5.QtWidgets import ( ) from novelwriter.common import makeFileNameSafe -from novelwriter.custom import QSwitch +from novelwriter.custom.switch import NSwitch logger = logging.getLogger(__name__) @@ -328,19 +328,19 @@ class ProjWizardCustomPage(QWizardPage): fS = self.mainConf.pxInt(4) # Root Folders - self.addPlot = QSwitch() + self.addPlot = NSwitch() self.addPlot.setChecked(True) self.addPlot.clicked.connect(self._syncSwitches) - self.addChar = QSwitch() + self.addChar = NSwitch() self.addChar.setChecked(True) self.addChar.clicked.connect(self._syncSwitches) - self.addWorld = QSwitch() + self.addWorld = NSwitch() self.addWorld.setChecked(False) self.addWorld.clicked.connect(self._syncSwitches) - self.addNotes = QSwitch() + self.addNotes = NSwitch() self.addNotes.setChecked(False) # Generate Content diff --git a/novelwriter/tools/writingstats.py b/novelwriter/tools/writingstats.py index a5981985..93da7f63 100644 --- a/novelwriter/tools/writingstats.py +++ b/novelwriter/tools/writingstats.py @@ -40,8 +40,8 @@ from PyQt5.QtWidgets import ( from novelwriter.enum import nwAlert from novelwriter.error import formatException from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax -from novelwriter.custom import QSwitch from novelwriter.constants import nwConst, nwFiles +from novelwriter.custom.switch import NSwitch logger = logging.getLogger(__name__) @@ -190,37 +190,37 @@ class GuiWritingStats(QDialog): self.filterForm = QGridLayout(self) self.filterBox.setLayout(self.filterForm) - self.incNovel = QSwitch(width=2*sPx, height=sPx) + self.incNovel = NSwitch(width=2*sPx, height=sPx) self.incNovel.setChecked( pOptions.getBool("GuiWritingStats", "incNovel", True) ) self.incNovel.clicked.connect(self._updateListBox) - self.incNotes = QSwitch(width=2*sPx, height=sPx) + self.incNotes = NSwitch(width=2*sPx, height=sPx) self.incNotes.setChecked( pOptions.getBool("GuiWritingStats", "incNotes", True) ) self.incNotes.clicked.connect(self._updateListBox) - self.hideZeros = QSwitch(width=2*sPx, height=sPx) + self.hideZeros = NSwitch(width=2*sPx, height=sPx) self.hideZeros.setChecked( pOptions.getBool("GuiWritingStats", "hideZeros", True) ) self.hideZeros.clicked.connect(self._updateListBox) - self.hideNegative = QSwitch(width=2*sPx, height=sPx) + self.hideNegative = NSwitch(width=2*sPx, height=sPx) self.hideNegative.setChecked( pOptions.getBool("GuiWritingStats", "hideNegative", False) ) self.hideNegative.clicked.connect(self._updateListBox) - self.groupByDay = QSwitch(width=2*sPx, height=sPx) + self.groupByDay = NSwitch(width=2*sPx, height=sPx) self.groupByDay.setChecked( pOptions.getBool("GuiWritingStats", "groupByDay", False) ) self.groupByDay.clicked.connect(self._updateListBox) - self.showIdleTime = QSwitch(width=2*sPx, height=sPx) + self.showIdleTime = NSwitch(width=2*sPx, height=sPx) self.showIdleTime.setChecked( pOptions.getBool("GuiWritingStats", "showIdleTime", False) )