Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
285 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
 
19
#include <QWidget>
20
#include <QScrollArea>
21
#include <QPixmap>
22
#include <QColor>
23
#include <QPainter>
24
#include <QVBoxLayout>
25
#include <QHBoxLayout>
26
#include <QLabel>
27
#include <QPoint>
28
#include <QMouseEvent>
29
#include <QScrollBar>
289 andreas 30
#include <QTimer>
285 andreas 31
 
32
#include "tqscrollarea.h"
33
#include "terror.h"
34
#include "tresources.h"
35
 
36
using std::vector;
37
 
288 andreas 38
/**
39
 * @brief TQScrollArea::TQScrollArea
40
 * Constructor for the class.
41
 */
285 andreas 42
TQScrollArea::TQScrollArea()
43
{
44
    DECL_TRACER("TQScrollArea::TQScrollArea()");
45
}
46
 
288 andreas 47
/**
48
 * @brief TQScrollArea::TQScrollArea
49
 * @param parent    The parent widget
50
 */
285 andreas 51
TQScrollArea::TQScrollArea(QWidget* parent)
52
    : mParent(parent)
53
{
54
    DECL_TRACER("TQScrollArea::TQScrollArea(QWidget* parent)");
55
 
56
    if (parent)
57
    {
58
        mWidth = parent->geometry().width();
59
        mHeight = parent->geometry().height();
60
    }
61
 
62
    init();
63
}
64
 
288 andreas 65
/**
66
 * @brief TQScrollArea::TQScrollArea
67
 * @param parent        Parent widget
68
 * @param w             Visible width in pixels
69
 * @param h             Visible height in pixels
70
 * @param vertical      TRUE: Scrolling in vertical direction
71
 */
285 andreas 72
TQScrollArea::TQScrollArea(QWidget* parent, int w, int h, bool vertical)
73
    : mParent(parent),
74
      mVertical(vertical)
75
{
76
    DECL_TRACER("TQScrollArea::TQScrollArea(QWidget* parent, int w, int h, bool vertical)");
77
 
78
    if (w > 0)
79
        mWidth = w;
80
 
81
    if (h > 0)
82
        mHeight = h;
83
 
84
    init();
85
}
86
 
288 andreas 87
/**
88
 * @brief TQScrollArea::TQScrollArea
89
 * @param parent    Parent widget
90
 * @param size      Size (width and height) of visible area
91
 * @param vertical  TRUE: Scrolling in vertical direction
92
 */
285 andreas 93
TQScrollArea::TQScrollArea(QWidget* parent, const QSize& size, bool vertical)
94
    : mParent(parent),
95
      mVertical(vertical)
96
{
97
    DECL_TRACER("TQScrollArea::TQScrollArea(QWidget* parent, const QSize& size, bool vertical)");
98
 
99
    if (size.width() > 0)
100
        mWidth = size.width();
101
 
102
    if (size.height() > 0)
103
        mHeight = size.height();
104
 
105
    init();
106
}
107
 
108
TQScrollArea::~TQScrollArea()
109
{
110
    DECL_TRACER("TQScrollArea::~TQScrollArea()");
288 andreas 111
 
112
    if (mMain)
113
        mMain->close();
289 andreas 114
 
115
    if (mMousePressTimer)
116
    {
117
        if (mMousePressTimer->isActive())
118
            mMousePressTimer->stop();
119
 
296 andreas 120
        disconnect(mMousePressTimer, &QTimer::timeout, this, &TQScrollArea::mouseTimerEvent);
289 andreas 121
        delete mMousePressTimer;
122
        mMousePressTimer = nullptr;
123
    }
285 andreas 124
}
125
 
126
void TQScrollArea::init()
127
{
128
    DECL_TRACER("TQScrollArea::init()");
129
 
130
    QScrollArea::setParent(mParent);
293 andreas 131
    QScrollArea::setViewportMargins(0, 0, 0, 0);
132
 
133
    if (mWidth > 0 || mHeight > 0)
134
        QScrollArea::setFixedSize(mWidth, mHeight);
135
 
285 andreas 136
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
137
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
138
    // Set a transparent background
286 andreas 139
    QPalette palette(this->palette());
140
    palette.setColor(QPalette::Window, QColor(Qt::transparent));
141
    setPalette(palette);
285 andreas 142
 
143
    if (!mMain)
289 andreas 144
        mMain = new QWidget(this);
285 andreas 145
 
289 andreas 146
    mMain->move(0, 0);
293 andreas 147
    mMain->setContentsMargins(0, 0, 0, 0);
289 andreas 148
 
285 andreas 149
    if (mWidth && mHeight)
150
        setFixedSize(mWidth, mHeight);
151
 
152
    setWidget(mMain);
153
 
154
    if (mVertical && !mVLayout)
295 andreas 155
    {
285 andreas 156
        mVLayout = new QVBoxLayout(mMain);
295 andreas 157
        mVLayout->setSpacing(0);
158
        mVLayout->setContentsMargins(0, 0, 0, 0);
159
    }
288 andreas 160
    else if (!mVertical && !mHLayout)
295 andreas 161
    {
285 andreas 162
        mHLayout = new QHBoxLayout(mMain);
295 andreas 163
        mHLayout->setSpacing(0);
164
        mHLayout->setContentsMargins(0, 0, 0, 0);
165
    }
289 andreas 166
 
295 andreas 167
 
289 andreas 168
    if (!mTotalWidth)
169
        mTotalWidth = mWidth;
170
 
171
    if (!mTotalHeight)
172
        mTotalHeight = mHeight;
285 andreas 173
}
174
 
