shift-shell/containments/homescreens/folio/foliowidget.cpp
2023-11-04 22:18:52 -07:00

272 lines
8.1 KiB
C++

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "foliowidget.h"
#include "homescreenstate.h"
#include "widgetsmanager.h"
FolioWidget::FolioWidget(QObject *parent, int id, int realGridWidth, int realGridHeight)
: QObject{parent}
, m_id{id}
, m_realGridWidth{realGridWidth}
, m_realGridHeight{realGridHeight}
, m_applet{nullptr}
, m_quickApplet{nullptr}
{
auto *applet = WidgetsManager::self()->getWidget(id);
if (applet) {
setApplet(applet);
}
init();
}
FolioWidget::FolioWidget(QObject *parent, Plasma::Applet *applet, int realGridWidth, int realGridHeight)
: QObject{parent}
, m_id{applet ? static_cast<int>(applet->id()) : -1}
, m_realGridWidth{realGridWidth}
, m_realGridHeight{realGridHeight}
{
setApplet(applet);
init();
}
void FolioWidget::init()
{
connect(HomeScreenState::self(), &HomeScreenState::pageOrientationChanged, this, [this]() {
Q_EMIT gridWidthChanged();
Q_EMIT gridHeightChanged();
});
connect(WidgetsManager::self(), &WidgetsManager::widgetAdded, this, [this](Plasma::Applet *applet) {
if (applet && static_cast<int>(applet->id()) == m_id) {
setApplet(applet);
}
});
connect(WidgetsManager::self(), &WidgetsManager::widgetRemoved, this, [this](Plasma::Applet *applet) {
if (applet && static_cast<int>(applet->id()) == m_id) {
setApplet(nullptr);
}
});
}
FolioWidget *FolioWidget::fromJson(QJsonObject &obj, QObject *parent)
{
int id = obj[QStringLiteral("id")].toInt();
int gridWidth = obj[QStringLiteral("gridWidth")].toInt();
int gridHeight = obj[QStringLiteral("gridHeight")].toInt();
return new FolioWidget(parent, id, gridWidth, gridHeight);
}
QJsonObject FolioWidget::toJson() const
{
QJsonObject obj;
obj[QStringLiteral("type")] = "widget";
obj[QStringLiteral("id")] = m_id;
obj[QStringLiteral("gridWidth")] = m_realGridWidth;
obj[QStringLiteral("gridHeight")] = m_realGridHeight;
return obj;
}
int FolioWidget::id() const
{
return m_id;
}
int FolioWidget::gridWidth() const
{
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
return m_realGridWidth;
case HomeScreenState::RotateClockwise:
return m_realGridHeight;
case HomeScreenState::RotateCounterClockwise:
return m_realGridHeight;
case HomeScreenState::RotateUpsideDown:
return m_realGridWidth;
}
return m_realGridWidth;
}
void FolioWidget::setGridWidth(int gridWidth)
{
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
setRealGridWidth(gridWidth);
break;
case HomeScreenState::RotateClockwise: {
int oldGridHeight = m_realGridHeight;
setRealGridHeight(gridWidth);
Q_EMIT realTopLeftPositionChanged(oldGridHeight - gridWidth, 0);
break;
}
case HomeScreenState::RotateCounterClockwise:
setRealGridHeight(gridWidth);
break;
case HomeScreenState::RotateUpsideDown: {
int oldGridWidth = m_realGridWidth;
setRealGridWidth(gridWidth);
Q_EMIT realTopLeftPositionChanged(0, oldGridWidth - gridWidth);
break;
}
}
}
int FolioWidget::gridHeight() const
{
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
return m_realGridHeight;
case HomeScreenState::RotateClockwise:
return m_realGridWidth;
case HomeScreenState::RotateCounterClockwise:
return m_realGridWidth;
case HomeScreenState::RotateUpsideDown:
return m_realGridHeight;
}
return m_realGridHeight;
}
void FolioWidget::setGridHeight(int gridHeight)
{
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
setRealGridHeight(gridHeight);
break;
case HomeScreenState::RotateClockwise:
setRealGridWidth(gridHeight);
break;
case HomeScreenState::RotateCounterClockwise: {
int oldGridWidth = m_realGridWidth;
setRealGridWidth(gridHeight);
Q_EMIT realTopLeftPositionChanged(0, oldGridWidth - gridHeight);
break;
}
case HomeScreenState::RotateUpsideDown: {
int oldGridHeight = m_realGridHeight;
setRealGridHeight(gridHeight);
Q_EMIT realTopLeftPositionChanged(oldGridHeight - gridHeight, 0);
break;
}
}
}
int FolioWidget::realGridWidth() const
{
return m_realGridWidth;
}
void FolioWidget::setRealGridWidth(int gridWidth)
{
if (m_realGridWidth != gridWidth) {
m_realGridWidth = gridWidth;
// emit both because realGridWidth could be either gridWidth or gridHeight
Q_EMIT gridWidthChanged();
Q_EMIT gridHeightChanged();
Q_EMIT saveRequested();
}
}
int FolioWidget::realGridHeight() const
{
return m_realGridHeight;
}
void FolioWidget::setRealGridHeight(int gridHeight)
{
if (m_realGridHeight != gridHeight) {
m_realGridHeight = gridHeight;
// emit both because realGridHeight could be either gridWidth or gridHeight
Q_EMIT gridWidthChanged();
Q_EMIT gridHeightChanged();
Q_EMIT saveRequested();
}
}
GridPosition FolioWidget::topLeftCorner(int row, int column)
{
switch (HomeScreenState::self()->pageOrientation()) {
case HomeScreenState::RegularPosition:
return {row, column};
case HomeScreenState::RotateClockwise:
return {row, column - gridWidth() + 1};
case HomeScreenState::RotateCounterClockwise:
return {row - gridHeight() + 1, column};
case HomeScreenState::RotateUpsideDown:
return {row - gridHeight() + 1, column - gridWidth() + 1};
}
return {row, column};
}
bool FolioWidget::isInBounds(int widgetRow, int widgetColumn, int row, int column)
{
return (row >= widgetRow) && (row <= widgetRow + gridHeight() - 1) && (column >= widgetColumn) && (column <= widgetColumn + gridWidth() - 1);
}
bool FolioWidget::overlapsWidget(int widgetRow, int widgetColumn, FolioWidget *otherWidget, int otherWidgetRow, int otherWidgetColumn)
{
if (!otherWidget) {
return false;
}
// property: if they overlap, then at least one corner of one widget is in the other widget
int widgetMaxRow = widgetRow + gridHeight() - 1;
int widgetMaxColumn = widgetColumn + gridWidth() - 1;
int otherWidgetMaxRow = otherWidgetRow + otherWidget->gridHeight() - 1;
int otherWidgetMaxColumn = otherWidgetColumn + otherWidget->gridWidth() - 1;
return isInBounds(widgetRow, widgetColumn, otherWidgetRow, otherWidgetColumn) || isInBounds(widgetRow, widgetColumn, otherWidgetMaxRow, otherWidgetColumn)
|| isInBounds(widgetRow, widgetColumn, otherWidgetRow, otherWidgetMaxColumn)
|| isInBounds(widgetRow, widgetColumn, otherWidgetMaxRow, otherWidgetMaxColumn)
|| otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetRow, widgetColumn)
|| otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetMaxRow, widgetColumn)
|| otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetRow, widgetMaxColumn)
|| otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetMaxRow, widgetMaxColumn);
}
Plasma::Applet *FolioWidget::applet() const
{
return m_applet;
}
void FolioWidget::setApplet(Plasma::Applet *applet)
{
m_applet = applet;
Q_EMIT appletChanged();
int id = applet ? applet->id() : -1;
if (m_id != id) {
m_id = id;
Q_EMIT idChanged();
// ensure the id is saved
Q_EMIT saveRequested();
}
if (m_applet) {
setVisualApplet(PlasmaQuick::AppletQuickItem::itemForApplet(m_applet));
} else {
setVisualApplet(nullptr);
}
}
PlasmaQuick::AppletQuickItem *FolioWidget::visualApplet() const
{
return m_quickApplet;
}
void FolioWidget::setVisualApplet(PlasmaQuick::AppletQuickItem *quickItem)
{
m_quickApplet = quickItem;
Q_EMIT visualAppletChanged();
}
void FolioWidget::destroyApplet()
{
if (m_applet) {
m_applet->destroy();
}
}