File indexing completed on 2024-05-12 17:08:55
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 0013 #include "appletslayout.h" 0014 0015 class QTimer; 0016 0017 class ConfigOverlay; 0018 0019 class ItemContainer : public QQuickItem 0020 { 0021 Q_OBJECT 0022 Q_INTERFACES(QQmlParserStatus) 0023 0024 Q_PROPERTY(AppletsLayout *layout READ layout NOTIFY layoutChanged) 0025 // TODO: make it unchangeable? probably not 0026 Q_PROPERTY(QString key READ key WRITE setKey NOTIFY keyChanged) 0027 Q_PROPERTY(ItemContainer::EditModeCondition editModeCondition READ editModeCondition WRITE setEditModeCondition NOTIFY editModeConditionChanged) 0028 Q_PROPERTY(bool editMode READ editMode WRITE setEditMode NOTIFY editModeChanged) 0029 Q_PROPERTY(bool dragActive READ dragActive NOTIFY dragActiveChanged) 0030 Q_PROPERTY(AppletsLayout::PreferredLayoutDirection preferredLayoutDirection READ preferredLayoutDirection WRITE setPreferredLayoutDirection NOTIFY 0031 preferredLayoutDirectionChanged) 0032 0033 Q_PROPERTY(QQmlComponent *configOverlayComponent READ configOverlayComponent WRITE setConfigOverlayComponent NOTIFY configOverlayComponentChanged) 0034 Q_PROPERTY(bool configOverlayVisible READ configOverlayVisible WRITE setConfigOverlayVisible NOTIFY configOverlayVisibleChanged) 0035 Q_PROPERTY(QQuickItem *configOverlayItem READ configOverlayItem NOTIFY configOverlayItemChanged) 0036 0037 /** 0038 * Initial size this container asks to have upon creation. only positive values are considered 0039 */ 0040 Q_PROPERTY(QSizeF initialSize READ initialSize WRITE setInitialSize NOTIFY initialSizeChanged) 0041 // From there mostly a clone of QQC2 Control 0042 Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged) 0043 Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged) 0044 0045 /** 0046 * Padding adds a space between each edge of the content item and the background item, effectively controlling the size of the content item. 0047 */ 0048 Q_PROPERTY(int leftPadding READ leftPadding WRITE setLeftPadding NOTIFY leftPaddingChanged) 0049 Q_PROPERTY(int rightPadding READ rightPadding WRITE setRightPadding NOTIFY rightPaddingChanged) 0050 Q_PROPERTY(int topPadding READ topPadding WRITE setTopPadding NOTIFY topPaddingChanged) 0051 Q_PROPERTY(int bottomPadding READ bottomPadding WRITE setBottomPadding NOTIFY bottomPaddingChanged) 0052 0053 /** 0054 * The size of the contents: the size of this item minus the padding 0055 */ 0056 Q_PROPERTY(int contentWidth READ contentWidth NOTIFY contentWidthChanged) 0057 Q_PROPERTY(int contentHeight READ contentHeight NOTIFY contentHeightChanged) 0058 0059 Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) 0060 // Q_CLASSINFO("DeferredPropertyNames", "background,contentItem") 0061 Q_CLASSINFO("DefaultProperty", "contentData") 0062 0063 public: 0064 enum EditModeCondition { 0065 Locked = AppletsLayout::EditModeCondition::Locked, 0066 Manual = AppletsLayout::EditModeCondition::Manual, 0067 AfterPressAndHold = AppletsLayout::EditModeCondition::AfterPressAndHold, 0068 AfterPress, 0069 AfterMouseOver, 0070 }; 0071 Q_ENUMS(EditModeCondition) 0072 0073 ItemContainer(QQuickItem *parent = nullptr); 0074 ~ItemContainer(); 0075 0076 QQmlListProperty<QObject> contentData(); 0077 0078 QString key() const; 0079 void setKey(const QString &id); 0080 0081 bool editMode() const; 0082 void setEditMode(bool edit); 0083 0084 bool dragActive() const; 0085 0086 Q_INVOKABLE void cancelEdit(); 0087 0088 EditModeCondition editModeCondition() const; 0089 void setEditModeCondition(EditModeCondition condition); 0090 0091 AppletsLayout::PreferredLayoutDirection preferredLayoutDirection() const; 0092 void setPreferredLayoutDirection(AppletsLayout::PreferredLayoutDirection direction); 0093 0094 QQmlComponent *configOverlayComponent() const; 0095 void setConfigOverlayComponent(QQmlComponent *component); 0096 0097 bool configOverlayVisible() const; 0098 void setConfigOverlayVisible(bool visible); 0099 0100 // TODO: keep this accessible? 0101 ConfigOverlay *configOverlayItem() const; 0102 0103 QSizeF initialSize() const; 0104 void setInitialSize(const QSizeF &size); 0105 0106 // Control-like api 0107 QQuickItem *contentItem() const; 0108 void setContentItem(QQuickItem *item); 0109 0110 QQuickItem *background() const; 0111 void setBackground(QQuickItem *item); 0112 0113 // Setters and getters for the padding 0114 int leftPadding() const; 0115 void setLeftPadding(int padding); 0116 0117 int topPadding() const; 0118 void setTopPadding(int padding); 0119 0120 int rightPadding() const; 0121 void setRightPadding(int padding); 0122 0123 int bottomPadding() const; 0124 void setBottomPadding(int padding); 0125 0126 int contentWidth() const; 0127 int contentHeight() const; 0128 0129 AppletsLayout *layout() const; 0130 0131 // Not for QML 0132 void setLayout(AppletsLayout *layout); 0133 0134 QObject *layoutAttached() const 0135 { 0136 return m_layoutAttached; 0137 } 0138 0139 protected: 0140 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0141 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0142 #else 0143 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0144 #endif 0145 0146 // void classBegin() override; 0147 void componentComplete() override; 0148 bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; 0149 void mousePressEvent(QMouseEvent *event) override; 0150 void mouseReleaseEvent(QMouseEvent *event) override; 0151 void mouseMoveEvent(QMouseEvent *event) override; 0152 void mouseUngrabEvent() override; 0153 void hoverEnterEvent(QHoverEvent *event) override; 0154 void hoverLeaveEvent(QHoverEvent *event) override; 0155 0156 Q_SIGNALS: 0157 0158 /** 0159 * The user manually dragged the ItemContainer around 0160 * @param newPosition new position of the ItemContainer in parent coordinates 0161 * @param dragCenter position in ItemContainer coordinates of the drag hotspot, i.e. where the user pressed the mouse or the 0162 * finger over the ItemContainer 0163 */ 0164 void userDrag(const QPointF &newPosition, const QPointF &dragCenter); 0165 0166 void dragActiveChanged(); 0167 0168 /** 0169 * The attached layout object changed some of its size hints 0170 */ 0171 void sizeHintsChanged(); 0172 0173 // QML property notifiers 0174 void layoutChanged(); 0175 void keyChanged(); 0176 void editModeConditionChanged(); 0177 void editModeChanged(bool editMode); 0178 void preferredLayoutDirectionChanged(); 0179 void configOverlayComponentChanged(); 0180 void configOverlayItemChanged(); 0181 void initialSizeChanged(); 0182 void configOverlayVisibleChanged(bool configOverlayVisile); 0183 0184 void backgroundChanged(); 0185 void contentItemChanged(); 0186 void leftPaddingChanged(); 0187 void rightPaddingChanged(); 0188 void topPaddingChanged(); 0189 void bottomPaddingChanged(); 0190 void contentWidthChanged(); 0191 void contentHeightChanged(); 0192 0193 private: 0194 void syncChildItemsGeometry(const QSizeF &size); 0195 void sendUngrabRecursive(QQuickItem *item); 0196 0197 // internal accessorts for the contentData QProperty 0198 static void contentData_append(QQmlListProperty<QObject> *prop, QObject *object); 0199 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0200 static int contentData_count(QQmlListProperty<QObject> *prop); 0201 static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index); 0202 #else 0203 static qsizetype contentData_count(QQmlListProperty<QObject> *prop); 0204 static QObject *contentData_at(QQmlListProperty<QObject> *prop, qsizetype index); 0205 #endif 0206 static void contentData_clear(QQmlListProperty<QObject> *prop); 0207 0208 QPointer<QQuickItem> m_contentItem; 0209 QPointer<QQuickItem> m_backgroundItem; 0210 0211 // Internal implementation detail: this is used to reparent all items to contentItem 0212 QList<QObject *> m_contentData; 0213 0214 /** 0215 * Padding adds a space between each edge of the content item and the background item, effectively controlling the size of the content item. 0216 */ 0217 int m_leftPadding = 0; 0218 int m_rightPadding = 0; 0219 int m_topPadding = 0; 0220 int m_bottomPadding = 0; 0221 0222 QString m_key; 0223 0224 QPointer<AppletsLayout> m_layout; 0225 QTimer *m_editModeTimer = nullptr; 0226 QTimer *m_closeEditModeTimer = nullptr; 0227 QTimer *m_sizeHintAdjustTimer = nullptr; 0228 QObject *m_layoutAttached = nullptr; 0229 EditModeCondition m_editModeCondition = Manual; 0230 QSizeF m_initialSize; 0231 0232 QPointer<QQmlComponent> m_configOverlayComponent; 0233 ConfigOverlay *m_configOverlay = nullptr; 0234 0235 QPointF m_lastMousePosition = QPoint(-1, -1); 0236 QPointF m_mouseDownPosition = QPoint(-1, -1); 0237 AppletsLayout::PreferredLayoutDirection m_preferredLayoutDirection = AppletsLayout::Closest; 0238 bool m_editMode = false; 0239 bool m_mouseDown = false; 0240 bool m_mouseSynthetizedFromTouch = false; 0241 bool m_dragActive = false; 0242 };