Skip to content
Snippets Groups Projects
Utils.h 8.81 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <boost/variant.hpp>
    
    
    #include "Cache.h"
    
    #include "timeline/widgets/AudioItem.h"
    #include "timeline/widgets/FileItem.h"
    #include "timeline/widgets/ImageItem.h"
    #include "timeline/widgets/VideoItem.h"
    
    #include <mtx/events/common.hpp>
    
    // Contains information about related events for
    // outgoing messages
    struct RelatedInfo
    {
    
            using MsgType = mtx::events::MessageType;
            MsgType type;
            QString room;
    
            QString quoted_body;
            std::string related_event;
            QString quoted_user;
    };
    
    
    namespace utils {
    
    using TimelineEvent = mtx::events::collections::TimelineEvents;
    
    
    QString
    replaceEmoji(const QString &body);
    
    
    float
    scaleFactor();
    
    void
    setScaleFactor(float factor);
    
    
    //! Whether or not we should respond to key requests for the given room.
    bool
    respondsToKeyRequests(const QString &roomId);
    bool
    respondsToKeyRequests(const std::string &roomId);
    
    void
    setKeyRequestsPreference(QString roomId, bool value);
    
    
    //! Human friendly timestamp representation.
    QString
    descriptiveTime(const QDateTime &then);
    
    //! Generate a message description from the event to be displayed
    //! in the RoomList.
    DescInfo
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    getMessageDescription(const TimelineEvent &event, const QString &localUser, const QString &room_id);
    
    
    //! Get the first character of a string, taking into account that
    //! surrogate pairs might be in use.
    QString
    firstChar(const QString &input);
    
    
    //! Get a human readable file size with the appropriate units attached.
    QString
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    humanReadableFileSize(uint64_t bytes);
    
    QString
    event_body(const mtx::events::collections::TimelineEvents &event);
    
    
    //! Match widgets/events with a description message.
    template<class T>
    QString
    messageDescription(const QString &username = "", const QString &body = "")
    {
    
            using Audio     = mtx::events::RoomEvent<mtx::events::msg::Audio>;
            using Emote     = mtx::events::RoomEvent<mtx::events::msg::Emote>;
            using File      = mtx::events::RoomEvent<mtx::events::msg::File>;
            using Image     = mtx::events::RoomEvent<mtx::events::msg::Image>;
            using Notice    = mtx::events::RoomEvent<mtx::events::msg::Notice>;
            using Sticker   = mtx::events::Sticker;
            using Text      = mtx::events::RoomEvent<mtx::events::msg::Text>;
            using Video     = mtx::events::RoomEvent<mtx::events::msg::Video>;
            using Encrypted = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
    
    
            if (std::is_same<T, AudioItem>::value || std::is_same<T, Audio>::value)
                    return QString("sent an audio clip");
            else if (std::is_same<T, ImageItem>::value || std::is_same<T, Image>::value)
                    return QString("sent an image");
            else if (std::is_same<T, FileItem>::value || std::is_same<T, File>::value)
                    return QString("sent a file");
            else if (std::is_same<T, VideoItem>::value || std::is_same<T, Video>::value)
                    return QString("sent a video clip");
            else if (std::is_same<T, StickerItem>::value || std::is_same<T, Sticker>::value)
                    return QString("sent a sticker");
            else if (std::is_same<T, Notice>::value)
                    return QString("sent a notification");
            else if (std::is_same<T, Text>::value)
                    return QString(": %1").arg(body);
            else if (std::is_same<T, Emote>::value)
                    return QString("* %1 %2").arg(username).arg(body);
    
            else if (std::is_same<T, Encrypted>::value)
                    return QString("sent an encrypted message");
    
    }
    
    template<class T, class Event>
    DescInfo
    createDescriptionInfo(const Event &event, const QString &localUser, const QString &room_id)
    {
            using Text  = mtx::events::RoomEvent<mtx::events::msg::Text>;
            using Emote = mtx::events::RoomEvent<mtx::events::msg::Emote>;
    
    
            const auto msg    = boost::get<T>(event);
    
            const auto sender = QString::fromStdString(msg.sender);
    
            const auto username = Cache::displayName(room_id, sender);
            const auto ts       = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
    
            bool isText  = std::is_same<T, Text>::value;
            bool isEmote = std::is_same<T, Emote>::value;
    
            return DescInfo{
    
              QString::fromStdString(msg.event_id),
    
              isEmote ? "" : (sender == localUser ? "You" : username),
              sender,
              (isText || isEmote)
                ? messageDescription<T>(username, QString::fromStdString(msg.content.body).trimmed())
                : QString(" %1").arg(messageDescription<T>()),
              utils::descriptiveTime(ts),
              ts};
    }
    
    
    //! Scale down an image to fit to the given width & height limitations.
    
    QPixmap
    scaleDown(uint64_t maxWidth, uint64_t maxHeight, const QPixmap &source);
    
    //! Delete items in a container based on a predicate.
    template<typename ContainerT, typename PredicateT>
    void
    erase_if(ContainerT &items, const PredicateT &predicate)
    {
            for (auto it = items.begin(); it != items.end();) {
                    if (predicate(*it))
                            it = items.erase(it);
                    else
                            ++it;
            }
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    }
    
    inline uint64_t
    event_timestamp(const mtx::events::collections::TimelineEvents &event)
    {
    
            return boost::apply_visitor([](auto msg) { return msg.origin_server_ts; }, event);
    
    }
    
    inline nlohmann::json
    serialize_event(const mtx::events::collections::TimelineEvents &event)
    {
    
            return boost::apply_visitor([](auto msg) { return json(msg); }, event);
    
    inline mtx::events::EventType
    event_type(const mtx::events::collections::TimelineEvents &event)
    {
    
            return boost::apply_visitor([](auto msg) { return msg.type; }, event);
    
    }
    
    inline std::string
    event_id(const mtx::events::collections::TimelineEvents &event)
    {
    
            return boost::apply_visitor([](auto msg) { return msg.event_id; }, event);
    
    }
    
    inline QString
    eventId(const mtx::events::collections::TimelineEvents &event)
    {
            return QString::fromStdString(event_id(event));
    }
    
    inline QString
    event_sender(const mtx::events::collections::TimelineEvents &event)
    {
    
            return boost::apply_visitor([](auto msg) { return QString::fromStdString(msg.sender); },
                                        event);
    
    }
    
    template<class T>
    QString
    message_body(const mtx::events::collections::TimelineEvents &event)
    {
    
            return QString::fromStdString(boost::get<T>(event).content.body);
    
    //! Calculate the Levenshtein distance between two strings with character skipping.
    int
    levenshtein_distance(const std::string &s1, const std::string &s2);
    
    
    QPixmap
    scaleImageToPixmap(const QImage &img, int size);
    
    
    //! Convert a Content Matrix URI to an HTTP link.
    QString
    mxcToHttp(const QUrl &url, const QString &server, int port);
    
    
    //! Convert a ed25519 fingerprint into a human readable form
    QString
    humanReadableFingerprint(const std::string &ed25519);
    
    QString
    humanReadableFingerprint(const QString &ed25519);
    
    
    //! Retrieve the message body taking into account the `formatted_body` field.
    //! If the `format` of the message is not supported we fallback to `body`.
    template<typename RoomMessageT>
    QString
    
    getMessageBody(const RoomMessageT &event)
    
    {
            if (event.content.format.empty())
    
                    return QString::fromStdString(event.content.body).toHtmlEscaped();
    
    
            if (event.content.format != common::FORMAT_MSG_TYPE)
    
                    return QString::fromStdString(event.content.body).toHtmlEscaped();
    
    
            return QString::fromStdString(event.content.formatted_body);
    }
    
    
    //! Replace raw URLs in text with HTML link tags.
    QString
    linkifyMessage(const QString &body);
    
    
    //! Convert the input markdown text to html.
    
    markdownToHtml(const QString &text);
    
    //! Generate a Rich Reply quote message
    QString
    getFormattedQuoteBody(const RelatedInfo &related, const QString &html);
    
    
    //! Get the body for the quote, depending on the event type.
    QString
    getQuoteBody(const RelatedInfo &related);
    
    
    //! Retrieve the color of the links based on the current theme.
    
    QString
    linkColor();
    
    //! Returns the hash code of the input QString
    
    hashQString(const QString &input);
    
    //! Generate a color (matching #RRGGBB) that has an acceptable contrast to background that is based
    //! on the input string.
    QString
    generateContrastingHexColor(const QString &input, const QString &background);
    
    //! Given two luminance values, compute the contrast ratio between them.
    qreal
    computeContrast(const qreal &one, const qreal &two);
    
    //! Compute the luminance of a single color.  Based on https://stackoverflow.com/a/9733420
    qreal
    luminance(const QColor &col);
    
    //! Center a widget in relation to another widget.
    void
    centerWidget(QWidget *widget, QWidget *parent);
    
    
    void
    restoreCombobox(QComboBox *combo, const QString &value);
    
    
    struct SideBarSizes
    {
            int small;
            int normal;
            int groups;
    
            int collapsePoint;
    
    };
    
    SideBarSizes
    calculateSidebarSizes(const QFont &f);