Files
neochat/src/mediasizehelper.h
2023-09-23 14:05:50 +00:00

106 lines
3.6 KiB
C++

// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include <QObject>
#include <QQmlEngine>
#include <QSize>
/**
* @class MediaSizeHelper
*
* A class to help calculate the current width of a media item within a chat delegate.
*
* The only realistic way to guarantee that a media item (e.g. an image or video)
* is the correct size in QML is to calculate the size manually.
*
* The rules for this component work as follows:
* - The output will always try to keep the media size if no limits are breached.
* - If no media width is set, the current size will be a placeholder at a 16:9 ratio
* calcualated from either the configured max width or the contentMaxWidth, whichever
* is smaller (if the contentMaxWidth isn't set, the configured max width is used).
* - The aspect ratio of the media will always be maintained if set (otherwise 16:9).
* - The current size will never be larger than any of the limits in either direction.
* - If any limit is breached the image size will be reduced while maintaining aspect
* ration, i.e. no stretching or squashing. This can mean that the width or height
* is reduced even if that parameter doesn't breach the limit itself.
*/
class MediaSizeHelper : public QObject
{
Q_OBJECT
QML_ELEMENT
/**
* @brief The maximum width (in px) the media can be.
*
* This is the upper limit placed upon the media by the delegate.
*/
Q_PROPERTY(qreal contentMaxWidth READ contentMaxWidth WRITE setContentMaxWidth NOTIFY contentMaxWidthChanged)
/**
* @brief The maximum height (in px) the media can be.
*
* This is the upper limit placed upon the media by the delegate.
*/
Q_PROPERTY(qreal contentMaxHeight READ contentMaxHeight WRITE setContentMaxHeight NOTIFY contentMaxHeightChanged)
/**
* @brief The base width (in px) of the media.
*/
Q_PROPERTY(qreal mediaWidth READ mediaWidth WRITE setMediaWidth NOTIFY mediaWidthChanged)
/**
* @brief The base height (in px) of the media.
*/
Q_PROPERTY(qreal mediaHeight READ mediaHeight WRITE setMediaHeight NOTIFY mediaHeightChanged)
/**
* @brief The size (in px) of the component based on the current input.
*
* Will always try to return a value even if some of the inputs are not set to
* account for being called before the parameters are intialised. For any parameters
* not set these will just be left out of the calcs.
*
* If no input values are provided a default placeholder value will be returned.
*/
Q_PROPERTY(QSize currentSize READ currentSize NOTIFY currentSizeChanged)
public:
explicit MediaSizeHelper(QObject *parent = nullptr);
qreal contentMaxWidth() const;
void setContentMaxWidth(qreal contentMaxWidth);
qreal contentMaxHeight() const;
void setContentMaxHeight(qreal contentMaxHeight);
qreal mediaWidth() const;
void setMediaWidth(qreal mediaWidth);
qreal mediaHeight() const;
void setMediaHeight(qreal mediaHeight);
QSize currentSize() const;
Q_SIGNALS:
void contentMaxWidthChanged();
void contentMaxHeightChanged();
void mediaWidthChanged();
void mediaHeightChanged();
void currentSizeChanged();
private:
qreal m_contentMaxWidth = -1.0;
qreal m_contentMaxHeight = -1.0;
qreal m_mediaWidth = -1.0;
qreal m_mediaHeight = -1.0;
qreal resolvedMediaWidth() const;
qreal resolvedMediaHeight() const;
qreal aspectRatio() const;
bool limitWidth() const;
qreal widthLimit() const;
qreal heightLimit() const;
};