initial fluent-widgets ui
This commit is contained in:
6
qfluentwidgets/components/dialog_box/__init__.py
Normal file
6
qfluentwidgets/components/dialog_box/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from .color_dialog import ColorDialog
|
||||
from .dialog import Dialog, MessageBox
|
||||
from .folder_list_dialog import FolderListDialog
|
||||
from .message_dialog import MessageDialog
|
||||
from .message_box_base import MessageBoxBase
|
||||
from .mask_dialog_base import MaskDialogBase
|
||||
414
qfluentwidgets/components/dialog_box/color_dialog.py
Normal file
414
qfluentwidgets/components/dialog_box/color_dialog.py
Normal file
@ -0,0 +1,414 @@
|
||||
# coding:utf-8
|
||||
from PySide6.QtCore import Qt, Signal, QPoint, QRegularExpression, QSize
|
||||
from PySide6.QtGui import (QBrush, QColor, QPixmap, QPainter,
|
||||
QPen, QIntValidator, QRegularExpressionValidator, QIcon)
|
||||
from PySide6.QtWidgets import QApplication, QLabel, QWidget, QPushButton, QPushButton, QFrame, QVBoxLayout
|
||||
|
||||
from ...common.style_sheet import FluentStyleSheet, isDarkTheme
|
||||
from ..widgets import ClickableSlider, SingleDirectionScrollArea, PushButton, PrimaryPushButton
|
||||
from ..widgets.line_edit import LineEdit
|
||||
from .mask_dialog_base import MaskDialogBase
|
||||
|
||||
|
||||
class HuePanel(QWidget):
|
||||
""" Hue panel """
|
||||
|
||||
colorChanged = Signal(QColor)
|
||||
|
||||
def __init__(self, color=QColor(255, 0, 0), parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setFixedSize(256, 256)
|
||||
self.huePixmap = QPixmap(":/qfluentwidgets/images/color_dialog/HuePanel.png")
|
||||
self.setColor(color)
|
||||
|
||||
def mousePressEvent(self, e):
|
||||
self.setPickerPosition(e.pos())
|
||||
|
||||
def mouseMoveEvent(self, e):
|
||||
self.setPickerPosition(e.pos())
|
||||
|
||||
def setPickerPosition(self, pos):
|
||||
""" set the position of """
|
||||
self.pickerPos = pos
|
||||
self.color.setHsv(
|
||||
int(max(0, min(1, pos.x() / self.width())) * 360),
|
||||
int(max(0, min(1, (self.height() - pos.y()) / self.height())) * 255),
|
||||
255
|
||||
)
|
||||
self.update()
|
||||
self.colorChanged.emit(self.color)
|
||||
|
||||
def setColor(self, color):
|
||||
""" set color """
|
||||
self.color = QColor(color)
|
||||
self.color.setHsv(self.color.hue(), self.color.saturation(), 255)
|
||||
self.pickerPos = QPoint(
|
||||
int(self.hue/360*self.width()),
|
||||
int((255 - self.saturation)/255*self.height())
|
||||
)
|
||||
self.update()
|
||||
|
||||
@property
|
||||
def hue(self):
|
||||
return self.color.hue()
|
||||
|
||||
@property
|
||||
def saturation(self):
|
||||
return self.color.saturation()
|
||||
|
||||
def paintEvent(self, e):
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHints(QPainter.Antialiasing |
|
||||
QPainter.SmoothPixmapTransform)
|
||||
|
||||
# draw hue panel
|
||||
painter.setBrush(QBrush(self.huePixmap))
|
||||
painter.setPen(QPen(QColor(0, 0, 0, 15), 2.4))
|
||||
painter.drawRoundedRect(self.rect(), 5.6, 5.6)
|
||||
|
||||
# draw picker
|
||||
if self.saturation > 153 or 40 < self.hue < 180:
|
||||
color = Qt.black
|
||||
else:
|
||||
color = QColor(255, 253, 254)
|
||||
|
||||
painter.setPen(QPen(color, 3))
|
||||
painter.setBrush(Qt.NoBrush)
|
||||
painter.drawEllipse(self.pickerPos.x() - 8,
|
||||
self.pickerPos.y() - 8, 16, 16)
|
||||
|
||||
|
||||
class BrightnessSlider(ClickableSlider):
|
||||
""" Brightness slider """
|
||||
|
||||
colorChanged = Signal(QColor)
|
||||
|
||||
def __init__(self, color, parent=None):
|
||||
super().__init__(Qt.Horizontal, parent)
|
||||
self.setRange(0, 255)
|
||||
self.setSingleStep(1)
|
||||
self.setColor(color)
|
||||
self.valueChanged.connect(self.__onValueChanged)
|
||||
|
||||
def setColor(self, color):
|
||||
""" set color """
|
||||
self.color = QColor(color)
|
||||
self.setValue(self.color.value())
|
||||
qss = FluentStyleSheet.COLOR_DIALOG.content()
|
||||
qss = qss.replace('--slider-hue', str(self.color.hue()))
|
||||
qss = qss.replace('--slider-saturation', str(self.color.saturation()))
|
||||
self.setStyleSheet(qss)
|
||||
|
||||
def __onValueChanged(self, value):
|
||||
""" slider value changed slot """
|
||||
self.color.setHsv(self.color.hue(), self.color.saturation(), value, self.color.alpha())
|
||||
self.setColor(self.color)
|
||||
self.colorChanged.emit(self.color)
|
||||
|
||||
|
||||
class ColorCard(QWidget):
|
||||
""" Color card """
|
||||
|
||||
def __init__(self, color, parent=None, enableAlpha=False):
|
||||
super().__init__(parent)
|
||||
self.setFixedSize(44, 128)
|
||||
self.setColor(color)
|
||||
self.enableAlpha = enableAlpha
|
||||
self.titledPixmap = self._createTitledBackground()
|
||||
|
||||
def _createTitledBackground(self):
|
||||
pixmap = QPixmap(8, 8)
|
||||
pixmap.fill(Qt.transparent)
|
||||
painter = QPainter(pixmap)
|
||||
|
||||
c = 255 if isDarkTheme() else 0
|
||||
color = QColor(c, c, c, 26)
|
||||
painter.fillRect(4, 0, 4, 4, color)
|
||||
painter.fillRect(0, 4, 4, 4, color)
|
||||
painter.end()
|
||||
return pixmap
|
||||
|
||||
def setColor(self, color):
|
||||
""" set the color of card """
|
||||
self.color = QColor(color)
|
||||
self.update()
|
||||
|
||||
def paintEvent(self, e):
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHints(QPainter.Antialiasing)
|
||||
|
||||
# draw tiled background
|
||||
if self.enableAlpha:
|
||||
painter.setBrush(QBrush(self.titledPixmap))
|
||||
painter.setPen(QColor(0, 0, 0, 13))
|
||||
painter.drawRoundedRect(self.rect(), 4, 4)
|
||||
|
||||
# draw color
|
||||
painter.setBrush(self.color)
|
||||
painter.setPen(QColor(0, 0, 0, 13))
|
||||
painter.drawRoundedRect(self.rect(), 4, 4)
|
||||
|
||||
|
||||
class ColorLineEdit(LineEdit):
|
||||
""" Color line edit """
|
||||
|
||||
valueChanged = Signal(str)
|
||||
|
||||
def __init__(self, value, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setText(str(value))
|
||||
self.setFixedSize(136, 33)
|
||||
self.setClearButtonEnabled(True)
|
||||
self.setValidator(QIntValidator(0, 255, self))
|
||||
|
||||
self.textEdited.connect(self._onTextEdited)
|
||||
|
||||
def _onTextEdited(self, text):
|
||||
""" text edited slot """
|
||||
state = self.validator().validate(text, 0)[0]
|
||||
if state == QIntValidator.Acceptable:
|
||||
self.valueChanged.emit(text)
|
||||
|
||||
|
||||
class HexColorLineEdit(ColorLineEdit):
|
||||
""" Hex color line edit """
|
||||
|
||||
def __init__(self, color, parent=None, enableAlpha=False):
|
||||
self.colorFormat = QColor.HexArgb if enableAlpha else QColor.HexRgb
|
||||
super().__init__(QColor(color).name(self.colorFormat)[1:], parent)
|
||||
|
||||
if enableAlpha:
|
||||
self.setValidator(QRegularExpressionValidator(QRegularExpression(r'[A-Fa-f0-9]{8}')))
|
||||
else:
|
||||
self.setValidator(QRegularExpressionValidator(QRegularExpression(r'[A-Fa-f0-9]{6}')))
|
||||
|
||||
self.setTextMargins(4, 0, 33, 0)
|
||||
self.prefixLabel = QLabel('#', self)
|
||||
self.prefixLabel.move(7, 2)
|
||||
self.prefixLabel.setObjectName('prefixLabel')
|
||||
|
||||
def setColor(self, color):
|
||||
""" set color """
|
||||
self.setText(color.name(self.colorFormat)[1:])
|
||||
|
||||
|
||||
class OpacityLineEdit(ColorLineEdit):
|
||||
""" Opacity line edit """
|
||||
|
||||
def __init__(self, value, parent=None, enableAlpha=False):
|
||||
super().__init__(int(value/255*100), parent)
|
||||
self.setValidator(QRegularExpressionValidator(QRegularExpression(r'[0-9][0-9]{0,1}|100')))
|
||||
self.setTextMargins(4, 0, 33, 0)
|
||||
self.suffixLabel = QLabel('%', self)
|
||||
self.suffixLabel.setObjectName('suffixLabel')
|
||||
self.textChanged.connect(self._adjustSuffixPos)
|
||||
|
||||
def showEvent(self, e):
|
||||
super().showEvent(e)
|
||||
self._adjustSuffixPos()
|
||||
|
||||
def _adjustSuffixPos(self):
|
||||
x = self.fontMetrics().boundingRect(self.text()).width() + 18
|
||||
self.suffixLabel.move(x, 2)
|
||||
|
||||
|
||||
class ColorDialog(MaskDialogBase):
|
||||
""" Color dialog """
|
||||
|
||||
colorChanged = Signal(QColor)
|
||||
|
||||
def __init__(self, color, title: str, parent=None, enableAlpha=False):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
color: `QColor` | `GlobalColor` | str
|
||||
initial color
|
||||
|
||||
title: str
|
||||
the title of dialog
|
||||
|
||||
parent: QWidget
|
||||
parent widget
|
||||
|
||||
enableAlpha: bool
|
||||
whether to enable the alpha channel
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.enableAlpha = enableAlpha
|
||||
if not enableAlpha:
|
||||
color = QColor(color)
|
||||
color.setAlpha(255)
|
||||
|
||||
self.oldColor = QColor(color)
|
||||
self.color = QColor(color)
|
||||
|
||||
self.scrollArea = SingleDirectionScrollArea(self.widget)
|
||||
self.scrollWidget = QWidget(self.scrollArea)
|
||||
|
||||
self.buttonGroup = QFrame(self.widget)
|
||||
self.yesButton = PrimaryPushButton(self.tr('OK'), self.buttonGroup)
|
||||
self.cancelButton = QPushButton(self.tr('Cancel'), self.buttonGroup)
|
||||
|
||||
self.titleLabel = QLabel(title, self.scrollWidget)
|
||||
self.huePanel = HuePanel(color, self.scrollWidget)
|
||||
self.newColorCard = ColorCard(color, self.scrollWidget, enableAlpha)
|
||||
self.oldColorCard = ColorCard(color, self.scrollWidget, enableAlpha)
|
||||
self.brightSlider = BrightnessSlider(color, self.scrollWidget)
|
||||
|
||||
self.editLabel = QLabel(self.tr('Edit Color'), self.scrollWidget)
|
||||
self.redLabel = QLabel(self.tr('Red'), self.scrollWidget)
|
||||
self.blueLabel = QLabel(self.tr('Blue'), self.scrollWidget)
|
||||
self.greenLabel = QLabel(self.tr('Green'), self.scrollWidget)
|
||||
self.opacityLabel = QLabel(self.tr('Opacity'), self.scrollWidget)
|
||||
self.hexLineEdit = HexColorLineEdit(color, self.scrollWidget, enableAlpha)
|
||||
self.redLineEdit = ColorLineEdit(self.color.red(), self.scrollWidget)
|
||||
self.greenLineEdit = ColorLineEdit(self.color.green(), self.scrollWidget)
|
||||
self.blueLineEdit = ColorLineEdit(self.color.blue(), self.scrollWidget)
|
||||
self.opacityLineEdit = OpacityLineEdit(self.color.alpha(), self.scrollWidget)
|
||||
|
||||
self.vBoxLayout = QVBoxLayout(self.widget)
|
||||
|
||||
self.__initWidget()
|
||||
|
||||
def __initWidget(self):
|
||||
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.scrollArea.setViewportMargins(48, 24, 0, 24)
|
||||
self.scrollArea.setWidget(self.scrollWidget)
|
||||
|
||||
self.widget.setMaximumSize(488, 696+40*self.enableAlpha)
|
||||
self.widget.resize(488, 696+40*self.enableAlpha)
|
||||
self.scrollWidget.resize(440, 560+40*self.enableAlpha)
|
||||
self.buttonGroup.setFixedSize(486, 81)
|
||||
self.yesButton.setFixedWidth(216)
|
||||
self.cancelButton.setFixedWidth(216)
|
||||
|
||||
self.setShadowEffect(60, (0, 10), QColor(0, 0, 0, 80))
|
||||
self.setMaskColor(QColor(0, 0, 0, 76))
|
||||
|
||||
self.__setQss()
|
||||
self.__initLayout()
|
||||
self.__connectSignalToSlot()
|
||||
|
||||
def __initLayout(self):
|
||||
self.huePanel.move(0, 46)
|
||||
self.newColorCard.move(288, 46)
|
||||
self.oldColorCard.move(288, self.newColorCard.geometry().bottom()+1)
|
||||
self.brightSlider.move(0, 324)
|
||||
|
||||
self.editLabel.move(0, 385)
|
||||
self.redLineEdit.move(0, 426)
|
||||
self.greenLineEdit.move(0, 470)
|
||||
self.blueLineEdit.move(0, 515)
|
||||
self.redLabel.move(144, 434)
|
||||
self.greenLabel.move(144, 478)
|
||||
self.blueLabel.move(144, 524)
|
||||
self.hexLineEdit.move(196, 381)
|
||||
|
||||
if self.enableAlpha:
|
||||
self.opacityLineEdit.move(0, 560)
|
||||
self.opacityLabel.move(144, 567)
|
||||
else:
|
||||
self.opacityLineEdit.hide()
|
||||
self.opacityLabel.hide()
|
||||
|
||||
self.vBoxLayout.setSpacing(0)
|
||||
self.vBoxLayout.setAlignment(Qt.AlignTop)
|
||||
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.vBoxLayout.addWidget(self.scrollArea, 1)
|
||||
self.vBoxLayout.addWidget(self.buttonGroup, 0, Qt.AlignBottom)
|
||||
|
||||
self.yesButton.move(24, 25)
|
||||
self.cancelButton.move(250, 25)
|
||||
|
||||
def __setQss(self):
|
||||
self.editLabel.setObjectName('editLabel')
|
||||
self.titleLabel.setObjectName('titleLabel')
|
||||
self.yesButton.setObjectName('yesButton')
|
||||
self.cancelButton.setObjectName('cancelButton')
|
||||
self.buttonGroup.setObjectName('buttonGroup')
|
||||
FluentStyleSheet.COLOR_DIALOG.apply(self)
|
||||
self.titleLabel.adjustSize()
|
||||
self.editLabel.adjustSize()
|
||||
|
||||
def setColor(self, color, movePicker=True):
|
||||
""" set color """
|
||||
self.color = QColor(color)
|
||||
self.brightSlider.setColor(color)
|
||||
self.newColorCard.setColor(color)
|
||||
self.hexLineEdit.setColor(color)
|
||||
self.redLineEdit.setText(str(color.red()))
|
||||
self.blueLineEdit.setText(str(color.blue()))
|
||||
self.greenLineEdit.setText(str(color.green()))
|
||||
if movePicker:
|
||||
self.huePanel.setColor(color)
|
||||
|
||||
def __onHueChanged(self, color):
|
||||
""" hue changed slot """
|
||||
self.color.setHsv(
|
||||
color.hue(), color.saturation(), self.color.value(), self.color.alpha())
|
||||
self.setColor(self.color)
|
||||
|
||||
def __onBrightnessChanged(self, color):
|
||||
""" brightness changed slot """
|
||||
self.color.setHsv(
|
||||
self.color.hue(), self.color.saturation(), color.value(), color.alpha())
|
||||
self.setColor(self.color, False)
|
||||
|
||||
def __onRedChanged(self, red):
|
||||
""" red channel changed slot """
|
||||
self.color.setRed(int(red))
|
||||
self.setColor(self.color)
|
||||
|
||||
def __onBlueChanged(self, blue):
|
||||
""" blue channel changed slot """
|
||||
self.color.setBlue(int(blue))
|
||||
self.setColor(self.color)
|
||||
|
||||
def __onGreenChanged(self, green):
|
||||
""" green channel changed slot """
|
||||
self.color.setGreen(int(green))
|
||||
self.setColor(self.color)
|
||||
|
||||
def __onOpacityChanged(self, opacity):
|
||||
""" opacity channel changed slot """
|
||||
self.color.setAlpha(int(int(opacity)/100*255))
|
||||
self.setColor(self.color)
|
||||
|
||||
def __onHexColorChanged(self, color):
|
||||
""" hex color changed slot """
|
||||
self.color.setNamedColor("#" + color)
|
||||
self.setColor(self.color)
|
||||
|
||||
def __onYesButtonClicked(self):
|
||||
""" yes button clicked slot """
|
||||
self.accept()
|
||||
if self.color != self.oldColor:
|
||||
self.colorChanged.emit(self.color)
|
||||
|
||||
def updateStyle(self):
|
||||
""" update style sheet """
|
||||
self.setStyle(QApplication.style())
|
||||
self.titleLabel.adjustSize()
|
||||
self.editLabel.adjustSize()
|
||||
self.redLabel.adjustSize()
|
||||
self.greenLabel.adjustSize()
|
||||
self.blueLabel.adjustSize()
|
||||
self.opacityLabel.adjustSize()
|
||||
|
||||
def showEvent(self, e):
|
||||
self.updateStyle()
|
||||
super().showEvent(e)
|
||||
|
||||
def __connectSignalToSlot(self):
|
||||
""" connect signal to slot """
|
||||
self.cancelButton.clicked.connect(self.reject)
|
||||
self.yesButton.clicked.connect(self.__onYesButtonClicked)
|
||||
|
||||
self.huePanel.colorChanged.connect(self.__onHueChanged)
|
||||
self.brightSlider.colorChanged.connect(self.__onBrightnessChanged)
|
||||
|
||||
self.redLineEdit.valueChanged.connect(self.__onRedChanged)
|
||||
self.blueLineEdit.valueChanged.connect(self.__onBlueChanged)
|
||||
self.greenLineEdit.valueChanged.connect(self.__onGreenChanged)
|
||||
self.hexLineEdit.valueChanged.connect(self.__onHexColorChanged)
|
||||
self.opacityLineEdit.valueChanged.connect(self.__onOpacityChanged)
|
||||
167
qfluentwidgets/components/dialog_box/dialog.py
Normal file
167
qfluentwidgets/components/dialog_box/dialog.py
Normal file
@ -0,0 +1,167 @@
|
||||
# coding:utf-8
|
||||
from PySide6.QtCore import Qt, Signal, QObject, QEvent
|
||||
from PySide6.QtGui import QColor
|
||||
from PySide6.QtWidgets import QLabel, QFrame, QVBoxLayout, QHBoxLayout, QPushButton
|
||||
from qframelesswindow import FramelessDialog
|
||||
|
||||
from ...common.auto_wrap import TextWrap
|
||||
from ...common.style_sheet import FluentStyleSheet
|
||||
from ..widgets.button import PrimaryPushButton
|
||||
from ..widgets.label import BodyLabel
|
||||
|
||||
from .mask_dialog_base import MaskDialogBase
|
||||
|
||||
|
||||
class Ui_MessageBox:
|
||||
""" Ui of message box """
|
||||
|
||||
yesSignal = Signal()
|
||||
cancelSignal = Signal()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def _setUpUi(self, title, content, parent):
|
||||
self.content = content
|
||||
self.titleLabel = QLabel(title, parent)
|
||||
self.contentLabel = BodyLabel(content, parent)
|
||||
|
||||
self.buttonGroup = QFrame(parent)
|
||||
self.yesButton = PrimaryPushButton(self.tr('OK'), self.buttonGroup)
|
||||
self.cancelButton = QPushButton(self.tr('Cancel'), self.buttonGroup)
|
||||
|
||||
self.vBoxLayout = QVBoxLayout(parent)
|
||||
self.textLayout = QVBoxLayout()
|
||||
self.buttonLayout = QHBoxLayout(self.buttonGroup)
|
||||
|
||||
self.__initWidget()
|
||||
|
||||
def __initWidget(self):
|
||||
self.__setQss()
|
||||
self.__initLayout()
|
||||
|
||||
# fixes https://github.com/zhiyiYo/PyQt-Fluent-Widgets/issues/19
|
||||
self.yesButton.setAttribute(Qt.WA_LayoutUsesWidgetRect)
|
||||
self.cancelButton.setAttribute(Qt.WA_LayoutUsesWidgetRect)
|
||||
|
||||
self.yesButton.setFocus()
|
||||
self.buttonGroup.setFixedHeight(81)
|
||||
|
||||
self.contentLabel.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||
self._adjustText()
|
||||
|
||||
self.yesButton.clicked.connect(self.__onYesButtonClicked)
|
||||
self.cancelButton.clicked.connect(self.__onCancelButtonClicked)
|
||||
|
||||
def _adjustText(self):
|
||||
if self.isWindow():
|
||||
if self.parent():
|
||||
w = max(self.titleLabel.width(), self.parent().width())
|
||||
chars = max(min(w / 9, 140), 30)
|
||||
else:
|
||||
chars = 100
|
||||
else:
|
||||
w = max(self.titleLabel.width(), self.window().width())
|
||||
chars = max(min(w / 9, 100), 30)
|
||||
|
||||
self.contentLabel.setText(TextWrap.wrap(self.content, chars, False)[0])
|
||||
|
||||
def __initLayout(self):
|
||||
self.vBoxLayout.setSpacing(0)
|
||||
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.vBoxLayout.addLayout(self.textLayout, 1)
|
||||
self.vBoxLayout.addWidget(self.buttonGroup, 0, Qt.AlignBottom)
|
||||
self.vBoxLayout.setSizeConstraint(QVBoxLayout.SetMinimumSize)
|
||||
|
||||
self.textLayout.setSpacing(12)
|
||||
self.textLayout.setContentsMargins(24, 24, 24, 24)
|
||||
self.textLayout.addWidget(self.titleLabel, 0, Qt.AlignTop)
|
||||
self.textLayout.addWidget(self.contentLabel, 0, Qt.AlignTop)
|
||||
|
||||
self.buttonLayout.setSpacing(12)
|
||||
self.buttonLayout.setContentsMargins(24, 24, 24, 24)
|
||||
self.buttonLayout.addWidget(self.yesButton, 1, Qt.AlignVCenter)
|
||||
self.buttonLayout.addWidget(self.cancelButton, 1, Qt.AlignVCenter)
|
||||
|
||||
def __onCancelButtonClicked(self):
|
||||
self.reject()
|
||||
self.cancelSignal.emit()
|
||||
|
||||
def __onYesButtonClicked(self):
|
||||
self.accept()
|
||||
self.yesSignal.emit()
|
||||
|
||||
def __setQss(self):
|
||||
self.titleLabel.setObjectName("titleLabel")
|
||||
self.contentLabel.setObjectName("contentLabel")
|
||||
self.buttonGroup.setObjectName('buttonGroup')
|
||||
self.cancelButton.setObjectName('cancelButton')
|
||||
|
||||
FluentStyleSheet.DIALOG.apply(self)
|
||||
FluentStyleSheet.DIALOG.apply(self.contentLabel)
|
||||
|
||||
self.yesButton.adjustSize()
|
||||
self.cancelButton.adjustSize()
|
||||
|
||||
def setContentCopyable(self, isCopyable: bool):
|
||||
""" set whether the content is copyable """
|
||||
if isCopyable:
|
||||
self.contentLabel.setTextInteractionFlags(
|
||||
Qt.TextInteractionFlag.TextSelectableByMouse)
|
||||
else:
|
||||
self.contentLabel.setTextInteractionFlags(
|
||||
Qt.TextInteractionFlag.NoTextInteraction)
|
||||
|
||||
|
||||
class Dialog(FramelessDialog, Ui_MessageBox):
|
||||
""" Dialog box """
|
||||
|
||||
yesSignal = Signal()
|
||||
cancelSignal = Signal()
|
||||
|
||||
def __init__(self, title: str, content: str, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self._setUpUi(title, content, self)
|
||||
|
||||
self.windowTitleLabel = QLabel(title, self)
|
||||
|
||||
self.setResizeEnabled(False)
|
||||
self.resize(240, 192)
|
||||
self.titleBar.hide()
|
||||
|
||||
self.vBoxLayout.insertWidget(0, self.windowTitleLabel, 0, Qt.AlignTop)
|
||||
self.windowTitleLabel.setObjectName('windowTitleLabel')
|
||||
FluentStyleSheet.DIALOG.apply(self)
|
||||
self.setFixedSize(self.size())
|
||||
|
||||
def setTitleBarVisible(self, isVisible: bool):
|
||||
self.windowTitleLabel.setVisible(isVisible)
|
||||
|
||||
|
||||
class MessageBox(MaskDialogBase, Ui_MessageBox):
|
||||
""" Message box """
|
||||
|
||||
yesSignal = Signal()
|
||||
cancelSignal = Signal()
|
||||
|
||||
def __init__(self, title: str, content: str, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self._setUpUi(title, content, self.widget)
|
||||
|
||||
self.setShadowEffect(60, (0, 10), QColor(0, 0, 0, 50))
|
||||
self.setMaskColor(QColor(0, 0, 0, 76))
|
||||
self._hBoxLayout.removeWidget(self.widget)
|
||||
self._hBoxLayout.addWidget(self.widget, 1, Qt.AlignCenter)
|
||||
|
||||
self.buttonGroup.setMinimumWidth(280)
|
||||
self.widget.setFixedSize(
|
||||
max(self.contentLabel.width(), self.titleLabel.width()) + 48,
|
||||
self.contentLabel.y() + self.contentLabel.height() + 105
|
||||
)
|
||||
|
||||
def eventFilter(self, obj, e: QEvent):
|
||||
if obj is self.window():
|
||||
if e.type() == QEvent.Resize:
|
||||
self._adjustText()
|
||||
|
||||
return super().eventFilter(obj, e)
|
||||
307
qfluentwidgets/components/dialog_box/folder_list_dialog.py
Normal file
307
qfluentwidgets/components/dialog_box/folder_list_dialog.py
Normal file
@ -0,0 +1,307 @@
|
||||
# coding:utf-8
|
||||
import os
|
||||
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtGui import (QBrush, QColor, QFont, QFontMetrics, QMouseEvent,
|
||||
QPainter, QPen, QPixmap)
|
||||
from PySide6.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel,
|
||||
QVBoxLayout, QWidget, QPushButton)
|
||||
|
||||
from ...common.config import isDarkTheme
|
||||
from ...common.icon import getIconColor
|
||||
from ...common.style_sheet import FluentStyleSheet
|
||||
from .dialog import Dialog
|
||||
from .mask_dialog_base import MaskDialogBase
|
||||
from ..widgets.scroll_area import SingleDirectionScrollArea
|
||||
|
||||
|
||||
class FolderListDialog(MaskDialogBase):
|
||||
""" Folder list dialog box """
|
||||
|
||||
folderChanged = Signal(list)
|
||||
|
||||
def __init__(self, folderPaths: list, title: str, content: str, parent):
|
||||
super().__init__(parent=parent)
|
||||
self.title = title
|
||||
self.content = content
|
||||
self.__originalPaths = folderPaths
|
||||
self.folderPaths = folderPaths.copy()
|
||||
|
||||
self.vBoxLayout = QVBoxLayout(self.widget)
|
||||
self.titleLabel = QLabel(title, self.widget)
|
||||
self.contentLabel = QLabel(content, self.widget)
|
||||
self.scrollArea = SingleDirectionScrollArea(self.widget)
|
||||
self.scrollWidget = QWidget(self.scrollArea)
|
||||
self.completeButton = QPushButton(self.tr('Done'), self.widget)
|
||||
self.addFolderCard = AddFolderCard(self.scrollWidget)
|
||||
self.folderCards = [FolderCard(i, self.scrollWidget)
|
||||
for i in folderPaths]
|
||||
self.__initWidget()
|
||||
|
||||
def __initWidget(self):
|
||||
""" initialize widgets """
|
||||
self.__setQss()
|
||||
|
||||
w = max(self.titleLabel.width()+48, self.contentLabel.width()+48, 352)
|
||||
self.widget.setFixedWidth(w)
|
||||
self.scrollArea.resize(294, 72)
|
||||
self.scrollWidget.resize(292, 72)
|
||||
self.scrollArea.setFixedWidth(294)
|
||||
self.scrollWidget.setFixedWidth(292)
|
||||
self.scrollArea.setMaximumHeight(400)
|
||||
self.scrollArea.setViewportMargins(0, 0, 0, 0)
|
||||
self.scrollArea.setWidgetResizable(True)
|
||||
self.scrollArea.setWidget(self.scrollWidget)
|
||||
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.scrollArea.hScrollBar.setForceHidden(True)
|
||||
self.__initLayout()
|
||||
|
||||
# connect signal to slot
|
||||
self.addFolderCard.clicked.connect(self.__showFileDialog)
|
||||
self.completeButton.clicked.connect(self.__onButtonClicked)
|
||||
for card in self.folderCards:
|
||||
card.clicked.connect(self.__showDeleteFolderCardDialog)
|
||||
|
||||
def __initLayout(self):
|
||||
""" initialize layout """
|
||||
self.vBoxLayout.setContentsMargins(24, 24, 24, 24)
|
||||
self.vBoxLayout.setSizeConstraint(QVBoxLayout.SetFixedSize)
|
||||
self.vBoxLayout.setAlignment(Qt.AlignTop)
|
||||
self.vBoxLayout.setSpacing(0)
|
||||
|
||||
# labels
|
||||
layout_1 = QVBoxLayout()
|
||||
layout_1.setContentsMargins(0, 0, 0, 0)
|
||||
layout_1.setSpacing(6)
|
||||
layout_1.addWidget(self.titleLabel, 0, Qt.AlignTop)
|
||||
layout_1.addWidget(self.contentLabel, 0, Qt.AlignTop)
|
||||
self.vBoxLayout.addLayout(layout_1, 0)
|
||||
self.vBoxLayout.addSpacing(12)
|
||||
|
||||
# cards
|
||||
layout_2 = QHBoxLayout()
|
||||
layout_2.setAlignment(Qt.AlignCenter)
|
||||
layout_2.setContentsMargins(4, 0, 4, 0)
|
||||
layout_2.addWidget(self.scrollArea, 0, Qt.AlignCenter)
|
||||
self.vBoxLayout.addLayout(layout_2, 1)
|
||||
self.vBoxLayout.addSpacing(24)
|
||||
|
||||
self.scrollLayout = QVBoxLayout(self.scrollWidget)
|
||||
self.scrollLayout.setAlignment(Qt.AlignTop)
|
||||
self.scrollLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.scrollLayout.setSpacing(8)
|
||||
self.scrollLayout.addWidget(self.addFolderCard, 0, Qt.AlignTop)
|
||||
for card in self.folderCards:
|
||||
self.scrollLayout.addWidget(card, 0, Qt.AlignTop)
|
||||
|
||||
# buttons
|
||||
layout_3 = QHBoxLayout()
|
||||
layout_3.setContentsMargins(0, 0, 0, 0)
|
||||
layout_3.addStretch(1)
|
||||
layout_3.addWidget(self.completeButton)
|
||||
self.vBoxLayout.addLayout(layout_3, 0)
|
||||
|
||||
self.__adjustWidgetSize()
|
||||
|
||||
def __showFileDialog(self):
|
||||
""" show file dialog to select folder """
|
||||
path = QFileDialog.getExistingDirectory(
|
||||
self, self.tr("Choose folder"), "./")
|
||||
|
||||
if not path or path in self.folderPaths:
|
||||
return
|
||||
|
||||
# create folder card
|
||||
card = FolderCard(path, self.scrollWidget)
|
||||
self.scrollLayout.addWidget(card, 0, Qt.AlignTop)
|
||||
card.clicked.connect(self.__showDeleteFolderCardDialog)
|
||||
card.show()
|
||||
|
||||
self.folderPaths.append(path)
|
||||
self.folderCards.append(card)
|
||||
|
||||
self.__adjustWidgetSize()
|
||||
|
||||
def __showDeleteFolderCardDialog(self):
|
||||
""" show delete folder card dialog """
|
||||
sender = self.sender()
|
||||
title = self.tr('Are you sure you want to delete the folder?')
|
||||
content = self.tr("If you delete the ") + f'"{sender.folderName}"' + \
|
||||
self.tr(" folder and remove it from the list, the folder will no "
|
||||
"longer appear in the list, but will not be deleted.")
|
||||
dialog = Dialog(title, content, self.window())
|
||||
dialog.yesSignal.connect(lambda: self.__deleteFolderCard(sender))
|
||||
dialog.exec_()
|
||||
|
||||
def __deleteFolderCard(self, folderCard):
|
||||
""" delete selected folder card """
|
||||
self.scrollLayout.removeWidget(folderCard)
|
||||
index = self.folderCards.index(folderCard)
|
||||
self.folderCards.pop(index)
|
||||
self.folderPaths.pop(index)
|
||||
folderCard.deleteLater()
|
||||
|
||||
# adjust height
|
||||
self.__adjustWidgetSize()
|
||||
|
||||
def __setQss(self):
|
||||
""" set style sheet """
|
||||
self.titleLabel.setObjectName('titleLabel')
|
||||
self.contentLabel.setObjectName('contentLabel')
|
||||
self.completeButton.setObjectName('completeButton')
|
||||
self.scrollWidget.setObjectName('scrollWidget')
|
||||
|
||||
FluentStyleSheet.FOLDER_LIST_DIALOG.apply(self)
|
||||
self.setStyle(QApplication.style())
|
||||
|
||||
self.titleLabel.adjustSize()
|
||||
self.contentLabel.adjustSize()
|
||||
self.completeButton.adjustSize()
|
||||
|
||||
def __onButtonClicked(self):
|
||||
""" done button clicked slot """
|
||||
if sorted(self.__originalPaths) != sorted(self.folderPaths):
|
||||
self.setEnabled(False)
|
||||
QApplication.processEvents()
|
||||
self.folderChanged.emit(self.folderPaths)
|
||||
|
||||
self.close()
|
||||
|
||||
def __adjustWidgetSize(self):
|
||||
N = len(self.folderCards)
|
||||
h = 72*(N+1) + 8*N
|
||||
self.scrollArea.setFixedHeight(min(h, 400))
|
||||
|
||||
|
||||
class ClickableWindow(QWidget):
|
||||
""" Clickable window """
|
||||
|
||||
clicked = Signal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setAttribute(Qt.WA_TranslucentBackground)
|
||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||
self.setFixedSize(292, 72)
|
||||
self._isPressed = None
|
||||
self._isEnter = False
|
||||
|
||||
def enterEvent(self, e):
|
||||
self._isEnter = True
|
||||
self.update()
|
||||
|
||||
def leaveEvent(self, e):
|
||||
self._isEnter = False
|
||||
self.update()
|
||||
|
||||
def mouseReleaseEvent(self, e):
|
||||
self._isPressed = False
|
||||
self.update()
|
||||
if e.button() == Qt.LeftButton:
|
||||
self.clicked.emit()
|
||||
|
||||
def mousePressEvent(self, e: QMouseEvent):
|
||||
self._isPressed = True
|
||||
self.update()
|
||||
|
||||
def paintEvent(self, e):
|
||||
""" paint window """
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHints(QPainter.Antialiasing)
|
||||
|
||||
isDark = isDarkTheme()
|
||||
bg = 51 if isDark else 204
|
||||
brush = QBrush(QColor(bg, bg, bg))
|
||||
painter.setPen(Qt.NoPen)
|
||||
|
||||
if not self._isEnter:
|
||||
painter.setBrush(brush)
|
||||
painter.drawRoundedRect(self.rect(), 4, 4)
|
||||
else:
|
||||
painter.setPen(QPen(QColor(bg, bg, bg), 2))
|
||||
painter.drawRect(1, 1, self.width() - 2, self.height() - 2)
|
||||
painter.setPen(Qt.NoPen)
|
||||
if not self._isPressed:
|
||||
bg = 24 if isDark else 230
|
||||
brush.setColor(QColor(bg, bg, bg))
|
||||
painter.setBrush(brush)
|
||||
painter.drawRect(2, 2, self.width() - 4, self.height() - 4)
|
||||
else:
|
||||
bg = 102 if isDark else 230
|
||||
brush.setColor(QColor(153, 153, 153))
|
||||
painter.setBrush(brush)
|
||||
painter.drawRoundedRect(
|
||||
5, 1, self.width() - 10, self.height() - 2, 2, 2)
|
||||
|
||||
|
||||
class FolderCard(ClickableWindow):
|
||||
""" Folder card """
|
||||
|
||||
def __init__(self, folderPath: str, parent=None):
|
||||
super().__init__(parent)
|
||||
self.folderPath = folderPath
|
||||
self.folderName = os.path.basename(folderPath)
|
||||
c = getIconColor()
|
||||
self.__closeIcon = QPixmap(f":/qfluentwidgets/images/folder_list_dialog/Close_{c}.png").scaled(
|
||||
12, 12, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
|
||||
def paintEvent(self, e):
|
||||
""" paint card """
|
||||
super().paintEvent(e)
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHints(
|
||||
QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform | QPainter.Antialiasing)
|
||||
|
||||
# paint text and icon
|
||||
color = Qt.white if isDarkTheme() else Qt.black
|
||||
painter.setPen(color)
|
||||
if self._isPressed:
|
||||
self.__drawText(painter, 12, 12, 12, 10)
|
||||
painter.drawPixmap(self.width() - 26, 18, self.__closeIcon)
|
||||
else:
|
||||
self.__drawText(painter, 10, 13, 10, 11)
|
||||
painter.drawPixmap(self.width() - 24, 20, self.__closeIcon)
|
||||
|
||||
def __drawText(self, painter, x1, fontSize1, x2, fontSize2):
|
||||
""" draw text """
|
||||
# paint folder name
|
||||
font = QFont("Microsoft YaHei")
|
||||
font.setBold(True)
|
||||
font.setPixelSize(fontSize1)
|
||||
painter.setFont(font)
|
||||
name = QFontMetrics(font).elidedText(
|
||||
self.folderName, Qt.ElideRight, self.width()-48)
|
||||
painter.drawText(x1, 30, name)
|
||||
|
||||
# paint folder path
|
||||
font = QFont("Microsoft YaHei")
|
||||
font.setPixelSize(fontSize2)
|
||||
painter.setFont(font)
|
||||
path = QFontMetrics(font).elidedText(
|
||||
self.folderPath, Qt.ElideRight, self.width()-24)
|
||||
painter.drawText(x2, 37, self.width() - 16, 18, Qt.AlignLeft, path)
|
||||
|
||||
|
||||
class AddFolderCard(ClickableWindow):
|
||||
""" Add folder card """
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
c = getIconColor()
|
||||
self.__iconPix = QPixmap(f":/qfluentwidgets/images/folder_list_dialog/Add_{c}.png").scaled(
|
||||
22, 22, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
|
||||
def paintEvent(self, e):
|
||||
""" paint card """
|
||||
super().paintEvent(e)
|
||||
painter = QPainter(self)
|
||||
w = self.width()
|
||||
h = self.height()
|
||||
pw = self.__iconPix.width()
|
||||
ph = self.__iconPix.height()
|
||||
if not self._isPressed:
|
||||
painter.drawPixmap(
|
||||
int(w/2 - pw/2), int(h/2 - ph/2), self.__iconPix)
|
||||
else:
|
||||
painter.drawPixmap(
|
||||
int(w/2 - (pw - 4)/2), int(h/2 - (ph - 4)/2), pw - 4, ph - 4, self.__iconPix)
|
||||
120
qfluentwidgets/components/dialog_box/mask_dialog_base.py
Normal file
120
qfluentwidgets/components/dialog_box/mask_dialog_base.py
Normal file
@ -0,0 +1,120 @@
|
||||
# coding:utf-8
|
||||
from PySide6.QtCore import QEasingCurve, QPropertyAnimation, Qt, QEvent, QPoint
|
||||
from PySide6.QtGui import QColor, QResizeEvent
|
||||
from PySide6.QtWidgets import (QDialog, QGraphicsDropShadowEffect,
|
||||
QGraphicsOpacityEffect, QHBoxLayout, QWidget, QFrame)
|
||||
|
||||
from ...common.config import isDarkTheme
|
||||
|
||||
|
||||
class MaskDialogBase(QDialog):
|
||||
""" Dialog box base class with a mask """
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self._isClosableOnMaskClicked = False
|
||||
self._isDraggable = False
|
||||
self._dragPos = QPoint()
|
||||
self._hBoxLayout = QHBoxLayout(self)
|
||||
self.windowMask = QWidget(self)
|
||||
|
||||
# dialog box in the center of mask, all widgets take it as parent
|
||||
self.widget = QFrame(self, objectName='centerWidget')
|
||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||
self.setAttribute(Qt.WA_TranslucentBackground)
|
||||
self.setGeometry(0, 0, parent.width(), parent.height())
|
||||
|
||||
c = 0 if isDarkTheme() else 255
|
||||
self.windowMask.resize(self.size())
|
||||
self.windowMask.setStyleSheet(f'background:rgba({c}, {c}, {c}, 0.6)')
|
||||
self._hBoxLayout.addWidget(self.widget)
|
||||
self.setShadowEffect()
|
||||
|
||||
self.window().installEventFilter(self)
|
||||
self.windowMask.installEventFilter(self)
|
||||
self.widget.installEventFilter(self)
|
||||
|
||||
def setShadowEffect(self, blurRadius=60, offset=(0, 10), color=QColor(0, 0, 0, 100)):
|
||||
""" add shadow to dialog """
|
||||
shadowEffect = QGraphicsDropShadowEffect(self.widget)
|
||||
shadowEffect.setBlurRadius(blurRadius)
|
||||
shadowEffect.setOffset(*offset)
|
||||
shadowEffect.setColor(color)
|
||||
self.widget.setGraphicsEffect(None)
|
||||
self.widget.setGraphicsEffect(shadowEffect)
|
||||
|
||||
def setMaskColor(self, color: QColor):
|
||||
""" set the color of mask """
|
||||
self.windowMask.setStyleSheet(f"""
|
||||
background: rgba({color.red()}, {color.green()}, {color.blue()}, {color.alpha()})
|
||||
""")
|
||||
|
||||
def showEvent(self, e):
|
||||
""" fade in """
|
||||
opacityEffect = QGraphicsOpacityEffect(self)
|
||||
self.setGraphicsEffect(opacityEffect)
|
||||
opacityAni = QPropertyAnimation(opacityEffect, b'opacity', self)
|
||||
opacityAni.setStartValue(0)
|
||||
opacityAni.setEndValue(1)
|
||||
opacityAni.setDuration(200)
|
||||
opacityAni.setEasingCurve(QEasingCurve.InSine)
|
||||
opacityAni.finished.connect(lambda: self.setGraphicsEffect(None))
|
||||
opacityAni.start()
|
||||
super().showEvent(e)
|
||||
|
||||
def done(self, code):
|
||||
""" fade out """
|
||||
self.widget.setGraphicsEffect(None)
|
||||
opacityEffect = QGraphicsOpacityEffect(self)
|
||||
self.setGraphicsEffect(opacityEffect)
|
||||
opacityAni = QPropertyAnimation(opacityEffect, b'opacity', self)
|
||||
opacityAni.setStartValue(1)
|
||||
opacityAni.setEndValue(0)
|
||||
opacityAni.setDuration(100)
|
||||
opacityAni.finished.connect(lambda: self._onDone(code))
|
||||
opacityAni.start()
|
||||
|
||||
def _onDone(self, code):
|
||||
self.setGraphicsEffect(None)
|
||||
QDialog.done(self, code)
|
||||
|
||||
def isClosableOnMaskClicked(self):
|
||||
return self._isClosableOnMaskClicked
|
||||
|
||||
def setClosableOnMaskClicked(self, isClosable: bool):
|
||||
self._isClosableOnMaskClicked = isClosable
|
||||
|
||||
def setDraggable(self, draggable: bool):
|
||||
self._isDraggable = draggable
|
||||
|
||||
def isDraggable(self) -> bool:
|
||||
return self._isDraggable
|
||||
|
||||
def resizeEvent(self, e):
|
||||
self.windowMask.resize(self.size())
|
||||
|
||||
def eventFilter(self, obj, e: QEvent):
|
||||
if obj is self.window():
|
||||
if e.type() == QEvent.Resize:
|
||||
re = QResizeEvent(e)
|
||||
self.resize(re.size())
|
||||
elif obj is self.windowMask:
|
||||
if e.type() == QEvent.MouseButtonRelease and e.button() == Qt.LeftButton \
|
||||
and self.isClosableOnMaskClicked():
|
||||
self.reject()
|
||||
elif obj is self.widget and self.isDraggable():
|
||||
if e.type() == QEvent.MouseButtonPress and e.button() == Qt.LeftButton:
|
||||
if not self.widget.childrenRegion().contains(e.pos()):
|
||||
self._dragPos = e.pos()
|
||||
return True
|
||||
elif e.type() == QEvent.MouseMove and not self._dragPos.isNull():
|
||||
pos = self.widget.pos() + e.pos() - self._dragPos
|
||||
pos.setX(max(0, min(pos.x(), self.width() - self.widget.width())))
|
||||
pos.setY(max(0, min(pos.y(), self.height() - self.widget.height())))
|
||||
|
||||
self.widget.move(pos)
|
||||
return True
|
||||
elif e.type() == QEvent.MouseButtonRelease:
|
||||
self._dragPos = QPoint()
|
||||
|
||||
return super().eventFilter(obj, e)
|
||||
92
qfluentwidgets/components/dialog_box/message_box_base.py
Normal file
92
qfluentwidgets/components/dialog_box/message_box_base.py
Normal file
@ -0,0 +1,92 @@
|
||||
# coding:utf-8
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtGui import QColor
|
||||
from PySide6.QtWidgets import QFrame, QVBoxLayout, QHBoxLayout, QPushButton
|
||||
|
||||
from ...common.style_sheet import FluentStyleSheet
|
||||
from ..widgets.button import PrimaryPushButton
|
||||
|
||||
from .mask_dialog_base import MaskDialogBase
|
||||
|
||||
|
||||
class MessageBoxBase(MaskDialogBase):
|
||||
""" Message box base """
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.buttonGroup = QFrame(self.widget)
|
||||
self.yesButton = PrimaryPushButton(self.tr('OK'), self.buttonGroup)
|
||||
self.cancelButton = QPushButton(self.tr('Cancel'), self.buttonGroup)
|
||||
|
||||
self.vBoxLayout = QVBoxLayout(self.widget)
|
||||
self.viewLayout = QVBoxLayout()
|
||||
self.buttonLayout = QHBoxLayout(self.buttonGroup)
|
||||
|
||||
self.__initWidget()
|
||||
|
||||
def __initWidget(self):
|
||||
self.__setQss()
|
||||
self.__initLayout()
|
||||
|
||||
self.setShadowEffect(60, (0, 10), QColor(0, 0, 0, 50))
|
||||
self.setMaskColor(QColor(0, 0, 0, 76))
|
||||
|
||||
# fixes https://github.com/zhiyiYo/PyQt-Fluent-Widgets/issues/19
|
||||
self.yesButton.setAttribute(Qt.WA_LayoutUsesWidgetRect)
|
||||
self.cancelButton.setAttribute(Qt.WA_LayoutUsesWidgetRect)
|
||||
|
||||
self.yesButton.setAttribute(Qt.WA_MacShowFocusRect, False)
|
||||
|
||||
self.yesButton.setFocus()
|
||||
self.buttonGroup.setFixedHeight(81)
|
||||
|
||||
self.yesButton.clicked.connect(self.__onYesButtonClicked)
|
||||
self.cancelButton.clicked.connect(self.__onCancelButtonClicked)
|
||||
|
||||
def __initLayout(self):
|
||||
self._hBoxLayout.removeWidget(self.widget)
|
||||
self._hBoxLayout.addWidget(self.widget, 1, Qt.AlignCenter)
|
||||
|
||||
self.vBoxLayout.setSpacing(0)
|
||||
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.vBoxLayout.addLayout(self.viewLayout, 1)
|
||||
self.vBoxLayout.addWidget(self.buttonGroup, 0, Qt.AlignBottom)
|
||||
|
||||
self.viewLayout.setSpacing(12)
|
||||
self.viewLayout.setContentsMargins(24, 24, 24, 24)
|
||||
|
||||
self.buttonLayout.setSpacing(12)
|
||||
self.buttonLayout.setContentsMargins(24, 24, 24, 24)
|
||||
self.buttonLayout.addWidget(self.yesButton, 1, Qt.AlignVCenter)
|
||||
self.buttonLayout.addWidget(self.cancelButton, 1, Qt.AlignVCenter)
|
||||
|
||||
def validate(self) -> bool:
|
||||
""" validate the data of form before closing dialog
|
||||
|
||||
Returns
|
||||
-------
|
||||
isValid: bool
|
||||
whether the data of form is legal
|
||||
"""
|
||||
return True
|
||||
|
||||
def __onCancelButtonClicked(self):
|
||||
self.reject()
|
||||
|
||||
def __onYesButtonClicked(self):
|
||||
if self.validate():
|
||||
self.accept()
|
||||
|
||||
def __setQss(self):
|
||||
self.buttonGroup.setObjectName('buttonGroup')
|
||||
self.cancelButton.setObjectName('cancelButton')
|
||||
FluentStyleSheet.DIALOG.apply(self)
|
||||
|
||||
def hideYesButton(self):
|
||||
self.yesButton.hide()
|
||||
self.buttonLayout.insertStretch(0, 1)
|
||||
|
||||
def hideCancelButton(self):
|
||||
self.cancelButton.hide()
|
||||
self.buttonLayout.insertStretch(0, 1)
|
||||
|
||||
65
qfluentwidgets/components/dialog_box/message_dialog.py
Normal file
65
qfluentwidgets/components/dialog_box/message_dialog.py
Normal file
@ -0,0 +1,65 @@
|
||||
# coding:utf-8
|
||||
from PySide6.QtCore import Signal
|
||||
from PySide6.QtWidgets import QLabel, QPushButton, QDialog
|
||||
|
||||
from ...common.auto_wrap import TextWrap
|
||||
from ...common.style_sheet import FluentStyleSheet
|
||||
from .mask_dialog_base import MaskDialogBase
|
||||
|
||||
|
||||
class MessageDialog(MaskDialogBase):
|
||||
""" Win10 style message dialog box with a mask """
|
||||
|
||||
yesSignal = Signal()
|
||||
cancelSignal = Signal()
|
||||
|
||||
def __init__(self, title: str, content: str, parent):
|
||||
super().__init__(parent=parent)
|
||||
self.content = content
|
||||
self.titleLabel = QLabel(title, self.widget)
|
||||
self.contentLabel = QLabel(content, self.widget)
|
||||
self.yesButton = QPushButton(self.tr('OK'), self.widget)
|
||||
self.cancelButton = QPushButton(self.tr('Cancel'), self.widget)
|
||||
self.__initWidget()
|
||||
|
||||
def __initWidget(self):
|
||||
""" initialize widgets """
|
||||
self.windowMask.resize(self.size())
|
||||
self.widget.setMaximumWidth(540)
|
||||
self.titleLabel.move(24, 24)
|
||||
self.contentLabel.move(24, 56)
|
||||
self.contentLabel.setText(TextWrap.wrap(self.content, 71)[0])
|
||||
|
||||
self.__setQss()
|
||||
self.__initLayout()
|
||||
|
||||
# connect signal to slot
|
||||
self.yesButton.clicked.connect(self.__onYesButtonClicked)
|
||||
self.cancelButton.clicked.connect(self.__onCancelButtonClicked)
|
||||
|
||||
def __initLayout(self):
|
||||
""" initialize layout """
|
||||
self.contentLabel.adjustSize()
|
||||
self.widget.setFixedSize(48+self.contentLabel.width(),
|
||||
self.contentLabel.y() + self.contentLabel.height()+92)
|
||||
self.yesButton.resize((self.widget.width() - 54) // 2, 32)
|
||||
self.cancelButton.resize(self.yesButton.width(), 32)
|
||||
self.yesButton.move(24, self.widget.height()-56)
|
||||
self.cancelButton.move(
|
||||
self.widget.width()-24-self.cancelButton.width(), self.widget.height()-56)
|
||||
|
||||
def __onCancelButtonClicked(self):
|
||||
self.cancelSignal.emit()
|
||||
self.reject()
|
||||
|
||||
def __onYesButtonClicked(self):
|
||||
self.setEnabled(False)
|
||||
self.yesSignal.emit()
|
||||
self.accept()
|
||||
|
||||
def __setQss(self):
|
||||
""" set style sheet """
|
||||
self.windowMask.setObjectName('windowMask')
|
||||
self.titleLabel.setObjectName('titleLabel')
|
||||
self.contentLabel.setObjectName('contentLabel')
|
||||
FluentStyleSheet.MESSAGE_DIALOG.apply(self)
|
||||
Reference in New Issue
Block a user