288 andreas 175
/**
176
 * @brief TQScrollArea::setObjectName
177
 * This sets the object name of the internal main QWidget.
178
 *
179
 * @param name  The name of the object.
180
 */
285 andreas 181
void TQScrollArea::setObjectName(const QString& name)
182
{
183
    DECL_TRACER("TQScrollArea::setObjectName(const QString& name)");
184
 
185
    if (mMain)
186
        mMain->setObjectName(name);
187
}
188
 
288 andreas 189
/**
190
 * @brief TQScrollArea::setSize
191
 * Sets the size of the visible area of the object.
192
 *
193
 * @param w     The width in pixels
194
 * @param h     The height in pixels
195
 */
285 andreas 196
void TQScrollArea::setSize(int w, int h)
197
{
198
    DECL_TRACER("TQScrollArea::setSize(int w, int h)");
199
 
200
    if (w < 1 || h < 1)
201
        return;
202
 
203
    mWidth = w;
204
    mHeight = h;
288 andreas 205
    setFixedSize(mWidth, mHeight);
285 andreas 206
}
207
 
288 andreas 208
/**
209
 * @brief TQScrollArea::setSize
210
 * Sets the size of the visible area of the object.
211
 *
212
 * @param size  The size (width and height)
213
 */
285 andreas 214
void TQScrollArea::setSize(QSize size)
215
{
216
    DECL_TRACER("TQScrollArea::setSize(QSize size)");
217
 
218
    mWidth = size.width();
219
    mHeight = size.height();
220
    setFixedSize(mWidth, mHeight);
221
}
222
 
288 andreas 223
/**
224
 * @brief TQScrollArea::getSize
225
 * Returns the size of the visible area.
226
 *
227
 * @return A QSize object containg the size in pixels.
228
 */
285 andreas 229
QSize TQScrollArea::getSize()
230
{
231
    DECL_TRACER("TQScrollArea::getSize()");
232
 
233
    return QSize(mWidth, mHeight);
234
}
235
 
300 andreas 236
void TQScrollArea::setScrollbar(bool sb)
237
{
238
    DECL_TRACER("TQScrollArea::setScrollbar(bool sb)");
239
 
240
    if (sb == mScrollbar)
241
        return;
242
 
243
    mScrollbar = sb;
244
 
245
    if (sb)
246
    {
247
        if (mVertical)
248
            setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
249
        else
250
            setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
251
    }
252
    else
253
    {
254
        if (mVertical)
255
            setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
256
        else
257
            setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
258
    }
259
}
260
 
261
void TQScrollArea::setScrollbarOffset(int offset)
262
{
263
    DECL_TRACER("TQScrollArea::setScrollbarOffset(int offset)");
264
 
265
    if (!mScrollbar)
266
        return;
267
 
268
    if (offset == 0)
269
    {
270
        mScrollbarOffset = 0;
271
        return;
272
    }
273
 
274
    mScrollbarOffset = scale(offset);
275
    QScrollBar *sbar = nullptr;
276
 
277
    if (mVertical)
278
        sbar = verticalScrollBar();
279
    else
280
        sbar = horizontalScrollBar();
281
 
282
    if (sbar)
283
        sbar->setSliderPosition(mScrollbarOffset);
284
}
285
 
286
void TQScrollArea::setAnchor(Button::SUBVIEW_POSITION_t position)
287
{
288
    DECL_TRACER("TQScrollArea::setAnchor(Button::SUBVIEW_POSITION_t position)");
289
 
290
    mPosition = position;
291
}
292
 
297 andreas 293
void TQScrollArea::show()
294
{
295
    DECL_TRACER("TQScrollArea::show()");
296
 
298 andreas 297
    if (!QScrollArea::isEnabled())
298
        QScrollArea::setEnabled(true);
299
 
297 andreas 300
    QScrollArea::show();
301
 
302
    if (mMain)
298 andreas 303
    {
304
        if (!mMain->isEnabled())
305
            mMain->setEnabled(true);
306
 
307
        if (!mMain->isVisible())
308
            mMain->show();
309
    }
302 andreas 310
 
311
    if (mWrapItems && !mMainWidgets.empty())
312
    {
313
        QWidget *anchor = nullptr;
314
        size_t pos = 0;
315
 
316
        switch (mPosition)
317
        {
318
            case Button::SVP_LEFT_TOP:
319
                anchor = mMainWidgets[0];
320
                break;
321
 
322
            case Button::SVP_CENTER:
323
                pos = mMainWidgets.size() / 2;
324
                anchor = mMainWidgets[pos];
325
                break;
326
 
327
            case Button::SVP_RIGHT_BOTTOM:
328
                pos = mMainWidgets.size() - 1;
329
                anchor = mMainWidgets[pos];
330
                break;
331
        }
332
 
333
        if (anchor)
334
            ensureWidgetVisible(anchor);
335
    }
297 andreas 336
}
337
 
288 andreas 338
/**
339
 * @brief TQScrollArea::setTotalWidth
340
 * Sets the total width of the scrolling area. This must be equal or grater
341
 * then the width of the visible area.
342
 *
343
 * @param w The width in pixels.
344
 */
285 andreas 345
void TQScrollArea::setTotalWidth(int w)
346
{
347
    DECL_TRACER("TQScrollArea::setTotalWidth(int w)");
348
 
349
    if (!mMain || w < mWidth)
350
        return;
351
 
352
    mTotalWidth = w;
288 andreas 353
    mMain->setFixedWidth(mTotalWidth);
285 andreas 354
}
355
 
