Subversion Repositories tpanel

Rev

Rev 301 | Blame | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2023 by Andreas Theofilu <andreas@theosys.at>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

#include <QWidget>
#include <QScrollArea>
#include <QPixmap>
#include <QColor>
#include <QPainter>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPoint>
#include <QMouseEvent>
#include <QScrollBar>
#include <QTimer>

#include "tqscrollarea.h"
#include "terror.h"
#include "tresources.h"

using std::vector;

/**
 * @brief TQScrollArea::TQScrollArea
 * Constructor for the class.
 */
TQScrollArea::TQScrollArea()
{
    DECL_TRACER("TQScrollArea::TQScrollArea()");
}

/**
 * @brief TQScrollArea::TQScrollArea
 * @param parent    The parent widget
 */
TQScrollArea::TQScrollArea(QWidget* parent)
    : mParent(parent)
{
    DECL_TRACER("TQScrollArea::TQScrollArea(QWidget* parent)");

    if (parent)
    {
        mWidth = parent->geometry().width();
        mHeight = parent->geometry().height();
    }

    init();
}

/**
 * @brief TQScrollArea::TQScrollArea
 * @param parent        Parent widget
 * @param w             Visible width in pixels
 * @param h             Visible height in pixels
 * @param vertical      TRUE: Scrolling in vertical direction
 */
TQScrollArea::TQScrollArea(QWidget* parent, int w, int h, bool vertical)
    : mParent(parent),
      mVertical(vertical)
{
    DECL_TRACER("TQScrollArea::TQScrollArea(QWidget* parent, int w, int h, bool vertical)");

    if (w > 0)
        mWidth = w;

    if (h > 0)
        mHeight = h;

    init();
}

/**
 * @brief TQScrollArea::TQScrollArea
 * @param parent    Parent widget
 * @param size      Size (width and height) of visible area
 * @param vertical  TRUE: Scrolling in vertical direction
 */
TQScrollArea::TQScrollArea(QWidget* parent, const QSize& size, bool vertical)
    : mParent(parent),
      mVertical(vertical)
{
    DECL_TRACER("TQScrollArea::TQScrollArea(QWidget* parent, const QSize& size, bool vertical)");

    if (size.width() > 0)
        mWidth = size.width();

    if (size.height() > 0)
        mHeight = size.height();

    init();
}

TQScrollArea::~TQScrollArea()
{
    DECL_TRACER("TQScrollArea::~TQScrollArea()");

    if (mMain)
        mMain->close();

    if (mMousePressTimer)
    {
        if (mMousePressTimer->isActive())
            mMousePressTimer->stop();

        disconnect(mMousePressTimer, &QTimer::timeout, this, &TQScrollArea::mouseTimerEvent);
        delete mMousePressTimer;
        mMousePressTimer = nullptr;
    }
}

void TQScrollArea::init()
{
    DECL_TRACER("TQScrollArea::init()");

    QScrollArea::setParent(mParent);
    QScrollArea::setViewportMargins(0, 0, 0, 0);

    if (mWidth > 0 || mHeight > 0)
        QScrollArea::setFixedSize(mWidth, mHeight);

    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    // Set a transparent background
    QPalette palette(this->palette());
    palette.setColor(QPalette::Window, QColor(Qt::transparent));
    setPalette(palette);

    if (!mMain)
        mMain = new QWidget(this);

    mMain->move(0, 0);
    mMain->setContentsMargins(0, 0, 0, 0);

    if (mWidth && mHeight)
        setFixedSize(mWidth, mHeight);

    setWidget(mMain);

    if (mVertical && !mVLayout)
    {
        mVLayout = new QVBoxLayout(mMain);
        mVLayout->setSpacing(0);
        mVLayout->setContentsMargins(0, 0, 0, 0);
    }
    else if (!mVertical && !mHLayout)
    {
        mHLayout = new QHBoxLayout(mMain);
        mHLayout->setSpacing(0);
        mHLayout->setContentsMargins(0, 0, 0, 0);
    }


    if (!mTotalWidth)
        mTotalWidth = mWidth;

    if (!mTotalHeight)
        mTotalHeight = mHeight;
}

