223 lines
6.0 KiB
Python
223 lines
6.0 KiB
Python
"""标准对话框(QMessageBox / QInputDialog / QFileDialog)与当前主题一致。"""
|
||
from __future__ import annotations
|
||
|
||
from PyQt6.QtWidgets import (
|
||
QFileDialog,
|
||
QInputDialog,
|
||
QMessageBox,
|
||
QWidget,
|
||
QDialog,
|
||
)
|
||
|
||
import ui.theme as theme
|
||
|
||
|
||
def stylesheet() -> str:
|
||
t = theme.current()
|
||
bg = t["menu_bg"]
|
||
fg = t["menu_color"]
|
||
border = t["menu_border"]
|
||
hover = t["menu_selected"]
|
||
inp = t["search_bg"]
|
||
inp_b = t["search_border"]
|
||
focus = t["search_focus"]
|
||
return f"""
|
||
QMessageBox {{
|
||
background-color: {bg};
|
||
color: {fg};
|
||
}}
|
||
QMessageBox QLabel {{
|
||
color: {fg};
|
||
background: transparent;
|
||
min-width: 160px;
|
||
}}
|
||
QMessageBox QPushButton {{
|
||
min-width: 64px;
|
||
padding: 6px 14px;
|
||
border: 1px solid {border};
|
||
border-radius: 5px;
|
||
background: {inp};
|
||
color: {fg};
|
||
}}
|
||
QMessageBox QPushButton:hover {{
|
||
background: {hover};
|
||
}}
|
||
QMessageBox QPushButton:default {{
|
||
border-color: {focus};
|
||
}}
|
||
QInputDialog {{
|
||
background-color: {bg};
|
||
color: {fg};
|
||
}}
|
||
QInputDialog QLabel {{
|
||
color: {fg};
|
||
background: transparent;
|
||
}}
|
||
QInputDialog QLineEdit {{
|
||
background: {inp};
|
||
border: 1px solid {inp_b};
|
||
border-radius: 5px;
|
||
padding: 6px 8px;
|
||
color: {fg};
|
||
min-width: 260px;
|
||
}}
|
||
QInputDialog QLineEdit:focus {{
|
||
border-color: {focus};
|
||
}}
|
||
QInputDialog QPushButton {{
|
||
min-width: 72px;
|
||
padding: 6px 14px;
|
||
border: 1px solid {border};
|
||
border-radius: 5px;
|
||
background: {inp};
|
||
color: {fg};
|
||
}}
|
||
QInputDialog QPushButton:hover {{
|
||
background: {hover};
|
||
}}
|
||
QFileDialog {{
|
||
background-color: {bg};
|
||
color: {fg};
|
||
}}
|
||
QFileDialog QLabel {{
|
||
color: {fg};
|
||
background: transparent;
|
||
}}
|
||
QFileDialog QLineEdit, QFileDialog QComboBox {{
|
||
background: {inp};
|
||
border: 1px solid {inp_b};
|
||
border-radius: 4px;
|
||
padding: 4px 6px;
|
||
color: {fg};
|
||
}}
|
||
QFileDialog QLineEdit:focus, QFileDialog QComboBox:focus {{
|
||
border-color: {focus};
|
||
}}
|
||
QFileDialog QTreeView, QFileDialog QListView, QFileDialog QTableView {{
|
||
background: {inp};
|
||
border: 1px solid {inp_b};
|
||
border-radius: 4px;
|
||
color: {fg};
|
||
outline: none;
|
||
}}
|
||
QFileDialog QTreeView::item:selected, QFileDialog QListView::item:selected {{
|
||
background: {hover};
|
||
}}
|
||
QFileDialog QPushButton {{
|
||
min-width: 72px;
|
||
padding: 6px 12px;
|
||
border: 1px solid {border};
|
||
border-radius: 5px;
|
||
background: {inp};
|
||
color: {fg};
|
||
}}
|
||
QFileDialog QPushButton:hover {{
|
||
background: {hover};
|
||
}}
|
||
QFileDialog QComboBox QAbstractItemView {{
|
||
background: {bg};
|
||
color: {fg};
|
||
border: 1px solid {border};
|
||
}}
|
||
"""
|
||
|
||
|
||
def _apply(w: QWidget | None) -> None:
|
||
if w is not None:
|
||
w.setStyleSheet(stylesheet())
|
||
|
||
|
||
def question(
|
||
parent: QWidget | None,
|
||
title: str,
|
||
text: str,
|
||
*,
|
||
buttons: QMessageBox.StandardButton = (
|
||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||
),
|
||
default_button: QMessageBox.StandardButton | None = None,
|
||
icon: QMessageBox.Icon = QMessageBox.Icon.Question,
|
||
) -> QMessageBox.StandardButton:
|
||
msg = QMessageBox(parent)
|
||
msg.setWindowTitle(title)
|
||
msg.setText(text)
|
||
msg.setIcon(icon)
|
||
msg.setStandardButtons(buttons)
|
||
if default_button is not None:
|
||
msg.setDefaultButton(default_button)
|
||
_apply(msg)
|
||
# 防止对话框因为文本长度/默认最小宽度变得过宽
|
||
msg.setFixedWidth(320)
|
||
return QMessageBox.StandardButton(msg.exec())
|
||
|
||
|
||
def warning(parent: QWidget | None, title: str, text: str) -> None:
|
||
msg = QMessageBox(parent)
|
||
msg.setWindowTitle(title)
|
||
msg.setText(text)
|
||
msg.setIcon(QMessageBox.Icon.Warning)
|
||
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
|
||
_apply(msg)
|
||
msg.setFixedWidth(320)
|
||
msg.exec()
|
||
|
||
|
||
def information(parent: QWidget | None, title: str, text: str) -> None:
|
||
msg = QMessageBox(parent)
|
||
msg.setWindowTitle(title)
|
||
msg.setText(text)
|
||
msg.setIcon(QMessageBox.Icon.Information)
|
||
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
|
||
_apply(msg)
|
||
msg.setFixedWidth(320)
|
||
msg.exec()
|
||
|
||
|
||
def get_text(
|
||
parent: QWidget | None,
|
||
title: str,
|
||
label: str,
|
||
text: str = "",
|
||
) -> tuple[str, bool]:
|
||
d = QInputDialog(parent)
|
||
d.setWindowTitle(title)
|
||
d.setLabelText(label)
|
||
d.setTextValue(text)
|
||
_apply(d)
|
||
ok = d.exec() == QDialog.DialogCode.Accepted
|
||
return d.textValue(), ok
|
||
|
||
|
||
def get_open_file_name(
|
||
parent: QWidget | None,
|
||
caption: str,
|
||
directory: str,
|
||
filter_str: str,
|
||
) -> tuple[str, str]:
|
||
fd = QFileDialog(parent, caption, directory, filter_str)
|
||
fd.setOption(QFileDialog.Option.DontUseNativeDialog, True)
|
||
fd.setFileMode(QFileDialog.FileMode.ExistingFile)
|
||
_apply(fd)
|
||
if fd.exec() == QDialog.DialogCode.Accepted:
|
||
files = fd.selectedFiles()
|
||
if files:
|
||
return files[0], fd.selectedNameFilter()
|
||
return "", ""
|
||
|
||
|
||
def get_existing_directory(
|
||
parent: QWidget | None,
|
||
caption: str,
|
||
directory: str = "",
|
||
) -> str:
|
||
fd = QFileDialog(parent, caption, directory)
|
||
fd.setOption(QFileDialog.Option.DontUseNativeDialog, True)
|
||
fd.setFileMode(QFileDialog.FileMode.Directory)
|
||
fd.setOption(QFileDialog.Option.ShowDirsOnly, True)
|
||
_apply(fd)
|
||
if fd.exec() == QDialog.DialogCode.Accepted:
|
||
files = fd.selectedFiles()
|
||
if files:
|
||
return files[0]
|
||
return ""
|