aboutsummaryrefslogtreecommitdiff
path: root/src/scrolltext.cpp
blob: 6cf075d28c05e505e120d70709c57c09aa7933ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "scrolltext.h"


ScrollText::ScrollText(QWidget *parent) :
    QWidget(parent), scrollPos(0)
{
    staticText.setTextFormat(Qt::PlainText);

//    setFixedHeight(fontMetrics().height()*2); //The theme sets this
    leftMargin = height() / 3;

    setSeparator("   ---   ");

    connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout()));
    timer.setInterval(50);
}

QString ScrollText::text() const
{
    return _text;
}

void ScrollText::setText(QString text)
{
    _text = text;
    updateText();
    update();
}

QString ScrollText::separator() const
{
    return _separator;
}

void ScrollText::setSeparator(QString separator)
{
    _separator = separator;
    updateText();
    update();
}

void ScrollText::updateText()
{
    timer.stop();

    singleTextWidth = fontMetrics().horizontalAdvance(_text);
    scrollEnabled = (singleTextWidth > width() - leftMargin*2);

    if(scrollEnabled)
    {
        scrollPos = -64;
        staticText.setText(_text + _separator);
        timer.start();
    }
    else
        staticText.setText(_text);

    staticText.prepare(QTransform(), font());
    wholeTextSize = QSize(fontMetrics().horizontalAdvance(staticText.text()), fontMetrics().height());
}

void ScrollText::paintEvent(QPaintEvent*)
{
    QPainter p(this);

    if(scrollEnabled)
    {
        buffer.fill(qRgba(0, 0, 0, 0));
        QPainter pb(&buffer);
        pb.setPen(p.pen());
        pb.setFont(p.font());

        int x = qMin(-scrollPos, 0) + leftMargin;
        while(x < width())
        {
            pb.drawStaticText(QPointF(x, (height() - wholeTextSize.height()) / 2), staticText);
            x += wholeTextSize.width();
        }

        //Apply Alpha Channel
        pb.setCompositionMode(QPainter::CompositionMode_DestinationIn);
        pb.setClipRect(width() - 15, 0, 15, height());
        pb.drawImage(0, 0, alphaChannel);
        pb.setClipRect(0, 0, 15, height());
        //initial situation: don't apply alpha channel in the left half of the image at all; apply it more and more until scrollPos gets positive
        if(scrollPos < 0)
            pb.setOpacity(static_cast<qreal>((qMax(-8, scrollPos) + 8) / 8.0));
        pb.drawImage(0, 0, alphaChannel);

        //pb.end();
        p.drawImage(0, 0, buffer);
    }
    else
    {
        p.drawStaticText(QPointF(leftMargin, (height() - wholeTextSize.height()) / 2), staticText);
    }
}

void ScrollText::resizeEvent(QResizeEvent*)
{
    //When the widget is resized, we need to update the alpha channel.

    alphaChannel = QImage(size(), QImage::Format_ARGB32_Premultiplied);
    buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied);

    //Create Alpha Channel:
    if(width() > 64)
    {
        //create first scanline
        QRgb* scanline1 = reinterpret_cast<QRgb*>(alphaChannel.scanLine(0));
        for(int x = 1; x < 16; ++x)
            scanline1[x - 1] = scanline1[width() - x] = qRgba(0, 0, 0, x << 4);
        for(int x = 15; x < width() - 15; ++x)
            scanline1[x] = qRgb(0, 0, 0);
        //copy scanline to the other ones
        for(int y = 1; y < height(); ++y)
            memcpy(alphaChannel.scanLine(y), scanline1, static_cast<uint>(width() * 4));
    }
    else
        alphaChannel.fill(qRgb(0, 0, 0));


    //Update scrolling state
    bool newScrollEnabled = (singleTextWidth > width() - leftMargin);
    if(newScrollEnabled != scrollEnabled)
        updateText();
}

void ScrollText::timer_timeout()
{
    scrollPos = (scrollPos + 2)
                % wholeTextSize.width();
    update();
}