/**
 * @brief TQScrollArea::setObjectName
 * This sets the object name of the internal main QWidget.
 *
 * @param name  The name of the object.
 */
void TQScrollArea::setObjectName(const QString& name)
{
    DECL_TRACER("TQScrollArea::setObjectName(const QString& name)");

    if (mMain)
        mMain->setObjectName(name);
}

/**
 * @brief TQScrollArea::setSize
 * Sets the size of the visible area of the object.
 *
 * @param w     The width in pixels
 * @param h     The height in pixels
 */
void TQScrollArea::setSize(int w, int h)
{
    DECL_TRACER("TQScrollArea::setSize(int w, int h)");

    if (w < 1 || h < 1)
        return;

    mWidth = w;
    mHeight = h;
    setFixedSize(mWidth, mHeight);
}

/**
 * @brief TQScrollArea::setSize
 * Sets the size of the visible area of the object.
 *
 * @param size  The size (width and height)
 */
void TQScrollArea::setSize(QSize size)
{
    DECL_TRACER("TQScrollArea::setSize(QSize size)");

    mWidth = size.width();
    mHeight = size.height();
    setFixedSize(mWidth, mHeight);
}

/**
 * @brief TQScrollArea::getSize
 * Returns the size of the visible area.
 *
 * @return A QSize object containg the size in pixels.
 */
QSize TQScrollArea::getSize()
{
    DECL_TRACER("TQScrollArea::getSize()");

    return QSize(mWidth, mHeight);
}

void TQScrollArea::setScrollbar(bool sb)
{
    DECL_TRACER("TQScrollArea::setScrollbar(bool sb)");

    if (sb == mScrollbar)
        return;

    mScrollbar = sb;

    if (sb)
    {
        if (mVertical)
            setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
        else
            setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    }
    else
    {
        if (mVertical)
            setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        else
            setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    }
}

void TQScrollArea::setScrollbarOffset(int offset)
{
    DECL_TRACER("TQScrollArea::setScrollbarOffset(int offset)");

    if (!mScrollbar)
        return;

    if (offset == 0)
    {
        mScrollbarOffset = 0;
        return;
    }

    mScrollbarOffset = scale(offset);
    QScrollBar *sbar = nullptr;

    if (mVertical)
        sbar = verticalScrollBar();
    else
        sbar = horizontalScrollBar();

    if (sbar)
        sbar->setSliderPosition(mScrollbarOffset);
}

void TQScrollArea::setAnchor(Button::SUBVIEW_POSITION_t position)
{
    DECL_TRACER("TQScrollArea::setAnchor(Button::SUBVIEW_POSITION_t position)");

    mPosition = position;
}

void TQScrollArea::show()
{
    DECL_TRACER("TQScrollArea::show()");

    if (!QScrollArea::isEnabled())
        QScrollArea::setEnabled(true);

    QScrollArea::show();

    if (mMain)
    {
        if (!mMain->isEnabled())
            mMain->setEnabled(true);

        if (!mMain->isVisible())
            mMain->show();
    }

    if (mWrapItems && !mMainWidgets.empty())
    {
        QWidget *anchor = nullptr;
        size_t pos = 0;

        switch (mPosition)
        {
            case Button::SVP_LEFT_TOP:
                anchor = mMainWidgets[0];
                break;

            case Button::SVP_CENTER:
                pos = mMainWidgets.size() / 2;
                anchor = mMainWidgets[pos];
                break;

            case Button::SVP_RIGHT_BOTTOM:
                pos = mMainWidgets.size() - 1;
                anchor = mMainWidgets[pos];
                break;
        }

        if (anchor)
            ensureWidgetVisible(anchor);
    }
}

/**
 * @brief TQScrollArea::setTotalWidth
 * Sets the total width of the scrolling area. This must be equal or grater
 * then the width of the visible area.
 *
 * @param w The width in pixels.
 */
