Skip to content
Snippets Groups Projects
SnackBar.cpp 3.27 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Werner's avatar
    Nicolas Werner committed
    // SPDX-FileCopyrightText: 2021 Nheko Contributors
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    #include <QPainter>
    
    #include "SnackBar.h"
    
    
    constexpr int STARTING_OFFSET         = 1;
    constexpr int BOX_PADDING             = 10;
    constexpr double MIN_WIDTH            = 400.0;
    constexpr double MIN_WIDTH_PERCENTAGE = 0.3;
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
    SnackBar::SnackBar(QWidget *parent)
      : OverlayWidget(parent)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
      , offset_anim(this, "offset", this)
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    {
    
            QFont font;
            font.setPointSizeF(font.pointSizeF() * 1.2);
    
            font.setWeight(50);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
            setFont(font);
    
    
            boxHeight_ = QFontMetrics(font).height() * 2;
            offset_    = STARTING_OFFSET;
            position_  = SnackBarPosition::Top;
    
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            offset_anim.setStartValue(1.0);
            offset_anim.setEndValue(0.0);
            offset_anim.setDuration(100);
            offset_anim.setEasingCurve(QEasingCurve::OutCubic);
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            connect(this, &SnackBar::offsetChanged, this, [this]() mutable { repaint(); });
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            connect(
              &offset_anim, &QPropertyAnimation::finished, this, [this]() { hideTimer_.start(10000); });
    
            connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
    
            hide();
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    }
    
    void
    SnackBar::start()
    {
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
            show();
            raise();
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            offset_anim.start();
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    }
    
    void
    SnackBar::hideMessage()
    {
            stopTimers();
            hide();
    
    
            if (!messages_.empty())
                    // Moving on to the next message.
                    messages_.pop_front();
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
    
            // Resetting the starting position of the widget.
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
            offset_ = STARTING_OFFSET;
    
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
                    start();
    }
    
    void
    SnackBar::stopTimers()
    {
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    }
    
    void
    SnackBar::showMessage(const QString &msg)
    {
            messages_.push_back(msg);
    
            // There is already an active message.
            if (isVisible())
                    return;
    
            start();
    }
    
    void
    SnackBar::mousePressEvent(QMouseEvent *)
    {
            hideMessage();
    }
    
    void
    SnackBar::paintEvent(QPaintEvent *event)
    {
            Q_UNUSED(event)
    
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
                    return;
    
    
            auto message_ = messages_.front();
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
            QPainter p(this);
            p.setRenderHint(QPainter::Antialiasing);
    
            QBrush brush;
            brush.setStyle(Qt::SolidPattern);
            brush.setColor(bgColor_);
            p.setBrush(brush);
    
    
            QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
            p.setPen(Qt::white);
            QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
    
            p.setPen(Qt::NoPen);
    
            r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
            const qreal s = 1 - offset_;
    
            if (position_ == SnackBarPosition::Bottom)
    
                    p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
                                height() - BOX_PADDING - s * (r.height()));
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
            else
    
                    p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
                                s * (r.height()) - 2 * BOX_PADDING);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
    
            br.moveCenter(r.center());
    
            p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
    
    Konstantinos Sideris's avatar
    Konstantinos Sideris committed
            p.setPen(textColor_);
            p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
    }