288 andreas 356
/**
357
 * @brief TQScrollArea::setTotalHeight
358
 * Sets the total height of the scrolling area. This must be equal or grater
359
 * then the height of the visible area.
360
 *
361
 * @param h  The height in pixels.
362
 */
285 andreas 363
void TQScrollArea::setTotalHeight(int h)
364
{
365
    DECL_TRACER("TQScrollArea::setTotalHeight(int h)");
366
 
367
    if (!mMain || h < mHeight)
368
        return;
369
 
370
    mTotalHeight = h;
288 andreas 371
    mMain->setFixedHeight(mTotalHeight);
285 andreas 372
}
373
 
288 andreas 374
/**
375
 * @brief TQScrollArea::setTotalSize
376
 * Sets the total size of the scrolling area. The width and height must be
377
 * equal or grater then the width and height of the visible area.
378
 *
379
 * @param w  The width in pixels.
380
 * @param h  The height in pixels.
381
 */
285 andreas 382
void TQScrollArea::setTotalSize(int w, int h)
383
{
384
    DECL_TRACER("TQScrollArea::setTotalSize(int w, int h)");
385
 
386
    if (!mMain || w < mWidth || h < mHeight)
387
        return;
388
 
389
    mTotalWidth = w;
390
    mTotalHeight = h;
288 andreas 391
    mMain->setFixedSize(mTotalWidth, mTotalHeight);
285 andreas 392
}
393
 
288 andreas 394
/**
395
 * @brief TQScrollArea::setTotalSize
396
 * Sets the total size of the scrolling area in pixels.
397
 *
398
 * @param size  The total size of the scrolling area.
399
 */
285 andreas 400
void TQScrollArea::setTotalSize(QSize& size)
401
{
402
    DECL_TRACER("TQScrollArea::setTotalSize(QSize& size)");
403
 
404
    if (!mMain || size.width() < mWidth || size.height() < mHeight)
405
        return;
406
 
407
    mTotalWidth = size.width();
408
    mTotalHeight = size.height();
288 andreas 409
    mMain->setFixedSize(mTotalWidth, mTotalHeight);
285 andreas 410
}
411
 
288 andreas 412
/**
413
 * @brief TQScrollArea::setBackgroundImage
414
 * This sets the background image of the scroll area. If the pixmap is smaller
415
 * then the total size, the image is painted in tiles.
416
 *
417
 * @param pix       The pixmap.
418
 */
285 andreas 419
void TQScrollArea::setBackgroundImage(const QPixmap& pix)
420
{
421
    DECL_TRACER("TQScrollArea::setBackgroundImage(const QPixmap& pix)");
422
 
423
    if (!mMain || pix.isNull())
424
        return;
425
 
426
    QPalette palette(mMain->palette());
427
    palette.setBrush(QPalette::Window, QBrush(pix));
428
    mMain->setPalette(palette);
429
}
430
 
288 andreas 431
/**
432
 * @brief TQScrollArea::setBackGroundColor
433
 * Sets the background color of the scroll area.
434
 *
435
 * @param color     The color
436
 */
285 andreas 437
void TQScrollArea::setBackGroundColor(QColor color)
438
{
439
    DECL_TRACER("TQScrollArea::setBackGroundColor(QColor color)");
440
 
441
    if (!mMain)
442
        return;
443
 
444
    QPalette palette(mMain->palette());
445
    palette.setColor(QPalette::Window, color);
446
    mMain->setPalette(palette);
447
}
448
 
288 andreas 449
/**
450
 * @brief TQScrollArea::setSpace
451
 * Sets the space between the items in percent. The pixels are calculated
452
 * from the total size of the scroll area. Then the spce is inserted.
453
 *
454
 * @param s     A value between 0 and 99. 0 Removes the space.
455
 */
285 andreas 456
void TQScrollArea::setSpace(int s)
457
{
458
    DECL_TRACER("TQScrollArea::setSpace(double s)");
459
 
288 andreas 460
    if (s < 0 || s > 99)
285 andreas 461
        return;
462
 
463
    mSpace = s;
464
}
465
 
288 andreas 466
/**
467
 * @brief TQScrollArea::addItem
468
 * Adds one item to the list of items.
469
 *
470
 * @param item  Item to add
471
 */
285 andreas 472
void TQScrollArea::addItem(PGSUBVIEWITEM_T& item)
473
{
474
    DECL_TRACER("TQScrollArea::addItem(PGSUBVIEWITEM_T& item)");
475
 
288 andreas 476
    mItems.push_back(item);
477
    addItems(mItems);
478
}
285 andreas 479
 
