Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
446 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>
30
#include <QTimer>
31
 
32
#include "tqscrollarea.h"
33
#include "terror.h"
34
#include "tresources.h"
35
 
36
using std::vector;
37
 
38
/**
39
 * @brief TQScrollArea::TQScrollArea
40
 * Constructor for the class.
41
 */
42
TQScrollArea::TQScrollArea()
43
{
44
    DECL_TRACER("TQScrollArea::TQScrollArea()");
45
}
46
 
47
/**
48
 * @brief TQScrollArea::TQScrollArea
49
 * @param parent    The parent widget
50
 */
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
 
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
 */
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
 
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
 */
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()");
111
 
112
    if (mMain)
113
        mMain->close();
114
 
115
    if (mMousePressTimer)
116
    {
117
        if (mMousePressTimer->isActive())
118
            mMousePressTimer->stop();
119
 
120
        disconnect(mMousePressTimer, &QTimer::timeout, this, &TQScrollArea::mouseTimerEvent);
121
        delete mMousePressTimer;
122
        mMousePressTimer = nullptr;
123
    }
124
}
125
 
126
void TQScrollArea::init()
127
{
128
    DECL_TRACER("TQScrollArea::init()");
129
 
130
    QScrollArea::setParent(mParent);
131
    QScrollArea::setViewportMargins(0, 0, 0, 0);
132
 
133
    if (mWidth > 0 || mHeight > 0)
134
        QScrollArea::setFixedSize(mWidth, mHeight);
135
 
136
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
137
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
138
    // Set a transparent background
139
    QPalette palette(this->palette());
140
    palette.setColor(QPalette::Window, Qt::transparent);
141
    setPalette(palette);
142
 
143
    if (!mMain)
144
        mMain = new QWidget(this);
145
 
146
    mMain->move(0, 0);
147
    mMain->setContentsMargins(0, 0, 0, 0);
148
 
149
    if (mWidth && mHeight)
150
        setFixedSize(mWidth, mHeight);
151
 
152
    setWidget(mMain);
153
 
154
    if (mVertical && !mVLayout)
155
    {
156
        mVLayout = new QVBoxLayout(mMain);
157
        mVLayout->setSpacing(0);
158
        mVLayout->setContentsMargins(0, 0, 0, 0);
159
    }
160
    else if (!mVertical && !mHLayout)
161
    {
162
        mHLayout = new QHBoxLayout(mMain);
163
        mHLayout->setSpacing(0);
164
        mHLayout->setContentsMargins(0, 0, 0, 0);
165
    }
166
 
167
 
168
    if (!mTotalWidth)
169
        mTotalWidth = mWidth;
170
 
171
    if (!mTotalHeight)
172
        mTotalHeight = mHeight;
173
}
174
 
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
 */
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
 
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
 */
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;
205
    setFixedSize(mWidth, mHeight);
206
}
207
 
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
 */
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
 
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
 */
229
QSize TQScrollArea::getSize()
230
{
231
    DECL_TRACER("TQScrollArea::getSize()");
232
 
233
    return QSize(mWidth, mHeight);
234
}
235
 
236
/**
237
 * @brief TQScrollArea::setScrollbar
238
 * Makes the scrollbar visible or invisible.
239
 *
240
 * @param sb    TRUE: The scrollbar is set to visible. It depends on the type
241
 *              of scroll area. On vertical areas the bottom scrollbar may
242
 *              become visible and on horizontal areas the right one.
243
 */
244
void TQScrollArea::setScrollbar(bool sb)
245
{
246
    DECL_TRACER("TQScrollArea::setScrollbar(bool sb)");
247
 
248
    if (sb == mScrollbar)
249
        return;
250
 
251
    mScrollbar = sb;
252
 
253
    if (sb)
254
    {
255
        if (mVertical)
256
            setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
257
        else
258
            setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
259
    }
260
    else
261
    {
262
        if (mVertical)
263
            setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
264
        else
265
            setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
266
    }
267
}
268
 
269
/**
270
 * @brief TQScrollArea::setScrollbarOffset
271
 * Positions the scrollbar to the \b offset position. On a vertical scroll
272
 * area the offset is alway the top visible pixel line and on horizontal
273
 * scroll areas it is the left visible pixel.
274
 *
275
 * @param offset    The offset position. If this is less then 0 or grater then
276
 *                  the whole size, the value is ignored.
277
 */
278
void TQScrollArea::setScrollbarOffset(int offset)
279
{
280
    DECL_TRACER("TQScrollArea::setScrollbarOffset(int offset)");
281
 
282
    if (!mScrollbar)
283
        return;
284
 
285
    if (offset <= 0)
286
        mScrollbarOffset = 0;
287
    else
288
        mScrollbarOffset = scale(offset);
289
 
290
    QScrollBar *sbar = nullptr;
291
 
292
    if (mVertical)
293
        sbar = verticalScrollBar();
294
    else
295
        sbar = horizontalScrollBar();
296
 
297
    if (sbar)
298
    {
299
        if (mScrollbarOffset > (mVertical ? sbar->pos().y() : sbar->pos().x()))
300
            mScrollbarOffset = (mVertical ? sbar->pos().y() : sbar->pos().x());
301
 
302
        sbar->setSliderPosition(mScrollbarOffset);
303
    }
304
}
305
 
