File indexing completed on 2024-06-23 04:17:57
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"