Files
CalibratorLauncher/widgets/launcherpage.cpp
2026-01-02 19:20:35 +09:00

208 lines
5.9 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 "launcherpage.h"
#include <QGridLayout>
#include <QResizeEvent>
#include <QPainter>
#include <QPainterPath>
#include <QTimer>
#include <QDebug>
LauncherPage::LauncherPage(const PageConfig &config, QWidget *parent)
: QWidget(parent), m_config(config), m_columns(4), m_rows(3), m_horizontalGap(20), m_verticalGap(18), m_horizontalPadding(30), m_verticalPadding(20)
{
setObjectName("launcherPage_" + config.id);
setupUI();
}
LauncherPage::~LauncherPage()
{
}
void LauncherPage::setupUI()
{
// 设置背景透明同时确保可以绑定paintEvent
setAttribute(Qt::WA_StyledBackground, true);
setStyleSheet("background: transparent;");
qDebug() << "=== LauncherPage setupUI ===";
qDebug() << "Page ID:" << m_config.id;
qDebug() << "Apps count:" << m_config.apps.size();
// 创建图标(不使用布局,使用绝对定位)
for (int i = 0; i < m_config.apps.size(); ++i)
{
const auto &appData = m_config.apps[i];
qDebug() << "Creating icon for:" << appData.name << "(" << appData.id << ")" << "group:" << appData.group;
AppIcon *icon = new AppIcon(appData, this);
icon->setFixedSize(190, 180);
connect(icon, &AppIcon::clicked, this, &LauncherPage::appClicked);
connect(icon, &AppIcon::longPressed, this, &LauncherPage::appLongPressed);
m_icons.append(icon);
// 收集分组信息
if (!appData.group.isEmpty())
{
if (!m_groups.contains(appData.group))
{
GroupInfo info;
info.groupId = appData.group;
m_groups[appData.group] = info;
}
m_groups[appData.group].iconIndices.append(i);
}
}
qDebug() << "Total icons created:" << m_icons.size();
qDebug() << "Groups found:" << m_groups.keys();
}
void LauncherPage::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
layoutIcons();
}
void LauncherPage::layoutIcons()
{
if (m_icons.isEmpty())
{
qDebug() << "layoutIcons: No icons to layout!";
return;
}
int w = width();
int h = height();
qDebug() << "=== layoutIcons ===";
qDebug() << "Page ID:" << m_config.id;
qDebug() << "Widget size:" << w << "x" << h;
qDebug() << "Icons count:" << m_icons.size();
// Android风格图标均匀分布
int iconWidth = 190;
int iconHeight = 180;
// 动态计算可以容纳的行数
int minVerticalSpacing = 12;
int maxPossibleRows = (h + minVerticalSpacing) / (iconHeight + minVerticalSpacing);
int actualRows = qMin(maxPossibleRows, m_rows);
actualRows = qMax(actualRows, 1); // 至少显示1行
qDebug() << "Max possible rows:" << maxPossibleRows << "Using rows:" << actualRows;
// 计算间距,使图标均匀分布
int horizontalSpacing = (w - m_columns * iconWidth) / (m_columns + 1);
int verticalSpacing = (h - actualRows * iconHeight) / (actualRows + 1);
// 确保最小间距
horizontalSpacing = qMax(horizontalSpacing, 10);
verticalSpacing = qMax(verticalSpacing, 12);
qDebug() << "Spacing - H:" << horizontalSpacing << "V:" << verticalSpacing;
// 重新计算起始位置使其居中
int startX = (w - (m_columns * iconWidth + (m_columns - 1) * horizontalSpacing)) / 2;
int startY = (h - (actualRows * iconHeight + (actualRows - 1) * verticalSpacing)) / 2;
qDebug() << "Start position - X:" << startX << "Y:" << startY;
// 布局图标,同时记录位置用于分组框计算
QMap<int, QRect> iconRects;
int index = 0;
for (AppIcon *icon : m_icons)
{
int row = index / m_columns;
int col = index % m_columns;
if (row < actualRows)
{
int x = startX + col * (iconWidth + horizontalSpacing);
int y = startY + row * (iconHeight + verticalSpacing);
qDebug() << " Icon" << index << "at" << x << "," << y;
icon->move(x, y);
icon->show();
// 记录计算出的位置
iconRects[index] = QRect(x, y, iconWidth, iconHeight);
}
else
{
qDebug() << " Icon" << index << "hidden (too many rows)";
icon->hide();
}
index++;
}
qDebug() << "layoutIcons done, visible icons:" << qMin(index, m_rows * m_columns);
// 更新分组矩形,使用计算出的位置
updateGroupRects(iconRects);
}
void LauncherPage::updateGroupRects(const QMap<int, QRect> &iconRects)
{
// 为每个分组计算边界矩形
for (auto it = m_groups.begin(); it != m_groups.end(); ++it)
{
GroupInfo &group = it.value();
if (group.iconIndices.isEmpty())
continue;
QRect boundingRect;
bool first = true;
for (int idx : group.iconIndices)
{
if (iconRects.contains(idx))
{
QRect iconRect = iconRects[idx];
qDebug() << " Group icon" << idx << "rect:" << iconRect;
if (first)
{
boundingRect = iconRect;
first = false;
}
else
{
boundingRect = boundingRect.united(iconRect);
}
}
}
// 扩展边界矩形,添加内边距
int padding = 3;
group.boundingRect = boundingRect.adjusted(-padding, -padding, padding, padding);
qDebug() << "Group" << group.groupId << "bounding rect:" << group.boundingRect;
}
// 触发重绘
update();
}
void LauncherPage::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制分组背景框
for (const GroupInfo &group : m_groups)
{
qDebug() << "Drawing group:" << group.groupId << "rect:" << group.boundingRect;
if (group.boundingRect.isValid() && !group.boundingRect.isEmpty())
{
// 设置半透明背景 - 增加透明度使其更明显
QColor bgColor(255, 255, 255, 50); // 白色半透明
painter.setBrush(bgColor);
// 设置边框
QColor borderColor(255, 255, 255, 100); // 白色半透明边框
painter.setPen(QPen(borderColor, 2.0));
// 绘制圆角矩形
QPainterPath path;
path.addRoundedRect(QRectF(group.boundingRect), 20, 20);
painter.drawPath(path);
}
}
}