first commit

This commit is contained in:
2026-01-02 19:20:35 +09:00
commit a10cb30c4a
94 changed files with 28609 additions and 0 deletions

283
widgets/appicon.cpp Normal file
View File

@@ -0,0 +1,283 @@
#include "appicon.h"
#include <QPainter>
#include <QPainterPath>
#include <QMouseEvent>
#include <QLinearGradient>
#include <QVBoxLayout>
#include <QDebug>
AppIcon::AppIcon(const AppIconData &data, QWidget *parent)
: QWidget(parent), m_data(data), m_scale(1.0), m_isPressed(false), m_longPressTimerId(0)
{
qDebug() << "AppIcon constructor:" << data.name << "(" << data.id << ")";
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setCursor(Qt::PointingHandCursor);
setAttribute(Qt::WA_Hover);
setupUI();
qDebug() << "AppIcon created successfully:" << data.name;
}
AppIcon::~AppIcon()
{
if (m_longPressTimerId)
{
killTimer(m_longPressTimerId);
}
}
void AppIcon::setupUI()
{
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(3, 3, 3, 3);
layout->setSpacing(5);
layout->setAlignment(Qt::AlignCenter);
// Android风格图标尺寸 - 10英寸屏幕优化
int iconSize = 80;
int borderRadius = 16;
QWidget *iconContainer = new QWidget(this);
iconContainer->setFixedSize(iconSize, iconSize);
iconContainer->setObjectName("iconContainer");
// 设置阴影效果 - 更明显的阴影
m_shadowEffect = new QGraphicsDropShadowEffect(this);
m_shadowEffect->setBlurRadius(16);
m_shadowEffect->setColor(QColor(0, 0, 0, 60));
m_shadowEffect->setOffset(0, 4);
iconContainer->setGraphicsEffect(m_shadowEffect);
// 图标标签
m_iconLabel = new QLabel(iconContainer);
m_iconLabel->setAlignment(Qt::AlignCenter);
m_iconLabel->setFixedSize(iconSize, iconSize);
m_iconLabel->move(0, 0);
// 设置图标样式
QString gradientStart = m_data.gradient.size() > 0 ? m_data.gradient[0] : m_data.color;
QString gradientEnd = m_data.gradient.size() > 1 ? m_data.gradient[1] : m_data.color;
QString iconStyle = QString(R"(
QLabel {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 %1, stop:1 %2);
border-radius: %3px;
font-size: 36px;
color: white;
}
)")
.arg(gradientStart, gradientEnd)
.arg(borderRadius);
m_iconLabel->setStyleSheet(iconStyle);
// 设置 SVG 图标
QString iconPath = getIconSymbol(m_data.id);
if (!iconPath.isEmpty())
{
QPixmap pixmap(iconPath);
if (!pixmap.isNull())
{
// 缩放图标到合适大小
int svgSize = iconSize - 24; // 留出边距
pixmap = pixmap.scaled(svgSize, svgSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
m_iconLabel->setPixmap(pixmap);
}
}
// 徽章标签 - 过滤掉emoji只显示纯文字badge
if (!m_data.badge.isEmpty())
{
QString badgeText = m_data.badge;
// 过滤掉emoji字符保留ASCII和常见中文字符
QString filteredBadge;
for (const QChar &ch : badgeText)
{
ushort unicode = ch.unicode();
// 保留基本ASCII32-126、中文字符0x4E00-0x9FFF、以及一些常用符号
if ((unicode >= 32 && unicode <= 126) ||
(unicode >= 0x4E00 && unicode <= 0x9FFF) ||
ch == QChar(0xB1) || // ±
ch == QChar(0x394) || // Δ
ch == QChar(0x3A9))
{ // Ω
filteredBadge += ch;
}
}
if (!filteredBadge.isEmpty())
{
m_badgeLabel = new QLabel(iconContainer);
m_badgeLabel->setText(filteredBadge);
m_badgeLabel->setFixedSize(26, 16);
m_badgeLabel->setAlignment(Qt::AlignCenter);
m_badgeLabel->move(iconSize - 28, iconSize - 18);
m_badgeLabel->setStyleSheet(R"(
QLabel {
background-color: rgba(255, 255, 255, 0.95);
color: #333;
border-radius: 4px;
font-size: 9px;
font-weight: bold;
}
)");
}
}
layout->addWidget(iconContainer, 0, Qt::AlignCenter);
// 名称标签 - Android风格白色文字带阴影
m_nameLabel = new QLabel(m_data.name, this);
m_nameLabel->setAlignment(Qt::AlignCenter);
m_nameLabel->setFixedWidth(150);
m_nameLabel->setWordWrap(false);
m_nameLabel->setStyleSheet(R"(
QLabel {
color: white;
font-size: 13px;
font-weight: 500;
background: transparent;
}
)");
layout->addWidget(m_nameLabel, 0, Qt::AlignCenter);
}
QString AppIcon::getIconSymbol(const QString &id) const
{
// 返回对应的SVG图标路径
static QMap<QString, QString> iconMap = {
{"rtd", ":/icons/ic_rtd.svg"},
{"rtd_measure", ":/icons/ic_rtd.svg"},
{"rtd_output", ":/icons/ic_rtd_output.svg"},
{"thermocouple", ":/icons/ic_thermocouple.svg"},
{"insulation", ":/icons/ic_insulation.svg"},
{"dc_current", ":/icons/ic_dc_current.svg"},
{"dc_voltage", ":/icons/ic_dc_voltage.svg"},
{"frequency", ":/icons/ic_frequency.svg"},
{"ac_voltage", ":/icons/ic_ac_voltage.svg"},
{"switch_detect", ":/icons/ic_switch.svg"},
{"ripple", ":/icons/ic_ripple.svg"},
{"ramp", ":/icons/ic_ramp.svg"},
{"waveform", ":/icons/ic_waveform.svg"},
{"dual_channel", ":/icons/ic_dual_channel.svg"},
{"trim", ":/icons/ic_trim.svg"},
{"data_management", ":/icons/ic_data.svg"},
{"wireless", ":/icons/ic_wireless.svg"},
{"sop", ":/icons/ic_sop.svg"},
{"rcp63", ":/icons/ic_rcp63.svg"},
{"settings", ":/icons/ic_settings.svg"},
{"network_test", ":/icons/ic_network_test.svg"},
{"dock_sop", ":/icons/ic_sop.svg"},
{"dock_rcp63", ":/icons/ic_rcp63.svg"},
{"dock_network", ":/icons/ic_network_test.svg"},
{"dock_settings", ":/icons/ic_settings.svg"}};
return iconMap.value(id, "");
}
void AppIcon::setScale(qreal scale)
{
if (qFuzzyCompare(m_scale, scale))
return;
m_scale = scale;
update();
}
void AppIcon::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
if (!qFuzzyCompare(m_scale, 1.0))
{
// 应用缩放变换
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QTransform transform;
transform.translate(width() / 2, height() / 2);
transform.scale(m_scale, m_scale);
transform.translate(-width() / 2, -height() / 2);
painter.setTransform(transform);
}
QWidget::paintEvent(event);
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void AppIcon::enterEvent(QEnterEvent *event)
#else
void AppIcon::enterEvent(QEvent *event)
#endif
{
Q_UNUSED(event)
m_shadowEffect->setBlurRadius(20);
m_shadowEffect->setColor(QColor(0, 0, 0, 60));
}
void AppIcon::leaveEvent(QEvent *event)
{
Q_UNUSED(event)
m_shadowEffect->setBlurRadius(16);
m_shadowEffect->setColor(QColor(0, 0, 0, 40));
}
void AppIcon::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_isPressed = true;
animateScale(0.95);
// 启动长按计时器
m_longPressTimerId = startTimer(LONG_PRESS_DELAY);
}
QWidget::mousePressEvent(event);
}
void AppIcon::mouseReleaseEvent(QMouseEvent *event)
{
if (m_longPressTimerId)
{
killTimer(m_longPressTimerId);
m_longPressTimerId = 0;
}
if (m_isPressed && event->button() == Qt::LeftButton)
{
m_isPressed = false;
animateScale(1.0);
if (rect().contains(event->pos()))
{
emit clicked(m_data.id);
}
}
QWidget::mouseReleaseEvent(event);
}
void AppIcon::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_longPressTimerId)
{
killTimer(m_longPressTimerId);
m_longPressTimerId = 0;
if (m_isPressed)
{
emit longPressed(m_data.id);
}
}
QWidget::timerEvent(event);
}
void AppIcon::animateScale(qreal targetScale, int duration)
{
QPropertyAnimation *anim = new QPropertyAnimation(this, "scale", this);
anim->setDuration(duration);
anim->setStartValue(m_scale);
anim->setEndValue(targetScale);
anim->setEasingCurve(QEasingCurve::OutCubic);
anim->start(QAbstractAnimation::DeleteWhenStopped);
}