208 lines
5.9 KiB
C++
208 lines
5.9 KiB
C++
#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);
|
||
}
|
||
}
|
||
}
|