void TQScrollArea::setTotalWidth(int w)
{
    DECL_TRACER("TQScrollArea::setTotalWidth(int w)");

    if (!mMain || w < mWidth)
        return;

    mTotalWidth = w;
    mMain->setFixedWidth(mTotalWidth);
}

/**
 * @brief TQScrollArea::setTotalHeight
 * Sets the total height of the scrolling area. This must be equal or grater
 * then the height of the visible area.
 *
 * @param h  The height in pixels.
 */
void TQScrollArea::setTotalHeight(int h)
{
    DECL_TRACER("TQScrollArea::setTotalHeight(int h)");

    if (!mMain || h < mHeight)
        return;

    mTotalHeight = h;
    mMain->setFixedHeight(mTotalHeight);
}

/**
 * @brief TQScrollArea::setTotalSize
 * Sets the total size of the scrolling area. The width and height must be
 * equal or grater then the width and height of the visible area.
 *
 * @param w  The width in pixels.
 * @param h  The height in pixels.
 */
void TQScrollArea::setTotalSize(int w, int h)
{
    DECL_TRACER("TQScrollArea::setTotalSize(int w, int h)");

    if (!mMain || w < mWidth || h < mHeight)
        return;

    mTotalWidth = w;
    mTotalHeight = h;
    mMain->setFixedSize(mTotalWidth, mTotalHeight);
}

/**
 * @brief TQScrollArea::setTotalSize
 * Sets the total size of the scrolling area in pixels.
 *
 * @param size  The total size of the scrolling area.
 */
void TQScrollArea::setTotalSize(QSize& size)
{
    DECL_TRACER("TQScrollArea::setTotalSize(QSize& size)");

    if (!mMain || size.width() < mWidth || size.height() < mHeight)
        return;

    mTotalWidth = size.width();
    mTotalHeight = size.height();
    mMain->setFixedSize(mTotalWidth, mTotalHeight);
}

/**
 * @brief TQScrollArea::setBackgroundImage
 * This sets the background image of the scroll area. If the pixmap is smaller
 * then the total size, the image is painted in tiles.
 *
 * @param pix       The pixmap.
 */
void TQScrollArea::setBackgroundImage(const QPixmap& pix)
{
    DECL_TRACER("TQScrollArea::setBackgroundImage(const QPixmap& pix)");

    if (!mMain || pix.isNull())
        return;

    QPalette palette(mMain->palette());
    palette.setBrush(QPalette::Window, QBrush(pix));
    mMain->setPalette(palette);
}

/**
 * @brief TQScrollArea::setBackGroundColor
 * Sets the background color of the scroll area.
 *
 * @param color     The color
 */
void TQScrollArea::setBackGroundColor(QColor color)
{
    DECL_TRACER("TQScrollArea::setBackGroundColor(QColor color)");

    if (!mMain)
        return;

    QPalette palette(mMain->palette());
    palette.setColor(QPalette::Window, color);
    mMain->setPalette(palette);
}

/**
 * @brief TQScrollArea::setSpace
 * Sets the space between the items in percent. The pixels are calculated
 * from the total size of the scroll area. Then the spce is inserted.
 *
 * @param s     A value between 0 and 99. 0 Removes the space.
 */
void TQScrollArea::setSpace(int s)
{
    DECL_TRACER("TQScrollArea::setSpace(double s)");

    if (s < 0 || s > 99)
        return;

    mSpace = s;
}

/**
 * @brief TQScrollArea::addItem
 * Adds one item to the list of items.
 *
 * @param item  Item to add
 */
void TQScrollArea::addItem(PGSUBVIEWITEM_T& item)
{
    DECL_TRACER("TQScrollArea::addItem(PGSUBVIEWITEM_T& item)");

    mItems.push_back(item);
    addItems(mItems);
}

