File indexing completed on 2024-05-12 17:08:54

0001 /*
0002     SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QPointer>
0010 #include <QQmlParserStatus>
0011 #include <QQuickItem>
0012 #include <QQuickWindow>
0013 
0014 class QTimer;
0015 
0016 namespace Plasma
0017 {
0018 class Containment;
0019 }
0020 
0021 namespace PlasmaQuick
0022 {
0023 class AppletQuickItem;
0024 }
0025 
0026 class AbstractLayoutManager;
0027 class AppletContainer;
0028 class ItemContainer;
0029 
0030 class AppletsLayout : public QQuickItem
0031 {
0032     Q_OBJECT
0033     Q_INTERFACES(QQmlParserStatus)
0034 
0035     Q_PROPERTY(QString configKey READ configKey WRITE setConfigKey NOTIFY configKeyChanged)
0036 
0037     // A config key that can be used as fallback when loading and configKey is not found
0038     // Is always a backup of the last used configKey. Useful when the configkey depends
0039     // from the screen size and plasma starts on an "unexpected" size
0040     Q_PROPERTY(QString fallbackConfigKey READ fallbackConfigKey WRITE setFallbackConfigKey NOTIFY fallbackConfigKeyChanged)
0041 
0042     Q_PROPERTY(bool relayoutLock READ relayoutLock WRITE setRelayoutLock NOTIFY relayoutLockChanged)
0043 
0044     Q_PROPERTY(PlasmaQuick::AppletQuickItem *containment READ containment WRITE setContainment NOTIFY containmentChanged)
0045 
0046     Q_PROPERTY(QJSValue acceptsAppletCallback READ acceptsAppletCallback WRITE setAcceptsAppletCallback NOTIFY acceptsAppletCallbackChanged)
0047 
0048     Q_PROPERTY(qreal minimumItemWidth READ minimumItemWidth WRITE setMinimumItemWidth NOTIFY minimumItemWidthChanged)
0049 
0050     Q_PROPERTY(qreal minimumItemHeight READ minimumItemHeight WRITE setMinimumItemHeight NOTIFY minimumItemHeightChanged)
0051 
0052     Q_PROPERTY(qreal defaultItemWidth READ defaultItemWidth WRITE setDefaultItemWidth NOTIFY defaultItemWidthChanged)
0053 
0054     Q_PROPERTY(qreal defaultItemHeight READ defaultItemHeight WRITE setDefaultItemHeight NOTIFY defaultItemHeightChanged)
0055 
0056     Q_PROPERTY(qreal cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
0057 
0058     Q_PROPERTY(qreal cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
0059 
0060     Q_PROPERTY(QQmlComponent *appletContainerComponent READ appletContainerComponent WRITE setAppletContainerComponent NOTIFY appletContainerComponentChanged)
0061 
0062     Q_PROPERTY(ItemContainer *placeHolder READ placeHolder WRITE setPlaceHolder NOTIFY placeHolderChanged);
0063 
0064     /**
0065      * if the applets layout contains some kind of main MouseArea,
0066      * MouseEventListener or Flickable, we want to filter its events to make the
0067      * long mouse press work
0068      */
0069     Q_PROPERTY(QQuickItem *eventManagerToFilter READ eventManagerToFilter WRITE setEventManagerToFilter NOTIFY eventManagerToFilterChanged);
0070 
0071     Q_PROPERTY(AppletsLayout::EditModeCondition editModeCondition READ editModeCondition WRITE setEditModeCondition NOTIFY editModeConditionChanged)
0072     Q_PROPERTY(bool editMode READ editMode WRITE setEditMode NOTIFY editModeChanged)
0073 
0074 public:
0075     enum PreferredLayoutDirection {
0076         Closest = 0,
0077         LeftToRight,
0078         RightToLeft,
0079         TopToBottom,
0080         BottomToTop,
0081     };
0082     Q_ENUM(PreferredLayoutDirection)
0083 
0084     enum EditModeCondition {
0085         Locked = 0,
0086         Manual,
0087         AfterPressAndHold,
0088     };
0089     Q_ENUM(EditModeCondition)
0090 
0091     enum LayoutChange {
0092         NoChange = 0,
0093         SizeChange = 1,
0094         ConfigKeyChange = 2,
0095     };
0096     Q_DECLARE_FLAGS(LayoutChanges, LayoutChange)
0097 
0098     AppletsLayout(QQuickItem *parent = nullptr);
0099     ~AppletsLayout();
0100 
0101     // QML setters and getters
0102     QString configKey() const;
0103     void setConfigKey(const QString &key);
0104 
0105     QString fallbackConfigKey() const;
0106     void setFallbackConfigKey(const QString &key);
0107 
0108     bool relayoutLock() const;
0109     void setRelayoutLock(bool lock);
0110 
0111     PlasmaQuick::AppletQuickItem *containment() const;
0112     void setContainment(PlasmaQuick::AppletQuickItem *containment);
0113 
0114     QJSValue acceptsAppletCallback() const;
0115     void setAcceptsAppletCallback(const QJSValue &callback);
0116 
0117     qreal minimumItemWidth() const;
0118     void setMinimumItemWidth(qreal width);
0119 
0120     qreal minimumItemHeight() const;
0121     void setMinimumItemHeight(qreal height);
0122 
0123     qreal defaultItemWidth() const;
0124     void setDefaultItemWidth(qreal width);
0125 
0126     qreal defaultItemHeight() const;
0127     void setDefaultItemHeight(qreal height);
0128 
0129     qreal cellWidth() const;
0130     void setCellWidth(qreal width);
0131 
0132     qreal cellHeight() const;
0133     void setCellHeight(qreal height);
0134 
0135     QQmlComponent *appletContainerComponent() const;
0136     void setAppletContainerComponent(QQmlComponent *component);
0137 
0138     ItemContainer *placeHolder() const;
0139     void setPlaceHolder(ItemContainer *placeHolder);
0140 
0141     QQuickItem *eventManagerToFilter() const;
0142     void setEventManagerToFilter(QQuickItem *item);
0143 
0144     EditModeCondition editModeCondition() const;
0145     void setEditModeCondition(EditModeCondition condition);
0146 
0147     bool editMode() const;
0148     void setEditMode(bool edit);
0149 
0150     Q_INVOKABLE void save();
0151     Q_INVOKABLE void showPlaceHolderAt(const QRectF &geom);
0152     Q_INVOKABLE void showPlaceHolderForItem(ItemContainer *item);
0153     Q_INVOKABLE void hidePlaceHolder();
0154 
0155     Q_INVOKABLE bool isRectAvailable(qreal x, qreal y, qreal width, qreal height);
0156     Q_INVOKABLE bool itemIsManaged(ItemContainer *item);
0157     Q_INVOKABLE void positionItem(ItemContainer *item);
0158     Q_INVOKABLE void restoreItem(ItemContainer *item);
0159     Q_INVOKABLE void releaseSpace(ItemContainer *item);
0160 
0161 Q_SIGNALS:
0162     /**
0163      * An applet has been refused by the layout: acceptsAppletCallback
0164      * returned false and will need to be managed in a different way
0165      */
0166     void appletRefused(QObject *applet, int x, int y);
0167 
0168     void configKeyChanged();
0169     void fallbackConfigKeyChanged();
0170     void relayoutLockChanged();
0171     void containmentChanged();
0172     void minimumItemWidthChanged();
0173     void minimumItemHeightChanged();
0174     void defaultItemWidthChanged();
0175     void defaultItemHeightChanged();
0176     void cellWidthChanged();
0177     void cellHeightChanged();
0178     void acceptsAppletCallbackChanged();
0179     void appletContainerComponentChanged();
0180     void placeHolderChanged();
0181     void eventManagerToFilterChanged();
0182     void editModeConditionChanged();
0183     void editModeChanged();
0184 
0185 protected:
0186     bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
0187     void updatePolish() override;
0188 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0189     void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0190 #else
0191     void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0192 #endif
0193 
0194     // void classBegin() override;
0195     void componentComplete() override;
0196     void mousePressEvent(QMouseEvent *event) override;
0197     void mouseMoveEvent(QMouseEvent *event) override;
0198     void mouseReleaseEvent(QMouseEvent *event) override;
0199     void mouseUngrabEvent() override;
0200 
0201 private Q_SLOTS:
0202     void appletAdded(QObject *applet, int x, int y);
0203     void appletRemoved(QObject *applet);
0204 
0205 private:
0206     AppletContainer *createContainerForApplet(PlasmaQuick::AppletQuickItem *appletItem);
0207 
0208     QString m_configKey;
0209     QString m_fallbackConfigKey;
0210     QTimer *m_saveLayoutTimer;
0211     QTimer *m_layoutChangeTimer;
0212     LayoutChanges m_layoutChanges = NoChange;
0213 
0214     PlasmaQuick::AppletQuickItem *m_containmentItem = nullptr;
0215     Plasma::Containment *m_containment = nullptr;
0216     QQmlComponent *m_appletContainerComponent = nullptr;
0217 
0218     AbstractLayoutManager *m_layoutManager = nullptr;
0219 
0220     QPointer<ItemContainer> m_placeHolder;
0221     QPointer<QQuickItem> m_eventManagerToFilter;
0222 
0223     QTimer *m_pressAndHoldTimer;
0224 
0225     QJSValue m_acceptsAppletCallback;
0226 
0227     AppletsLayout::EditModeCondition m_editModeCondition = AppletsLayout::Manual;
0228 
0229     QHash<PlasmaQuick::AppletQuickItem *, AppletContainer *> m_containerForApplet;
0230 
0231     QSizeF m_minimumItemSize;
0232     QSizeF m_defaultItemSize;
0233     QSizeF m_savedSize;
0234     QRectF m_geometryBeforeResolutionChange;
0235 
0236     QPointF m_mouseDownPosition = QPoint(-1, -1);
0237     bool m_mouseDownWasEditMode = false;
0238     bool m_editMode = false;
0239     bool m_relayoutLock = false;
0240 };
0241 
0242 Q_DECLARE_OPERATORS_FOR_FLAGS(AppletsLayout::LayoutChanges)