// ============================================================================
//  qdialog_showcase —— QDialog 教学综合示例
//  参考川大 wiki「6 对话框 QDialog」(pageId 183664881) 的 6.2–6.5：
//    6.3 模态/非模态（exec / open / show + WA_DeleteOnClose）
//    6.4 QMessageBox（六个 static + 实例 API）
//    6.2/6.5 标准对话框（QFileDialog / QColorDialog / QFontDialog / QInputDialog）
//  形态：一个 QWidget 布满 pushbutton，每个按钮触发一种 QDialog 行为。
//  纯代码（无 .ui）；主类不定义信号槽，全部用 lambda 连接 QPushButton::clicked。
// ============================================================================
#include <utility>

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QDialog>
#include <QMessageBox>
#include <QFileDialog>
#include <QColorDialog>
#include <QFontDialog>
#include <QInputDialog>
#include <QLineEdit>
#include <QTimer>
#include "dialog.h"

class DialogShowcase : public QWidget {
public:
    explicit DialogShowcase(QWidget *parent = nullptr) : QWidget(parent) {
        auto *root = new QVBoxLayout(this);

        // 反馈标签：显示标准对话框 / question 的返回值
        statusLabel = new QLabel(QStringLiteral("点击下方按钮，体验不同的 QDialog 行为。"));
        statusLabel->setWordWrap(true);
        statusLabel->setMinimumHeight(36);

        // ① 模态/非模态（6.3） -------------------------------------------------
        auto *g1 = new QGroupBox(QStringLiteral("① 模态/非模态（6.3）"));
        auto *l1 = new QGridLayout(g1);
        addBtn(l1, 0, 0, QStringLiteral("模态 exec"), [this] {
            QDialog d(this);
            d.setWindowTitle(QStringLiteral("模态对话框（exec）"));
            d.exec();   // 应用级模态：阻塞整个应用，直到关闭
            setStatus(QStringLiteral("exec() 返回 —— 应用级模态已关闭"));
        });
        addBtn(l1, 0, 1, QStringLiteral("窗口模态 open"), [this] {
            auto *d = new QDialog(this);
            d->setWindowTitle(QStringLiteral("窗口级模态（open）"));
            d->setAttribute(Qt::WA_DeleteOnClose);
            d->open();  // 窗口级模态：仅阻塞父窗口，其余窗口仍可交互
            setStatus(QStringLiteral("open() 弹出窗口级模态（仅阻塞父窗口）"));
        });
        addBtn(l1, 1, 0, QStringLiteral("非模态 show"), [this] {
            // 必须用堆对象：栈对象在 show() 返回后随作用域结束而析构，对话框一闪而过
            // （页面 6.3 强调的坑）。这里给 parent this，由 Qt 对象树托管生命周期。
            auto *d = new QDialog(this);
            d->setWindowTitle(QStringLiteral("非模态对话框（show）"));
            d->show();  // 非模态：立即返回、不阻塞，可与主窗口同时操作
            setStatus(QStringLiteral("show() 非模态弹出（不阻塞）"));
        });
        addBtn(l1, 1, 1, QStringLiteral("非模态+删除关闭"), [this] {
            // 无 parent 的堆对象：靠 WA_DeleteOnClose 在关闭时自动 delete，避免泄漏
            auto *d = new QDialog;
            d->setWindowTitle(QStringLiteral("WA_DeleteOnClose"));
            d->setAttribute(Qt::WA_DeleteOnClose);
            d->show();
            setStatus(QStringLiteral("show() + WA_DeleteOnClose：关闭即销毁"));
        });

        // ② QMessageBox（6.4） -------------------------------------------------
        auto *g2 = new QGroupBox(QStringLiteral("② QMessageBox（6.4）"));
        auto *l2 = new QGridLayout(g2);
        addBtn(l2, 0, 0, QStringLiteral("about"), [this] {
            QMessageBox::about(this, QStringLiteral("about"),
                               QStringLiteral("这是 about 对话框（只有一个 OK）。"));
        });
        addBtn(l2, 0, 1, QStringLiteral("aboutQt"), [this] {
            QMessageBox::aboutQt(this, QStringLiteral("aboutQt"));
        });
        addBtn(l2, 0, 2, QStringLiteral("critical"), [this] {
            QMessageBox::critical(this, QStringLiteral("critical"), QStringLiteral("严重错误！"));
        });
        addBtn(l2, 1, 0, QStringLiteral("information"), [this] {
            QMessageBox::information(this, QStringLiteral("information"), QStringLiteral("提示信息。"));
        });
        addBtn(l2, 1, 1, QStringLiteral("question"), [this] {
            const auto r = QMessageBox::question(this, QStringLiteral("question"),
                                                 QStringLiteral("你确定吗？"),
                                                 QMessageBox::Yes | QMessageBox::No,
                                                 QMessageBox::Yes);
            setStatus(QStringLiteral("question 返回：%1")
                          .arg(r == QMessageBox::Yes ? QStringLiteral("Yes") : QStringLiteral("No")));
        });
        addBtn(l2, 1, 2, QStringLiteral("warning"), [this] {
            QMessageBox::warning(this, QStringLiteral("warning"), QStringLiteral("警告！"));
        });
        addBtn(l2, 2, 0, QStringLiteral("自定义消息框"), [this] {
            QMessageBox box(QMessageBox::Question, QStringLiteral("自定义消息框"),
                            QStringLiteral("文档已被修改。"),
                            QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, this);
            box.setInformativeText(QStringLiteral("是否保存修改？"));
            box.setDetailedText(QStringLiteral("这里是详细差异信息……"));
            box.setDefaultButton(QMessageBox::Save);
            const int r = box.exec();
            const QString name =
                (r == QMessageBox::Save)    ? QStringLiteral("保存") :
                (r == QMessageBox::Discard) ? QStringLiteral("丢弃") :
                                              QStringLiteral("取消");
            setStatus(QStringLiteral("自定义消息框返回：%1").arg(name));
        });

        // ③ 标准对话框（6.2 / 6.5） -------------------------------------------
        auto *g3 = new QGroupBox(QStringLiteral("③ 标准对话框（6.2 / 6.5）"));
        auto *l3 = new QGridLayout(g3);
        addBtn(l3, 0, 0, QStringLiteral("打开文件"), [this] {
            const QString f = QFileDialog::getOpenFileName(this, QStringLiteral("打开文件"));
            if (!f.isEmpty()) setStatus(QStringLiteral("打开文件：%1").arg(f));
        });
        addBtn(l3, 0, 1, QStringLiteral("保存文件"), [this] {
            const QString f = QFileDialog::getSaveFileName(this, QStringLiteral("保存文件"));
            if (!f.isEmpty()) setStatus(QStringLiteral("保存文件：%1").arg(f));
        });
        addBtn(l3, 1, 0, QStringLiteral("选颜色"), [this] {
            const QColor c = QColorDialog::getColor(Qt::white, this, QStringLiteral("选颜色"));
            if (c.isValid())
                setStatus(QStringLiteral("选中颜色 RGB(%1,%2,%3)")
                              .arg(c.red()).arg(c.green()).arg(c.blue()));
        });
        addBtn(l3, 1, 1, QStringLiteral("选字体"), [this] {
            bool ok = false;
            const QFont f = QFontDialog::getFont(&ok, font(), this, QStringLiteral("选字体"));
            if (ok) setStatus(QStringLiteral("选中字体：%1").arg(f.family()));
        });
        addBtn(l3, 2, 0, QStringLiteral("输入文字"), [this] {
            bool ok = false;
            const QString s = QInputDialog::getText(this, QStringLiteral("输入文字"),
                                                    QStringLiteral("请输入："),
                                                    QLineEdit::Normal, QString(), &ok);
            if (ok) setStatus(QStringLiteral("输入：%1").arg(s));
        });
        addBtn(l3, 2, 0, QStringLiteral("输入文字"), [this] {
            bool ok = false;
            const QString s = QInputDialog::getText(this, QStringLiteral("输入文字"),
                                                    QStringLiteral("请输入："),
                                                    QLineEdit::Normal, QString(), &ok);
            if (ok) setStatus(QStringLiteral("输入：%1").arg(s));
        });
        addBtn(l3, 2, 1, QStringLiteral("自定义对话框"), [] {
            QDialog *customDialog = new Dialog();
            customDialog->setAttribute(Qt::WA_DeleteOnClose);
            customDialog->exec();
        });
        root->addWidget(g1);
        root->addWidget(g2);
        root->addWidget(g3);
        root->addWidget(statusLabel);

        setWindowTitle(QStringLiteral("QDialog 教学综合示例"));
        resize(520, 430);
    }

private:
    QLabel *statusLabel = nullptr;

    // 在 QGridLayout(row, col) 放一个按钮，clicked 连到 lambda
    template <typename F>
    void addBtn(QGridLayout *layout, int row, int col, const QString &text, F &&slot) {
        auto *btn = new QPushButton(text, this);
        layout->addWidget(btn, row, col);
        connect(btn, &QPushButton::clicked, this, std::forward<F>(slot));
    }

    void setStatus(const QString &s) { statusLabel->setText(s); }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    DialogShowcase w;
    w.show();
    // 仅在离屏自动化验证时 200ms 后自动退出（仿 p03 风格）；
    // 正常运行窗口保持，不自动退出。不点按钮则不触发任何对话框。
    if (qgetenv("QT_QPA_PLATFORM") == "offscreen") {
        QTimer::singleShot(200, &app, &QApplication::quit);
    }
    return app.exec();
}