void TQScrollArea::addItems(std::vector<PGSUBVIEWITEM_T>& items)
{
    DECL_TRACER("TQScrollArea::addItems(std::vector<PGSUBVIEWITEM_T>& items)");

    if (items.empty())
        return;

    mWrapItems = items[0].wrap;

    if (mMainWidgets.size() > 0)
    {
        vector<QWidget *>::iterator iter;

        for (iter = mMainWidgets.begin(); iter != mMainWidgets.end(); ++iter)
        {
            QWidget *w = *iter;
            w->close();
        }

        mMainWidgets.clear();
    }

    mItems = items;

    if (mVertical)
        mTotalHeight = 0;
    else
        mTotalWidth = 0;

    int total = 0;      // The total width or height
    vector<PGSUBVIEWITEM_T>::iterator iter;
    // First calculate the total width and height if it was not set by a previous call
    if ((mTotalWidth <= 0 && !mVertical) || (mTotalHeight <= 0 && mVertical))
    {
        if (mTotalWidth <= 0)
            mTotalWidth = mWidth;

        if (mTotalHeight <= 0)
            mTotalHeight = mHeight;

        if (!mVertical || mTotalWidth <= 0)
            mTotalWidth = 0;

        if (mVertical || mTotalHeight <= 0)
            mTotalHeight = 0;

        int num = 0;

        for (iter = items.begin(); iter != items.end(); ++iter)
        {
            if (!mVertical)
                mTotalWidth += iter->width;
            else
                mTotalHeight += iter->height;

            MSG_DEBUG("Item " << num << " (" << handleToString(iter->handle) << "): Size: " << iter->width << " x " << iter->height);
            num++;
        }

        if (mVertical)
        {
            mTotalHeight = scale(mTotalHeight);
            total = mTotalHeight;
        }
        else
        {
            mTotalWidth = scale(mTotalWidth);
            total = mTotalWidth;
        }

        if (mMain)
            mMain->setFixedSize(mTotalWidth, mTotalHeight);

        MSG_DEBUG("Total size: " << mTotalWidth << " x " << mTotalHeight << " (Vertical is " << (mVertical ? "TRUE" : "FALSE") << ")");
    }

    MSG_DEBUG("Number of items: " << items.size());

    if (mSpace > 0)
    {
        int space = (int)((double)total / 100.0 * (double)mSpace);

        if (space > 0 && mVertical && mVLayout && mMain)
        {
            int newHeight = space + mTotalHeight;
            mMain->setFixedHeight(newHeight);
            MSG_DEBUG("Calculated space: " << space << " (" << mSpace << "%). Total height: " << newHeight << ", Old total height: " << mTotalHeight);
            mTotalHeight = newHeight;
        }
        else if (space > 0 && !mVertical && mHLayout && mMain)
        {
            int newWidth = space + mTotalWidth;
            mMain->setFixedWidth(newWidth);
            MSG_DEBUG("Calculated space: " << space << " (" << mSpace << "%). Total width: " << newWidth << ", Old total width: " << mTotalWidth);
            mTotalWidth = newWidth;
        }
    }

    for (iter = items.begin(); iter != items.end(); ++iter)
    {
        int iWidth = scale(iter->width);
        int iHeight = scale(iter->height);
        QWidget *item = new QWidget;
        item->setObjectName(QString("Item_%1").arg(handleToString(iter->handle).c_str()));
        item->setFixedSize(iWidth, iHeight);
        item->setAutoFillBackground(true);
        QColor bgcolor(qRgba(iter->bgcolor.red, iter->bgcolor.green, iter->bgcolor.blue, iter->bgcolor.alpha));

        if (iter->image.getSize() > 0)
        {
            QPixmap pixmap(iWidth, iHeight);

            if (iter->bgcolor.alpha == 0)
                pixmap.fill(Qt::transparent);
            else
                pixmap.fill(bgcolor);

            QImage img(iter->image.getBitmap(), iter->image.getWidth(), iter->image.getHeight(), iter->image.getPixline(), QImage::Format_ARGB32);  // Original size
            bool ret = false;

            if (mScaleFactor != 1.0)
            {
                QSize size(iWidth, iHeight);
                ret = pixmap.convertFromImage(img.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));   // Scaled size
            }
            else
                ret = pixmap.convertFromImage(img);

            if (!ret || pixmap.isNull())
            {
                MSG_ERROR("Unable to create a pixmap out of an image!");
                return;
            }

            QPalette palette(item->palette());
            palette.setBrush(QPalette::Window, QBrush(pixmap));
            item->setPalette(palette);
        }
        else
        {
            QPalette palette(item->palette());

            if (iter->bgcolor.alpha == 0)
                palette.setColor(QPalette::Window, Qt::transparent);
            else
                palette.setColor(QPalette::Window, bgcolor);

            item->setPalette(palette);
        }

        // Add the buttons to the item widget
        if (iter->atoms.empty())
        {
            delete item;
            continue;
        }

        vector<PGSUBVIEWATOM_T>::iterator itAtom;

        for (itAtom = iter->atoms.begin(); itAtom != iter->atoms.end(); ++itAtom)
        {
            int scaWidth = scale(itAtom->width);
            int scaHeight = scale(itAtom->height);

            QLabel *label = new QLabel(item);
            label->move(scale(itAtom->left), scale(itAtom->top));
            label->setFixedSize(scaWidth, scaHeight);
            label->setObjectName(QString("Label_%1").arg(handleToString(itAtom->handle).c_str()));
            setAtom(*itAtom, label);
        }

        mMainWidgets.push_back(item);

        if (mVertical && mVLayout)
            mVLayout->addWidget(item);
        else if (!mVertical && mHLayout)
            mHLayout->addWidget(item);
        else
        {
            MSG_ERROR("Layout not initialized!");
        }
    }
}

