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

207
widgets/launcherpage.cpp Normal file
View File

@@ -0,0 +1,207 @@
#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);
}
}
}