ScreenLockDetector/src/customwidget.cpp

426 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "customwidget.h"
#include <QPaintEvent>
#include <QPainterPath>
#include <QDebug>
#include <cmath>
CustomWidget::CustomWidget(QWidget *parent)
: RenderWidgetBase(parent)
, m_animationTimer(nullptr)
, m_paintingEnabled(true)
, m_frameCount(0)
, m_rotationAngle(0.0)
, m_wavePhase(0.0)
, m_startTime(QDateTime::currentDateTime())
, m_lastLockDuration(0)
, m_lastLockFrameCount(0)
, m_lockPaintFrameCount(0)
, m_lockCount(0)
, m_lastFrameTime(QDateTime::currentDateTime())
, m_currentFps(0.0)
{
// 设置窗口属性
setMinimumSize(600, 400);
// 创建动画定时器 - 60 FPS
m_animationTimer = new QTimer(this);
connect(m_animationTimer, &QTimer::timeout, this, &CustomWidget::onAnimationTimer);
m_animationTimer->start(16); // 约60 FPS (1000/60 ≈ 16ms)
// Initialize FPS calculation
m_frameTimes.reserve(FPS_SAMPLE_COUNT);
qDebug() << "CustomWidget created, animation timer started";
}
CustomWidget::~CustomWidget()
{
if (m_animationTimer) {
m_animationTimer->stop();
}
qDebug() << "CustomWidget destroyed, total frames painted:" << m_frameCount;
}
void CustomWidget::setPaintingEnabled(bool enabled)
{
if (m_paintingEnabled != enabled) {
m_paintingEnabled = enabled;
if (enabled) {
qDebug() << "Painting ENABLED - Resuming animations";
m_animationTimer->start(16);
// 解锁:计算锁屏持续时间
if (m_lastLockTime.isValid()) {
QDateTime unlockTime = QDateTime::currentDateTime();
m_lastLockDuration = m_lastLockTime.secsTo(unlockTime);
// 计算锁屏期间绘制的帧数通常应该是0或很小
m_lockPaintFrameCount = m_frameCount - m_lastLockFrameCount;
qDebug() << "Screen was locked for" << m_lastLockDuration << "seconds";
qDebug() << "Frames at lock:" << m_lastLockFrameCount
<< "- Frames painted during lock:" << m_lockPaintFrameCount;
}
m_startTime = QDateTime::currentDateTime();
} else {
qDebug() << "Painting DISABLED - Stopping animations";
m_animationTimer->stop();
// 锁屏:记录锁屏时间
m_pauseTime = QDateTime::currentDateTime();
m_lastLockTime = m_pauseTime;
m_lastLockFrameCount = m_frameCount;
m_lockCount++;
qDebug() << "Screen locked at" << m_lastLockTime.toString("yyyy-MM-dd hh:mm:ss")
<< "- Lock count:" << m_lockCount
<< "- Frame count at lock:" << m_lastLockFrameCount;
}
// 触发重绘以更新状态显示
update();
}
}
bool CustomWidget::isPaintingEnabled() const
{
return m_paintingEnabled;
}
int CustomWidget::getPaintFrameCount() const
{
return m_frameCount;
}
void CustomWidget::resetFrameCount()
{
m_frameCount = 0;
qDebug() << "Frame count reset";
}
// 实现 RenderWidgetBase 接口
bool CustomWidget::initializeRenderer()
{
// QPainter不需要特殊初始化始终返回true
return true;
}
void CustomWidget::setRenderingEnabled(bool enabled)
{
setPaintingEnabled(enabled);
}
bool CustomWidget::isRenderingEnabled() const
{
return isPaintingEnabled();
}
int CustomWidget::getRenderFrameCount() const
{
return getPaintFrameCount();
}
bool CustomWidget::isInitialized() const
{
// QPainter始终处于初始化状态
return true;
}
QString CustomWidget::getLastError() const
{
// QPainter通常不会有错误
return QString();
}
QString CustomWidget::getRendererType() const
{
return QString("QPainter");
}
void CustomWidget::onAnimationTimer()
{
if (m_paintingEnabled) {
// 更新动画参数
m_rotationAngle += 2.0;
if (m_rotationAngle >= 360.0) {
m_rotationAngle -= 360.0;
}
m_wavePhase += 0.05;
if (m_wavePhase >= 2 * M_PI) {
m_wavePhase -= 2 * M_PI;
}
// 触发重绘
update();
}
}
void CustomWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
// 如果绘制被禁用,仅绘制一次状态信息然后返回
if (!m_paintingEnabled) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制暗背景
painter.fillRect(rect(), QColor(40, 40, 40));
// 绘制禁用状态信息
painter.setPen(QColor(200, 200, 200));
QFont font = painter.font();
font.setPointSize(16);
font.setBold(true);
painter.setFont(font);
QString text = "PAINTING DISABLED\n(Screen Locked)";
painter.drawText(rect(), Qt::AlignCenter, text);
// 绘制统计信息
font.setPointSize(12);
font.setBold(false);
painter.setFont(font);
painter.setPen(QColor(150, 150, 150));
QString stats = QString("Total Frames Painted: %1\nPaused at: %2")
.arg(m_frameCount)
.arg(m_pauseTime.toString("hh:mm:ss"));
QRect statsRect = rect().adjusted(20, 0, -20, -20);
painter.drawText(statsRect, Qt::AlignBottom | Qt::AlignLeft, stats);
return;
}
// 正常绘制流程
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Calculate FPS
QDateTime currentTime = QDateTime::currentDateTime();
qint64 frameTimeUs = m_lastFrameTime.msecsTo(currentTime) * 1000; // Convert to microseconds
m_lastFrameTime = currentTime;
if (frameTimeUs > 0) {
// Add frame time to circular buffer
if (m_frameTimes.size() >= FPS_SAMPLE_COUNT) {
m_frameTimes.erase(m_frameTimes.begin());
}
m_frameTimes.push_back(frameTimeUs);
// Calculate average FPS from recent frames
if (!m_frameTimes.empty()) {
qint64 totalTimeUs = 0;
for (qint64 time : m_frameTimes) {
totalTimeUs += time;
}
double avgFrameTimeUs = static_cast<double>(totalTimeUs) / m_frameTimes.size();
m_currentFps = 1000000.0 / avgFrameTimeUs; // Convert microseconds to FPS
}
}
// 增加帧计数
m_frameCount++;
// 绘制各个图层
drawBackground(painter);
drawRotatingCircles(painter);
drawWaveEffect(painter);
drawStatusInfo(painter);
}
void CustomWidget::drawBackground(QPainter &painter)
{
// 绘制渐变背景
QLinearGradient gradient(0, 0, width(), height());
// 根据时间变化颜色
double time = m_rotationAngle / 360.0;
int r1 = static_cast<int>(100 + 50 * sin(time * 2 * M_PI));
int g1 = static_cast<int>(150 + 50 * sin(time * 2 * M_PI + M_PI / 3));
int b1 = static_cast<int>(200 + 55 * sin(time * 2 * M_PI + 2 * M_PI / 3));
gradient.setColorAt(0, QColor(r1, g1, b1));
gradient.setColorAt(1, QColor(30, 30, 60));
painter.fillRect(rect(), gradient);
}
void CustomWidget::drawRotatingCircles(QPainter &painter)
{
painter.save();
int centerX = width() / 2;
int centerY = height() / 2;
painter.translate(centerX, centerY);
painter.rotate(m_rotationAngle);
// 绘制多个旋转的圆圈
for (int i = 0; i < 8; i++) {
double angle = (i * 2 * M_PI) / 8;
int radius = 80;
int x = static_cast<int>(radius * cos(angle));
int y = static_cast<int>(radius * sin(angle));
QColor color;
color.setHsv((i * 360 / 8 + static_cast<int>(m_rotationAngle)) % 360, 200, 255, 180);
painter.setPen(QPen(color, 2));
painter.setBrush(color);
painter.drawEllipse(QPoint(x, y), 15, 15);
}
painter.restore();
}
void CustomWidget::drawWaveEffect(QPainter &painter)
{
painter.save();
painter.setPen(QPen(QColor(255, 255, 255, 150), 2));
// 绘制正弦波
QPainterPath path;
bool firstPoint = true;
for (int x = 0; x < width(); x += 5) {
double y = height() * 0.7 + 30 * sin(m_wavePhase + x * 0.02);
if (firstPoint) {
path.moveTo(x, y);
firstPoint = false;
} else {
path.lineTo(x, y);
}
}
painter.drawPath(path);
// 绘制第二条波浪(相位偏移)
painter.setPen(QPen(QColor(255, 255, 100, 120), 2));
path = QPainterPath();
firstPoint = true;
for (int x = 0; x < width(); x += 5) {
double y = height() * 0.7 + 30 * sin(m_wavePhase + M_PI + x * 0.02);
if (firstPoint) {
path.moveTo(x, y);
firstPoint = false;
} else {
path.lineTo(x, y);
}
}
painter.drawPath(path);
painter.restore();
}
void CustomWidget::drawStatusInfo(QPainter &painter)
{
painter.save();
// 绘制标题
QFont titleFont = painter.font();
titleFont.setPointSize(18);
titleFont.setBold(true);
painter.setFont(titleFont);
painter.setPen(QColor(255, 255, 255));
QString title = "Screen Lock Detector - Painting Active";
QRect titleRect(0, 20, width(), 40);
painter.drawText(titleRect, Qt::AlignCenter, title);
// 绘制统计信息
QFont infoFont = painter.font();
infoFont.setPointSize(12);
infoFont.setBold(false);
painter.setFont(infoFont);
QDateTime now = QDateTime::currentDateTime();
qint64 elapsed = m_startTime.secsTo(now);
QString stats = QString(
"Frame Count: %1\n"
"FPS: %2\n"
"Rotation: %3°\n"
"Running Time: %4s"
).arg(m_frameCount)
.arg(static_cast<int>(m_currentFps))
.arg(static_cast<int>(m_rotationAngle))
.arg(elapsed);
// 绘制半透明背景框
QRect statsRect(10, 70, 200, 110);
painter.fillRect(statsRect, QColor(0, 0, 0, 150));
painter.setPen(QColor(200, 255, 200));
painter.drawText(statsRect.adjusted(10, 5, -10, -5), Qt::AlignLeft | Qt::AlignTop, stats);
if (m_lastLockTime.isValid()) {
drawLockInfo(painter);
}
// 绘制提示信息
painter.setPen(QColor(255, 255, 150));
infoFont.setPointSize(11);
painter.setFont(infoFont);
QString hint = "Lock your screen to see the painting stop automatically!";
QRect hintRect(0, height() - 40, width(), 30);
painter.drawText(hintRect, Qt::AlignCenter, hint);
painter.restore();
}
void CustomWidget::drawLockInfo(QPainter &painter)
{
QFont infoFont = painter.font();
QRect lockInfoRect(10, 180, 200, 150);
painter.fillRect(lockInfoRect, QColor(60, 0, 60, 180));
painter.setPen(QColor(255, 200, 255));
infoFont.setBold(true);
infoFont.setPointSize(11);
painter.setFont(infoFont);
painter.drawText(lockInfoRect.adjusted(10, 5, -10, -5), Qt::AlignLeft | Qt::AlignTop,
"Last Lock Info:");
infoFont.setBold(false);
infoFont.setPointSize(9);
painter.setFont(infoFont);
painter.setPen(QColor(255, 220, 255));
// 格式化锁屏时长
QString durationStr;
if (m_lastLockDuration < 60) {
durationStr = QString("%1 s").arg(m_lastLockDuration);
} else if (m_lastLockDuration < 3600) {
int minutes = m_lastLockDuration / 60;
int seconds = m_lastLockDuration % 60;
durationStr = QString("%1m %2s").arg(minutes).arg(seconds);
} else {
int hours = m_lastLockDuration / 3600;
int minutes = (m_lastLockDuration % 3600) / 60;
int seconds = m_lastLockDuration % 60;
durationStr = QString("%1h %2m %3s").arg(hours).arg(minutes).arg(seconds);
}
QString lockInfo = QString(
"\nLock Time: %1\n"
"Duration: %2\n"
"Frame Count at Lock: %3\n"
"Frames During Lock: %4\n"
"Total Locks: %5"
).arg(m_lastLockTime.toString("yyyy-MM-dd hh:mm:ss"))
.arg(durationStr)
.arg(m_lastLockFrameCount)
.arg(m_lockPaintFrameCount)
.arg(m_lockCount);
painter.drawText(lockInfoRect.adjusted(10, 25, -10, -5), Qt::AlignLeft | Qt::AlignTop, lockInfo);
}