/* SPDX-FileCopyrightText: 2019 Marco Martin SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include #include #include #include class QTimer; namespace Plasma { class Applet; class Containment; } namespace PlasmaQuick { class AppletQuickItem; } class AbstractLayoutManager; class AppletContainer; class ItemContainer; class AppletsLayout : public QQuickItem { Q_OBJECT QML_ELEMENT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString configKey READ configKey WRITE setConfigKey NOTIFY configKeyChanged) // A config key that can be used as fallback when loading and configKey is not found // Is always a backup of the last used configKey. Useful when the configkey depends // from the screen size and plasma starts on an "unexpected" size Q_PROPERTY(QString fallbackConfigKey READ fallbackConfigKey WRITE setFallbackConfigKey NOTIFY fallbackConfigKeyChanged) Q_PROPERTY(bool relayoutLock READ relayoutLock WRITE setRelayoutLock NOTIFY relayoutLockChanged) Q_PROPERTY(Plasma::Containment *containment READ containment WRITE setContainment NOTIFY containmentChanged) Q_PROPERTY(PlasmaQuick::AppletQuickItem *containmentItem READ containmentItem WRITE setContainmentItem NOTIFY containmentItemChanged) Q_PROPERTY(QJSValue acceptsAppletCallback READ acceptsAppletCallback WRITE setAcceptsAppletCallback NOTIFY acceptsAppletCallbackChanged) Q_PROPERTY(qreal minimumItemWidth READ minimumItemWidth WRITE setMinimumItemWidth NOTIFY minimumItemWidthChanged) Q_PROPERTY(qreal minimumItemHeight READ minimumItemHeight WRITE setMinimumItemHeight NOTIFY minimumItemHeightChanged) Q_PROPERTY(qreal defaultItemWidth READ defaultItemWidth WRITE setDefaultItemWidth NOTIFY defaultItemWidthChanged) Q_PROPERTY(qreal defaultItemHeight READ defaultItemHeight WRITE setDefaultItemHeight NOTIFY defaultItemHeightChanged) Q_PROPERTY(qreal cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged) Q_PROPERTY(qreal cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged) Q_PROPERTY(QQmlComponent *appletContainerComponent READ appletContainerComponent WRITE setAppletContainerComponent NOTIFY appletContainerComponentChanged) Q_PROPERTY(ItemContainer *placeHolder READ placeHolder WRITE setPlaceHolder NOTIFY placeHolderChanged) /** * if the applets layout contains some kind of main MouseArea, * MouseEventListener or Flickable, we want to filter its events to make the * long mouse press work */ Q_PROPERTY(QQuickItem *eventManagerToFilter READ eventManagerToFilter WRITE setEventManagerToFilter NOTIFY eventManagerToFilterChanged) Q_PROPERTY(AppletsLayout::EditModeCondition editModeCondition READ editModeCondition WRITE setEditModeCondition NOTIFY editModeConditionChanged) Q_PROPERTY(bool editMode READ editMode WRITE setEditMode NOTIFY editModeChanged) public: enum PreferredLayoutDirection { Closest = 0, LeftToRight, RightToLeft, TopToBottom, BottomToTop, }; Q_ENUM(PreferredLayoutDirection) enum EditModeCondition { Locked = 0, Manual, AfterPressAndHold, }; Q_ENUM(EditModeCondition) enum LayoutChange { NoChange = 0, SizeChange = 1, ConfigKeyChange = 2, }; Q_DECLARE_FLAGS(LayoutChanges, LayoutChange) AppletsLayout(QQuickItem *parent = nullptr); ~AppletsLayout(); // QML setters and getters QString configKey() const; void setConfigKey(const QString &key); QString fallbackConfigKey() const; void setFallbackConfigKey(const QString &key); bool relayoutLock() const; void setRelayoutLock(bool lock); Plasma::Containment *containment() const; void setContainment(Plasma::Containment *containment); PlasmaQuick::AppletQuickItem *containmentItem() const; void setContainmentItem(PlasmaQuick::AppletQuickItem *containment); QJSValue acceptsAppletCallback() const; void setAcceptsAppletCallback(const QJSValue &callback); qreal minimumItemWidth() const; void setMinimumItemWidth(qreal width); qreal minimumItemHeight() const; void setMinimumItemHeight(qreal height); qreal defaultItemWidth() const; void setDefaultItemWidth(qreal width); qreal defaultItemHeight() const; void setDefaultItemHeight(qreal height); qreal cellWidth() const; void setCellWidth(qreal width); qreal cellHeight() const; void setCellHeight(qreal height); QQmlComponent *appletContainerComponent() const; void setAppletContainerComponent(QQmlComponent *component); ItemContainer *placeHolder() const; void setPlaceHolder(ItemContainer *placeHolder); QQuickItem *eventManagerToFilter() const; void setEventManagerToFilter(QQuickItem *item); EditModeCondition editModeCondition() const; void setEditModeCondition(EditModeCondition condition); bool editMode() const; void setEditMode(bool edit); Q_INVOKABLE void save(); Q_INVOKABLE void showPlaceHolderAt(const QRectF &geom); Q_INVOKABLE void showPlaceHolderForItem(ItemContainer *item); Q_INVOKABLE void hidePlaceHolder(); Q_INVOKABLE bool isRectAvailable(qreal x, qreal y, qreal width, qreal height); Q_INVOKABLE bool itemIsManaged(ItemContainer *item); Q_INVOKABLE void positionItem(ItemContainer *item); Q_INVOKABLE void restoreItem(ItemContainer *item); Q_INVOKABLE void releaseSpace(ItemContainer *item); Q_SIGNALS: /** * An applet has been refused by the layout: acceptsAppletCallback * returned false and will need to be managed in a different way */ void appletRefused(QObject *applet, int x, int y); void configKeyChanged(); void fallbackConfigKeyChanged(); void relayoutLockChanged(); void containmentChanged(); void minimumItemWidthChanged(); void minimumItemHeightChanged(); void defaultItemWidthChanged(); void defaultItemHeightChanged(); void cellWidthChanged(); void cellHeightChanged(); void acceptsAppletCallbackChanged(); void appletContainerComponentChanged(); void placeHolderChanged(); void eventManagerToFilterChanged(); void editModeConditionChanged(); void editModeChanged(); void containmentItemChanged(); protected: bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; void updatePolish() override; void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; // void classBegin() override; void componentComplete() override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void touchEvent(QTouchEvent *event) override; void touchUngrabEvent() override; private Q_SLOTS: void appletAdded(Plasma::Applet *applet); void appletRemoved(Plasma::Applet *applet); private: AppletContainer *createContainerForApplet(PlasmaQuick::AppletQuickItem *appletItem); void handleMoveEvent(const QPointF &scenePosition); void handleReleaseEvent(const QPointF &scenePosition); QString m_configKey; QString m_fallbackConfigKey; QTimer *m_saveLayoutTimer; QTimer *m_layoutChangeTimer; LayoutChanges m_layoutChanges = NoChange; Plasma::Containment *m_containment = nullptr; QQmlComponent *m_appletContainerComponent = nullptr; QPointer m_containmentItem; AbstractLayoutManager *m_layoutManager = nullptr; QPointer m_placeHolder; QPointer m_eventManagerToFilter; QTimer *m_pressAndHoldTimer; QJSValue m_acceptsAppletCallback; AppletsLayout::EditModeCondition m_editModeCondition = AppletsLayout::Manual; QHash m_containerForApplet; QSizeF m_minimumItemSize; QSizeF m_defaultItemSize; QSizeF m_savedSize; QRectF m_geometryBeforeResolutionChange; QPointF m_touchDownPosition = QPoint(-1, -1); bool m_touchDownWasEditMode = false; bool m_editMode = false; bool m_relayoutLock = false; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AppletsLayout::LayoutChanges)