kchart

KDChart.cpp

00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003    */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2001-2003 Klar�vdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KDChart library.
00009  **
00010  ** This file may be distributed and/or modified under the terms of the
00011  ** GNU General Public License version 2 as published by the Free Software
00012  ** Foundation and appearing in the file LICENSE.GPL included in the
00013  ** packaging of this file.
00014  **
00015  ** Licensees holding valid commercial KDChart licenses may use this file in
00016  ** accordance with the KDChart Commercial License Agreement provided with
00017  ** the Software.
00018  **
00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021  **
00022  ** See http://www.klaralvdalens-datakonsult.se/?page=products for
00023  **   information about KDChart Commercial License Agreements.
00024  **
00025  ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 
00033 #include <KDChart.h>
00034 #include <KDChartPainter.h>
00035 #include <KDChartParams.h>
00036 #include <KDChartGlobal.h>
00037 #include <KDChartAxisParams.h>
00038 
00039 #include <qglobal.h>
00040 #include <qpainter.h>
00041 #include <qpaintdevice.h>
00042 #include <qpaintdevicemetrics.h>
00043 
00064 KDChartParams* KDChart::oldParams = 0;
00065 KDChartPainter* KDChart::cpainter = 0;
00066 KDChartPainter* KDChart::cpainter2 = 0;
00067 KDChartParams::ChartType KDChart::cpainterType = KDChartParams::NoType;
00068 KDChartParams::ChartType KDChart::cpainterType2 = KDChartParams::NoType;
00069 
00074 void cleanupPainter();
00075 
00076 
00077 bool hasCartesianAxes( KDChartParams::ChartType chartType )
00078 {
00079     switch( chartType ){
00080         case KDChartParams::NoType:     return false;
00081         case KDChartParams::Bar:        return true;
00082         case KDChartParams::Line:       return true;
00083         case KDChartParams::Area:       return true;
00084         case KDChartParams::Pie:        return false;
00085         case KDChartParams::HiLo:       return true;
00086         case KDChartParams::Ring:       return false;
00087         case KDChartParams::Polar:      return false; // Polar axes are NO cartesian axes!
00088         case KDChartParams::BoxWhisker: return true;
00089         default:
00090                                         qDebug("\n\n\n\nKDCHART ERROR: Type missing in KDChart.cpp hasCartesianAxes()\n"
00091                                                 "=============================================================\n"
00092                                                 "=============================================================\n\n\n\n");
00093     }
00094     return false;
00095 }
00096 
00097 
00111 bool KDChart::painterToDrawRect( QPainter* painter, QRect& drawRect )
00112 {
00113     if( painter ){
00114         QPaintDeviceMetrics painterMetrics( painter->device() );
00115         drawRect = QRect( 0, 0, painterMetrics.width(), painterMetrics.height() );
00116         drawRect.setWidth(  drawRect.width() -2 );
00117         drawRect.setHeight( drawRect.height()-2 );
00118         return true;
00119     }else{
00120         drawRect = QRect( QPoint(0,0), QSize(0,0) );
00121         qDebug("ERROR: KDChartPainter::painterToDrawRect() was called with *no* painter.");
00122         return false;
00123     }
00124 }
00125 
00126 
00145 bool KDChart::setupGeometry( QPainter* painter,
00146                              KDChartParams* params,
00147                              KDChartTableDataBase* data,
00148                              const QRect& drawRect )
00149 {
00150 //qDebug("INVOKING: KDChart::setupGeometry()");
00151     if( !params ){
00152         qDebug("ERROR: setupGeometry::paint() was called with *no* params.");
00153         return false;
00154     }
00155     if( !data ){
00156         qDebug("ERROR: setupGeometry::paint() was called with *no* data.");
00157         return false;
00158     }
00159     // don't crash due to memory problems when running on windows
00160 #ifdef Q_WS_WIN
00161     QPixmap::setDefaultOptimization(QPixmap::MemoryOptim);
00162 #endif
00163 
00164     // Install a cleanup routine that is called when the Qt
00165     // application shuts down and cleans up any potentially still
00166     // existing painters. Only do this once.
00167     static bool bFirstCleanUpInstall = true;
00168     if( bFirstCleanUpInstall ) {
00169         bFirstCleanUpInstall = false;
00170         qAddPostRoutine( cleanupPainter );
00171     }
00172 
00173     // Check whether last call of this methode gave us the same params pointer.
00174     // If params changed we must create new painter(s).
00175     bool paramsHasChanged = ( params != oldParams );
00176     if( paramsHasChanged )
00177         oldParams = params;
00178 
00179     // Check whether there already is painter and, if that is the
00180     // case, whether the painter still has the correct type (the chart
00181     // type might have changed in the meantime).
00182     if ( paramsHasChanged || !cpainter || cpainterType != params->chartType() )
00183     {
00184         delete cpainter; /* save, since always 0 if there was not yet
00185                             a chart painter */
00186         // create a new painter
00187         cpainter = KDChartPainter::create( params, false );
00188         cpainterType = params->chartType();
00189     }
00190 
00191     // Check whether there already is a 2nd painter and, if that is the
00192     // case, whether the painter still has the correct type (the
00193     // additional chart type might have changed in the meantime).
00194     if ( paramsHasChanged || !cpainter2 || cpainterType2 != params->additionalChartType() )
00195     {
00196         delete cpainter2; /* save, since always 0 if there was not yet
00197                              a chart painter */
00198         // create a new painter
00199         if( hasCartesianAxes( params->chartType() )
00200                 && hasCartesianAxes( params->additionalChartType() ) ){
00201             cpainter2 = KDChartPainter::create( params, true );
00202             cpainterType2 = params->additionalChartType();
00203         }else{
00204             cpainter2 = 0;
00205             cpainterType2 = KDChartParams::NoType;
00206         }
00207     }
00208 
00209     if ( cpainter ){  // can be 0 if no exceptions are used
00210         cpainter->setupGeometry( painter, data, drawRect );
00211     }
00212 
00213     if ( cpainter2 ){  // can be 0 if no exceptions are used
00214         cpainter2->setupGeometry( painter, data, drawRect );
00215     }
00216 
00217     return true;
00218 }
00219 
00238 void KDChart::paint( QPainter*              painter,
00239                      KDChartParams*         paraParams,
00240                      KDChartTableDataBase*  paraData,
00241                      KDChartDataRegionList* regions,
00242                      const QRect*           rect,
00243                      bool                   mustCalculateGeometry )
00244 {
00245 //qDebug("KDChart::paint() mustCalculateGeometry: "+QString(mustCalculateGeometry?"TRUE":"FALSE") );
00246 #if defined KDAB_EVAL
00247     EvalDialog::checkEvalLicense( "KD Chart" );
00248 #endif
00249 
00250     KDChartParams*        params = paraParams;
00251     KDChartTableDataBase* data   = paraData;
00252     if( !paraParams && !paraData ){
00253         qDebug("-----");
00254         qDebug("Note:  KDChart::paint() was called without \"params\" and without \"data\".");
00255         qDebug("-----  Showing a default bar chart.");
00256         params = new KDChartParams();
00257         params->setDatasetGap(3 * params->valueBlockGap());
00258         params->setPrintDataValues( false );
00259         params->setLegendPosition( KDChartParams::NoLegend );
00260         params->setAxisLabelsVisible( KDChartAxisParams::AxisPosBottom, false );
00261         params->setAxisShowGrid( KDChartAxisParams::AxisPosBottom, false );
00262         params->setHeader1Text( "KDChartWidget" );
00263         data = new KDChartTableData( 3, 1 );
00264         // 1st series
00265         data->setCell( 0, 0,    12.5   );
00266         // 2nd series
00267         data->setCell( 1, 0,     8.0   );
00268         // 3rd series
00269         data->setCell( 2, 0,    15.0   );
00270     }
00271 
00272     QRect drawRect;
00273     bool bOk = true;
00274     if( mustCalculateGeometry || !cpainter || cpainter->outermostRect().isNull() ){
00275         if( rect )
00276             drawRect = *rect;
00277         else if( !painterToDrawRect( painter, drawRect ) ){
00278             qDebug("ERROR: KDChart::paint() could not calculate a drawing area.");
00279             bOk = false;
00280         }
00281         //qDebug("xxx" );
00282         if( (params || data) && !setupGeometry( painter, params, data, drawRect ) ){
00283             qDebug("ERROR: KDChart::paint() could not calculate the chart geometry.");
00284             bOk = false;
00285         }
00286     }else{
00287         drawRect = cpainter->outermostRect();
00288     }
00289 
00290     //qDebug("yyy" );
00291 
00292     if( bOk ){
00293         // Note: the following *must* paint the main-chart first
00294         //       and the additional chart afterwards
00295         //       since all axes computations are only done when
00296         //       the first chart is painted but will be needed for both of course.
00297         //
00298         bool paintFirst = true;
00299         bool paintLast  = ! ( cpainter && cpainter2 );
00300         if ( cpainter ) {  // can be 0 if no exceptions are used
00301             //qDebug("zzz" );
00302             cpainter->paint( painter, data, paintFirst, paintLast, regions, &drawRect, false );
00303 
00304             paintFirst = false;
00305         }
00306         paintLast = true;
00307         if ( cpainter2 )   // can be 0 if no exceptions are used
00308             cpainter2->paint( painter, data, paintFirst, paintLast, regions, &drawRect, false );
00309     }
00310 
00311     if( !paraParams && !paraData ){
00312         delete params;
00313         delete data;
00314     }
00315     KDChartAutoColor::freeInstance(); // stuff that memory leak
00316 }
00317 
00318 
00332 void KDChart::print( QPainter* painter, KDChartParams* params,
00333         KDChartTableDataBase* data,
00334         KDChartDataRegionList* regions,
00335         const QRect* rect,
00336         bool mustCalculateGeometry )
00337 {
00338     bool oldOpt=true;
00339     if( params ){
00340         oldOpt = params->optimizeOutputForScreen();
00341         params->setOptimizeOutputForScreen( false );
00342     }
00343     paint( painter, params, data, regions, rect, mustCalculateGeometry );
00344     if( params )
00345         params->setOptimizeOutputForScreen( oldOpt );
00346 }
00347 
00348 
00349 /*
00350    This method is called at application shut-down and cleans up the
00351    last created painter.
00352    */
00353 void cleanupPainter()
00354 {
00355     delete KDChart::cpainter;
00356     delete KDChart::cpainter2;
00357     KDChart::oldParams = 0;
00358 }
KDE Home | KDE Accessibility Home | Description of Access Keys