void TQScrollArea::updateItem(PGSUBVIEWITEM_T& item)
{
    DECL_TRACER("TQScrollArea::updateItem(PGSUBVIEWITEM_T& item)");

    if (mItems.empty())
        return;

    vector<PGSUBVIEWITEM_T>::iterator iter;

    for (iter = mItems.begin(); iter != mItems.end(); ++iter)
    {
        if (iter->handle == item.handle)
        {
            iter->bgcolor = item.bgcolor;
            iter->bounding = item.bounding;
            iter->image = item.image;

            if (!item.atoms.empty())
                iter->atoms = item.atoms;
            // Find the item and change it in the scroll area
            vector<QWidget *>::iterator wit;

            for (wit = mMainWidgets.begin(); wit != mMainWidgets.end(); ++wit)
            {
                QWidget *w = *wit;
                ulong handle = extractHandle(w->objectName().toStdString());

                // If we have new "atoms" we search for it and update it
                if (iter->handle == handle && !iter->atoms.empty())
                {
                    QObjectList list = w->children();
                    QList<QObject *>::Iterator obit;
                    vector<PGSUBVIEWATOM_T>::iterator atit;

                    for (atit = iter->atoms.begin(); atit != iter->atoms.end(); ++atit)
                    {
                        for (obit = list.begin(); obit != list.end(); ++obit)
                        {
                            QObject *o = *obit;
                            QString obname = o->objectName();
                            ulong atHandle = extractHandle(obname.toStdString());

                            if (atit->handle == atHandle && obname.startsWith("Label_"))
                            {
                                QLabel *lbl = dynamic_cast<QLabel *>(o);
                                setAtom(*atit, lbl);
                                break;
                            }
                        }
                    }

                    break;
                }
            }

            break;
        }
    }
}

