Skip to content
Snippets Groups Projects
Utils.h 11.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Werner's avatar
    Nicolas Werner committed
    #include <variant>
    
    #include <QCoreApplication>
    
    #include <mtx/events/collections.hpp>
    
    #include <mtx/events/common.hpp>
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    struct DescInfo;
    
    
    namespace cache {
    // Forward declarations to prevent dependency on Cache.h, since this header is included often!
    QString
    displayName(const QString &room_id, const QString &user_id);
    }
    
    
    // Contains information about related events for
    // outgoing messages
    struct RelatedInfo
    {
    
            using MsgType = mtx::events::MessageType;
            MsgType type;
            QString room;
    
            QString quoted_body, quoted_formatted_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
    
    getMessageDescription(const TimelineEvent &event,
                          const QString &localUser,
                          const QString &displayName);
    
    
    //! 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     = "",
                       const bool isLocal      = false)
    
    trilene's avatar
    trilene committed
            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 CallInvite = mtx::events::RoomEvent<mtx::events::msg::CallInvite>;
            using CallAnswer = mtx::events::RoomEvent<mtx::events::msg::CallAnswer>;
            using CallHangUp = mtx::events::RoomEvent<mtx::events::msg::CallHangUp>;
            using Encrypted  = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            if (std::is_same<T, Audio>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent an audio clip");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent an audio clip")
                              .arg(username);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            } else if (std::is_same<T, Image>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent an image");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent an image")
                              .arg(username);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            } else if (std::is_same<T, File>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent a file");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent a file")
                              .arg(username);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            } else if (std::is_same<T, Video>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent a video");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent a video")
                              .arg(username);
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            } else if (std::is_same<T, Sticker>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent a sticker");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent a sticker")
                              .arg(username);
    
            } else if (std::is_same<T, Notice>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent a notification");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent a notification")
                              .arg(username);
    
            } else if (std::is_same<T, Text>::value) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:", "You: %1")
                              .arg(body);
                    else
                            return QCoreApplication::translate("message-description sent:", "%1: %2")
                              .arg(username)
                              .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) {
    
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You sent an encrypted message");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 sent an encrypted message")
                              .arg(username);
    
    trilene's avatar
    trilene committed
            } else if (std::is_same<T, CallInvite>::value) {
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You placed a call");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 placed a call")
                              .arg(username);
            } else if (std::is_same<T, CallAnswer>::value) {
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You answered a call");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 answered a call")
                              .arg(username);
            } else if (std::is_same<T, CallHangUp>::value) {
                    if (isLocal)
                            return QCoreApplication::translate("message-description sent:",
                                                               "You ended a call");
                    else
                            return QCoreApplication::translate("message-description sent:",
                                                               "%1 ended a call")
                              .arg(username);
    
            } else {
                    return QCoreApplication::translate("utils", "Unknown Message Type");
            }
    
    //! 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
    }
    
    template<class T>
    QString
    message_body(const mtx::events::collections::TimelineEvents &event)
    {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            return QString::fromStdString(std::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 != mtx::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);
    
    //! Escape every html tag, that was not whitelisted
    QString
    escapeBlacklistedHtml(const QString &data);
    
    
    //! 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);
    
    
    //! Read image respecting exif orientation
    QImage
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    readImage(const QByteArray *data);