306
/**
307
 * @brief TQScrollArea::setAnchor
308
 * Sets the anchor position. This can be left, center or right for horizontal
309
 * scroll areas or top, center or bottom for vertical.
310
 * The anchor position is the one the items scroll to if they should appear at
311
 * this position. The center position is the default one.
312
 *
313
 * @param position  Defines the anchor position.
314
 */
315
void TQScrollArea::setAnchor(Button::SUBVIEW_POSITION_t position)
316
{
317
    DECL_TRACER("TQScrollArea::setAnchor(Button::SUBVIEW_POSITION_t position)");
318
 
319
    mPosition = position;
320
 
321
    if (!mWrapItems)
322
    {
323
        QWidget *w = mMain->childAt(mWidth / 2, mHeight / 2);
324
 
325
        if (w)
326
            setPosition(w, 0);
327
    }
328
    else
329
        setPosition();
330
}
331
 
332
/**
333
 * @brief TQScrollArea::show
334
 * Shows all items in the scroll area. If some were invisible or not enabled,
335
 * they are visible and enabled. Depending on the set anchor position the
336
 * whole area is set to it. This means for example, that the center item is
337
 * moved into the view area if the anchor position is set to SVP_CENTER.
338
 */
339
void TQScrollArea::show()
340
{
341
    DECL_TRACER("TQScrollArea::show()");
342
 
343
    if (!QScrollArea::isEnabled())
344
        QScrollArea::setEnabled(true);
345
 
346
    QScrollArea::show();
347
 
348
    if (mMain)
349
    {
350
        if (!mMain->isEnabled())
351
            mMain->setEnabled(true);
352
 
353
        if (!mMain->isVisible())
354
            mMain->show();
355
    }
356
 
357
    if (mWrapItems)
358
        setPosition();
359
}
360
 
361
/**
362
 * @brief TQScrollArea::setTotalWidth
363
 * Sets the total width of the scrolling area. This must be equal or grater
364
 * then the width of the visible area.
365
 *
366
 * @param w The width in pixels.
367
 */
368
void TQScrollArea::setTotalWidth(int w)
369
{
370
    DECL_TRACER("TQScrollArea::setTotalWidth(int w)");
371
 
372
    if (!mMain || w < mWidth)
373
        return;
374
 
375
    mTotalWidth = w;
376
    mMain->setFixedWidth(mTotalWidth);
377
}
378
 
379
/**
380
 * @brief TQScrollArea::setTotalHeight
381
 * Sets the total height of the scrolling area. This must be equal or grater
382
 * then the height of the visible area.
383
 *
384
 * @param h  The height in pixels.
385
 */
386
void TQScrollArea::setTotalHeight(int h)
387
{
388
    DECL_TRACER("TQScrollArea::setTotalHeight(int h)");
389
 
390
    if (!mMain || h < mHeight)
391
        return;
392
 
393
    mTotalHeight = h;
394
    mMain->setFixedHeight(mTotalHeight);
395
}
396
 
397
/**
398
 * @brief TQScrollArea::setTotalSize
399
 * Sets the total size of the scrolling area. The width and height must be
400
 * equal or grater then the width and height of the visible area.
401
 *
402
 * @param w  The width in pixels.
403
 * @param h  The height in pixels.
404
 */
405
void TQScrollArea::setTotalSize(int w, int h)
406
{
407
    DECL_TRACER("TQScrollArea::setTotalSize(int w, int h)");
408
 
409
    if (!mMain || w < mWidth || h < mHeight)
410
        return;
411
 
412
    mTotalWidth = w;
413
    mTotalHeight = h;
414
    mMain->setFixedSize(mTotalWidth, mTotalHeight);
415
}
416
 
417
/**
418
 * @brief TQScrollArea::setTotalSize
419
 * Sets the total size of the scrolling area in pixels.
420
 *
421
 * @param size  The total size of the scrolling area.
422
 */
423
void TQScrollArea::setTotalSize(QSize& size)
424
{
425
    DECL_TRACER("TQScrollArea::setTotalSize(QSize& size)");
426
 
427
    if (!mMain || size.width() < mWidth || size.height() < mHeight)
428
        return;
429
 
430
    mTotalWidth = size.width();
431
    mTotalHeight = size.height();
432
    mMain->setFixedSize(mTotalWidth, mTotalHeight);
433
}
434
 
435
/**
436
 * @brief TQScrollArea::setBackgroundImage
437
 * This sets the background image of the scroll area. If the pixmap is smaller
438
 * then the total size, the image is painted in tiles.
439
 *
440
 * @param pix       The pixmap.
441
 */
442
void TQScrollArea::setBackgroundImage(const QPixmap& pix)
443
{
444
    DECL_TRACER("TQScrollArea::setBackgroundImage(const QPixmap& pix)");
445
 
446
    if (!mMain || pix.isNull())
447
        return;
448
 
449
    QPalette palette(mMain->palette());
450
    palette.setBrush(QPalette::Window, QBrush(pix));
451
    mMain->setPalette(palette);
452
}
453
 
454
/**
455
 * @brief TQScrollArea::setBackGroundColor
456
 * Sets the background color of the scroll area.
457
 *
458
 * @param color     The color
459
 */
460
void TQScrollArea::setBackGroundColor(QColor color)
461
{
462
    DECL_TRACER("TQScrollArea::setBackGroundColor(QColor color)");
463
 
464
    if (!mMain)
465
        return;
466
 
467
    QPalette palette(mMain->palette());
468
    palette.setColor(QPalette::Window, color);
469
    mMain->setPalette(palette);
470
}
471
 
