File indexing completed on 2024-06-16 04:09:02

0001 /**
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include <QApplication>
0010 #include <QStandardItemModel>
0011 #include <QTreeView>
0012 #include <QTimer>
0013 #include <QWidget>
0014 #include <QSplitter>
0015 #include <QPushButton>
0016 
0017 #include <math.h>
0018 
0019 #include <KChartChart>
0020 #include <KChartPlotter>
0021 
0022 #include "timeaxis.h"
0023 #include "timechartmodel.h"
0024 
0025 class ChartWidget : public QWidget {
0026     Q_OBJECT
0027 public:
0028     explicit ChartWidget(QWidget* parent = nullptr) : QWidget(parent), m_counter(0) {
0029         QSplitter* splitter = new QSplitter(this);
0030         QHBoxLayout* l = new QHBoxLayout(this);
0031         setLayout(l);
0032         l->addWidget( splitter );
0033 
0034         QWidget* leftWidget = new QWidget( splitter );
0035         QVBoxLayout* leftLayout = new QVBoxLayout(leftWidget);
0036         leftWidget->setLayout(leftLayout);
0037         
0038         QPushButton* button = new QPushButton("Animate", leftWidget);
0039         leftLayout->addWidget( button );
0040         button->setCheckable( true );
0041         connect( button, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)) );
0042 
0043         QTreeView* tv = new QTreeView( leftWidget );
0044         leftLayout->addWidget( tv );
0045 
0046         m_chart = new KChart::Chart( splitter );
0047         
0048         m_model = new QStandardItemModel( 365, 2, this );
0049         for ( int i = 0; i < 365; ++i ) {
0050             const QDateTime dt = QDateTime( QDate( 2010, 1, 1 ), QTime() );
0051             m_model->setData( m_model->index( i, 0 ), dt.addDays( i ) );
0052             m_model->setData( m_model->index( i, 1 ), sin( i / 10.0 ) * 10 );
0053         }
0054 
0055         TimeChartModel* proxy = new TimeChartModel( this );
0056         proxy->setSourceModel( m_model );
0057         proxy->setVisibleRange( QDateTime( QDate( 2010, 2, 1 ), QTime() ),
0058                                 QDateTime( QDate( 2010, 3, 31 ), QTime() ) );
0059 
0060         KChart::Plotter* plotter = new KChart::Plotter;
0061         m_chart->coordinatePlane()->replaceDiagram( plotter );
0062 
0063         tv->setModel( proxy );
0064         tv->show();
0065 
0066         TimeAxis* axis = new TimeAxis( plotter );
0067         axis->setPosition( TimeAxis::Bottom );
0068         plotter->addAxis( axis );
0069 
0070         plotter->setModel( proxy );
0071 
0072         connect( proxy, SIGNAL(rowsInserted(QModelIndex,int,int)),
0073                  m_chart->coordinatePlane(), SLOT(adjustRangesToData()) );
0074         connect( proxy, SIGNAL(rowsRemoved(QModelIndex,int,int)),
0075                  m_chart->coordinatePlane(), SLOT(adjustRangesToData()) );
0076 
0077         proxy->setVisibleRange( QDateTime( QDate( 2010, 3, 15 ), QTime() ),
0078                                 QDateTime( QDate( 2010, 5, 18 ), QTime() ) );
0079         qobject_cast< KChart::CartesianCoordinatePlane* >( m_chart->coordinatePlane() )->adjustRangesToData();
0080 
0081         m_timer = new QTimer(this);
0082         connect( m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()) );
0083     }
0084 private Q_SLOTS:
0085     void slotTimeout() {
0086 
0087         // An ugly hack to prevent the QAbstractItemModel from emitting dataChanged
0088         // for every single call to setData which would result in a full relayout
0089         // every time. That is horrible for performance and what we do is we prevent
0090         // QAbstractItemModel from emitting dataChanged, we collect what data changed and
0091         // we emit the signal at the end ourself.
0092         m_model->blockSignals(true);
0093         QModelIndexList indexes;
0094 
0095         for ( int i = 0; i < 365; ++i ) {
0096             QModelIndex idx = m_model->index( i, 1 );
0097             indexes.append(idx);
0098             m_model->setData( idx, sin( i / 10.0 + m_counter ) * 10 );
0099         }
0100 
0101         m_model->blockSignals(false);
0102         if (!indexes.isEmpty()) {
0103             m_model->metaObject()->invokeMethod(m_model, "dataChanged", Qt::DirectConnection, Q_ARG(QModelIndex,indexes.first()), Q_ARG(QModelIndex,indexes.last()));
0104         }
0105 
0106         m_counter += 0.02;
0107     }
0108     void buttonToggled(bool checked) {
0109         if (checked)
0110             m_timer->start( 200 );
0111         else
0112             m_timer->stop();
0113     }
0114 private:
0115     KChart::Chart* m_chart;
0116     QStandardItemModel* m_model;
0117     QTimer* m_timer;
0118     qreal m_counter;
0119 };
0120 
0121 /**
0122  * This example demonstrates how to use time-based plots with timestamp-value data points
0123  * based on seconds and how to use a proxy model for defining the plotted "window" of the
0124  * measurement data.
0125  */
0126 int main( int argc, char* argv[] )
0127 {
0128     QApplication app( argc, argv );
0129     
0130     ChartWidget w;
0131     w.show();
0132 
0133     return app.exec();
0134 }
0135 
0136 #include "main.moc"