288 andreas 480
void TQScrollArea::addItems(std::vector<PGSUBVIEWITEM_T>& items)
481
{
482
    DECL_TRACER("TQScrollArea::addItems(std::vector<PGSUBVIEWITEM_T>& items)");
285 andreas 483
 
288 andreas 484
    if (items.empty())
485
        return;
285 andreas 486
 
302 andreas 487
    mWrapItems = items[0].wrap;
488
 
288 andreas 489
    if (mMainWidgets.size() > 0)
285 andreas 490
    {
288 andreas 491
        vector<QWidget *>::iterator iter;
285 andreas 492
 
288 andreas 493
        for (iter = mMainWidgets.begin(); iter != mMainWidgets.end(); ++iter)
285 andreas 494
        {
288 andreas 495
            QWidget *w = *iter;
496
            w->close();
285 andreas 497
        }
498
 
288 andreas 499
        mMainWidgets.clear();
285 andreas 500
    }
501
 
288 andreas 502
    mItems = items;
285 andreas 503
 
288 andreas 504
    if (mVertical)
505
        mTotalHeight = 0;
285 andreas 506
    else
288 andreas 507
        mTotalWidth = 0;
285 andreas 508
 
509
    int total = 0;      // The total width or height
510
    vector<PGSUBVIEWITEM_T>::iterator iter;
511
    // First calculate the total width and height if it was not set by a previous call
512
    if ((mTotalWidth <= 0 && !mVertical) || (mTotalHeight <= 0 && mVertical))
513
    {
514
        if (mTotalWidth <= 0)
515
            mTotalWidth = mWidth;
516
 
517
        if (mTotalHeight <= 0)
518
            mTotalHeight = mHeight;
519
 
520
        if (!mVertical || mTotalWidth <= 0)
521
            mTotalWidth = 0;
522
 
523
        if (mVertical || mTotalHeight <= 0)
524
            mTotalHeight = 0;
525
 
289 andreas 526
        int num = 0;
527
 
285 andreas 528
        for (iter = items.begin(); iter != items.end(); ++iter)
529
        {
530
            if (!mVertical)
531
                mTotalWidth += iter->width;
532
            else
533
                mTotalHeight += iter->height;
289 andreas 534
 
535
            MSG_DEBUG("Item " << num << " (" << handleToString(iter->handle) << "): Size: " << iter->width << " x " << iter->height);
536
            num++;
285 andreas 537
        }
538
 
539
        if (mVertical)
288 andreas 540
        {
541
            mTotalHeight = scale(mTotalHeight);
285 andreas 542
            total = mTotalHeight;
288 andreas 543
        }
285 andreas 544
        else
288 andreas 545
        {
546
            mTotalWidth = scale(mTotalWidth);
285 andreas 547
            total = mTotalWidth;
288 andreas 548
        }
285 andreas 549
 
288 andreas 550
        if (mMain)
551
            mMain->setFixedSize(mTotalWidth, mTotalHeight);
552
 
287 andreas 553
        MSG_DEBUG("Total size: " << mTotalWidth << " x " << mTotalHeight << " (Vertical is " << (mVertical ? "TRUE" : "FALSE") << ")");
285 andreas 554
    }
555
 
289 andreas 556
    MSG_DEBUG("Number of items: " << items.size());
557
 
285 andreas 558
    if (mSpace > 0)
559
    {
560
        int space = (int)((double)total / 100.0 * (double)mSpace);
561
 
288 andreas 562
        if (space > 0 && mVertical && mVLayout && mMain)
563
        {
289 andreas 564
            int newHeight = space + mTotalHeight;
565
            mMain->setFixedHeight(newHeight);
566
            MSG_DEBUG("Calculated space: " << space << " (" << mSpace << "%). Total height: " << newHeight << ", Old total height: " << mTotalHeight);
567
            mTotalHeight = newHeight;
288 andreas 568
        }
569
        else if (space > 0 && !mVertical && mHLayout && mMain)
570
        {
289 andreas 571
            int newWidth = space + mTotalWidth;
572
            mMain->setFixedWidth(newWidth);
573
            MSG_DEBUG("Calculated space: " << space << " (" << mSpace << "%). Total width: " << newWidth << ", Old total width: " << mTotalWidth);
574
            mTotalWidth = newWidth;
288 andreas 575
        }
285 andreas 576
    }
577
 
578
    for (iter = items.begin(); iter != items.end(); ++iter)
579
    {
287 andreas 580
        int iWidth = scale(iter->width);
581
        int iHeight = scale(iter->height);
289 andreas 582
        QWidget *item = new QWidget;
285 andreas 583
        item->setObjectName(QString("Item_%1").arg(handleToString(iter->handle).c_str()));
287 andreas 584
        item->setFixedSize(iWidth, iHeight);
285 andreas 585
        item->setAutoFillBackground(true);
289 andreas 586
        QColor bgcolor(qRgba(iter->bgcolor.red, iter->bgcolor.green, iter->bgcolor.blue, iter->bgcolor.alpha));
285 andreas 587
 
588
        if (iter->image.getSize() > 0)
589
        {
287 andreas 590
            QPixmap pixmap(iWidth, iHeight);
289 andreas 591
 
592
            if (iter->bgcolor.alpha == 0)
593
                pixmap.fill(Qt::transparent);
594
            else
595
                pixmap.fill(bgcolor);
596
 
287 andreas 597
            QImage img(iter->image.getBitmap(), iter->image.getWidth(), iter->image.getHeight(), iter->image.getPixline(), QImage::Format_ARGB32);  // Original size
285 andreas 598
            bool ret = false;
599
 
287 andreas 600
            if (mScaleFactor != 1.0)
601
            {
289 andreas 602
                QSize size(iWidth, iHeight);
603
                ret = pixmap.convertFromImage(img.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));   // Scaled size
287 andreas 604
            }
605
            else
606
                ret = pixmap.convertFromImage(img);
285 andreas 607
 
608
            if (!ret || pixmap.isNull())
609
            {
610
                MSG_ERROR("Unable to create a pixmap out of an image!");
611
                return;
612
            }
613
 
614
            QPalette palette(item->palette());
615
            palette.setBrush(QPalette::Window, QBrush(pixmap));
616
            item->setPalette(palette);
617
        }
618
        else
289 andreas 619
        {
620
            QPalette palette(item->palette());
621
 
622
            if (iter->bgcolor.alpha == 0)
623
                palette.setColor(QPalette::Window, Qt::transparent);
624
            else
625
                palette.setColor(QPalette::Window, bgcolor);
626
 
627
            item->setPalette(palette);
628
        }
629
 
285 andreas 630
        // Add the buttons to the item widget
631
        if (iter->atoms.empty())
632
        {
633
            delete item;
634
            continue;
635
        }
636
 
637
        vector<PGSUBVIEWATOM_T>::iterator itAtom;
638
 
639
        for (itAtom = iter->atoms.begin(); itAtom != iter->atoms.end(); ++itAtom)
640
        {
287 andreas 641
            int scaWidth = scale(itAtom->width);
642
            int scaHeight = scale(itAtom->height);
285 andreas 643
 
644
            QLabel *label = new QLabel(item);
287 andreas 645
            label->move(scale(itAtom->left), scale(itAtom->top));
285 andreas 646
            label->setFixedSize(scaWidth, scaHeight);
647
            label->setObjectName(QString("Label_%1").arg(handleToString(itAtom->handle).c_str()));
300 andreas 648
            setAtom(*itAtom, label);
649
        }
285 andreas 650
 
300 andreas 651
        mMainWidgets.push_back(item);
289 andreas 652
 
300 andreas 653
        if (mVertical && mVLayout)
654
            mVLayout->addWidget(item);
655
        else if (!mVertical && mHLayout)
656
            mHLayout->addWidget(item);
657
        else
658
        {
659
            MSG_ERROR("Layout not initialized!");
660
        }
661
    }
