File indexing completed on 2024-05-12 05:37:14
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(QUrl configOverlaySource READ configOverlaySource WRITE setConfigOverlaySource NOTIFY configOverlaySourceChanged) 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 QUrl configOverlaySource() const; 0095 void setConfigOverlaySource(const QUrl &url); 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 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0141 0142 // void classBegin() override; 0143 void componentComplete() override; 0144 bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; 0145 void mousePressEvent(QMouseEvent *event) override; 0146 void mouseReleaseEvent(QMouseEvent *event) override; 0147 void mouseMoveEvent(QMouseEvent *event) override; 0148 void mouseUngrabEvent() override; 0149 void hoverEnterEvent(QHoverEvent *event) override; 0150 void hoverLeaveEvent(QHoverEvent *event) override; 0151 0152 Q_SIGNALS: 0153 0154 /** 0155 * The user manually dragged the ItemContainer around 0156 * @param newPosition new position of the ItemContainer in parent coordinates 0157 * @param dragCenter position in ItemContainer coordinates of the drag hotspot, i.e. where the user pressed the mouse or the 0158 * finger over the ItemContainer 0159 */ 0160 void userDrag(const QPointF &newPosition, const QPointF &dragCenter); 0161 0162 void dragActiveChanged(); 0163 0164 /** 0165 * The attached layout object changed some of its size hints 0166 */ 0167 void sizeHintsChanged(); 0168 0169 // QML property notifiers 0170 void layoutChanged(); 0171 void keyChanged(); 0172 void editModeConditionChanged(); 0173 void editModeChanged(bool editMode); 0174 void preferredLayoutDirectionChanged(); 0175 void configOverlaySourceChanged(); 0176 void configOverlayItemChanged(); 0177 void initialSizeChanged(); 0178 void configOverlayVisibleChanged(bool configOverlayVisile); 0179 0180 void backgroundChanged(); 0181 void contentItemChanged(); 0182 void leftPaddingChanged(); 0183 void rightPaddingChanged(); 0184 void topPaddingChanged(); 0185 void bottomPaddingChanged(); 0186 void contentWidthChanged(); 0187 void contentHeightChanged(); 0188 0189 private Q_SLOTS: 0190 void onConfigOverlayComponentStatusChanged(QQmlComponent::Status status, QQmlComponent *component = nullptr); 0191 0192 private: 0193 void syncChildItemsGeometry(const QSizeF &size); 0194 void sendUngrabRecursive(QQuickItem *item); 0195 0196 void loadConfigOverlayItem(); 0197 0198 // internal accessorts for the contentData QProperty 0199 static void contentData_append(QQmlListProperty<QObject> *prop, QObject *object); 0200 static qsizetype contentData_count(QQmlListProperty<QObject> *prop); 0201 static QObject *contentData_at(QQmlListProperty<QObject> *prop, qsizetype index); 0202 static void contentData_clear(QQmlListProperty<QObject> *prop); 0203 0204 QPointer<QQuickItem> m_contentItem; 0205 QPointer<QQuickItem> m_backgroundItem; 0206 0207 // Internal implementation detail: this is used to reparent all items to contentItem 0208 QList<QObject *> m_contentData; 0209 0210 /** 0211 * Padding adds a space between each edge of the content item and the background item, effectively controlling the size of the content item. 0212 */ 0213 int m_leftPadding = 0; 0214 int m_rightPadding = 0; 0215 int m_topPadding = 0; 0216 int m_bottomPadding = 0; 0217 0218 QString m_key; 0219 0220 QPointer<AppletsLayout> m_layout; 0221 QTimer *m_editModeTimer = nullptr; 0222 QTimer *m_closeEditModeTimer = nullptr; 0223 QTimer *m_sizeHintAdjustTimer = nullptr; 0224 QObject *m_layoutAttached = nullptr; 0225 EditModeCondition m_editModeCondition = Manual; 0226 QSizeF m_initialSize; 0227 0228 QUrl m_configOverlaySource; 0229 ConfigOverlay *m_configOverlay = nullptr; 0230 bool m_configOverlayVisible = false; 0231 0232 QPointF m_lastMousePosition = QPoint(-1, -1); 0233 QPointF m_mouseDownPosition = QPoint(-1, -1); 0234 AppletsLayout::PreferredLayoutDirection m_preferredLayoutDirection = AppletsLayout::Closest; 0235 bool m_editMode = false; 0236 bool m_mouseDown = false; 0237 bool m_mouseSynthetizedFromTouch = false; 0238 bool m_dragActive = false; 0239 };