File indexing completed on 2024-04-28 04:59:46

0001 // SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 #pragma once
0005 
0006 #include <QObject>
0007 #include <QQmlEngine>
0008 #include <QSize>
0009 
0010 /**
0011  * @class MediaSizeHelper
0012  *
0013  * A class to help calculate the current width of a media item within a chat delegate.
0014  *
0015  * The only realistic way to guarantee that a media item (e.g. an image or video)
0016  * is the correct size in QML is to calculate the size manually.
0017  *
0018  * The rules for this component work as follows:
0019  *  - The output will always try to keep the media size if no limits are breached.
0020  *  - If no media width is set, the current size will be a placeholder at a 16:9 ratio
0021  *    calcualated from either the configured max width or the contentMaxWidth, whichever
0022  *    is smaller (if the contentMaxWidth isn't set, the configured max width is used).
0023  *  - The aspect ratio of the media will always be maintained if set (otherwise 16:9).
0024  *  - The current size will never be larger than any of the limits in either direction.
0025  *  - If any limit is breached the image size will be reduced while maintaining aspect
0026  *    ration, i.e. no stretching or squashing. This can mean that the width or height
0027  *    is reduced even if that parameter doesn't breach the limit itself.
0028  */
0029 class MediaSizeHelper : public QObject
0030 {
0031     Q_OBJECT
0032     QML_ELEMENT
0033 
0034     /**
0035      * @brief The maximum width (in px) the media can be.
0036      *
0037      * This is the upper limit placed upon the media by the delegate.
0038      */
0039     Q_PROPERTY(qreal contentMaxWidth READ contentMaxWidth WRITE setContentMaxWidth NOTIFY contentMaxWidthChanged)
0040 
0041     /**
0042      * @brief The maximum height (in px) the media can be.
0043      *
0044      * This is the upper limit placed upon the media by the delegate.
0045      */
0046     Q_PROPERTY(qreal contentMaxHeight READ contentMaxHeight WRITE setContentMaxHeight NOTIFY contentMaxHeightChanged)
0047 
0048     /**
0049      * @brief The base width (in px) of the media.
0050      */
0051     Q_PROPERTY(qreal mediaWidth READ mediaWidth WRITE setMediaWidth NOTIFY mediaWidthChanged)
0052 
0053     /**
0054      * @brief The base height (in px) of the media.
0055      */
0056     Q_PROPERTY(qreal mediaHeight READ mediaHeight WRITE setMediaHeight NOTIFY mediaHeightChanged)
0057 
0058     /**
0059      * @brief The size (in px) of the component based on the current input.
0060      *
0061      * Will always try to return a value even if some of the inputs are not set to
0062      * account for being called before the parameters are intialised. For any parameters
0063      * not set these will just be left out of the calcs.
0064      *
0065      * If no input values are provided a default placeholder value will be returned.
0066      */
0067     Q_PROPERTY(QSize currentSize READ currentSize NOTIFY currentSizeChanged)
0068 
0069 public:
0070     explicit MediaSizeHelper(QObject *parent = nullptr);
0071 
0072     qreal contentMaxWidth() const;
0073     void setContentMaxWidth(qreal contentMaxWidth);
0074 
0075     qreal contentMaxHeight() const;
0076     void setContentMaxHeight(qreal contentMaxHeight);
0077 
0078     qreal mediaWidth() const;
0079     void setMediaWidth(qreal mediaWidth);
0080 
0081     qreal mediaHeight() const;
0082     void setMediaHeight(qreal mediaHeight);
0083 
0084     QSize currentSize() const;
0085 
0086 Q_SIGNALS:
0087     void contentMaxWidthChanged();
0088     void contentMaxHeightChanged();
0089     void mediaWidthChanged();
0090     void mediaHeightChanged();
0091     void currentSizeChanged();
0092 
0093 private:
0094     qreal m_contentMaxWidth = -1.0;
0095     qreal m_contentMaxHeight = -1.0;
0096     qreal m_mediaWidth = -1.0;
0097     qreal m_mediaHeight = -1.0;
0098 
0099     qreal resolvedMediaWidth() const;
0100     qreal resolvedMediaHeight() const;
0101     qreal aspectRatio() const;
0102     bool limitWidth() const;
0103     qreal widthLimit() const;
0104     qreal heightLimit() const;
0105 };