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 disconnect( diagram, SIGNAL( modelDataChanged() ), this, SLOT( relayout()) );
00121 layoutDiagrams();
00122 update();
00123 }
00124 }
00125
00126
00127 AbstractDiagram* AbstractCoordinatePlane::diagram()
00128 {
00129 if ( d->diagrams.isEmpty() )
00130 {
00131 return 0;
00132 } else {
00133 return d->diagrams.first();
00134 }
00135 }
00136
00137 AbstractDiagramList AbstractCoordinatePlane::diagrams()
00138 {
00139 return d->diagrams;
00140 }
00141
00142 ConstAbstractDiagramList AbstractCoordinatePlane::diagrams() const
00143 {
00144 ConstAbstractDiagramList list;
00145 #ifndef QT_NO_STL
00146 qCopy( d->diagrams.begin(), d->diagrams.end(), std::back_inserter( list ) );
00147 #else
00148 Q_FOREACH( AbstractDiagram * a, d->diagrams )
00149 list.push_back( a );
00150 #endif
00151 return list;
00152 }
00153
00154 QSize KDChart::AbstractCoordinatePlane::minimumSizeHint() const
00155 {
00156 return QSize( 200, 200 );
00157 }
00158
00159
00160 QSizePolicy KDChart::AbstractCoordinatePlane::sizePolicy() const
00161 {
00162 return QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
00163 }
00164
00165 void KDChart::AbstractCoordinatePlane::setGlobalGridAttributes( const GridAttributes& a )
00166 {
00167 d->gridAttributes = a;
00168 update();
00169 }
00170
00171 GridAttributes KDChart::AbstractCoordinatePlane::globalGridAttributes() const
00172 {
00173 return d->gridAttributes;
00174 }
00175
00176 KDChart::DataDimensionsList KDChart::AbstractCoordinatePlane::gridDimensionsList()
00177 {
00178
00179
00180
00181 return d->grid->updateData( this );
00182 }
00183
00184 void KDChart::AbstractCoordinatePlane::setGridNeedsRecalculate()
00185 {
00186 d->grid->setNeedRecalculate();
00187 }
00188
00189 void KDChart::AbstractCoordinatePlane::setReferenceCoordinatePlane( AbstractCoordinatePlane * plane )
00190 {
00191 d->referenceCoordinatePlane = plane;
00192 }
00193
00194 AbstractCoordinatePlane * KDChart::AbstractCoordinatePlane::referenceCoordinatePlane( ) const
00195 {
00196 return d->referenceCoordinatePlane;
00197 }
00198
00199 void KDChart::AbstractCoordinatePlane::setParent( KDChart::Chart* parent )
00200 {
00201 d->parent = parent;
00202 }
00203
00204 const KDChart::Chart* KDChart::AbstractCoordinatePlane::parent() const
00205 {
00206 return d->parent;
00207 }
00208
00209 KDChart::Chart* KDChart::AbstractCoordinatePlane::parent()
00210 {
00211 return d->parent;
00212 }
00213
00214
00215 bool KDChart::AbstractCoordinatePlane::isEmpty() const
00216 {
00217 return false;
00218
00219
00220 }
00221
00222 Qt::Orientations KDChart::AbstractCoordinatePlane::expandingDirections() const
00223 {
00224 return Qt::Vertical | Qt::Horizontal;
00225 }
00226
00227 QSize KDChart::AbstractCoordinatePlane::maximumSize() const
00228 {
00229
00230
00231 return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
00232 }
00233
00234 QSize KDChart::AbstractCoordinatePlane::minimumSize() const
00235 {
00236 return QSize(60, 60);
00237 }
00238
00239 QSize KDChart::AbstractCoordinatePlane::sizeHint() const
00240 {
00241
00242
00243 return maximumSize();
00244 }
00245
00246 void KDChart::AbstractCoordinatePlane::setGeometry( const QRect& r )
00247 {
00248
00249 if( d->geometry != r ){
00250
00251
00252
00253 emit internal_geometryChanged( d->geometry, r );
00254
00255 d->geometry = r;
00256
00257
00258
00259 }
00260 }
00261
00262 QRect KDChart::AbstractCoordinatePlane::geometry() const
00263 {
00264 return d->geometry;
00265 }
00266
00267 void KDChart::AbstractCoordinatePlane::update()
00268 {
00269
00270 emit needUpdate();
00271 }
00272
00273 void KDChart::AbstractCoordinatePlane::relayout()
00274 {
00275
00276 emit needRelayout();
00277 }
00278
00279 void KDChart::AbstractCoordinatePlane::layoutPlanes()
00280 {
00281
00282 emit needLayoutPlanes();
00283 }
00284
00285 void KDChart::AbstractCoordinatePlane::setRubberBandZoomingEnabled( bool enable )
00286 {
00287 d->enableRubberBandZooming = enable;
00288
00289 if( !enable && d->rubberBand != 0 )
00290 {
00291 delete d->rubberBand;
00292 d->rubberBand = 0;
00293 }
00294 }
00295
00296 bool KDChart::AbstractCoordinatePlane::isRubberBandZoomingEnabled() const
00297 {
00298 return d->enableRubberBandZooming;
00299 }
00300
00301 void KDChart::AbstractCoordinatePlane::mousePressEvent( QMouseEvent* event )
00302 {
00303 if( event->button() == Qt::LeftButton )
00304 {
00305 if( d->enableRubberBandZooming && d->rubberBand == 0 )
00306 d->rubberBand = new QRubberBand( QRubberBand::Rectangle, qobject_cast< QWidget* >( parent() ) );
00307
00308 if( d->rubberBand != 0 )
00309 {
00310 d->rubberBandOrigin = event->pos();
00311 d->rubberBand->setGeometry( QRect( event->pos(), QSize() ) );
00312 d->rubberBand->show();
00313
00314 event->accept();
00315 }
00316 }
00317 else if( event->button() == Qt::RightButton )
00318 {
00319 if( d->enableRubberBandZooming && !d->rubberBandZoomConfigHistory.isEmpty() )
00320 {
00321
00322 ZoomParameters config = d->rubberBandZoomConfigHistory.pop();
00323 setZoomFactorX( config.xFactor );
00324 setZoomFactorY( config.yFactor );
00325 setZoomCenter( config.center() );
00326
00327 QWidget* const p = qobject_cast< QWidget* >( parent() );
00328 if( p != 0 )
00329 p->update();
00330
00331 event->accept();
00332 }
00333 }
00334
00335 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00336 {
00337 a->mousePressEvent( event );
00338 }
00339 }
00340
00341 void KDChart::AbstractCoordinatePlane::mouseDoubleClickEvent( QMouseEvent* event )
00342 {
00343 if( event->button() == Qt::RightButton )
00344 {
00345
00346
00347 mousePressEvent( event );
00348 }
00349 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00350 {
00351 a->mouseDoubleClickEvent( event );
00352 }
00353 }
00354
00355 void KDChart::AbstractCoordinatePlane::mouseReleaseEvent( QMouseEvent* event )
00356 {
00357 if( d->rubberBand != 0 )
00358 {
00359
00360 d->rubberBandZoomConfigHistory.push( ZoomParameters( zoomFactorX(), zoomFactorY(), zoomCenter() ) );
00361
00362
00363 const double rubberWidth = static_cast< double >( d->rubberBand->width() );
00364 const double rubberHeight = static_cast< double >( d->rubberBand->height() );
00365
00366 if( rubberWidth > 0.0 && rubberHeight > 0.0 )
00367 {
00368
00369 const double rubberCenterX = static_cast< double >( d->rubberBand->geometry().center().x() - geometry().x() );
00370 const double rubberCenterY = static_cast< double >( d->rubberBand->geometry().center().y() - geometry().y() );
00371
00372
00373 const double myWidth = static_cast< double >( geometry().width() );
00374 const double myHeight = static_cast< double >( geometry().height() );
00375
00376
00377 const double newCenterX = rubberCenterX / myWidth / zoomFactorX() + zoomCenter().x() - 0.5 / zoomFactorX();
00378 const double newCenterY = rubberCenterY / myHeight / zoomFactorY() + zoomCenter().y() - 0.5 / zoomFactorY();
00379
00380
00381 const double newZoomFactorX = zoomFactorX() * myWidth / rubberWidth;
00382 const double newZoomFactorY = zoomFactorY() * myHeight / rubberHeight;
00383
00384
00385 const QPointF newZoomCenter( newCenterX, newCenterY );
00386
00387 setZoomFactorX( newZoomFactorX );
00388 setZoomFactorY( newZoomFactorY );
00389 setZoomCenter( newZoomCenter );
00390 }
00391
00392 d->rubberBand->parentWidget()->update();
00393 delete d->rubberBand;
00394 d->rubberBand = 0;
00395
00396 event->accept();
00397 }
00398
00399 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00400 {
00401 a->mouseReleaseEvent( event );
00402 }
00403 }
00404
00405 void KDChart::AbstractCoordinatePlane::mouseMoveEvent( QMouseEvent* event )
00406 {
00407 if( d->rubberBand != 0 )
00408 {
00409 const QRect normalized = QRect( d->rubberBandOrigin, event->pos() ).normalized();
00410 d->rubberBand->setGeometry( normalized & geometry() );
00411
00412 event->accept();
00413 }
00414
00415 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00416 {
00417 a->mouseMoveEvent( event );
00418 }
00419 }
00420
00421 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00422 const
00423 #endif
00424 bool KDChart::AbstractCoordinatePlane::isVisiblePoint( const QPointF& point ) const
00425 {
00426 return d->isVisiblePoint( this, point );
00427 }
00428
00429 AbstractCoordinatePlane* KDChart::AbstractCoordinatePlane::sharedAxisMasterPlane( QPainter* p )
00430 {
00431 Q_UNUSED( p );
00432 return this;
00433 }
00434
00435 #if !defined(QT_NO_DEBUG_STREAM)
00436 #include "KDChartEnums.h"
00437
00438 QDebug KDChart::operator<<( QDebug stream, const DataDimension& r )
00439 {
00440 stream << "DataDimension("
00441 << " start=" << r.start
00442 << " end=" << r.end
00443 << " sequence=" << KDChartEnums::granularitySequenceToString( r.sequence )
00444 << " isCalculated=" << r.isCalculated
00445 << " calcMode=" << ( r.calcMode == AbstractCoordinatePlane::Logarithmic ? "Logarithmic" : "Linear" )
00446 << " stepWidth=" << r.stepWidth
00447 << " subStepWidth=" << r.subStepWidth
00448 << " )";
00449 return stream;
00450 }
00451 #endif
00452
00453 #undef d