662
}
289 andreas 663
 
300 andreas 664
void TQScrollArea::updateItem(PGSUBVIEWITEM_T& item)
665
{
666
    DECL_TRACER("TQScrollArea::updateItem(PGSUBVIEWITEM_T& item)");
285 andreas 667
 
300 andreas 668
    if (mItems.empty())
669
        return;
285 andreas 670
 
300 andreas 671
    vector<PGSUBVIEWITEM_T>::iterator iter;
289 andreas 672
 
300 andreas 673
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
674
    {
675
        if (iter->handle == item.handle)
676
        {
677
            iter->bgcolor = item.bgcolor;
678
            iter->bounding = item.bounding;
679
            iter->image = item.image;
680
 
681
            if (!item.atoms.empty())
682
                iter->atoms = item.atoms;
683
            // Find the item and change it in the scroll area
684
            vector<QWidget *>::iterator wit;
685
 
686
            for (wit = mMainWidgets.begin(); wit != mMainWidgets.end(); ++wit)
289 andreas 687
            {
300 andreas 688
                QWidget *w = *wit;
689
                ulong handle = extractHandle(w->objectName().toStdString());
285 andreas 690
 
300 andreas 691
                // If we have new "atoms" we search for it and update it
692
                if (iter->handle == handle && !iter->atoms.empty())
693
                {
694
                    QObjectList list = w->children();
695
                    QList<QObject *>::Iterator obit;
696
                    vector<PGSUBVIEWATOM_T>::iterator atit;
289 andreas 697
 
300 andreas 698
                    for (atit = iter->atoms.begin(); atit != iter->atoms.end(); ++atit)
699
                    {
700
                        for (obit = list.begin(); obit != list.end(); ++obit)
701
                        {
702
                            QObject *o = *obit;
703
                            QString obname = o->objectName();
704
                            ulong atHandle = extractHandle(obname.toStdString());
705
 
706
                            if (atit->handle == atHandle && obname.startsWith("Label_"))
707
                            {
708
                                QLabel *lbl = dynamic_cast<QLabel *>(o);
709
                                setAtom(*atit, lbl);
710
                                break;
711
                            }
712
                        }
713
                    }
714
 
715
                    break;
716
                }
289 andreas 717
            }
300 andreas 718
 
719
            break;
285 andreas 720
        }
300 andreas 721
    }
722
}
285 andreas 723
 
