146 lines
4.8 KiB
Python
146 lines
4.8 KiB
Python
"""
|
||
novelWriter – GUI Quotes Dialog
|
||
===============================
|
||
|
||
File History:
|
||
Created: 2020-06-18 [0.9.0] GuiQuoteSelect
|
||
|
||
This file is a part of novelWriter
|
||
Copyright (C) 2021 Veronica Berglyd Olsen and novelWriter contributors
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful, but
|
||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
""" # noqa
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
|
||
from PyQt6.QtCore import QSize, pyqtSlot
|
||
from PyQt6.QtGui import QFontMetrics
|
||
from PyQt6.QtWidgets import (
|
||
QDialogButtonBox, QFrame, QHBoxLayout, QLabel, QListWidget,
|
||
QListWidgetItem, QVBoxLayout, QWidget
|
||
)
|
||
|
||
from novelwriter import SHARED
|
||
from novelwriter.constants import nwQuotes, trConst
|
||
from novelwriter.enum import nwStandardButton
|
||
from novelwriter.extensions.modified import NDialog
|
||
from novelwriter.types import QtAccepted, QtAlignCenter, QtAlignTop, QtUserRole
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class GuiQuoteSelect(NDialog):
|
||
"""GUI: Quote Selector Dialog."""
|
||
|
||
_selected = ""
|
||
|
||
D_KEY = QtUserRole
|
||
|
||
def __init__(self, parent: QWidget, current: str = '"') -> None:
|
||
super().__init__(parent=parent)
|
||
|
||
logger.debug("Create: GuiQuoteSelect")
|
||
self.setObjectName("GuiQuoteSelect")
|
||
self.setWindowTitle(self.tr("Select Quote Style"))
|
||
|
||
self.outerBox = QVBoxLayout()
|
||
self.innerBox = QHBoxLayout()
|
||
self.labelBox = QVBoxLayout()
|
||
|
||
self._selected = current
|
||
|
||
lblFont = self.font()
|
||
lblFont.setPointSizeF(4*lblFont.pointSizeF())
|
||
metrics = QFontMetrics(self.font())
|
||
|
||
# Preview Label
|
||
self.previewLabel = QLabel(current, self)
|
||
self.previewLabel.setFont(lblFont)
|
||
self.previewLabel.setFixedSize(QSize(4*metrics.maxWidth(), 5*metrics.height()))
|
||
self.previewLabel.setAlignment(QtAlignCenter)
|
||
self.previewLabel.setFrameStyle(QFrame.Shape.Box | QFrame.Shadow.Plain)
|
||
|
||
# Quote Symbols
|
||
self.listBox = QListWidget(self)
|
||
self.listBox.itemSelectionChanged.connect(self._selectedSymbol)
|
||
|
||
minSize = 100
|
||
for sKey, sLabel in nwQuotes.SYMBOLS.items():
|
||
text = f"[ {sKey} ] {trConst(sLabel)}"
|
||
minSize = max(minSize, metrics.boundingRect(text).width())
|
||
qtItem = QListWidgetItem(text)
|
||
qtItem.setData(self.D_KEY, sKey)
|
||
self.listBox.addItem(qtItem)
|
||
if sKey == current:
|
||
self.listBox.setCurrentItem(qtItem)
|
||
|
||
self.listBox.setMinimumWidth(minSize + 40)
|
||
self.listBox.setMinimumHeight(150)
|
||
|
||
# Buttons
|
||
self.btnOk = SHARED.theme.getStandardButton(nwStandardButton.OK, self)
|
||
self.btnOk.clicked.connect(self.accept)
|
||
|
||
self.btnCancel = SHARED.theme.getStandardButton(nwStandardButton.CANCEL, self)
|
||
self.btnCancel.clicked.connect(self.reject)
|
||
|
||
self.btnBox = QDialogButtonBox(self)
|
||
self.btnBox.addButton(self.btnOk, QDialogButtonBox.ButtonRole.AcceptRole)
|
||
self.btnBox.addButton(self.btnCancel, QDialogButtonBox.ButtonRole.RejectRole)
|
||
|
||
# Assemble
|
||
self.labelBox.addWidget(self.previewLabel, 0, QtAlignTop)
|
||
self.labelBox.addStretch(1)
|
||
|
||
self.innerBox.addLayout(self.labelBox)
|
||
self.innerBox.addWidget(self.listBox)
|
||
|
||
self.outerBox.addLayout(self.innerBox)
|
||
self.outerBox.addWidget(self.btnBox)
|
||
|
||
self.setLayout(self.outerBox)
|
||
|
||
logger.debug("Ready: GuiQuoteSelect")
|
||
|
||
def __del__(self) -> None: # pragma: no cover
|
||
logger.debug("Delete: GuiQuoteSelect")
|
||
|
||
@property
|
||
def selectedQuote(self) -> str:
|
||
"""Return the selected quote symbol."""
|
||
return self._selected
|
||
|
||
@classmethod
|
||
def getQuote(cls, parent: QWidget, current: str = "") -> tuple[str, bool]:
|
||
"""Pop the dialog and return the result."""
|
||
dialog = cls(parent, current=current)
|
||
dialog.exec()
|
||
quote = dialog._selected
|
||
accepted = dialog.result() == QtAccepted
|
||
dialog.softDelete()
|
||
return quote, accepted
|
||
|
||
##
|
||
# Private Slots
|
||
##
|
||
|
||
@pyqtSlot()
|
||
def _selectedSymbol(self) -> None:
|
||
"""Update the preview label and the selected quote style."""
|
||
if items := self.listBox.selectedItems():
|
||
quote = items[0].data(self.D_KEY)
|
||
self.previewLabel.setText(quote)
|
||
self._selected = quote
|