void TQScrollArea::showItem(ulong handle, int position)
{
    DECL_TRACER("TQScrollArea::showItem(ulong handle, int position)");

    if (mMainWidgets.empty())
        return;

    vector<QWidget *>::iterator iter;

    for (iter = mMainWidgets.begin(); iter != mMainWidgets.end(); ++iter)
    {
        QWidget *w = *iter;
        ulong h = extractHandle(w->objectName().toStdString());
        MSG_DEBUG("Evaluating item " << handleToString(h));

        if (h == handle)
        {
            int defPosX = 50;
            int defPosY = 50;

            if (position > 0 && position < 65535)
            {
                if (mVertical)
                {
                    defPosY = position;
                    defPosX = 0;
                }
                else
                {
                    defPosY = position;
                    defPosX = 0;
                }

                ensureWidgetVisible(w, defPosX, defPosY);
            }
            else if (mPosition == Button::SVP_LEFT_TOP)
            {
                if (mVertical)
                {
                    int top = w->geometry().y();
                    QScrollBar *bar = verticalScrollBar();

                    if (bar)
                        bar->setSliderPosition(top);
                }
                else
                {
                    int left = w->geometry().x();
                    QScrollBar *bar = horizontalScrollBar();

                    if (bar)
                        bar->setSliderPosition(left);
                }
            }
            else if (mPosition == Button::SVP_CENTER)
            {
                if (mVertical)
                {
                    int topMargin = (mHeight - w->geometry().height()) / 2;
                    int top = w->geometry().y() - topMargin;
                    QScrollBar *bar = verticalScrollBar();

                    if (bar)
                        bar->setSliderPosition(top);
                }
                else
                {
                    int leftMargin = (mWidth - w->geometry().width()) / 2;
                    int left = w->geometry().x() - leftMargin;
                    QScrollBar *bar = horizontalScrollBar();

                    if (bar)
                        bar->setSliderPosition(left);
                }
            }
            else if (mPosition == Button::SVP_RIGHT_BOTTOM)
            {
                if (mVertical)
                {
                    int bottom = w->geometry().y() + w->geometry().height();
                    QScrollBar *bar = verticalScrollBar();

                    if (bar)
                        bar->setSliderPosition(bottom);
                }
                else
                {
                    int right = w->geometry().x() + w->geometry().width();
                    QScrollBar *bar = horizontalScrollBar();

                    if (bar)
                        bar->setSliderPosition(right);
                }
            }

            break;
        }
    }
}

int TQScrollArea::scale(int value)
{
    DECL_TRACER("TQScrollArea::scale(int value)");

    if (mScaleFactor != 1.0)
        return (int)((double)value * mScaleFactor);

    return value;
}

void TQScrollArea::setScaleFactor(const double& factor)
{
    DECL_TRACER("TQScrollArea::setScaleFactor(const double& factor)");

    if (factor > 0.0 && factor != 1.0)
        mScaleFactor = factor;
}