472
/**
473
 * @brief TQScrollArea::setSpace
474
 * Sets the space between the items in percent. The pixels are calculated
475
 * from the total size of the scroll area. Then the spce is inserted.
476
 *
477
 * @param s     A value between 0 and 99. 0 Removes the space.
478
 */
479
void TQScrollArea::setSpace(int s)
480
{
481
    DECL_TRACER("TQScrollArea::setSpace(double s)");
482
 
483
    if (s < 0 || s > 99 || mSpace == s)
484
        return;
485
 
486
    mSpace = s;
487
    refresh();
488
}
489
 
490
/**
491
 * @brief TQScrollArea::addItem
492
 * Adds one item to the list of items.
493
 *
494
 * @param item  Item to add
495
 */
496
void TQScrollArea::addItem(PGSUBVIEWITEM_T& item)
497
{
498
    DECL_TRACER("TQScrollArea::addItem(PGSUBVIEWITEM_T& item)");
499
 
500
    _clearAllItems();
501
    resetSlider();
502
    mItems.push_back(subViewItemToItem(item));
503
    _addItems(mItems, true);
504
}
505
 
506
/**
507
 * @brief TQScrollArea::addItems
508
 * Adds one or more items to the scroll area and sizes the scroll area large
509
 * enough to hold all items. It calculates also the space between the items.
510
 * If there were already some items visible, they are deleted first. Then they
511
 * are displayed again.
512
 *
513
 * @param items     A list of items to be displayed
514
 */
515
void TQScrollArea::addItems(std::vector<PGSUBVIEWITEM_T>& items)
516
{
517
    DECL_TRACER("TQScrollArea::addItems(std::vector<PGSUBVIEWITEM_T>& items)");
518
 
519
    if (items.empty())
520
        return;
521
 
522
    _clearAllItems();
523
    resetSlider();
524
    mItems.clear();
525
 
526
    vector<PGSUBVIEWITEM_T>::iterator iter;
527
 
528
    for (iter = items.begin(); iter != items.end(); ++iter)
529
        mItems.push_back(subViewItemToItem(*iter));
530
 
531
    _addItems(mItems, true);
532
}
533
 
