Qt 5.11 | Qt Widgets | Tool Tips Example | sortingbox.cpp Example File

Qt 5.11.3 Reference Documentation

# sortingbox.cpp Example File

widgets/tooltips/sortingbox.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, 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(QRandomGenerator::global()->bounded(width() - 120), QRandomGenerator::global()->bounded(height() - 120));
      }

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

      QColor SortingBox::randomItemColor()
      {
          return QColor::fromHsv(QRandomGenerator::global()->bounded(256), 255, 190);
      }