File indexing completed on 2024-06-02 05:42:16

0001 // SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003 
0004 #include "foliowidget.h"
0005 #include "homescreenstate.h"
0006 #include "widgetsmanager.h"
0007 
0008 FolioWidget::FolioWidget(QObject *parent, int id, int realGridWidth, int realGridHeight)
0009     : QObject{parent}
0010     , m_id{id}
0011     , m_realGridWidth{realGridWidth}
0012     , m_realGridHeight{realGridHeight}
0013     , m_applet{nullptr}
0014     , m_quickApplet{nullptr}
0015 {
0016     auto *applet = WidgetsManager::self()->getWidget(id);
0017     if (applet) {
0018         setApplet(applet);
0019     }
0020     init();
0021 }
0022 
0023 FolioWidget::FolioWidget(QObject *parent, Plasma::Applet *applet, int realGridWidth, int realGridHeight)
0024     : QObject{parent}
0025     , m_id{applet ? static_cast<int>(applet->id()) : -1}
0026     , m_realGridWidth{realGridWidth}
0027     , m_realGridHeight{realGridHeight}
0028 {
0029     setApplet(applet);
0030     init();
0031 }
0032 
0033 void FolioWidget::init()
0034 {
0035     connect(HomeScreenState::self(), &HomeScreenState::pageOrientationChanged, this, [this]() {
0036         Q_EMIT gridWidthChanged();
0037         Q_EMIT gridHeightChanged();
0038     });
0039 
0040     connect(WidgetsManager::self(), &WidgetsManager::widgetAdded, this, [this](Plasma::Applet *applet) {
0041         if (applet && static_cast<int>(applet->id()) == m_id) {
0042             setApplet(applet);
0043         }
0044     });
0045     connect(WidgetsManager::self(), &WidgetsManager::widgetRemoved, this, [this](Plasma::Applet *applet) {
0046         if (applet && static_cast<int>(applet->id()) == m_id) {
0047             setApplet(nullptr);
0048         }
0049     });
0050 }
0051 
0052 FolioWidget *FolioWidget::fromJson(QJsonObject &obj, QObject *parent)
0053 {
0054     int id = obj[QStringLiteral("id")].toInt();
0055     int gridWidth = obj[QStringLiteral("gridWidth")].toInt();
0056     int gridHeight = obj[QStringLiteral("gridHeight")].toInt();
0057     return new FolioWidget(parent, id, gridWidth, gridHeight);
0058 }
0059 
0060 QJsonObject FolioWidget::toJson() const
0061 {
0062     QJsonObject obj;
0063     obj[QStringLiteral("type")] = "widget";
0064     obj[QStringLiteral("id")] = m_id;
0065     obj[QStringLiteral("gridWidth")] = m_realGridWidth;
0066     obj[QStringLiteral("gridHeight")] = m_realGridHeight;
0067     return obj;
0068 }
0069 
0070 int FolioWidget::id() const
0071 {
0072     return m_id;
0073 }
0074 
0075 int FolioWidget::gridWidth() const
0076 {
0077     switch (HomeScreenState::self()->pageOrientation()) {
0078     case HomeScreenState::RegularPosition:
0079         return m_realGridWidth;
0080     case HomeScreenState::RotateClockwise:
0081         return m_realGridHeight;
0082     case HomeScreenState::RotateCounterClockwise:
0083         return m_realGridHeight;
0084     case HomeScreenState::RotateUpsideDown:
0085         return m_realGridWidth;
0086     }
0087     return m_realGridWidth;
0088 }
0089 
0090 void FolioWidget::setGridWidth(int gridWidth)
0091 {
0092     switch (HomeScreenState::self()->pageOrientation()) {
0093     case HomeScreenState::RegularPosition:
0094         setRealGridWidth(gridWidth);
0095         break;
0096     case HomeScreenState::RotateClockwise: {
0097         int oldGridHeight = m_realGridHeight;
0098         setRealGridHeight(gridWidth);
0099         Q_EMIT realTopLeftPositionChanged(oldGridHeight - gridWidth, 0);
0100         break;
0101     }
0102     case HomeScreenState::RotateCounterClockwise:
0103         setRealGridHeight(gridWidth);
0104         break;
0105     case HomeScreenState::RotateUpsideDown: {
0106         int oldGridWidth = m_realGridWidth;
0107         setRealGridWidth(gridWidth);
0108         Q_EMIT realTopLeftPositionChanged(0, oldGridWidth - gridWidth);
0109         break;
0110     }
0111     }
0112 }
0113 
0114 int FolioWidget::gridHeight() const
0115 {
0116     switch (HomeScreenState::self()->pageOrientation()) {
0117     case HomeScreenState::RegularPosition:
0118         return m_realGridHeight;
0119     case HomeScreenState::RotateClockwise:
0120         return m_realGridWidth;
0121     case HomeScreenState::RotateCounterClockwise:
0122         return m_realGridWidth;
0123     case HomeScreenState::RotateUpsideDown:
0124         return m_realGridHeight;
0125     }
0126     return m_realGridHeight;
0127 }
0128 
0129 void FolioWidget::setGridHeight(int gridHeight)
0130 {
0131     switch (HomeScreenState::self()->pageOrientation()) {
0132     case HomeScreenState::RegularPosition:
0133         setRealGridHeight(gridHeight);
0134         break;
0135     case HomeScreenState::RotateClockwise:
0136         setRealGridWidth(gridHeight);
0137         break;
0138     case HomeScreenState::RotateCounterClockwise: {
0139         int oldGridWidth = m_realGridWidth;
0140         setRealGridWidth(gridHeight);
0141         Q_EMIT realTopLeftPositionChanged(0, oldGridWidth - gridHeight);
0142         break;
0143     }
0144     case HomeScreenState::RotateUpsideDown: {
0145         int oldGridHeight = m_realGridHeight;
0146         setRealGridHeight(gridHeight);
0147         Q_EMIT realTopLeftPositionChanged(oldGridHeight - gridHeight, 0);
0148         break;
0149     }
0150     }
0151 }
0152 
0153 int FolioWidget::realGridWidth() const
0154 {
0155     return m_realGridWidth;
0156 }
0157 
0158 void FolioWidget::setRealGridWidth(int gridWidth)
0159 {
0160     if (m_realGridWidth != gridWidth) {
0161         m_realGridWidth = gridWidth;
0162 
0163         // emit both because realGridWidth could be either gridWidth or gridHeight
0164         Q_EMIT gridWidthChanged();
0165         Q_EMIT gridHeightChanged();
0166 
0167         Q_EMIT saveRequested();
0168     }
0169 }
0170 
0171 int FolioWidget::realGridHeight() const
0172 {
0173     return m_realGridHeight;
0174 }
0175 
0176 void FolioWidget::setRealGridHeight(int gridHeight)
0177 {
0178     if (m_realGridHeight != gridHeight) {
0179         m_realGridHeight = gridHeight;
0180 
0181         // emit both because realGridHeight could be either gridWidth or gridHeight
0182         Q_EMIT gridWidthChanged();
0183         Q_EMIT gridHeightChanged();
0184 
0185         Q_EMIT saveRequested();
0186     }
0187 }
0188 
0189 GridPosition FolioWidget::topLeftCorner(int row, int column)
0190 {
0191     switch (HomeScreenState::self()->pageOrientation()) {
0192     case HomeScreenState::RegularPosition:
0193         return {row, column};
0194     case HomeScreenState::RotateClockwise:
0195         return {row, column - gridWidth() + 1};
0196     case HomeScreenState::RotateCounterClockwise:
0197         return {row - gridHeight() + 1, column};
0198     case HomeScreenState::RotateUpsideDown:
0199         return {row - gridHeight() + 1, column - gridWidth() + 1};
0200     }
0201     return {row, column};
0202 }
0203 
0204 bool FolioWidget::isInBounds(int widgetRow, int widgetColumn, int row, int column)
0205 {
0206     return (row >= widgetRow) && (row <= widgetRow + gridHeight() - 1) && (column >= widgetColumn) && (column <= widgetColumn + gridWidth() - 1);
0207 }
0208 
0209 bool FolioWidget::overlapsWidget(int widgetRow, int widgetColumn, FolioWidget *otherWidget, int otherWidgetRow, int otherWidgetColumn)
0210 {
0211     if (!otherWidget) {
0212         return false;
0213     }
0214 
0215     // property: if they overlap, then at least one corner of one widget is in the other widget
0216     int widgetMaxRow = widgetRow + gridHeight() - 1;
0217     int widgetMaxColumn = widgetColumn + gridWidth() - 1;
0218     int otherWidgetMaxRow = otherWidgetRow + otherWidget->gridHeight() - 1;
0219     int otherWidgetMaxColumn = otherWidgetColumn + otherWidget->gridWidth() - 1;
0220 
0221     return isInBounds(widgetRow, widgetColumn, otherWidgetRow, otherWidgetColumn) || isInBounds(widgetRow, widgetColumn, otherWidgetMaxRow, otherWidgetColumn)
0222         || isInBounds(widgetRow, widgetColumn, otherWidgetRow, otherWidgetMaxColumn)
0223         || isInBounds(widgetRow, widgetColumn, otherWidgetMaxRow, otherWidgetMaxColumn)
0224         || otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetRow, widgetColumn)
0225         || otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetMaxRow, widgetColumn)
0226         || otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetRow, widgetMaxColumn)
0227         || otherWidget->isInBounds(otherWidgetRow, otherWidgetColumn, widgetMaxRow, widgetMaxColumn);
0228 }
0229 
0230 Plasma::Applet *FolioWidget::applet() const
0231 {
0232     return m_applet;
0233 }
0234 
0235 void FolioWidget::setApplet(Plasma::Applet *applet)
0236 {
0237     m_applet = applet;
0238     Q_EMIT appletChanged();
0239 
0240     int id = applet ? applet->id() : -1;
0241     if (m_id != id) {
0242         m_id = id;
0243         Q_EMIT idChanged();
0244 
0245         // ensure the id is saved
0246         Q_EMIT saveRequested();
0247     }
0248 
0249     if (m_applet) {
0250         setVisualApplet(PlasmaQuick::AppletQuickItem::itemForApplet(m_applet));
0251     } else {
0252         setVisualApplet(nullptr);
0253     }
0254 }
0255 
0256 PlasmaQuick::AppletQuickItem *FolioWidget::visualApplet() const
0257 {
0258     return m_quickApplet;
0259 }
0260 
0261 void FolioWidget::setVisualApplet(PlasmaQuick::AppletQuickItem *quickItem)
0262 {
0263     m_quickApplet = quickItem;
0264     Q_EMIT visualAppletChanged();
0265 }
0266 
0267 void FolioWidget::destroyApplet()
0268 {
0269     if (m_applet) {
0270         m_applet->destroy();
0271     }
0272 }