534
void TQScrollArea::_addItems(std::vector<_ITEMS_T>& items, bool intern)
535
{
536
//    DECL_TRACER("_addItems(std::vector<ITEMS_T>& items, bool intern)");
537
 
538
    mWrapItems = items[0].wrap;     // Endless scroll
539
 
540
    if (!intern)
541
        mItems = items;             // Store the items to the internal vector array
542
 
543
    if (mVertical)
544
        mTotalHeight = 0;
545
    else
546
        mTotalWidth = 0;
547
 
548
    int total = 0;                  // The total width or height
549
    vector<_ITEMS_T>::iterator iter;
550
    // First calculate the total width and height if it was not set by a previous call
551
    if ((mTotalWidth <= 0 && !mVertical) || (mTotalHeight <= 0 && mVertical))
552
    {
553
        if (mTotalWidth <= 0)
554
            mTotalWidth = mWidth;
555
 
556
        if (mTotalHeight <= 0)
557
            mTotalHeight = mHeight;
558
 
559
        if (!mVertical || mTotalWidth <= 0)
560
            mTotalWidth = 0;
561
 
562
        if (mVertical || mTotalHeight <= 0)
563
            mTotalHeight = 0;
564
 
565
//        int num = 0;
566
 
567
        for (iter = items.begin(); iter != items.end(); ++iter)
568
        {
569
            if (!mVertical)
570
                mTotalWidth += iter->width;
571
            else
572
                mTotalHeight += iter->height;
573
 
574
//            num++;
575
        }
576
 
577
        if (mVertical)
578
        {
579
            mTotalHeight = scale(mTotalHeight);
580
            total = mTotalHeight;
581
        }
582
        else
583
        {
584
            mTotalWidth = scale(mTotalWidth);
585
            total = mTotalWidth;
586
        }
587
 
588
        if (mMain)
589
            mMain->setFixedSize(mTotalWidth, mTotalHeight);
590
    }
591
 
592
//    MSG_DEBUG("Number of items: " << items.size());
593
 
594
    if (mSpace > 0)
595
    {
596
        int space = (int)((double)total / 100.0 * (double)mSpace);
597
 
598
        if (space > 0 && mVertical && mVLayout && mMain)
599
        {
600
            int newHeight = space + mTotalHeight;
601
            mMain->setFixedHeight(newHeight);
602
//            MSG_DEBUG("Calculated space: " << space << " (" << mSpace << "%). Total height: " << newHeight << ", Old total height: " << mTotalHeight);
603
            mTotalHeight = newHeight;
604
        }
605
        else if (space > 0 && !mVertical && mHLayout && mMain)
606
        {
607
            int newWidth = space + mTotalWidth;
608
            mMain->setFixedWidth(newWidth);
609
//            MSG_DEBUG("Calculated space: " << space << " (" << mSpace << "%). Total width: " << newWidth << ", Old total width: " << mTotalWidth);
610
            mTotalWidth = newWidth;
611
        }
612
    }
613
 
614
    for (iter = items.begin(); iter != items.end(); ++iter)
615
    {
616
        int iWidth = scale(iter->width);
617
        int iHeight = scale(iter->height);
618
        QWidget *item = new QWidget;
619
        item->setObjectName(QString("Item_%1").arg(handleToString(iter->handle).c_str()));
620
        item->setFixedSize(iWidth, iHeight);
621
        item->setAutoFillBackground(true);
622
        QColor bgcolor(qRgba(iter->bgcolor.red, iter->bgcolor.green, iter->bgcolor.blue, iter->bgcolor.alpha));
623
 
624
        if (iter->image.getSize() > 0)
625
        {
626
            QPixmap pixmap(iWidth, iHeight);
627
 
628
            if (iter->bgcolor.alpha == 0)
629
                pixmap.fill(Qt::transparent);
630
            else
631
                pixmap.fill(bgcolor);
632
 
633
            QImage img(iter->image.getBitmap(), iter->image.getWidth(), iter->image.getHeight(), iter->image.getPixline(), QImage::Format_ARGB32);  // Original size
634
            bool ret = false;
635
 
636
            if (mScaleFactor != 1.0)
637
            {
638
                QSize size(iWidth, iHeight);
639
                ret = pixmap.convertFromImage(img.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));   // Scaled size
640
            }
641
            else
642
                ret = pixmap.convertFromImage(img);
643
 
644
            if (!ret || pixmap.isNull())
645
            {
646
                MSG_ERROR("Unable to create a pixmap out of an image!");
647
                return;
648
            }
649
 
650
            QPalette palette(item->palette());
651
            palette.setBrush(QPalette::Window, QBrush(pixmap));
652
            item->setPalette(palette);
653
        }
654
        else
655
        {
656
            QPalette palette(item->palette());
657
 
658
            if (iter->bgcolor.alpha == 0)
659
                palette.setColor(QPalette::Window, Qt::transparent);
660
            else
661
                palette.setColor(QPalette::Window, bgcolor);
662
 
663
            item->setPalette(palette);
664
        }
665
 
666
        // Add the buttons to the item widget
667
        if (iter->atoms.empty())
668
        {
669
            delete item;
670
            continue;
671
        }
672
 
673
        vector<PGSUBVIEWATOM_T>::iterator itAtom;
674
 
675
        for (itAtom = iter->atoms.begin(); itAtom != iter->atoms.end(); ++itAtom)
676
        {
677
            int scaWidth = scale(itAtom->width);
678
            int scaHeight = scale(itAtom->height);
679
 
680
            QLabel *label = new QLabel(item);
681
            label->move(scale(itAtom->left), scale(itAtom->top));
682
            label->setFixedSize(scaWidth, scaHeight);
683
            label->setObjectName(QString("Label_%1").arg(handleToString(itAtom->handle).c_str()));
684
            setAtom(*itAtom, label);
685
        }
686
 
687
        iter->item = item;
688
 
689
        if (mVertical && mVLayout)
690
            mVLayout->addWidget(item);
691
        else if (!mVertical && mHLayout)
692
            mHLayout->addWidget(item);
693
        else
694
        {
695
            MSG_ERROR("Layout not initialized!");
696
        }
697
    }
698
 
699
    if (mOldActPosition > 0)
700
    {
701
        MSG_DEBUG("Setting position to old value " << mOldActPosition);
702
        resetSlider(mOldActPosition);
703
        mOldActPosition = 0;
704
    }
705
}
706
 
707
/**
708
 * @brief TQScrollArea::updateItem
709
 * Updates one item.
710
 *
711
 * @param item  The item to update.
712
 */
713
void TQScrollArea::updateItem(PGSUBVIEWITEM_T& item)
714
{
715
    DECL_TRACER("TQScrollArea::updateItem(PGSUBVIEWITEM_T& item)");
716
 
717
    if (mItems.empty())
718
        return;
719
 
720
    vector<_ITEMS_T>::iterator iter;
721
 
722
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
723
    {
724
        if (iter->handle == item.handle)
725
        {
726
            iter->bgcolor = item.bgcolor;
727
            iter->bounding = item.bounding;
728
            iter->image = item.image;
729
            iter->atoms = item.atoms;
730
 
731
            if (!iter->atoms.empty())
732
            {
733
                QObjectList list = iter->item->children();
734
                QList<QObject *>::Iterator obit;
735
                vector<PGSUBVIEWATOM_T>::iterator atit;
736
 
737
                for (atit = iter->atoms.begin(); atit != iter->atoms.end(); ++atit)
738
                {
739
                    for (obit = list.begin(); obit != list.end(); ++obit)
740
                    {
741
                        QObject *o = *obit;
742
                        QString obname = o->objectName();
743
                        ulong atHandle = extractHandle(obname.toStdString());
744
 
745
                        if (atit->handle == atHandle && obname.startsWith("Label_"))
746
                        {
747
                            QLabel *lbl = dynamic_cast<QLabel *>(o);
748
                            setAtom(*atit, lbl);
749
                            break;
750
                        }
751
                    }
752
                }
753
 
754
                iter->item->show();
755
            }
756
 
757
            break;
758
        }
759
    }
760
}
761
 
