"""标准对话框(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 ""