- Qt 5.5
- Qt Widgets
- Tool Tips Example
- sortingbox.cpp Example File
- Qt 5.5.1 Reference Documentation

# sortingbox.cpp Example File

widgets/tooltips/sortingbox.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** You may use this file under the terms of the BSD license as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/

    #include <QtWidgets>

    #include <stdlib.h>

    #include "sortingbox.h"

    SortingBox::SortingBox()
    {
        setMouseTracking(true);
        setBackgroundRole(QPalette::Base);

        itemInMotion = 0;

        newCircleButton = createToolButton(tr("New Circle"),
                                           QIcon(":/images/circle.png"),
                                           SLOT(createNewCircle()));

        newSquareButton = createToolButton(tr("New Square"),
                                           QIcon(":/images/square.png"),
                                           SLOT(createNewSquare()));

        newTriangleButton = createToolButton(tr("New Triangle"),
                                             QIcon(":/images/triangle.png"),
                                             SLOT(createNewTriangle()));

        circlePath.addEllipse(QRect(0, 0, 100, 100));
        squarePath.addRect(QRect(0, 0, 100, 100));

        qreal x = trianglePath.currentPosition().x();
        qreal y = trianglePath.currentPosition().y();
        trianglePath.moveTo(x + 120 / 2, y);
        trianglePath.lineTo(0, 100);
        trianglePath.lineTo(120, 100);
        trianglePath.lineTo(x + 120 / 2, y);

        setWindowTitle(tr("Tool Tips"));
        resize(500, 300);

        createShapeItem(circlePath, tr("Circle"), initialItemPosition(circlePath),
                        initialItemColor());
        createShapeItem(squarePath, tr("Square"), initialItemPosition(squarePath),
                        initialItemColor());
        createShapeItem(trianglePath, tr("Triangle"),
                        initialItemPosition(trianglePath), initialItemColor());
    }

    bool SortingBox::event(QEvent *event)
    {
        if (event->type() == QEvent::ToolTip) {
            QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
            int index = itemAt(helpEvent->pos());
            if (index != -1) {
                QToolTip::showText(helpEvent->globalPos(), shapeItems[index].toolTip());
            } else {
                QToolTip::hideText();
                event->ignore();
            }

            return true;
        }
        return QWidget::event(event);
    }

    void SortingBox::resizeEvent(QResizeEvent * /* event */)
    {
        int margin = style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin);
        int x = width() - margin;
        int y = height() - margin;

        y = updateButtonGeometry(newCircleButton, x, y);
        y = updateButtonGeometry(newSquareButton, x, y);
        updateButtonGeometry(newTriangleButton, x, y);
    }

    void SortingBox::paintEvent(QPaintEvent * /* event */)
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        foreach (ShapeItem shapeItem, shapeItems) {
            painter.translate(shapeItem.position());
            painter.setBrush(shapeItem.color());
            painter.drawPath(shapeItem.path());
            painter.translate(-shapeItem.position());
        }
    }

    void SortingBox::mousePressEvent(QMouseEvent *event)
    {
        if (event->button() == Qt::LeftButton) {
            int index = itemAt(event->pos());
            if (index != -1) {
                itemInMotion = &shapeItems[index];
                previousPosition = event->pos();
                shapeItems.move(index, shapeItems.size() - 1);
                update();
            }
        }
    }

    void SortingBox::mouseMoveEvent(QMouseEvent *event)
    {
        if ((event->buttons() & Qt::LeftButton) && itemInMotion)
            moveItemTo(event->pos());
    }

    void SortingBox::mouseReleaseEvent(QMouseEvent *event)
    {
        if (event->button() == Qt::LeftButton && itemInMotion) {
            moveItemTo(event->pos());
            itemInMotion = 0;
        }
    }

    void SortingBox::createNewCircle()
    {
        static int count = 1;
        createShapeItem(circlePath, tr("Circle <%1>").arg(++count),
                        randomItemPosition(), randomItemColor());
    }

    void SortingBox::createNewSquare()
    {
        static int count = 1;
        createShapeItem(squarePath, tr("Square <%1>").arg(++count),
                        randomItemPosition(), randomItemColor());
    }

    void SortingBox::createNewTriangle()
    {
        static int count = 1;
        createShapeItem(trianglePath, tr("Triangle <%1>").arg(++count),
                        randomItemPosition(), randomItemColor());
    }

    int SortingBox::itemAt(const QPoint &pos)
    {
        for (int i = shapeItems.size() - 1; i >= 0; --i) {
            const ShapeItem &item = shapeItems[i];
            if (item.path().contains(pos - item.position()))
                return i;
        }
        return -1;
    }

    void SortingBox::moveItemTo(const QPoint &pos)
    {
        QPoint offset = pos - previousPosition;
        itemInMotion->setPosition(itemInMotion->position() + offset);
        previousPosition = pos;
        update();
    }

    int SortingBox::updateButtonGeometry(QToolButton *button, int x, int y)
    {
        QSize size = button->sizeHint();
        button->setGeometry(x - size.rwidth(), y - size.rheight(),
                            size.rwidth(), size.rheight());

        return y - size.rheight()
               - style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
    }

    void SortingBox::createShapeItem(const QPainterPath &path,
                                     const QString &toolTip, const QPoint &pos,
                                     const QColor &color)
    {
        ShapeItem shapeItem;
        shapeItem.setPath(path);
        shapeItem.setToolTip(toolTip);
        shapeItem.setPosition(pos);
        shapeItem.setColor(color);
        shapeItems.append(shapeItem);
        update();
    }

    QToolButton *SortingBox::createToolButton(const QString &toolTip,
                                              const QIcon &icon, const char *member)
    {
        QToolButton *button = new QToolButton(this);
        button->setToolTip(toolTip);
        button->setIcon(icon);
        button->setIconSize(QSize(32, 32));
        connect(button, SIGNAL(clicked()), this, member);

        return button;
    }

    QPoint SortingBox::initialItemPosition(const QPainterPath &path)
    {
        int x;
        int y = (height() - (int)path.controlPointRect().height()) / 2;
        if (shapeItems.size() == 0)
            x = ((3 * width()) / 2 - (int)path.controlPointRect().width()) / 2;
        else
            x = (width() / shapeItems.size()
                 - (int)path.controlPointRect().width()) / 2;

        return QPoint(x, y);
    }

    QPoint SortingBox::randomItemPosition()
    {
        return QPoint(qrand() % (width() - 120), qrand() % (height() - 120));
    }

    QColor SortingBox::initialItemColor()
    {
        return QColor::fromHsv(((shapeItems.size() + 1) * 85) % 256, 255, 190);
    }

    QColor SortingBox::randomItemColor()
    {
        return QColor::fromHsv(qrand() % 256, 255, 190);
    }