762
void TQScrollArea::showItem(ulong handle, int position)
763
{
764
    DECL_TRACER("TQScrollArea::showItem(ulong handle, int position)");
765
 
766
    if (mItems.empty())
767
        return;
768
 
769
    vector<_ITEMS_T>::iterator iter;
770
 
771
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
772
    {
773
        if (!iter->item)
774
            continue;
775
 
776
        if (iter->handle == handle)
777
        {
778
            if (!iter->item->isVisible())
779
                iter->item->setVisible(true);
780
 
781
            setPosition(iter->item, position);
782
            break;
783
        }
784
    }
785
}
786
 
787
void TQScrollArea::toggleItem(ulong handle, int position)
788
{
789
    DECL_TRACER("TQScrollArea::toggleItem(ulong handle, int position)");
790
 
791
    if (mItems.empty())
792
        return;
793
 
794
    vector<_ITEMS_T>::iterator iter;
795
 
796
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
797
    {
798
        if (iter->handle == handle && iter->item)
799
        {
800
            if (iter->item->isVisible())
801
                iter->item->setVisible(false);
802
            else
803
            {
804
                iter->item->setVisible(true);
805
                setPosition(iter->item, position);
806
            }
807
 
808
            break;
809
        }
810
    }
811
}
812
 
813
void TQScrollArea::hideAllItems()
814
{
815
    DECL_TRACER("TQScrollArea::hideAllItems()");
816
 
817
    if (mItems.empty())
818
        return;
819
 
820
    resetSlider();
821
    vector<_ITEMS_T>::iterator iter;
822
 
823
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
824
    {
825
        if (iter->item)
826
            iter->item->setVisible(false);
827
    }
828
}
829
 
830
void TQScrollArea::hideItem(ulong handle)
831
{
832
    DECL_TRACER("TQScrollArea::hideItem(ulong handle)");
833
 
834
    if (mItems.empty())
835
        return;
836
 
837
    vector<_ITEMS_T>::iterator iter;
838
 
839
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
840
    {
841
        if (iter->handle == handle && iter->item)
842
        {
843
            iter->item->setVisible(false);
844
            return;
845
        }
846
    }
847
}
848
 
849
int TQScrollArea::scale(int value)
850
{
851
//    DECL_TRACER("TQScrollArea::scale(int value)");
852
 
853
    if (mScaleFactor != 1.0)
854
        return (int)((double)value * mScaleFactor);
855
 
856
    return value;
857
}
858
 
859
void TQScrollArea::setScaleFactor(const double& factor)
860
{
861
    DECL_TRACER("TQScrollArea::setScaleFactor(const double& factor)");
862
 
863
    if (factor > 0.0 && factor != 1.0)
864
        mScaleFactor = factor;
865
}
866
 
