00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KDChartAbstractCoordinatePlane.h"
00024 #include "KDChartAbstractCoordinatePlane_p.h"
00025
00026 #include <QGridLayout>
00027 #include <QRubberBand>
00028 #include <QMouseEvent>
00029
00030 #include "KDChartChart.h"
00031 #include "KDChartGridAttributes.h"
00032
00033 #include <KDABLibFakes>
00034
00035
00036 using namespace KDChart;
00037
00038 #define d d_func()
00039
00040 AbstractCoordinatePlane::Private::Private()
00041 : AbstractArea::Private()
00042 , parent( 0 )
00043 , grid( 0 )
00044 , referenceCoordinatePlane( 0 )
00045 , enableRubberBandZooming( false )
00046 , rubberBand( 0 )
00047 {
00048
00049 }
00050
00051
00052 AbstractCoordinatePlane::AbstractCoordinatePlane ( KDChart::Chart* parent )
00053 : AbstractArea ( new Private() )
00054 {
00055 d->parent = parent;
00056 d->init();
00057 }
00058
00059 AbstractCoordinatePlane::~AbstractCoordinatePlane()
00060 {
00061 emit destroyedCoordinatePlane( this );
00062 }
00063
00064 void AbstractCoordinatePlane::init()
00065 {
00066 d->initialize();
00067 connect( this, SIGNAL(internal_geometryChanged( QRect, QRect )),
00068 this, SIGNAL(geometryChanged( QRect, QRect )),
00069 Qt::QueuedConnection );
00070 }
00071
00072 void AbstractCoordinatePlane::addDiagram ( AbstractDiagram* diagram )
00073 {
00074
00075 diagram->hide();
00076
00077 d->diagrams.append( diagram );
00078 diagram->setParent( d->parent );
00079 diagram->setCoordinatePlane( this );
00080 layoutDiagrams();
00081 layoutPlanes();
00082 connect( diagram, SIGNAL( modelsChanged() ), this, SLOT( layoutPlanes() ) );
00083 connect( diagram, SIGNAL( modelDataChanged() ), this, SLOT( update()) );
00084 connect( diagram, SIGNAL( modelDataChanged() ), this, SLOT( relayout()) );
00085
00086 update();
00087 }
00088
00089
00090 void AbstractCoordinatePlane::replaceDiagram ( AbstractDiagram* diagram, AbstractDiagram* oldDiagram_ )
00091 {
00092 if( diagram && oldDiagram_ != diagram ){
00093 AbstractDiagram* oldDiagram = oldDiagram_;
00094 if( d->diagrams.count() ){
00095 if( ! oldDiagram ){
00096 oldDiagram = d->diagrams.first();
00097 if( oldDiagram == diagram )
00098 return;
00099 }
00100 takeDiagram( oldDiagram );
00101 }
00102 delete oldDiagram;
00103 addDiagram( diagram );
00104 layoutDiagrams();
00105 layoutPlanes();
00106 update();
00107 }
00108 }
00109
00110
00111 void AbstractCoordinatePlane::takeDiagram ( AbstractDiagram* diagram )
00112 {
00113 const int idx = d->diagrams.indexOf( diagram );
00114 if( idx != -1 ){
00115 d->diagrams.removeAt( idx );
00116 diagram->setParent( 0 );
00117 diagram->setCoordinatePlane( 0 );
00118 disconnect( diagram, SIGNAL( modelsChanged() ), this, SLOT( layoutPlanes() ) );
00119 disconnect( diagram, SIGNAL( modelDataChanged() ), this, SLOT( update()) );
00120 layoutDiagrams();
00121 update();
00122 }
00123 }
00124
00125
00126 AbstractDiagram* AbstractCoordinatePlane::diagram()
00127 {
00128 if ( d->diagrams.isEmpty() )
00129 {
00130 return 0;
00131 } else {
00132 return d->diagrams.first();
00133 }
00134 }
00135
00136 AbstractDiagramList AbstractCoordinatePlane::diagrams()
00137 {
00138 return d->diagrams;
00139 }
00140
00141 ConstAbstractDiagramList AbstractCoordinatePlane::diagrams() const
00142 {
00143 ConstAbstractDiagramList list;
00144 #ifndef QT_NO_STL
00145 qCopy( d->diagrams.begin(), d->diagrams.end(), std::back_inserter( list ) );
00146 #else
00147 Q_FOREACH( AbstractDiagram * a, d->diagrams )
00148 list.push_back( a );
00149 #endif
00150 return list;
00151 }
00152
00153 QSize KDChart::AbstractCoordinatePlane::minimumSizeHint() const
00154 {
00155 return QSize( 200, 200 );
00156 }
00157
00158
00159 QSizePolicy KDChart::AbstractCoordinatePlane::sizePolicy() const
00160 {
00161 return QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
00162 }
00163
00164 void KDChart::AbstractCoordinatePlane::setGlobalGridAttributes( const GridAttributes& a )
00165 {
00166 d->gridAttributes = a;
00167 update();
00168 }
00169
00170 GridAttributes KDChart::AbstractCoordinatePlane::globalGridAttributes() const
00171 {
00172 return d->gridAttributes;
00173 }
00174
00175 KDChart::DataDimensionsList KDChart::AbstractCoordinatePlane::gridDimensionsList()
00176 {
00177
00178
00179
00180 return d->grid->updateData( this );
00181 }
00182
00183 void KDChart::AbstractCoordinatePlane::setGridNeedsRecalculate()
00184 {
00185 d->grid->setNeedRecalculate();
00186 }
00187
00188 void KDChart::AbstractCoordinatePlane::setReferenceCoordinatePlane( AbstractCoordinatePlane * plane )
00189 {
00190 d->referenceCoordinatePlane = plane;
00191 }
00192
00193 AbstractCoordinatePlane * KDChart::AbstractCoordinatePlane::referenceCoordinatePlane( ) const
00194 {
00195 return d->referenceCoordinatePlane;
00196 }
00197
00198 void KDChart::AbstractCoordinatePlane::setParent( KDChart::Chart* parent )
00199 {
00200 d->parent = parent;
00201 }
00202
00203 const KDChart::Chart* KDChart::AbstractCoordinatePlane::parent() const
00204 {
00205 return d->parent;
00206 }
00207
00208 KDChart::Chart* KDChart::AbstractCoordinatePlane::parent()
00209 {
00210 return d->parent;
00211 }
00212
00213
00214 bool KDChart::AbstractCoordinatePlane::isEmpty() const
00215 {
00216 return false;
00217
00218
00219 }
00220
00221 Qt::Orientations KDChart::AbstractCoordinatePlane::expandingDirections() const
00222 {
00223 return Qt::Vertical | Qt::Horizontal;
00224 }
00225
00226 QSize KDChart::AbstractCoordinatePlane::maximumSize() const
00227 {
00228
00229
00230 return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
00231 }
00232
00233 QSize KDChart::AbstractCoordinatePlane::minimumSize() const
00234 {
00235 return QSize(60, 60);
00236 }
00237
00238 QSize KDChart::AbstractCoordinatePlane::sizeHint() const
00239 {
00240
00241
00242 return maximumSize();
00243 }
00244
00245 void KDChart::AbstractCoordinatePlane::setGeometry( const QRect& r )
00246 {
00247
00248 if( d->geometry != r ){
00249
00250
00251
00252 emit internal_geometryChanged( d->geometry, r );
00253
00254 d->geometry = r;
00255
00256
00257
00258 }
00259 }
00260
00261 QRect KDChart::AbstractCoordinatePlane::geometry() const
00262 {
00263 return d->geometry;
00264 }
00265
00266 void KDChart::AbstractCoordinatePlane::update()
00267 {
00268
00269 emit needUpdate();
00270 }
00271
00272 void KDChart::AbstractCoordinatePlane::relayout()
00273 {
00274
00275 emit needRelayout();
00276 }
00277
00278 void KDChart::AbstractCoordinatePlane::layoutPlanes()
00279 {
00280
00281 emit needLayoutPlanes();
00282 }
00283
00284 void KDChart::AbstractCoordinatePlane::setRubberBandZoomingEnabled( bool enable )
00285 {
00286 d->enableRubberBandZooming = enable;
00287
00288 if( !enable && d->rubberBand != 0 )
00289 {
00290 delete d->rubberBand;
00291 d->rubberBand = 0;
00292 }
00293 }
00294
00295 bool KDChart::AbstractCoordinatePlane::isRubberBandZoomingEnabled() const
00296 {
00297 return d->enableRubberBandZooming;
00298 }
00299
00300 void KDChart::AbstractCoordinatePlane::mousePressEvent( QMouseEvent* event )
00301 {
00302 if( event->button() == Qt::LeftButton )
00303 {
00304 if( d->enableRubberBandZooming && d->rubberBand == 0 )
00305 d->rubberBand = new QRubberBand( QRubberBand::Rectangle, qobject_cast< QWidget* >( parent() ) );
00306
00307 if( d->rubberBand != 0 )
00308 {
00309 d->rubberBandOrigin = event->pos();
00310 d->rubberBand->setGeometry( QRect( event->pos(), QSize() ) );
00311 d->rubberBand->show();
00312
00313 event->accept();
00314 }
00315 }
00316 else if( event->button() == Qt::RightButton )
00317 {
00318 if( d->enableRubberBandZooming && !d->rubberBandZoomConfigHistory.isEmpty() )
00319 {
00320
00321 ZoomParameters config = d->rubberBandZoomConfigHistory.pop();
00322 setZoomFactorX( config.xFactor );
00323 setZoomFactorY( config.yFactor );
00324 setZoomCenter( config.center() );
00325
00326 QWidget* const p = qobject_cast< QWidget* >( parent() );
00327 if( p != 0 )
00328 p->update();
00329
00330 event->accept();
00331 }
00332 }
00333
00334 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00335 {
00336 a->mousePressEvent( event );
00337 }
00338 }
00339
00340 void KDChart::AbstractCoordinatePlane::mouseDoubleClickEvent( QMouseEvent* event )
00341 {
00342 if( event->button() == Qt::RightButton )
00343 {
00344
00345
00346 mousePressEvent( event );
00347 }
00348 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00349 {
00350 a->mouseDoubleClickEvent( event );
00351 }
00352 }
00353
00354 void KDChart::AbstractCoordinatePlane::mouseReleaseEvent( QMouseEvent* event )
00355 {
00356 if( d->rubberBand != 0 )
00357 {
00358
00359 d->rubberBandZoomConfigHistory.push( ZoomParameters( zoomFactorX(), zoomFactorY(), zoomCenter() ) );
00360
00361
00362 const double rubberWidth = static_cast< double >( d->rubberBand->width() );
00363 const double rubberHeight = static_cast< double >( d->rubberBand->height() );
00364
00365 if( rubberWidth > 0.0 && rubberHeight > 0.0 )
00366 {
00367
00368 const double rubberCenterX = static_cast< double >( d->rubberBand->geometry().center().x() - geometry().x() );
00369 const double rubberCenterY = static_cast< double >( d->rubberBand->geometry().center().y() - geometry().y() );
00370
00371
00372 const double myWidth = static_cast< double >( geometry().width() );
00373 const double myHeight = static_cast< double >( geometry().height() );
00374
00375
00376 const double newCenterX = rubberCenterX / myWidth / zoomFactorX() + zoomCenter().x() - 0.5 / zoomFactorX();
00377 const double newCenterY = rubberCenterY / myHeight / zoomFactorY() + zoomCenter().y() - 0.5 / zoomFactorY();
00378
00379
00380 const double newZoomFactorX = zoomFactorX() * myWidth / rubberWidth;
00381 const double newZoomFactorY = zoomFactorY() * myHeight / rubberHeight;
00382
00383
00384 const QPointF newZoomCenter( newCenterX, newCenterY );
00385
00386 setZoomFactorX( newZoomFactorX );
00387 setZoomFactorY( newZoomFactorY );
00388 setZoomCenter( newZoomCenter );
00389 }
00390
00391 d->rubberBand->parentWidget()->update();
00392 delete d->rubberBand;
00393 d->rubberBand = 0;
00394
00395 event->accept();
00396 }
00397
00398 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00399 {
00400 a->mouseReleaseEvent( event );
00401 }
00402 }
00403
00404 void KDChart::AbstractCoordinatePlane::mouseMoveEvent( QMouseEvent* event )
00405 {
00406 if( d->rubberBand != 0 )
00407 {
00408 const QRect normalized = QRect( d->rubberBandOrigin, event->pos() ).normalized();
00409 d->rubberBand->setGeometry( normalized & geometry() );
00410
00411 event->accept();
00412 }
00413
00414 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00415 {
00416 a->mouseMoveEvent( event );
00417 }
00418 }
00419
00420 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00421 const
00422 #endif
00423 bool KDChart::AbstractCoordinatePlane::isVisiblePoint( const QPointF& point ) const
00424 {
00425 return d->isVisiblePoint( this, point );
00426 }
00427
00428 AbstractCoordinatePlane* KDChart::AbstractCoordinatePlane::sharedAxisMasterPlane( QPainter* p )
00429 {
00430 Q_UNUSED( p );
00431 return this;
00432 }
00433
00434 #if !defined(QT_NO_DEBUG_STREAM)
00435 #include "KDChartEnums.h"
00436
00437 QDebug KDChart::operator<<( QDebug stream, const DataDimension& r )
00438 {
00439 stream << "DataDimension("
00440 << " start=" << r.start
00441 << " end=" << r.end
00442 << " sequence=" << KDChartEnums::granularitySequenceToString( r.sequence )
00443 << " isCalculated=" << r.isCalculated
00444 << " calcMode=" << ( r.calcMode == AbstractCoordinatePlane::Logarithmic ? "Logarithmic" : "Linear" )
00445 << " stepWidth=" << r.stepWidth
00446 << " subStepWidth=" << r.subStepWidth
00447 << " )";
00448 return stream;
00449 }
00450 #endif
00451
00452 #undef d