300 andreas 724
void TQScrollArea::showItem(ulong handle, int position)
725
{
726
    DECL_TRACER("TQScrollArea::showItem(ulong handle, int position)");
288 andreas 727
 
301 andreas 728
    if (mMainWidgets.empty())
729
        return;
730
 
300 andreas 731
    vector<QWidget *>::iterator iter;
732
 
733
    for (iter = mMainWidgets.begin(); iter != mMainWidgets.end(); ++iter)
734
    {
735
        QWidget *w = *iter;
736
        ulong h = extractHandle(w->objectName().toStdString());
737
        MSG_DEBUG("Evaluating item " << handleToString(h));
738
 
739
        if (h == handle)
285 andreas 740
        {
300 andreas 741
            int defPosX = 50;
742
            int defPosY = 50;
743
 
744
            if (position > 0 && position < 65535)
745
            {
746
                if (mVertical)
747
                {
748
                    defPosY = position;
749
                    defPosX = 0;
750
                }
751
                else
752
                {
753
                    defPosY = position;
754
                    defPosX = 0;
755
                }
301 andreas 756
 
757
                ensureWidgetVisible(w, defPosX, defPosY);
300 andreas 758
            }
301 andreas 759
            else if (mPosition == Button::SVP_LEFT_TOP)
760
            {
761
                if (mVertical)
762
                {
763
                    int top = w->geometry().y();
302 andreas 764
                    QScrollBar *bar = verticalScrollBar();
765
 
766
                    if (bar)
767
                        bar->setSliderPosition(top);
301 andreas 768
                }
769
                else
770
                {
771
                    int left = w->geometry().x();
302 andreas 772
                    QScrollBar *bar = horizontalScrollBar();
773
 
774
                    if (bar)
775
                        bar->setSliderPosition(left);
301 andreas 776
                }
777
            }
778
            else if (mPosition == Button::SVP_CENTER)
779
            {
780
                if (mVertical)
781
                {
302 andreas 782
                    int topMargin = (mHeight - w->geometry().height()) / 2;
783
                    int top = w->geometry().y() - topMargin;
784
                    QScrollBar *bar = verticalScrollBar();
785
 
786
                    if (bar)
787
                        bar->setSliderPosition(top);
301 andreas 788
                }
789
                else
790
                {
302 andreas 791
                    int leftMargin = (mWidth - w->geometry().width()) / 2;
792
                    int left = w->geometry().x() - leftMargin;
793
                    QScrollBar *bar = horizontalScrollBar();
794
 
795
                    if (bar)
796
                        bar->setSliderPosition(left);
301 andreas 797
                }
798
            }
799
            else if (mPosition == Button::SVP_RIGHT_BOTTOM)
800
            {
801
                if (mVertical)
802
                {
803
                    int bottom = w->geometry().y() + w->geometry().height();
302 andreas 804
                    QScrollBar *bar = verticalScrollBar();
805
 
806
                    if (bar)
807
                        bar->setSliderPosition(bottom);
301 andreas 808
                }
809
                else
810
                {
811
                    int right = w->geometry().x() + w->geometry().width();
302 andreas 812
                    QScrollBar *bar = horizontalScrollBar();
813
 
814
                    if (bar)
815
                        bar->setSliderPosition(right);
301 andreas 816
                }
817
            }
300 andreas 818
 
819
            break;
285 andreas 820
        }
821
    }
822
}
823
 
287 andreas 824
int TQScrollArea::scale(int value)
825
{
826
    DECL_TRACER("TQScrollArea::scale(int value)");
827
 
828
    if (mScaleFactor != 1.0)
829
        return (int)((double)value * mScaleFactor);
830
 
831
    return value;
832
}
833
 
834
void TQScrollArea::setScaleFactor(const double& factor)
835
{
836
    DECL_TRACER("TQScrollArea::setScaleFactor(const double& factor)");
837
 
838
    if (factor > 0.0 && factor != 1.0)
839
        mScaleFactor = factor;
840
}
841
 
