Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
390 andreas 1
/*
2
 * Copyright (C) 2023 by Andreas Theofilu <andreas@theosys.at>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
#include <QPainter>
19
#include <QString>
20
#include <QStaticText>
421 andreas 21
#include <QRegion>
22
#include <QApplication>
390 andreas 23
 
419 andreas 24
#include <vector>
422 andreas 25
#include <chrono>
419 andreas 26
 
390 andreas 27
#include "tqmarquee.h"
28
#include "terror.h"
29
 
419 andreas 30
using std::vector;
31
 
390 andreas 32
TQMarquee::TQMarquee(QWidget* parent)
391 andreas 33
    : QLabel(parent),
390 andreas 34
      mParent(parent)
35
{
36
    DECL_TRACER("TQMarquee::TQMarquee(QWidget* parent)");
37
 
38
    init();
39
}
40
 
391 andreas 41
TQMarquee::TQMarquee(QWidget* parent, int msec, MQ_TYPES type, bool enable)
42
    : QLabel(parent),
390 andreas 43
      mParent(parent),
391 andreas 44
      mScrollEnabled(enable),
422 andreas 45
      mType(type)
390 andreas 46
{
391 andreas 47
    DECL_TRACER("TQMarquee::TQMarquee(QWidget* parent, int msec, MQ_TYPES type, bool enable)");
390 andreas 48
 
422 andreas 49
    if (msec >= 1 && msec <= 10)
424 andreas 50
        mInterval = BASE_SPEED - 2 + msec * 2;
391 andreas 51
 
390 andreas 52
    init();
53
}
54
 
55
TQMarquee::~TQMarquee()
56
{
57
    DECL_TRACER("TQMarquee::~TQMarquee()");
421 andreas 58
 
59
    if (mTimer)
60
    {
61
        if (mTimer->isActive())
62
            mTimer->stop();
63
 
64
        delete mTimer;
65
    }
390 andreas 66
}
67
 
68
void TQMarquee::init()
69
{
70
    DECL_TRACER("TQMarquee::init()");
71
 
391 andreas 72
    switch(mType)
73
    {
395 andreas 74
        case MQ_LEFT:   mDirection = Qt::RightToLeft; break;
75
        case MQ_RIGHT:  mDirection = Qt::LeftToRight; break;
390 andreas 76
 
391 andreas 77
        default:
395 andreas 78
            mDirection = Qt::RightToLeft;
391 andreas 79
    }
390 andreas 80
 
422 andreas 81
//    setAutoFillBackground(false);
421 andreas 82
    mTimer = new QTimer(this);
83
    mTimer->setTimerType(Qt::CoarseTimer);
84
    connect(mTimer, &QTimer::timeout, this, &TQMarquee::refreshLabel);
85
    // By default the background is transparent
390 andreas 86
    setBackgroundColor(mBgColor);
437 andreas 87
    mFontPointSize = font().pointSize() / 2;
88
    mTextLength = fontMetrics().horizontalAdvance(mText);
89
    mTextHeight = fontMetrics().height();
422 andreas 90
    mTimer->start(mInterval);
390 andreas 91
}
92
 
391 andreas 93
void TQMarquee::setAlignment(Qt::Alignment al)
94
{
95
    DECL_TRACER("TQMarquee::setAlignment(Qt::Alignment al)");
96
 
97
    mAlign = al;
98
    updateCoordinates();
99
}
100
 
101
void TQMarquee::setFrame(int left, int top, int right, int bottom)
102
{
103
    DECL_TRACER("TQMarquee::setFrame(int left, int top, int right, int bottom)");
104
 
394 andreas 105
    mFrameLeft = (left > 0 && left < width() ? left : 0);
106
    mFrameTop = (top > 0 && top < height() ? top : 0);
107
    mFrameRight = (right > 0 && right < width() ? right : 0);
108
    mFrameBottom = (bottom > 0 && bottom < height() ? bottom : 0);
109
 
395 andreas 110
    if ((mFrameLeft + mFrameRight) > width())
111
        mFrameLeft = mFrameRight = 0;
394 andreas 112
 
395 andreas 113
    if ((mFrameTop + mFrameBottom) > height())
114
        mFrameTop = mFrameBottom = 0;
394 andreas 115
 
419 andreas 116
    update();
391 andreas 117
}
118
 
390 andreas 119
void TQMarquee::setText(const QString& text)
120
{
121
    DECL_TRACER("TQMarquee::setText(const QString& text)");
122
 
123
    mText = text;
437 andreas 124
    mFontPointSize = font().pointSize() / 2;
125
    mTextLength = fontMetrics().horizontalAdvance(mText);
126
    mTextHeight = fontMetrics().height();
391 andreas 127
    refreshLabel();
390 andreas 128
    update();
129
}
130
 
437 andreas 131
void TQMarquee::setFont(const QFont &f)
132
{
133
    DECL_TRACER("TQMarquee::setFont(const QFont &font)");
134
 
135
    QLabel::setFont(f);
136
    mFontPointSize = font().pointSize() / 2;
137
    mTextLength = fontMetrics().horizontalAdvance(mText);
138
    mTextHeight = fontMetrics().height();
139
}
140
 
391 andreas 141
void TQMarquee::setSpeed(int msec)
390 andreas 142
{
391 andreas 143
    DECL_TRACER("TQMarquee::setSpeed(int msec)");
390 andreas 144
 
391 andreas 145
    if (msec < 1 || msec > 10)
146
    {
147
        MSG_WARNING("Wrong speed " << msec << "! The speed must be between 1 and 10.");
148
        return;
149
    }
150
 
422 andreas 151
    if (!mTimer)
152
    {
153
        MSG_ERROR("Timer is not initialized!");
154
        return;
155
    }
391 andreas 156
 
424 andreas 157
    mInterval = BASE_SPEED - 2 + msec * 2;
422 andreas 158
 
421 andreas 159
    if (mTimer->isActive())
422 andreas 160
        mTimer->start(mInterval);
391 andreas 161
    else
422 andreas 162
        mTimer->setInterval(mInterval);
390 andreas 163
}
164
 
391 andreas 165
void TQMarquee::pause()
390 andreas 166
{
391 andreas 167
    DECL_TRACER("TQMarquee::pause()");
390 andreas 168
 
422 andreas 169
    if (!mTimer)
170
        return;
171
 
421 andreas 172
    if (mTimer->isActive())
173
        mTimer->stop();
417 andreas 174
 
175
    mPaused = true;
390 andreas 176
}
177
 
391 andreas 178
void TQMarquee::resume()
390 andreas 179
{
391 andreas 180
    DECL_TRACER("TQMarquee::resume()");
390 andreas 181
 
422 andreas 182
    if (!mTimer)
183
        return;
184
 
421 andreas 185
    if (!mTimer->isActive())
422 andreas 186
        mTimer->start(mInterval);
417 andreas 187
 
188
    mPaused = false;
390 andreas 189
}
190
 
191
QColor TQMarquee::backgroundColor()
192
{
193
    DECL_TRACER("TQMarquee::backgroundColor()");
194
 
195
    QPalette::ColorRole colorRole = backgroundRole();
196
    QBrush brush = palette().brush(colorRole);
197
    return brush.color();
198
}
199
 
200
void TQMarquee::setBackgroundColor(QColor& color)
201
{
202
    DECL_TRACER("TQMarquee::setBackgroundColor(QColor& color)");
203
 
204
    QBrush brush;
205
    brush.setColor(color);
206
    QPalette pal;
207
    pal.setBrush(backgroundRole(), brush);
208
    setPalette(pal);
209
}
210
 
391 andreas 211
QPixmap TQMarquee::background()
390 andreas 212
{
213
    DECL_TRACER("TQMarquee::background()");
214
 
215
    return mBackgroundImage;
216
}
217
 
391 andreas 218
void TQMarquee::setBackground(QPixmap& image)
390 andreas 219
{
391 andreas 220
    DECL_TRACER("TQMarquee::setBackground(QPixmap& image)");
390 andreas 221
 
222
    mBackgroundImage = image;
391 andreas 223
    setPixmap(mBackgroundImage);
419 andreas 224
    update();
390 andreas 225
}
226
 
391 andreas 227
void TQMarquee::setDirection(MQ_TYPES type)
390 andreas 228
{
391 andreas 229
    DECL_TRACER("TQMarquee::setDirection(MQ_TYPES type)");
390 andreas 230
 
391 andreas 231
    mType = type;
390 andreas 232
 
391 andreas 233
    switch(type)
234
    {
395 andreas 235
        case MQ_LEFT:   mDirection = Qt::RightToLeft; break;
236
        case MQ_RIGHT:  mDirection = Qt::LeftToRight; break;
390 andreas 237
 
391 andreas 238
        default:
395 andreas 239
            mDirection = Qt::RightToLeft;
391 andreas 240
    }
241
 
395 andreas 242
    if (mType == MQ_RIGHT || mType == MQ_PONG)
391 andreas 243
        px = width() - (mTextLength + mFrameLeft + mFrameRight);
395 andreas 244
    else if (mType == MQ_LEFT)
391 andreas 245
        px = mFrameLeft;
393 andreas 246
    else if (mType == MQ_DOWN)
419 andreas 247
    {
393 andreas 248
        py = height() - (mTextHeight + mFrameTop + mFrameBottom);
419 andreas 249
        px = width() / 2 - mTextLength / 2;
250
    }
393 andreas 251
    else if (mType == MQ_UP)
419 andreas 252
    {
393 andreas 253
        py = mFrameTop;
419 andreas 254
        px = width() / 2 - mTextLength / 2;
255
    }
391 andreas 256
 
257
    refreshLabel();
390 andreas 258
}
259
 
391 andreas 260
void TQMarquee::refreshLabel()
390 andreas 261
{
421 andreas 262
//    DECL_TRACER("TQMarquee::refreshLabel()");       // This would fill up a logfile, if there is one.
390 andreas 263
 
419 andreas 264
    update();
390 andreas 265
}
266
 
421 andreas 267
void TQMarquee::hideEvent(QHideEvent *e)
417 andreas 268
{
269
    DECL_TRACER("TQMarquee::hideEvent(QHideEvent*)");
270
 
271
    pause();
421 andreas 272
    QLabel::hideEvent(e);
417 andreas 273
}
274
 
421 andreas 275
void TQMarquee::showEvent(QShowEvent *e)
417 andreas 276
{
277
    DECL_TRACER("TQMarquee::showEvent(QShowEvent*)");
278
 
279
    resume();
421 andreas 280
    QLabel::showEvent(e);
417 andreas 281
}
282
 
421 andreas 283
bool TQMarquee::testVisibility(const QRegion& region)
284
{
285
    if (region.isEmpty() || region.isNull())
286
        return false;
287
 
422 andreas 288
    return true;
421 andreas 289
}
290
 
390 andreas 291
void TQMarquee::paintEvent(QPaintEvent*)
292
{
391 andreas 293
//    DECL_TRACER("TQMarquee::paintEvent(QPaintEvent*)");   // This would fill up a logfile, if there is one.
390 andreas 294
 
422 andreas 295
    if (!testVisibility(visibleRegion()))
417 andreas 296
        return;
297
 
390 andreas 298
    QPainter p(this);
391 andreas 299
    p.drawPixmap(0, 0, mBackgroundImage);
390 andreas 300
 
422 andreas 301
    if (mScrollEnabled && !mPaused)
390 andreas 302
    {
395 andreas 303
        if(mType == MQ_LEFT)
391 andreas 304
        {
305
            px -= mSpeed;
390 andreas 306
 
391 andreas 307
            if(px <= (-mTextLength))
308
                px = width();
309
        }
395 andreas 310
        else if (mType == MQ_RIGHT)
391 andreas 311
        {
312
            px += mSpeed;
390 andreas 313
 
391 andreas 314
            if(px >= width())
393 andreas 315
                px = -mTextLength;
390 andreas 316
        }
393 andreas 317
        else if (mType == MQ_PONG)
318
        {
319
            if (mDirection == Qt::LeftToRight)
320
            {
321
                px -= mSpeed;
322
                bool changeDirection = false;
390 andreas 323
 
393 andreas 324
                if (mTextLength > width())
421 andreas 325
                    changeDirection = (px <= (width() - mTextLength - mFrameLeft));
393 andreas 326
                else
327
                    changeDirection = (px <= mFrameLeft);
328
 
329
                if (changeDirection)
330
                    mDirection = Qt::RightToLeft;
331
            }
332
            else
333
            {
334
                px += mSpeed;
335
                bool changeDirection = false;
336
 
421 andreas 337
                if (mTextLength > width())
393 andreas 338
                    changeDirection = (px >= mFrameLeft);
339
                else
340
                    changeDirection = (px >= (width() - mTextLength - mFrameRight));
341
 
342
                if (changeDirection)
343
                    mDirection = Qt::LeftToRight;
344
            }
345
        }
346
        else if (mType == MQ_DOWN)
347
        {
348
            py += mSpeed;
349
 
350
            if (py >= height())
351
                py = -mTextHeight;
352
        }
353
        else if (mType == MQ_UP)
354
        {
355
            py -= mSpeed;
356
 
357
            if (py <= (-mTextHeight))
358
                py = height();
359
        }
360
 
394 andreas 361
        if (mFrameLeft || mFrameRight || mFrameTop || mFrameBottom)
362
            p.setClipRect(QRect(mFrameLeft, mFrameTop, width() - mFrameLeft - mFrameRight, height() - mFrameBottom - mFrameTop), Qt::ReplaceClip);
393 andreas 363
 
391 andreas 364
        p.drawText(px, py + mFontPointSize, mText);
365
        p.translate(px,0);
390 andreas 366
    }
422 andreas 367
//    else
368
//        QLabel::setText(mText);
391 andreas 369
}
390 andreas 370
 
391 andreas 371
void TQMarquee::resizeEvent(QResizeEvent* evt)
372
{
373
    DECL_TRACER("TQMarquee::resizeEvent(QResizeEvent* evt)");
390 andreas 374
 
391 andreas 375
    updateCoordinates();
376
    QLabel::resizeEvent(evt);
390 andreas 377
}
378
 
391 andreas 379
void TQMarquee::updateCoordinates()
390 andreas 380
{
391 andreas 381
    DECL_TRACER("TQMarquee::updateCoordinates()");
390 andreas 382
 
437 andreas 383
//    mFontPointSize = font().pointSize() / 2;
384
//    mTextLength = fontMetrics().horizontalAdvance(mText);
385
//    mTextHeight = fontMetrics().height();
417 andreas 386
 
419 andreas 387
    vector<Qt::Alignment> alignList = {
388
        Qt::AlignLeft, Qt::AlignHCenter, Qt::AlignRight,
389
        Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom };
390
    vector<Qt::Alignment>::iterator iter;
391
 
392
    for (iter = alignList.begin(); iter != alignList.end(); ++iter)
390 andreas 393
    {
421 andreas 394
        bool al = (mAlign & *iter) == *iter;
417 andreas 395
 
421 andreas 396
        if (al)
419 andreas 397
        {
421 andreas 398
            switch(*iter)
399
            {
400
                case Qt::AlignTop:      py = mFrameTop + mTextHeight / 2; break;
401
                case Qt::AlignBottom:   py = height() - (mFrameTop + mFrameBottom + mTextHeight / 2); break;
402
                case Qt::AlignVCenter:  py = height() / 2; break;
419 andreas 403
 
421 andreas 404
                case Qt::AlignLeft:     px = mFrameLeft; break;
405
                case Qt::AlignRight:    px = width() - mTextLength - mFrameRight; break;
406
                case Qt::AlignHCenter:  px = width() / 2 - mTextLength / 2; break;
419 andreas 407
 
421 andreas 408
                default:
409
                    px = width() / 2 - mTextLength / 2;
410
                    py = height() / 2;
411
            }
419 andreas 412
        }
390 andreas 413
    }
414
}