widget.cpp Example File

nesteddonuts/widget.cpp

  /****************************************************************************
  **
  ** Copyright (C) 2016 The Qt Company Ltd.
  ** Contact: https://www.qt.io/licensing/
  **
  ** This file is part of the Qt Charts module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:GPL$
  ** 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.
  **
  ** GNU General Public License Usage
  ** Alternatively, this file may be used under the terms of the GNU
  ** General Public License version 3 or (at your option) any later version
  ** approved by the KDE Free Qt Foundation. The licenses are as published by
  ** the Free Software Foundation and appearing in the file LICENSE.GPL3
  ** included in the packaging of this file. Please review the following
  ** information to ensure the GNU General Public License requirements will
  ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
  **
  ** $QT_END_LICENSE$
  **
  ****************************************************************************/
  #include "widget.h"
  #include <QtCharts/QChartView>
  #include <QtCharts/QChart>
  #include <QtCharts/QLegend>
  #include <QtCharts/QPieSeries>
  #include <QtCharts/QPieSlice>
  #include <QtCore/QTime>
  #include <QtWidgets/QGridLayout>
  #include <QtCore/QTimer>

  QT_CHARTS_USE_NAMESPACE

  Widget::Widget(QWidget *parent)
      : QWidget(parent)
  {
      setMinimumSize(800, 600);
      qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));

      QChartView *chartView = new QChartView;
      chartView->setRenderHint(QPainter::Antialiasing);
      QChart *chart = chartView->chart();
      chart->legend()->setVisible(false);
      chart->setTitle("Nested donuts demo");
      chart->setAnimationOptions(QChart::AllAnimations);

      qreal minSize = 0.1;
      qreal maxSize = 0.9;
      int donutCount = 5;

      for (int i = 0; i < donutCount; i++) {
          QPieSeries *donut = new QPieSeries;
          int sliceCount =  3 + qrand() % 3;
          for (int j = 0; j < sliceCount; j++) {
              qreal value = 100 + qrand() % 100;
              QPieSlice *slice = new QPieSlice(QString("%1").arg(value), value);
              slice->setLabelVisible(true);
              slice->setLabelColor(Qt::white);
              slice->setLabelPosition(QPieSlice::LabelInsideTangential);
              connect(slice, SIGNAL(hovered(bool)), this, SLOT(explodeSlice(bool)));
              donut->append(slice);
              donut->setHoleSize(minSize + i * (maxSize - minSize) / donutCount);
              donut->setPieSize(minSize + (i + 1) * (maxSize - minSize) / donutCount);
          }
          m_donuts.append(donut);
          chartView->chart()->addSeries(donut);
      }

      // create main layout
      QGridLayout *mainLayout = new QGridLayout;
      mainLayout->addWidget(chartView, 1, 1);
      setLayout(mainLayout);

      updateTimer = new QTimer(this);
      connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateRotation()));
      updateTimer->start(1250);
  }

  Widget::~Widget()
  {

  }

  void Widget::updateRotation()
  {
      for (int i = 0; i < m_donuts.count(); i++) {
          QPieSeries *donut = m_donuts.at(i);
          qreal phaseShift =  -50 + qrand() % 100;
          donut->setPieStartAngle(donut->pieStartAngle() + phaseShift);
          donut->setPieEndAngle(donut->pieEndAngle() + phaseShift);
      }
  }

  void Widget::explodeSlice(bool exploded)
  {
      QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
      if (exploded) {
          updateTimer->stop();
          qreal sliceStartAngle = slice->startAngle();
          qreal sliceEndAngle = slice->startAngle() + slice->angleSpan();

          QPieSeries *donut = slice->series();
          qreal seriesIndex = m_donuts.indexOf(donut);
          for (int i = seriesIndex + 1; i < m_donuts.count(); i++) {
              m_donuts.at(i)->setPieStartAngle(sliceEndAngle);
              m_donuts.at(i)->setPieEndAngle(360 + sliceStartAngle);
          }
      } else {
          for (int i = 0; i < m_donuts.count(); i++) {
              m_donuts.at(i)->setPieStartAngle(0);
              m_donuts.at(i)->setPieEndAngle(360);
          }
          updateTimer->start();
      }
      slice->setExploded(exploded);
  }