Files
2026-11-06 01:04:35 +08:00

92 lines
3.9 KiB
C++

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
#include <QShortcut>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_clock.start();
m_refreshTimer.setInterval(100);
connect(&m_refreshTimer, &QTimer::timeout, this, &MainWindow::refreshDisplay);
for (QSpinBox *spin : {ui->hoursSpin, ui->minutesSpin, ui->secondsSpin})
connect(spin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
this, &MainWindow::durationChanged);
connect(ui->startButton, &QPushButton::clicked, this, [this] {
m_countdown.start(m_clock.elapsed());
refreshDisplay();
});
connect(ui->pauseButton, &QPushButton::clicked, this, [this] {
const auto previousState = m_countdown.state();
m_countdown.pause(m_clock.elapsed());
if (previousState == Countdown::State::Running
&& m_countdown.state() == Countdown::State::Finished
&& ui->soundCheck->isChecked())
QApplication::beep();
refreshDisplay();
});
connect(ui->resetButton, &QPushButton::clicked, this, [this] {
m_countdown.reset();
refreshDisplay();
});
connect(ui->fullscreenButton, &QPushButton::clicked, this, [this] {
if (isFullScreen()) showNormal(); else showFullScreen();
ui->fullscreenButton->setText(isFullScreen() ? tr("退出全屏") : tr("全屏显示"));
});
auto *escape = new QShortcut(QKeySequence(Qt::Key_Escape), this);
connect(escape, &QShortcut::activated, this, [this] {
if (isFullScreen()) {
showNormal();
ui->fullscreenButton->setText(tr("全屏显示"));
}
});
durationChanged();
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::durationChanged()
{
const qint64 seconds = ui->hoursSpin->value() * 3600
+ ui->minutesSpin->value() * 60 + ui->secondsSpin->value();
m_countdown.setDuration(seconds * 1000);
refreshDisplay();
}
void MainWindow::refreshDisplay()
{
const qint64 now = m_clock.elapsed();
const auto previousState = m_countdown.state();
m_countdown.update(now);
const auto state = m_countdown.state();
const bool running = state == Countdown::State::Running;
const bool paused = state == Countdown::State::Paused;
if (running && !m_refreshTimer.isActive()) m_refreshTimer.start();
if (!running) m_refreshTimer.stop();
const qint64 remaining = m_countdown.remaining(now);
// 向上取整:还剩 1 毫秒时显示 1 秒,真正到时才显示零。
const qint64 seconds = (remaining + 999) / 1000;
ui->timeLabel->setText(QStringLiteral("%1:%2:%3")
.arg(seconds / 3600, 2, 10, QLatin1Char('0'))
.arg((seconds / 60) % 60, 2, 10, QLatin1Char('0'))
.arg(seconds % 60, 2, 10, QLatin1Char('0')));
ui->progressBar->setValue(m_countdown.duration() == 0 ? 0
: static_cast<int>(remaining * 1000 / m_countdown.duration()));
ui->durationGroup->setEnabled(!running && !paused);
ui->startButton->setEnabled(!running && m_countdown.duration() > 0);
ui->pauseButton->setEnabled(running);
ui->startButton->setText(paused ? tr("继续") :
state == Countdown::State::Finished ? tr("重新开始") : tr("开始"));
if (running) ui->statusLabel->setText(tr("正在计时"));
else if (paused) ui->statusLabel->setText(tr("已暂停 · 点击“继续”接着计时"));
else if (state == Countdown::State::Finished)
ui->statusLabel->setText(tr("时间到!本轮计时已结束。"));
else ui->statusLabel->setText(m_countdown.duration() > 0
? tr("准备就绪 · 点击“开始”") : tr("请先设置大于 0 的时长。"));
if (previousState == Countdown::State::Running && state == Countdown::State::Finished
&& ui->soundCheck->isChecked())
QApplication::beep();
}