867
void TQScrollArea::setAtom(PGSUBVIEWATOM_T& atom, QLabel *label)
868
{
869
//    DECL_TRACER("TQScrollArea::setAtom(PGSUBVIEWATOM_T& atom, QLabel *label)");
870
 
871
    if (!label)
872
        return;
873
 
874
    int scaWidth = scale(atom.width);
875
    int scaHeight = scale(atom.height);
876
    QColor bg(qRgba(atom.bgcolor.red, atom.bgcolor.green, atom.bgcolor.blue, atom.bgcolor.alpha));
877
 
878
    if (atom.image.isValid())
879
    {
880
        QPixmap pix(scaWidth, scaHeight);
881
 
882
        if (atom.bgcolor.alpha == 0)
883
            pix.fill(Qt::transparent);
884
        else
885
            pix.fill(bg);
886
 
887
        QImage img(atom.image.getBitmap(), atom.image.getWidth(), atom.image.getHeight(), atom.image.getPixline(), QImage::Format_ARGB32);
888
        bool ret = false;
889
 
890
        if (mScaleFactor != 1.0)
891
        {
892
            QSize size(scaWidth, scaHeight);
893
            ret = pix.convertFromImage(img.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Scaled size
894
        }
895
        else
896
            ret = pix.convertFromImage(img);
897
 
898
        if (!ret || pix.isNull())
899
        {
900
            MSG_ERROR("Unable to create a pixmap out of an image!");
901
            return;
902
        }
903
 
904
        label->setPixmap(pix);
905
    }
906
    else
907
    {
908
        QPalette palette(label->palette());
909
 
910
        if (atom.bgcolor.alpha == 0)
911
            palette.setColor(QPalette::Window, Qt::transparent);
912
        else
913
            palette.setColor(QPalette::Window, bg);
914
 
915
        label->setPalette(palette);
916
    }
917
}
918
 
919
void TQScrollArea::refresh()
920
{
921
    DECL_TRACER("TQScrollArea::refresh()");
922
 
923
    if (!mMain || mItems.empty())
924
        return;
925
 
926
    resetSlider();
927
    _clearAllItems();
928
    _addItems(mItems, true);
929
}
930
 
931
void TQScrollArea::setPosition()
932
{
933
    DECL_TRACER("TQScrollArea::setPosition()");
934
 
935
    if (mItems.empty())
936
        return;
937
 
938
    QWidget *anchor = nullptr;
939
    size_t pos = 0;
940
    MSG_DEBUG("Wrap items: " << (mWrapItems ? "TRUE" : "FALSE") << ", number items: " << mItems.size());
941
 
942
    switch (mPosition)
943
    {
944
        case Button::SVP_LEFT_TOP:
945
            anchor = mItems[0].item;
946
        break;
947
 
948
        case Button::SVP_CENTER:
949
            pos = mItems.size() / 2;
950
            anchor = mItems[pos].item;
951
        break;
952
 
953
        case Button::SVP_RIGHT_BOTTOM:
954
            pos = mItems.size() - 1;
955
            anchor = mItems[pos].item;
956
        break;
957
    }
958
 
959
    if (anchor)
960
    {
961
        QRect geom = anchor->geometry();
962
        bool makeVisible = false;
963
 
964
        if (mVertical)
965
        {
966
            if ((geom.y() + geom.height()) < mActPosition ||
967
                    geom.y() > (mActPosition + mHeight))
968
                makeVisible = true;
969
        }
970
        else
971
        {
972
            if ((geom.x() + geom.width()) < mActPosition ||
973
                    geom.x() > (mActPosition + mWidth))
974
                makeVisible = true;
975
        }
976
 
977
        ulong handle = extractHandle(anchor->objectName().toStdString());
978
 
979
        if (makeVisible)
980
        {
981
            ensureWidgetVisible(anchor);
982
            MSG_DEBUG("Item number " << pos << " (" << handleToString(handle) << ") was moved to position.");
983
        }
984
        else
985
        {
986
            MSG_DEBUG("Item number " << pos << " (" << handleToString(handle) << ") is already at visible position.");
987
        }
988
    }
989
}
990
 
991
void TQScrollArea::setPosition(QWidget* w, int position)
992
{
993
    DECL_TRACER("TQScrollArea::setPosition(QWidget* w, int position)");
994
 
995
    int defPosX = 50;
996
    int defPosY = 50;
997
 
998
    if (position > 0 && position < 65535)
999
    {
1000
        if (mVertical)
1001
        {
1002
            defPosY = position;
1003
            defPosX = 0;
1004
        }
1005
        else
1006
        {
1007
            defPosY = 0;
1008
            defPosX = position;
1009
        }
1010
 
1011
        ensureWidgetVisible(w, defPosX, defPosY);
1012
    }
1013
    else if (mPosition == Button::SVP_LEFT_TOP)
1014
    {
1015
        if (mVertical)
1016
        {
1017
            int top = w->geometry().y();
1018
            QScrollBar *bar = verticalScrollBar();
1019
 
1020
            if (bar)
1021
                bar->setSliderPosition(top);
1022
        }
1023
        else
1024
        {
1025
            int left = w->geometry().x();
1026
            QScrollBar *bar = horizontalScrollBar();
1027
 
1028
            if (bar)
1029
                bar->setSliderPosition(left);
1030
        }
1031
    }
1032
    else if (mPosition == Button::SVP_CENTER)
1033
    {
1034
        if (mVertical)
1035
        {
1036
            int topMargin = (mHeight - w->geometry().height()) / 2;
1037
            int top = w->geometry().y() - topMargin;
1038
            QScrollBar *bar = verticalScrollBar();
1039
 
1040
            if (bar)
1041
                bar->setSliderPosition(top);
1042
        }
1043
        else
1044
        {
1045
            int leftMargin = (mWidth - w->geometry().width()) / 2;
1046
            int left = w->geometry().x() - leftMargin;
1047
            QScrollBar *bar = horizontalScrollBar();
1048
 
1049
            if (bar)
1050
                bar->setSliderPosition(left);
1051
        }
1052
    }
1053
    else if (mPosition == Button::SVP_RIGHT_BOTTOM)
1054
    {
1055
        if (mVertical)
1056
        {
1057
            int bottom = w->geometry().y() + w->geometry().height();
1058
            QScrollBar *bar = verticalScrollBar();
1059
 
1060
            if (bar)
1061
                bar->setSliderPosition(bottom);
1062
        }
1063
        else
1064
        {
1065
            int right = w->geometry().x() + w->geometry().width();
1066
            QScrollBar *bar = horizontalScrollBar();
1067
 
1068
            if (bar)
1069
                bar->setSliderPosition(right);
1070
        }
1071
    }
1072
}
1073
 
1074
TQScrollArea::_ITEMS_T TQScrollArea::subViewItemToItem(PGSUBVIEWITEM_T& item)
1075
{
1076
//    DECL_TRACER("TQScrollArea::subViewItemToItem(PGSUBVIEWITEM_T& item)");
1077
 
1078
    _ITEMS_T it;
1079
    it.handle = item.handle;
1080
    it.parent = item.parent;
1081
    it.width = item.width;
1082
    it.height = item.height;
1083
    it.bgcolor = item.bgcolor;
1084
    it.bounding = item.bounding;
1085
    it.image = item.image;
1086
    it.position = item.position;
1087
    it.scrollbar = item.scrollbar;
1088
    it.scrollbarOffset = item.scrollbarOffset;
1089
    it.wrap = item.wrap;
1090
    it.atoms = item.atoms;
1091
 
1092
    return it;
1093
}
1094
 
1095
void TQScrollArea::_clearAllItems()
1096
{
1097
//    DECL_TRACER("TQScrollArea::_clearAllItems()");
1098
 
1099
    if (mItems.empty())
1100
        return;
1101
 
1102
    vector<_ITEMS_T>::iterator clIter;
1103
 
1104
    for (clIter = mItems.begin(); clIter != mItems.end(); ++clIter)
1105
    {
1106
        if (clIter->item)
1107
        {
1108
            if (mVertical)
1109
            {
1110
                if (mVLayout)
1111
                    mVLayout->removeWidget(clIter->item);
1112
            }
1113
            else
1114
            {
1115
                if (mHLayout)
1116
                    mHLayout->removeWidget(clIter->item);
1117
            }
1118
 
1119
            clIter->item->close();
1120
            clIter->item = nullptr;
1121
        }
1122
    }
1123
}
1124
 
1125
void TQScrollArea::resetSlider(int position)
1126
{
1127
    DECL_TRACER("TQScrollArea::resetSlider(int position)");
1128
 
1129
    if (mActPosition <= 0)
1130
        return;
1131
 
1132
    QScrollBar *sbar = nullptr;
1133
 
1134
    if (mVertical)
1135
        sbar = verticalScrollBar();
1136
    else
1137
        sbar = horizontalScrollBar();
1138
 
1139
    if (sbar)
1140
    {
1141
        mOldActPosition = sbar->value();
1142
        sbar->setSliderPosition(position);
1143
    }
1144
    else
1145
        mOldActPosition = mActPosition;
1146
}
1147
 
1148
/*****************************************************************************
1149
 * Signals and overwritten functions start here
1150
 *****************************************************************************/
1151
 
1152
void TQScrollArea::scrollContentsBy(int dx, int dy)
1153
{
1154
    DECL_TRACER("TQScrollArea::scrollContentsBy(int dx, int dy)");
1155
 
1156
    QScrollArea::scrollContentsBy(dx, dy);      // First let the original class do it's job.
1157
    QScrollBar *sbar = nullptr;
1158
 
1159
    if (mVertical)
1160
        sbar = verticalScrollBar();
1161
    else
1162
        sbar = horizontalScrollBar();
1163
 
1164
    if (sbar)
1165
    {
1166
        mActPosition = sbar->value();
1167
        MSG_DEBUG("Actual slider position: " << mActPosition);
1168
 
1169
        if (mScrollbar && mScrollbarOffset > 0 && mActPosition < mScrollbarOffset)
1170
        {
1171
            sbar->setSliderPosition(mScrollbarOffset);
1172
            mActPosition = sbar->value();
1173
        }
1174
    }
1175
}
1176
 
1177
void TQScrollArea::mouseMoveEvent(QMouseEvent* event)
1178
{
1179
    DECL_TRACER("TQScrollArea::mouseMoveEvent(QMouseEvent* event)");
1180
 
1181
    mMousePress = false;
1182
    mMouseScroll = true;
1183
    mDoMouseEvent = false;
1184
 
1185
    if (mMousePressTimer && mMousePressTimer->isActive())
1186
        mMousePressTimer->stop();
1187
 
1188
    int move = 0;
1189
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1190
    MSG_DEBUG("Scroll event at " << event->pos().x() << "x" << event->pos().y() << ", old point at " << mOldPoint.x() << "x" << mOldPoint.y());
1191
#else
1192
    MSG_DEBUG("Scroll event at " << event->position().x() << "x" << event->position().y() << ", old point at " << mOldPoint.x() << "x" << mOldPoint.y());
1193
#endif
1194
    if (mVertical)
1195
    {
1196
        if (mOldPoint.y() != 0)
1197
        {
1198
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1199
            move = event->pos().y() - mOldPoint.y();
1200
#else
1201
            move = event->position().y() - mOldPoint.y();
1202
#endif
1203
            QScrollBar *bar = verticalScrollBar();
1204
 
1205
            if (bar)
1206
            {
1207
                int value = bar->value();
1208
                value += (move * -1);
1209
                bar->setValue(value);
1210
            }
1211
        }
1212
    }
1213
    else
1214
    {
1215
        if (mOldPoint.x() != 0)
1216
        {
1217
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1218
            move = event->pos().x() - mOldPoint.x();
1219
#else
1220
            move = event->position().x() - mOldPoint.x();
1221
#endif
1222
            QScrollBar *bar = horizontalScrollBar();
1223
 
1224
            if (bar)
1225
            {
1226
                int value = bar->value();
1227
                int newValue = value + (move * -1);
1228
 
1229
                if (newValue >= 0 && newValue != value)
1230
                    bar->setValue(newValue);
1231
            }
1232
        }
1233
    }
1234
 
1235
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1236
    mOldPoint = event->pos();
1237
#else
1238
    mOldPoint = event->position();
1239
#endif
1240
}
1241
 
1242
void TQScrollArea::mousePressEvent(QMouseEvent* event)
1243
{
1244
    DECL_TRACER("TQScrollArea::mousePressEvent(QMouseEvent* event)");
1245
 
1246
    if (!event || mMouseScroll || event->button() != Qt::LeftButton)
1247
        return;
1248
 
1249
    mMousePress = true;
1250
    mOldPoint.setX(0.0);
1251
    mOldPoint.setY(0.0);
1252
 
1253
    int x = 0, y = 0;
1254
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1255
    x = event->pos().x();
1256
    y = event->pos().y();
1257
#else
1258
    x = event->position().x();
1259
    y = event->position().y();
1260
#endif
1261
    mLastMousePress.setX(x);
1262
    mLastMousePress.setY(y);
1263
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1264
    MSG_DEBUG("Mouse press event at " << x << " x " << y << " // " << event->globalX() << " x " << event->globalY());
1265
#else
1266
    MSG_DEBUG("Mouse press event at " << x << " x " << y << " // " << event->globalPosition().x() << " x " << event->globalPosition().y());
1267
#endif
1268
    /*
1269
        * Here we're starting a timer with 200 ms. If after this time the
1270
        * mouse button is still pressed and no scroll event was detected,
1271
        * then we've a real click.
1272
        * In case of a real click the method mouseTimerEvent() will call a
1273
        * signal to inform the parent about the click.
1274
        */
1275
    mClick = true;  // This means PRESSED state
1276
    mMouseTmEventActive = true;
1277
    mDoMouseEvent = true;
1278
    QTimer::singleShot(200, this, &TQScrollArea::mouseTimerEvent);
1279
}
1280
 
1281
void TQScrollArea::mouseReleaseEvent(QMouseEvent* event)
1282
{
1283
    DECL_TRACER("TQScrollArea::mouseReleaseEvent(QMouseEvent* event)");
1284
 
1285
    if (!event || event->button() != Qt::LeftButton)
1286
        return;
1287
 
1288
    mDoMouseEvent = false;
1289
 
1290
    if (mMouseTmEventActive)
1291
    {
1292
        if (!mMouseScroll)
1293
        {
1294
            mClick = true;      // This means PRESSED state
1295
            doMouseEvent();
1296
            mClick = false;     // This means RELEASED state
1297
            doMouseEvent();
1298
        }
1299
    }
1300
    else if (!mMouseScroll && mClick)
1301
    {
1302
        mClick = false;         // This means RELEASED state
1303
        doMouseEvent();
1304
    }
1305
 
1306
    mMousePress = false;
1307
    mMouseScroll = false;
1308
    mOldPoint.setX(0.0);
1309
    mOldPoint.setY(0.0);
1310
}
1311
 
1312
void TQScrollArea::doMouseEvent()
1313
{
1314
    DECL_TRACER("TQScrollArea::doMouseEvent()");
1315
 
1316
    if (!mMousePress || mMouseScroll || !mMain)
1317
        return;
1318
 
1319
    QWidget *w = nullptr;
1320
 
1321
    if (mVertical)
1322
        w = mMain->childAt(mLastMousePress.x(), mActPosition + mLastMousePress.y());
1323
    else
1324
        w = mMain->childAt(mActPosition + mLastMousePress.x(), mLastMousePress.y());
1325
 
1326
    if (!w)
1327
        return;
1328
 
1329
    QString obname = w->objectName();
1330
    ulong handle = extractHandle(obname.toStdString());
1331
 
1332
    if (!handle)
1333
        return;
1334
 
1335
    // We must make sure the found object is not marked as pass through.
1336
    // Because of this we'll scan the items for the handle and if we
1337
    // find that it is marked as pass through we must look for another
1338
    // one on the same position. If there is none, the click is ignored.
1339
    //
1340
    // Find the object in our list
1341
    vector<_ITEMS_T>::iterator iter;
1342
    QRect rect;
1343
    bool call = true;
1344
 
1345
    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
1346
    {
1347
        if (iter->handle == handle)     // Handle found?
1348
        {                               // Yes, then ...
1349
            if (iter->bounding == "passThru")   // Item marked as pass through?
1350
            {                                   // Yes, then start to search for another item
1351
                rect = w->rect();
1352
                call = false;
1353
                // Walk through the childs to find another one on the
1354
                // clicked position.
1355
                QObjectList ol = mMain->children(); // Get list of all objects
1356
                QList<QObject *>::iterator obiter;  // Define an iterator
1357
                // Loop through all objects
1358
                for (obiter = ol.begin(); obiter != ol.end(); ++obiter)
1359
                {
1360
                    QObject *object = *obiter;
1361
 
1362
                    if (object->objectName() != obname && object->objectName().startsWith("Label_"))    // Have we found a QLabel object?
1363
                    {                                                                                   // Yes, then test it's position
1364
                        QLabel *lb = dynamic_cast<QLabel *>(object);    // Cast the object to a QLabel
1365
 
1366
                        if (lb->rect().contains(mLastMousePress))       // Is the QLabel under the mouse coordinates?
1367
                        {                                               // Yes, then select it.
1368
                            ulong h = extractHandle(lb->objectName().toStdString());  // Get the handle
1369
 
1370
                            if (!h)
1371
                                break;
1372
 
1373
                            handle = h;
1374
                            // Reset the main loop
1375
                            iter = mItems.begin();
1376
                            break;
1377
                        }
1378
                    }
1379
                }
1380
            }
1381
            else
1382
            {
1383
                call = true;
1384
                break;
1385
            }
1386
        }
1387
    }
1388
 
1389
    if (call)
1390
    {
1391
        MSG_DEBUG("Calling signal with handle " << (handle >> 16 & 0x0000ffff) << ":" << (handle & 0x0000ffff) << ": STATE=" << (mClick ? "PRESSED" : "RELEASED"));
1392
        emit objectClicked(handle, mClick);
1393
        mClick = false;
1394
    }
1395
}
1396
 
1397
void TQScrollArea::mouseTimerEvent()
1398
{
1399
    DECL_TRACER("TQScrollArea::mouseTimerEvent()");
1400
 
1401
    if (!mDoMouseEvent)
1402
        return;
1403
 
1404
    mDoMouseEvent = false;
1405
 
1406
    if (mClick)         // Only if PRESSED
1407
        doMouseEvent();
1408
 
1409
    mMouseTmEventActive = false;
1410
}
1411