323 lines
8.5 KiB
C++
323 lines
8.5 KiB
C++
#include "overlaydialogswidget.h"
|
||
#include <QApplication>
|
||
|
||
OverlayDialog::OverlayDialog(QWidget *parent)
|
||
: QWidget(parent), m_type(Information), m_inputMode(false)
|
||
{
|
||
setupUI();
|
||
hide();
|
||
}
|
||
|
||
void OverlayDialog::setupUI()
|
||
{
|
||
// 设置为覆盖整个父窗口
|
||
setAttribute(Qt::WA_StyledBackground);
|
||
setStyleSheet("background: transparent;");
|
||
|
||
auto *mainLayout = new QVBoxLayout(this);
|
||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||
|
||
// 半透明背景遮罩
|
||
m_backgroundOverlay = new QWidget(this);
|
||
m_backgroundOverlay->setStyleSheet("background: rgba(0, 0, 0, 0.5);");
|
||
mainLayout->addWidget(m_backgroundOverlay);
|
||
|
||
// 对话框容器 - 居中显示
|
||
m_dialogContainer = new QWidget(m_backgroundOverlay);
|
||
m_dialogContainer->setFixedWidth(420);
|
||
m_dialogContainer->setStyleSheet(
|
||
"QWidget { background: white; border-radius: 12px; }");
|
||
|
||
auto *dialogLayout = new QVBoxLayout(m_dialogContainer);
|
||
dialogLayout->setContentsMargins(24, 24, 24, 20);
|
||
dialogLayout->setSpacing(16);
|
||
|
||
// 标题栏
|
||
auto *headerLayout = new QHBoxLayout();
|
||
headerLayout->setSpacing(12);
|
||
|
||
m_iconLabel = new QLabel(this);
|
||
m_iconLabel->setFixedSize(32, 32);
|
||
m_iconLabel->setAlignment(Qt::AlignCenter);
|
||
m_iconLabel->setStyleSheet("font-size: 24px;");
|
||
headerLayout->addWidget(m_iconLabel);
|
||
|
||
m_titleLabel = new QLabel("提示", this);
|
||
m_titleLabel->setStyleSheet(
|
||
"font-size: 18px; font-weight: bold; color: #263238;");
|
||
headerLayout->addWidget(m_titleLabel, 1);
|
||
|
||
dialogLayout->addLayout(headerLayout);
|
||
|
||
// 消息内容
|
||
m_messageLabel = new QLabel(this);
|
||
m_messageLabel->setWordWrap(true);
|
||
m_messageLabel->setStyleSheet(
|
||
"font-size: 14px; color: #546E7A; line-height: 1.6; padding: 8px 0;");
|
||
dialogLayout->addWidget(m_messageLabel);
|
||
|
||
// 输入框(默认隐藏)
|
||
m_inputEdit = new QLineEdit(this);
|
||
m_inputEdit->setFixedHeight(44);
|
||
m_inputEdit->setStyleSheet(
|
||
"QLineEdit { border: 2px solid #E0E0E0; border-radius: 8px; padding: 0 12px; "
|
||
"font-size: 14px; background: #FAFAFA; }"
|
||
"QLineEdit:focus { border-color: #1976D2; background: white; }");
|
||
m_inputEdit->hide();
|
||
dialogLayout->addWidget(m_inputEdit);
|
||
|
||
// 按钮区域
|
||
auto *buttonLayout = new QHBoxLayout();
|
||
buttonLayout->setSpacing(12);
|
||
buttonLayout->addStretch();
|
||
|
||
m_rejectBtn = new QPushButton("取消", this);
|
||
m_rejectBtn->setFixedSize(100, 44);
|
||
m_rejectBtn->setCursor(Qt::PointingHandCursor);
|
||
m_rejectBtn->setStyleSheet(
|
||
"QPushButton { background: #ECEFF1; color: #546E7A; border: none; "
|
||
"border-radius: 8px; font-size: 14px; font-weight: 500; }"
|
||
"QPushButton:hover { background: #CFD8DC; }"
|
||
"QPushButton:pressed { background: #B0BEC5; }");
|
||
connect(m_rejectBtn, &QPushButton::clicked, this, &OverlayDialog::onRejectClicked);
|
||
buttonLayout->addWidget(m_rejectBtn);
|
||
|
||
m_acceptBtn = new QPushButton("确定", this);
|
||
m_acceptBtn->setFixedSize(100, 44);
|
||
m_acceptBtn->setCursor(Qt::PointingHandCursor);
|
||
m_acceptBtn->setStyleSheet(
|
||
"QPushButton { background: #1976D2; color: white; border: none; "
|
||
"border-radius: 8px; font-size: 14px; font-weight: 500; }"
|
||
"QPushButton:hover { background: #1565C0; }"
|
||
"QPushButton:pressed { background: #0D47A1; }");
|
||
connect(m_acceptBtn, &QPushButton::clicked, this, &OverlayDialog::onAcceptClicked);
|
||
buttonLayout->addWidget(m_acceptBtn);
|
||
|
||
dialogLayout->addLayout(buttonLayout);
|
||
|
||
// 居中布局
|
||
auto *overlayLayout = new QVBoxLayout(m_backgroundOverlay);
|
||
overlayLayout->addStretch();
|
||
auto *centerLayout = new QHBoxLayout();
|
||
centerLayout->addStretch();
|
||
centerLayout->addWidget(m_dialogContainer);
|
||
centerLayout->addStretch();
|
||
overlayLayout->addLayout(centerLayout);
|
||
overlayLayout->addStretch();
|
||
}
|
||
|
||
void OverlayDialog::setTitle(const QString &title)
|
||
{
|
||
m_titleLabel->setText(title);
|
||
}
|
||
|
||
void OverlayDialog::setMessage(const QString &message)
|
||
{
|
||
m_messageLabel->setText(message);
|
||
}
|
||
|
||
void OverlayDialog::setDialogType(DialogType type)
|
||
{
|
||
m_type = type;
|
||
updateTypeIcon();
|
||
|
||
// 根据类型调整按钮显示
|
||
switch (type)
|
||
{
|
||
case Information:
|
||
case Warning:
|
||
m_rejectBtn->hide();
|
||
m_acceptBtn->setText("确定");
|
||
break;
|
||
case Question:
|
||
m_rejectBtn->show();
|
||
m_rejectBtn->setText("取消");
|
||
m_acceptBtn->setText("确定");
|
||
break;
|
||
case Input:
|
||
m_rejectBtn->show();
|
||
m_rejectBtn->setText("取消");
|
||
m_acceptBtn->setText("确定");
|
||
break;
|
||
}
|
||
}
|
||
|
||
void OverlayDialog::setInputMode(bool inputMode, const QString &placeholder)
|
||
{
|
||
m_inputMode = inputMode;
|
||
m_inputEdit->setVisible(inputMode);
|
||
m_inputEdit->setPlaceholderText(placeholder);
|
||
m_inputEdit->clear();
|
||
}
|
||
|
||
void OverlayDialog::setCallback(std::function<void(bool, const QString &)> callback)
|
||
{
|
||
m_callback = callback;
|
||
}
|
||
|
||
void OverlayDialog::updateTypeIcon()
|
||
{
|
||
QString icon;
|
||
QString color;
|
||
|
||
switch (m_type)
|
||
{
|
||
case Information:
|
||
icon = "ℹ";
|
||
color = "#1976D2";
|
||
break;
|
||
case Warning:
|
||
icon = "⚠";
|
||
color = "#F57C00";
|
||
break;
|
||
case Question:
|
||
icon = "?";
|
||
color = "#1976D2";
|
||
break;
|
||
case Input:
|
||
icon = "✏";
|
||
color = "#1976D2";
|
||
break;
|
||
}
|
||
|
||
m_iconLabel->setText(icon);
|
||
m_iconLabel->setStyleSheet(QString("font-size: 24px; color: %1;").arg(color));
|
||
}
|
||
|
||
void OverlayDialog::showDialog()
|
||
{
|
||
if (parentWidget())
|
||
{
|
||
setGeometry(parentWidget()->rect());
|
||
}
|
||
show();
|
||
raise();
|
||
animateShow();
|
||
|
||
if (m_inputMode)
|
||
{
|
||
m_inputEdit->setFocus();
|
||
}
|
||
}
|
||
|
||
void OverlayDialog::hideDialog()
|
||
{
|
||
animateHide();
|
||
}
|
||
|
||
void OverlayDialog::onAcceptClicked()
|
||
{
|
||
QString inputText = m_inputMode ? m_inputEdit->text() : QString();
|
||
emit accepted(inputText);
|
||
|
||
if (m_callback)
|
||
{
|
||
m_callback(true, inputText);
|
||
}
|
||
|
||
hideDialog();
|
||
}
|
||
|
||
void OverlayDialog::onRejectClicked()
|
||
{
|
||
emit rejected();
|
||
|
||
if (m_callback)
|
||
{
|
||
m_callback(false, QString());
|
||
}
|
||
|
||
hideDialog();
|
||
}
|
||
|
||
void OverlayDialog::animateShow()
|
||
{
|
||
QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(this);
|
||
setGraphicsEffect(effect);
|
||
|
||
QPropertyAnimation *animation = new QPropertyAnimation(effect, "opacity");
|
||
animation->setDuration(150);
|
||
animation->setStartValue(0.0);
|
||
animation->setEndValue(1.0);
|
||
animation->start(QPropertyAnimation::DeleteWhenStopped);
|
||
}
|
||
|
||
void OverlayDialog::animateHide()
|
||
{
|
||
QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(this);
|
||
setGraphicsEffect(effect);
|
||
|
||
QPropertyAnimation *animation = new QPropertyAnimation(effect, "opacity");
|
||
animation->setDuration(100);
|
||
animation->setStartValue(1.0);
|
||
animation->setEndValue(0.0);
|
||
|
||
connect(animation, &QPropertyAnimation::finished, this, [this]()
|
||
{
|
||
hide();
|
||
deleteLater(); });
|
||
animation->start(QPropertyAnimation::DeleteWhenStopped);
|
||
}
|
||
|
||
// 静态便捷方法
|
||
void OverlayDialog::information(QWidget *parent, const QString &title, const QString &message)
|
||
{
|
||
// 找到顶层窗口
|
||
QWidget *topLevel = parent;
|
||
while (topLevel->parentWidget())
|
||
topLevel = topLevel->parentWidget();
|
||
|
||
auto *dialog = new OverlayDialog(topLevel);
|
||
dialog->setTitle(title);
|
||
dialog->setMessage(message);
|
||
dialog->setDialogType(Information);
|
||
dialog->showDialog();
|
||
}
|
||
|
||
void OverlayDialog::warning(QWidget *parent, const QString &title, const QString &message)
|
||
{
|
||
QWidget *topLevel = parent;
|
||
while (topLevel->parentWidget())
|
||
topLevel = topLevel->parentWidget();
|
||
|
||
auto *dialog = new OverlayDialog(topLevel);
|
||
dialog->setTitle(title);
|
||
dialog->setMessage(message);
|
||
dialog->setDialogType(Warning);
|
||
dialog->showDialog();
|
||
}
|
||
|
||
void OverlayDialog::question(QWidget *parent, const QString &title, const QString &message,
|
||
std::function<void(bool)> callback)
|
||
{
|
||
QWidget *topLevel = parent;
|
||
while (topLevel->parentWidget())
|
||
topLevel = topLevel->parentWidget();
|
||
|
||
auto *dialog = new OverlayDialog(topLevel);
|
||
dialog->setTitle(title);
|
||
dialog->setMessage(message);
|
||
dialog->setDialogType(Question);
|
||
dialog->setCallback([callback](bool accepted, const QString &)
|
||
{ callback(accepted); });
|
||
dialog->showDialog();
|
||
}
|
||
|
||
void OverlayDialog::input(QWidget *parent, const QString &title, const QString &prompt,
|
||
std::function<void(bool, const QString &)> callback,
|
||
const QString &defaultText)
|
||
{
|
||
QWidget *topLevel = parent;
|
||
while (topLevel->parentWidget())
|
||
topLevel = topLevel->parentWidget();
|
||
|
||
auto *dialog = new OverlayDialog(topLevel);
|
||
dialog->setTitle(title);
|
||
dialog->setMessage(prompt);
|
||
dialog->setDialogType(Input);
|
||
dialog->setInputMode(true, "请输入...");
|
||
dialog->m_inputEdit->setText(defaultText);
|
||
dialog->setCallback(callback);
|
||
dialog->showDialog();
|
||
}
|