void TQScrollArea::setAtom(PGSUBVIEWATOM_T& atom, QLabel *label)
{
    DECL_TRACER("TQScrollArea::setAtom(PGSUBVIEWATOM_T& atom, QLabel *label)");

    if (!label)
        return;

    int scaWidth = scale(atom.width);
    int scaHeight = scale(atom.height);
    QColor bg(qRgba(atom.bgcolor.red, atom.bgcolor.green, atom.bgcolor.blue, atom.bgcolor.alpha));

    if (atom.image.isValid())
    {
        QPixmap pix(scaWidth, scaHeight);

        if (atom.bgcolor.alpha == 0)
            pix.fill(Qt::transparent);
        else
            pix.fill(bg);

        QImage img(atom.image.getBitmap(), atom.image.getWidth(), atom.image.getHeight(), atom.image.getPixline(), QImage::Format_ARGB32);
        bool ret = false;

        if (mScaleFactor != 1.0)
        {
            QSize size(scaWidth, scaHeight);
            ret = pix.convertFromImage(img.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Scaled size
        }
        else
            ret = pix.convertFromImage(img);

        if (!ret || pix.isNull())
        {
            MSG_ERROR("Unable to create a pixmap out of an image!");
            return;
        }

        label->setPixmap(pix);
    }
    else
    {
        QPalette palette(label->palette());

        if (atom.bgcolor.alpha == 0)
            palette.setColor(QPalette::Window, Qt::transparent);
        else
            palette.setColor(QPalette::Window, bg);

        label->setPalette(palette);
    }

}

/*****************************************************************************
 * Signals and overwritten functions start here
 *****************************************************************************/
/*
bool TQScrollArea::event(QEvent* event)
{
    if (event->type() == QEvent::MouseMove && mMousePress)
    {
        if (mMousePressTimer && mMousePressTimer->isActive())
        {
            mMousePressTimer->stop();
            mClick = false;
        }

        QMouseEvent *me = static_cast<QMouseEvent*>(event);
        int move = 0;
        mMouseScroll = true;

        if (mVertical)
        {
            if (mOldPoint.y() != 0)
            {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
                move = me->pos().y() - mOldPoint.y();
#else
                move = me->position().y() - mOldPoint.y();
#endif
                QScrollBar *bar = verticalScrollBar();

                if (bar)
                {
                    int value = bar->value();
                    value += (move * -1);
                    bar->setValue(value);
                }
            }
        }
        else
        {
            if (mOldPoint.x() != 0)
            {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
                move = me->pos().x() - mOldPoint.x();
#else
                move = me->position().x() - mOldPoint.x();
#endif
                scrollContentsBy(move, 0);
                QScrollBar *bar = horizontalScrollBar();

                if (bar)
                {
                    int value = bar->value();
                    value += (move * -1);
                    bar->setValue(value);
                }
            }
        }
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        mOldPoint = me->pos();
#else
        mOldPoint = me->position();
#endif
    }

    return QScrollArea::event(event);
}
*/
void TQScrollArea::mouseMoveEvent(QMouseEvent* event)
{
    DECL_TRACER("TQScrollArea::mouseMoveEvent(QMouseEvent* event)");

    mMousePress = false;
    mMouseScroll = true;

    if (mMousePressTimer && mMousePressTimer->isActive())
        mMousePressTimer->stop();

    int move = 0;

    MSG_DEBUG("Scroll event at " << event->position().x() << "x" << event->position().y() << ", old point at " << mOldPoint.x() << "x" << mOldPoint.y());
    if (mVertical)
    {
        if (mOldPoint.y() != 0)
        {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
            move = me->pos().y() - mOldPoint.y();
#else
            move = event->position().y() - mOldPoint.y();
#endif
            QScrollBar *bar = verticalScrollBar();

            if (bar)
            {
                int value = bar->value();
                value += (move * -1);
                bar->setValue(value);
            }
        }
    }
    else
    {
        if (mOldPoint.x() != 0)
        {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
            move = me->pos().x() - mOldPoint.x();
#else
            move = event->position().x() - mOldPoint.x();
#endif
            QScrollBar *bar = horizontalScrollBar();

            if (bar)
            {
                int value = bar->value();
                int newValue = value + (move * -1);

                if (newValue >= 0 && newValue != value)
                    bar->setValue(newValue);

                MSG_DEBUG("Moving mouse to value " << newValue << " (old: " << value << "). Step is " << move);
            }
        }
    }

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    mOldPoint = me->pos();
#else
    mOldPoint = event->position();
#endif
}

void TQScrollArea::mousePressEvent(QMouseEvent* event)
{
    DECL_TRACER("TQScrollArea::mousePressEvent(QMouseEvent* event)");

    if (!event || mMouseScroll)
        return;

    if (event->button() == Qt::LeftButton)
    {
        mMousePress = true;
        mOldPoint.setX(0.0);
        mOldPoint.setY(0.0);

        int x = 0, y = 0;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        x = event->pos().x();
        y = event->pos().y();
#else
        x = event->position().x();
        y = event->position().y();
#endif
        mLastMousePress.setX(x);
        mLastMousePress.setY(y);

        MSG_DEBUG("Mouse press event at " << x << " x " << y << " // " << event->globalX() << " x " << event->globalY());
        /*
         * Here we're starting a timer with 200 ms. If after this time the
         * mouse button is still pressed and no scroll event was detected,
         * then we've a real click.
         * In case of a real click the method mouseTimerEvent() will call a
         * signal to inform the parent about the click.
         */
        mClick = true;

        if (!mMousePressTimer)
        {
            mMousePressTimer = new QTimer(this);
            connect(mMousePressTimer, &QTimer::timeout, this, &TQScrollArea::mouseTimerEvent);
        }

        mMousePressTimer->start(200);
    }
}

void TQScrollArea::mouseReleaseEvent(QMouseEvent* event)
{
    DECL_TRACER("TQScrollArea::mouseReleaseEvent(QMouseEvent* event)");

    if (!event)
        return;

    if(event->button() == Qt::LeftButton)
    {
        if (mMousePressTimer && mMousePressTimer->isActive())
        {
            mMousePressTimer->stop();

            if (!mMouseScroll)
            {
                mClick = true;
                mouseTimerEvent();
                mClick = false;
                mouseTimerEvent();
            }
        }
        else if (!mMouseScroll && mClick)
        {
            mClick = false;
            mouseTimerEvent();
        }

        mMousePress = false;
        mMouseScroll = false;
        mOldPoint.setX(0.0);
        mOldPoint.setY(0.0);
    }
}

void TQScrollArea::scrollContentsBy(int dx, int dy)
{
    DECL_TRACER("TQScrollArea::scrollContentsBy(int dx, int dy)");

    QScrollArea::scrollContentsBy(dx, dy);      // First let the original class do it's job.

    QScrollBar *sbar = nullptr;

    if (mVertical)
        sbar = verticalScrollBar();
    else
        sbar = horizontalScrollBar();

    if (sbar)
    {
        mActPosition = sbar->value();

        if (mScrollbar && mScrollbarOffset > 0 && mActPosition < mScrollbarOffset)
        {
            sbar->setSliderPosition(mScrollbarOffset);
            mActPosition = sbar->value();
        }
    }
}

void TQScrollArea::mouseTimerEvent()
{
    DECL_TRACER("TQScrollArea::mouseTimerEvent()");

    if (mMousePressTimer && mMousePressTimer->isActive())
        mMousePressTimer->stop();

    if (!mMousePress || mMouseScroll)
        return;

    if (mMain)
    {
        QWidget *w = nullptr;

        if (mVertical)
            w = mMain->childAt(mLastMousePress.x(), mActPosition + mLastMousePress.y());
        else
            w = mMain->childAt(mActPosition + mLastMousePress.x(), mLastMousePress.y());

        if (w)
        {
            QString obname = w->objectName();
            ulong handle = extractHandle(obname.toStdString());

            if (!handle)
                return;

            // We must make sure the found object is not marked as pass through.
            // Because of this we'll scan the items for the handle and if we
            // find that it is marked as pass through we must look for another
            // one on the same position. If there is none, the click is ignored.
            //
            // Find the object in our list
            vector<PGSUBVIEWITEM_T>::iterator iter;
            QRect rect;
            bool call = true;

            for (iter = mItems.begin(); iter != mItems.end(); ++iter)
            {
                if (iter->handle == handle)     // Handle found?
                {                               // Yes, then ...
                    if (iter->bounding == "passThru")   // Item marked as pass through?
                    {                                   // Yes, then start to search for another item
                        rect = w->rect();
                        call = false;
                        // Walk through the childs to find another one on the
                        // clicked position.
                        QObjectList ol = mMain->children(); // Get list of all objects
                        QList<QObject *>::iterator obiter;  // Define an iterator
                        // Loop through all objects
                        for (obiter = ol.begin(); obiter != ol.end(); ++obiter)
                        {
                            QObject *object = *obiter;

                            if (object->objectName() != obname && object->objectName().startsWith("Label_"))    // Have we found a QLabel object?
                            {                                                                                   // Yes, then test it's position
                                QLabel *lb = dynamic_cast<QLabel *>(object);    // Cast the object to a QLabel

                                if (lb->rect().contains(mLastMousePress))       // Is the QLabel under the mouse coordinates?
                                {                                               // Yes, then select it.
                                    ulong h = extractHandle(lb->objectName().toStdString());  // Get the handle

                                    if (!h)
                                        break;

                                    handle = h;
                                    // Reset the main loop
                                    iter = mItems.begin();
                                    break;
                                }
                            }
                        }
                    }
                    else
                        call = true;
                }
            }

            if (call)
            {
                MSG_DEBUG("Calling signal with handle " << (handle >> 16 & 0x0000ffff) << ":" << (handle & 0x0000ffff) << ": STATE=" << (mClick ? "PRESSED" : "RELEASED"));
                emit objectClicked(handle, mClick);
            }
        }
    }
}