300 andreas 842
void TQScrollArea::setAtom(PGSUBVIEWATOM_T& atom, QLabel *label)
843
{
844
    DECL_TRACER("TQScrollArea::setAtom(PGSUBVIEWATOM_T& atom, QLabel *label)");
845
 
846
    if (!label)
847
        return;
848
 
849
    int scaWidth = scale(atom.width);
850
    int scaHeight = scale(atom.height);
851
    QColor bg(qRgba(atom.bgcolor.red, atom.bgcolor.green, atom.bgcolor.blue, atom.bgcolor.alpha));
852
 
853
    if (atom.image.isValid())
854
    {
855
        QPixmap pix(scaWidth, scaHeight);
856
 
857
        if (atom.bgcolor.alpha == 0)
858
            pix.fill(Qt::transparent);
859
        else
860
            pix.fill(bg);
861
 
862
        QImage img(atom.image.getBitmap(), atom.image.getWidth(), atom.image.getHeight(), atom.image.getPixline(), QImage::Format_ARGB32);
863
        bool ret = false;
864
 
865
        if (mScaleFactor != 1.0)
866
        {
867
            QSize size(scaWidth, scaHeight);
868
            ret = pix.convertFromImage(img.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Scaled size
869
        }
870
        else
871
            ret = pix.convertFromImage(img);
872
 
873
        if (!ret || pix.isNull())
874
        {
875
            MSG_ERROR("Unable to create a pixmap out of an image!");
876
            return;
877
        }
878
 
879
        label->setPixmap(pix);
880
    }
881
    else
882
    {
883
        QPalette palette(label->palette());
884
 
885
        if (atom.bgcolor.alpha == 0)
886
            palette.setColor(QPalette::Window, Qt::transparent);
887
        else
888
            palette.setColor(QPalette::Window, bg);
889
 
890
        label->setPalette(palette);
891
    }
892
 
893
}
894
 
285 andreas 895
/*****************************************************************************
896
 * Signals and overwritten functions start here
897
 *****************************************************************************/
300 andreas 898
/*
285 andreas 899
bool TQScrollArea::event(QEvent* event)
900
{
901
    if (event->type() == QEvent::MouseMove && mMousePress)
902
    {
289 andreas 903
        if (mMousePressTimer && mMousePressTimer->isActive())
904
        {
905
            mMousePressTimer->stop();
906
            mClick = false;
907
        }
908
 
285 andreas 909
        QMouseEvent *me = static_cast<QMouseEvent*>(event);
910
        int move = 0;
289 andreas 911
        mMouseScroll = true;
285 andreas 912
 
913
        if (mVertical)
914
        {
915
            if (mOldPoint.y() != 0)
916
            {
286 andreas 917
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
918
                move = me->pos().y() - mOldPoint.y();
919
#else
285 andreas 920
                move = me->position().y() - mOldPoint.y();
286 andreas 921
#endif
285 andreas 922
                QScrollBar *bar = verticalScrollBar();
923
 
924
                if (bar)
925
                {
926
                    int value = bar->value();
927
                    value += (move * -1);
928
                    bar->setValue(value);
929
                }
930
            }
931
        }
932
        else
933
        {
934
            if (mOldPoint.x() != 0)
935
            {
286 andreas 936
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
937
                move = me->pos().x() - mOldPoint.x();
938
#else
285 andreas 939
                move = me->position().x() - mOldPoint.x();
286 andreas 940
#endif
285 andreas 941
                scrollContentsBy(move, 0);
942
                QScrollBar *bar = horizontalScrollBar();
943
 
944
                if (bar)
945
                {
946
                    int value = bar->value();
947
                    value += (move * -1);
948
                    bar->setValue(value);
949
                }
950
            }
951
        }
286 andreas 952
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
953
        mOldPoint = me->pos();
954
#else
285 andreas 955
        mOldPoint = me->position();
286 andreas 956
#endif
285 andreas 957
    }
958
 
959
    return QScrollArea::event(event);
960
}
300 andreas 961
*/
962
void TQScrollArea::mouseMoveEvent(QMouseEvent* event)
963
{
964
    DECL_TRACER("TQScrollArea::mouseMoveEvent(QMouseEvent* event)");
285 andreas 965
 
300 andreas 966
    mMousePress = false;
967
    mMouseScroll = true;
301 andreas 968
 
969
    if (mMousePressTimer && mMousePressTimer->isActive())
970
        mMousePressTimer->stop();
971
 
300 andreas 972
    int move = 0;
973
 
974
    MSG_DEBUG("Scroll event at " << event->position().x() << "x" << event->position().y() << ", old point at " << mOldPoint.x() << "x" << mOldPoint.y());
975
    if (mVertical)
976
    {
977
        if (mOldPoint.y() != 0)
978
        {
979
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
980
            move = me->pos().y() - mOldPoint.y();
981
#else
982
            move = event->position().y() - mOldPoint.y();
983
#endif
984
            QScrollBar *bar = verticalScrollBar();
985
 
986
            if (bar)
987
            {
988
                int value = bar->value();
989
                value += (move * -1);
990
                bar->setValue(value);
991
            }
992
        }
993
    }
994
    else
995
    {
996
        if (mOldPoint.x() != 0)
997
        {
998
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
999
            move = me->pos().x() - mOldPoint.x();
1000
#else
1001
            move = event->position().x() - mOldPoint.x();
1002
#endif
1003
            QScrollBar *bar = horizontalScrollBar();
1004
 
1005
            if (bar)
1006
            {
1007
                int value = bar->value();
301 andreas 1008
                int newValue = value + (move * -1);
1009
 
1010
                if (newValue >= 0 && newValue != value)
1011
                    bar->setValue(newValue);
1012
 
1013
                MSG_DEBUG("Moving mouse to value " << newValue << " (old: " << value << "). Step is " << move);
300 andreas 1014
            }
1015
        }
1016
    }
301 andreas 1017
 
300 andreas 1018
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1019
    mOldPoint = me->pos();
1020
#else
1021
    mOldPoint = event->position();
1022
#endif
1023
}
1024
 
285 andreas 1025
void TQScrollArea::mousePressEvent(QMouseEvent* event)
1026
{
294 andreas 1027
    DECL_TRACER("TQScrollArea::mousePressEvent(QMouseEvent* event)");
1028
 
301 andreas 1029
    if (!event || mMouseScroll)
289 andreas 1030
        return;
1031
 
300 andreas 1032
    if (event->button() == Qt::LeftButton)
285 andreas 1033
    {
1034
        mMousePress = true;
301 andreas 1035
        mOldPoint.setX(0.0);
1036
        mOldPoint.setY(0.0);
289 andreas 1037
 
1038
        int x = 0, y = 0;
1039
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
301 andreas 1040
        x = event->pos().x();
1041
        y = event->pos().y();
289 andreas 1042
#else
301 andreas 1043
        x = event->position().x();
1044
        y = event->position().y();
289 andreas 1045
#endif
1046
        mLastMousePress.setX(x);
1047
        mLastMousePress.setY(y);
1048
 
1049
        MSG_DEBUG("Mouse press event at " << x << " x " << y << " // " << event->globalX() << " x " << event->globalY());
1050
        /*
1051
         * Here we're starting a timer with 200 ms. If after this time the
1052
         * mouse button is still pressed and no scroll event was detected,
1053
         * then we've a real click.
1054
         * In case of a real click the method mouseTimerEvent() will call a
1055
         * signal to inform the parent about the click.
1056
         */
1057
        mClick = true;
301 andreas 1058
 
289 andreas 1059
        if (!mMousePressTimer)
1060
        {
1061
            mMousePressTimer = new QTimer(this);
1062
            connect(mMousePressTimer, &QTimer::timeout, this, &TQScrollArea::mouseTimerEvent);
1063
        }
301 andreas 1064
 
1065
        mMousePressTimer->start(200);
285 andreas 1066
    }
1067
}
1068
 
1069
void TQScrollArea::mouseReleaseEvent(QMouseEvent* event)
1070
{
294 andreas 1071
    DECL_TRACER("TQScrollArea::mouseReleaseEvent(QMouseEvent* event)");
1072
 
301 andreas 1073
    if (!event)
289 andreas 1074
        return;
1075
 
285 andreas 1076
    if(event->button() == Qt::LeftButton)
289 andreas 1077
    {
1078
        if (mMousePressTimer && mMousePressTimer->isActive())
1079
        {
1080
            mMousePressTimer->stop();
301 andreas 1081
 
1082
            if (!mMouseScroll)
1083
            {
1084
                mClick = true;
1085
                mouseTimerEvent();
1086
                mClick = false;
1087
                mouseTimerEvent();
1088
            }
289 andreas 1089
        }
301 andreas 1090
        else if (!mMouseScroll && mClick)
289 andreas 1091
        {
1092
            mClick = false;
1093
            mouseTimerEvent();
1094
        }
301 andreas 1095
 
285 andreas 1096
        mMousePress = false;
301 andreas 1097
        mMouseScroll = false;
1098
        mOldPoint.setX(0.0);
1099
        mOldPoint.setY(0.0);
289 andreas 1100
    }
285 andreas 1101
}
289 andreas 1102
 
1103
void TQScrollArea::scrollContentsBy(int dx, int dy)
1104
{
294 andreas 1105
    DECL_TRACER("TQScrollArea::scrollContentsBy(int dx, int dy)");
1106
 
289 andreas 1107
    QScrollArea::scrollContentsBy(dx, dy);      // First let the original class do it's job.
1108
 
1109
    QScrollBar *sbar = nullptr;
1110
 
1111
    if (mVertical)
1112
        sbar = verticalScrollBar();
1113
    else
1114
        sbar = horizontalScrollBar();
1115
 
1116
    if (sbar)
300 andreas 1117
    {
289 andreas 1118
        mActPosition = sbar->value();
300 andreas 1119
 
1120
        if (mScrollbar && mScrollbarOffset > 0 && mActPosition < mScrollbarOffset)
1121
        {
1122
            sbar->setSliderPosition(mScrollbarOffset);
1123
            mActPosition = sbar->value();
1124
        }
1125
    }
289 andreas 1126
}
1127
 
1128
void TQScrollArea::mouseTimerEvent()
1129
{
294 andreas 1130
    DECL_TRACER("TQScrollArea::mouseTimerEvent()");
1131
 
301 andreas 1132
    if (mMousePressTimer && mMousePressTimer->isActive())
1133
        mMousePressTimer->stop();
289 andreas 1134
 
1135
    if (!mMousePress || mMouseScroll)
1136
        return;
1137
 
1138
    if (mMain)
1139
    {
1140
        QWidget *w = nullptr;
1141
 
1142
        if (mVertical)
1143
            w = mMain->childAt(mLastMousePress.x(), mActPosition + mLastMousePress.y());
1144
        else
1145
            w = mMain->childAt(mActPosition + mLastMousePress.x(), mLastMousePress.y());
1146
 
1147
        if (w)
1148
        {
1149
            QString obname = w->objectName();
298 andreas 1150
            ulong handle = extractHandle(obname.toStdString());
289 andreas 1151
 
293 andreas 1152
            if (!handle)
289 andreas 1153
                return;
1154
 
293 andreas 1155
            // We must make sure the found object is not marked as pass through.
1156
            // Because of this we'll scan the items for the handle and if we
1157
            // find that it is marked as pass through we must look for another
1158
            // one on the same position. If there is none, the click is ignored.
1159
            //
1160
            // Find the object in our list
1161
            vector<PGSUBVIEWITEM_T>::iterator iter;
1162
            QRect rect;
1163
            bool call = true;
289 andreas 1164
 
293 andreas 1165
            for (iter = mItems.begin(); iter != mItems.end(); ++iter)
1166
            {
1167
                if (iter->handle == handle)     // Handle found?
1168
                {                               // Yes, then ...
1169
                    if (iter->bounding == "passThru")   // Item marked as pass through?
1170
                    {                                   // Yes, then start to search for another item
1171
                        rect = w->rect();
1172
                        call = false;
1173
                        // Walk through the childs to find another one on the
1174
                        // clicked position.
1175
                        QObjectList ol = mMain->children(); // Get list of all objects
1176
                        QList<QObject *>::iterator obiter;  // Define an iterator
1177
                        // Loop through all objects
1178
                        for (obiter = ol.begin(); obiter != ol.end(); ++obiter)
1179
                        {
1180
                            QObject *object = *obiter;
289 andreas 1181
 
293 andreas 1182
                            if (object->objectName() != obname && object->objectName().startsWith("Label_"))    // Have we found a QLabel object?
1183
                            {                                                                                   // Yes, then test it's position
1184
                                QLabel *lb = dynamic_cast<QLabel *>(object);    // Cast the object to a QLabel
1185
 
1186
                                if (lb->rect().contains(mLastMousePress))       // Is the QLabel under the mouse coordinates?
1187
                                {                                               // Yes, then select it.
298 andreas 1188
                                    ulong h = extractHandle(lb->objectName().toStdString());  // Get the handle
293 andreas 1189
 
1190
                                    if (!h)
1191
                                        break;
1192
 
1193
                                    handle = h;
1194
                                    // Reset the main loop
1195
                                    iter = mItems.begin();
1196
                                    break;
1197
                                }
1198
                            }
1199
                        }
1200
                    }
1201
                    else
1202
                        call = true;
1203
                }
1204
            }
1205
 
1206
            if (call)
1207
            {
1208
                MSG_DEBUG("Calling signal with handle " << (handle >> 16 & 0x0000ffff) << ":" << (handle & 0x0000ffff) << ": STATE=" << (mClick ? "PRESSED" : "RELEASED"));
1209
                emit objectClicked(handle, mClick);
1210
            }
289 andreas 1211
        }
1212
    }
1213
}
293 andreas 1214