File indexing completed on 2024-11-10 05:11:08

0001 /*
0002  *   Copyright 2018 by Marco Martin <mart@kde.org>
0003  *
0004  * Licensed under the Apache License, Version 2.0 (the "License");
0005  * you may not use this file except in compliance with the License.
0006  * You may obtain a copy of the License at
0007  *
0008  *    http://www.apache.org/licenses/LICENSE-2.0
0009  *
0010  * Unless required by applicable law or agreed to in writing, software
0011  * distributed under the License is distributed on an "AS IS" BASIS,
0012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013  * See the License for the specific language governing permissions and
0014  * limitations under the License.
0015  *
0016  */
0017 
0018 #pragma once
0019 
0020 #include <QQuickItem>
0021 #include <QQmlParserStatus>
0022 #include <QQmlPropertyMap>
0023 #include <QPointer>
0024 
0025 #include "sessiondatamap.h"
0026 #include "abstractskillview.h"
0027 
0028 class MycroftController;
0029 
0030 class DelegateLoader : public QObject {
0031     Q_OBJECT
0032 public:
0033     DelegateLoader(AbstractSkillView *parent);
0034     ~DelegateLoader();
0035 
0036     void init(const QString skillId, const QUrl &url);
0037     AbstractDelegate *delegate();
0038 
0039     void setFocus(bool focus);
0040 
0041     QUrl translationsUrl() const;
0042 
0043 Q_SIGNALS:
0044     void delegateCreated();
0045 
0046 private:
0047     void createObject();
0048 
0049     QString m_skillId;
0050     QUrl m_delegateUrl;
0051     bool m_focus = false;
0052     QQmlComponent *m_component = nullptr;
0053     AbstractSkillView *m_view;
0054     QPointer <AbstractDelegate> m_delegate;
0055 };
0056 
0057 class AbstractDelegate: public QQuickItem
0058 {
0059     Q_OBJECT
0060     Q_INTERFACES(QQmlParserStatus)
0061 
0062     /**
0063      * The skill data sent by the server.
0064      */
0065     Q_PROPERTY(SessionDataMap *sessionData READ sessionData CONSTANT)
0066 
0067     /**
0068      * When true the delegate will always take the full screen width. (default false)
0069      */
0070     Q_PROPERTY(bool fillWidth MEMBER m_fillWidth NOTIFY fillWidthChanged)
0071 
0072     /**
0073      * The idle time after Mycroft stopped talking  before the delegate wants to return to the resting face expressed in milliseconds.
0074      * The view may or may not follow this.
0075      * By default, it's 5 seconsa
0076      */
0077     Q_PROPERTY(int timeout MEMBER m_timeout NOTIFY timeoutChanged)
0078 
0079     /**
0080      * Source file for a skill-wide background (independent to the background item): it can be either an image or a QML file. 
0081      * The view may or may not decide to display it, if different delegates of the same skill have different skillBackgrounds, it will fade between them when the current delegate changes.
0082      * Both relative paths and remote urls are supported
0083      */
0084     Q_PROPERTY(QString skillBackgroundSource MEMBER m_backgroundSource NOTIFY skillBackgroundSourceChanged)
0085 
0086     /**
0087      * Color to be used as an overlay for the skill-wide background.
0088      * If you are using skillBackgroundSource as well, consider using a semi transparent color.
0089      * By default is completely transparent on this implementation and Delegate has a slightly translucent black or white depending on the color scheme
0090      */
0091     Q_PROPERTY(QColor skillBackgroundColorOverlay MEMBER m_skillBackgroundColorOverlay NOTIFY skillBackgroundColorOverlayChanged)
0092 
0093     Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged)
0094     Q_PROPERTY(bool contentItemAutoHeight MEMBER m_contentItemAutoHeight NOTIFY contentItemAutoHeightChanged)
0095     Q_PROPERTY(bool contentItemAutoWidth MEMBER m_contentItemAutoWidth NOTIFY contentItemAutoWidthChanged)
0096     Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged)
0097 
0098     /**
0099      * Padding adds a space between each edge of the content item and the background item, effectively controlling the size of the content item.
0100      */
0101     Q_PROPERTY(int leftPadding READ leftPadding WRITE setLeftPadding NOTIFY leftPaddingChanged)
0102     Q_PROPERTY(int rightPadding READ rightPadding WRITE setRightPadding NOTIFY rightPaddingChanged)
0103     Q_PROPERTY(int topPadding READ topPadding WRITE setTopPadding NOTIFY topPaddingChanged)
0104     Q_PROPERTY(int bottomPadding READ bottomPadding WRITE setBottomPadding NOTIFY bottomPaddingChanged)
0105 
0106     /**
0107      * Inset adds a space between the delagate edges and the background, adding an extra empty padding around the delegate
0108      */
0109     Q_PROPERTY(int leftInset READ leftInset WRITE setLeftInset NOTIFY leftInsetChanged)
0110     Q_PROPERTY(int rightInset READ rightInset WRITE setRightInset NOTIFY rightInsetChanged)
0111     Q_PROPERTY(int topInset READ topInset WRITE setTopInset NOTIFY topInsetChanged)
0112     Q_PROPERTY(int bottomInset READ bottomInset WRITE setBottomInset NOTIFY bottomInsetChanged)
0113 
0114     /**
0115      * The size of the contents: the size of this item minux the padding
0116      */
0117     Q_PROPERTY(int contentWidth READ contentWidth NOTIFY contentWidthChanged)
0118     Q_PROPERTY(int contentHeight READ contentHeight NOTIFY contentHeightChanged)
0119 
0120     Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
0121    // Q_CLASSINFO("DeferredPropertyNames", "background,contentItem")
0122     Q_CLASSINFO("DefaultProperty", "contentData")
0123 
0124 public:
0125     AbstractDelegate(QQuickItem *parent = nullptr);
0126     ~AbstractDelegate();
0127 
0128     QQmlListProperty<QObject> contentData();
0129 
0130 /*
0131  * QML properties setters and getters
0132  */
0133     QQuickItem *contentItem() const;
0134     void setContentItem(QQuickItem *item);
0135 
0136     QQuickItem *background() const;
0137     void setBackground(QQuickItem *item);
0138 
0139     /**
0140      * The only way the skill UI has to access the data sent by the server
0141      */
0142     SessionDataMap *sessionData() const;
0143 
0144     // Setters and getters for the padding
0145     int leftPadding() const;
0146     void setLeftPadding(int padding);
0147 
0148     int topPadding() const;
0149     void setTopPadding(int padding);
0150 
0151     int rightPadding() const;
0152     void setRightPadding(int padding);
0153 
0154     int bottomPadding() const;
0155     void setBottomPadding(int padding);
0156 
0157     // Setters and getters for the inset
0158     int leftInset() const;
0159     void setLeftInset(int inset);
0160 
0161     int topInset() const;
0162     void setTopInset(int inset);
0163 
0164     int rightInset() const;
0165     void setRightInset(int inset);
0166 
0167     int bottomInset() const;
0168     void setBottomInset(int inset);
0169 
0170     int contentWidth() const;
0171     int contentHeight() const;
0172 
0173 /*
0174  * @internal All the following API is meant to be used only by AbstractSkillView during initialization, *NOT* QML from where is not accessible at all.
0175  */
0176 
0177     /**
0178      * The sessiondata is writable only by AbstractskillView internally, not from QML
0179      */
0180     void setSessionData(SessionDataMap *data);
0181 
0182     void setSkillView(AbstractSkillView *view);
0183     AbstractSkillView *skillView() const;
0184 
0185     /**
0186      * @internal Url of the qml file that generated this instance
0187      */
0188     void setQmlUrl(const QUrl &url);
0189     QUrl qmlUrl() const;
0190 
0191     /**
0192      * @internal skill id this delegate belongs to
0193      */
0194     void setSkillId(const QString &skillId);
0195 
0196 public Q_SLOTS:
0197     /**
0198      * Trigger an event either for this skill or a system one
0199      * Is not possible to trigger events belonging to different skills
0200      */
0201     void triggerGuiEvent(const QString &eventName, const QVariantMap &parameters);
0202     QString skillId() const;
0203 
0204 protected:
0205     void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0206     protected:
0207     //void classBegin() override;
0208     void componentComplete() override;
0209     bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
0210     void mousePressEvent(QMouseEvent *event) override;
0211     void keyReleaseEvent(QKeyEvent *event) override;
0212     void focusInEvent(QFocusEvent *event) override;
0213 
0214 Q_SIGNALS:
0215     /**
0216      * Emitted when the server triggered an event.
0217      * It is guaranteed the event will be either a system event or an event belonging to our skill, but never to another skill.
0218      * The Skill writer can access this by implementing the following code on the root element of the delegate:
0219      * @code
0220      *  onGuiEvent: {
0221      *      switch (eventName) {
0222      *      case "myevent1":
0223      *       ....
0224      *      }
0225      *  }
0226      * @endcode
0227      * @param eventName the unique name for the event
0228      * @param data the data for this event in JSon form
0229      */
0230     void guiEvent(const QString &eventName, const QVariantMap &data);
0231 
0232     //QML property notifiers
0233     void skillBackgroundSourceChanged();
0234     void skillBackgroundColorOverlayChanged();
0235     void backgroundChanged();
0236     void contentItemChanged();
0237     void contentItemAutoWidthChanged();
0238     void contentItemAutoHeightChanged();
0239     void timeoutChanged();
0240     void fillWidthChanged();
0241     void leftPaddingChanged();
0242     void rightPaddingChanged();
0243     void topPaddingChanged();
0244     void bottomPaddingChanged();
0245     void leftInsetChanged();
0246     void rightInsetChanged();
0247     void topInsetChanged();
0248     void bottomInsetChanged();
0249     void contentWidthChanged();
0250     void contentHeightChanged();
0251 
0252 private:
0253     void syncChildItemsGeometry(const QSizeF &size);
0254     //internal accessorts for the contentData QProperty
0255     static void contentData_append(QQmlListProperty<QObject> *prop, QObject *object);
0256     static qsizetype contentData_count(QQmlListProperty<QObject> *prop);
0257     static QObject *contentData_at(QQmlListProperty<QObject> *prop, qsizetype index);
0258     static void contentData_clear(QQmlListProperty<QObject> *prop);
0259 
0260     QPointer<QQuickItem> m_contentItem;
0261     QPointer<QQuickItem> m_backgroundItem;
0262 
0263     //Internal implementation detail: this is used to reparent all items to contentItem
0264     QList<QObject *> m_contentData;
0265 
0266 
0267     //The main data from the Mycroft server
0268     QPointer<SessionDataMap> m_data;
0269     QPointer<AbstractSkillView> m_skillView;
0270 
0271     QUrl m_qmlUrl;
0272     QString m_skillId;
0273 
0274     QString m_backgroundSource;
0275     QColor m_skillBackgroundColorOverlay = Qt::transparent;
0276     int m_timeout = 5000; //Completely arbitrary 5 seconds of timeout
0277     bool m_fillWidth = false;
0278 
0279     /**
0280      * Padding adds a space between each edge of the content item and the background item, effectively controlling the size of the content item.
0281      */
0282     int m_leftPadding = 0;
0283     int m_rightPadding = 0;
0284     int m_topPadding = 0;
0285     int m_bottomPadding = 0;
0286 
0287     int m_leftInset = 0;
0288     int m_rightInset = 0;
0289     int m_topInset = 0;
0290     int m_bottomInset = 0;
0291 
0292     bool m_contentItemAutoWidth = true;
0293     bool m_contentItemAutoHeight = true;
0294     friend class ServerTest;
0295 };
0296