KDEUI
kplotobject.cpp
Go to the documentation of this file.
00001 /* -*- C++ -*- 00002 This file is part of the KDE libraries 00003 Copyright (C) 2003 Jason Harris <kstars@30doradus.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kplotobject.h" 00022 00023 #include <QtAlgorithms> 00024 #include <QPainter> 00025 00026 #include <kdebug.h> 00027 00028 #include "kplotpoint.h" 00029 #include "kplotwidget.h" 00030 00031 class KPlotObject::Private 00032 { 00033 public: 00034 Private( KPlotObject * qq ) 00035 : q( qq ) 00036 { 00037 } 00038 00039 ~Private() 00040 { 00041 qDeleteAll( pList ); 00042 } 00043 00044 KPlotObject *q; 00045 00046 QList<KPlotPoint*> pList; 00047 PlotTypes type; 00048 PointStyle pointStyle; 00049 double size; 00050 QPen pen, linePen, barPen, labelPen; 00051 QBrush brush, barBrush; 00052 }; 00053 00054 KPlotObject::KPlotObject( const QColor &c, PlotType t, double size, PointStyle ps ) 00055 : d( new Private( this ) ) 00056 { 00057 //By default, all pens and brushes are set to the given color 00058 setBrush( c ); 00059 setBarBrush( c ); 00060 setPen( QPen( brush(), 1 ) ); 00061 setLinePen( pen() ); 00062 setBarPen( pen() ); 00063 setLabelPen( pen() ); 00064 00065 d->type |= t; 00066 setSize( size ); 00067 setPointStyle( ps ); 00068 } 00069 00070 KPlotObject::~KPlotObject() 00071 { 00072 delete d; 00073 } 00074 00075 KPlotObject::PlotTypes KPlotObject::plotTypes() const 00076 { 00077 return d->type; 00078 } 00079 00080 void KPlotObject::setShowPoints( bool b ) 00081 { 00082 if ( b ) 00083 { 00084 d->type |= KPlotObject::Points; 00085 } 00086 else 00087 { 00088 d->type &= ~KPlotObject::Points; 00089 } 00090 } 00091 00092 void KPlotObject::setShowLines( bool b ) 00093 { 00094 if ( b ) 00095 { 00096 d->type |= KPlotObject::Lines; 00097 } 00098 else 00099 { 00100 d->type &= ~KPlotObject::Lines; 00101 } 00102 } 00103 00104 void KPlotObject::setShowBars( bool b ) 00105 { 00106 if ( b ) 00107 { 00108 d->type |= KPlotObject::Bars; 00109 } 00110 else 00111 { 00112 d->type &= ~KPlotObject::Bars; 00113 } 00114 } 00115 00116 double KPlotObject::size() const 00117 { 00118 return d->size; 00119 } 00120 00121 void KPlotObject::setSize( double s ) 00122 { 00123 d->size = s; 00124 } 00125 00126 KPlotObject::PointStyle KPlotObject::pointStyle() const 00127 { 00128 return d->pointStyle; 00129 } 00130 00131 void KPlotObject::setPointStyle( PointStyle p ) 00132 { 00133 d->pointStyle = p; 00134 } 00135 00136 const QPen& KPlotObject::pen() const 00137 { 00138 return d->pen; 00139 } 00140 00141 void KPlotObject::setPen( const QPen &p ) 00142 { 00143 d->pen = p; 00144 } 00145 00146 const QPen& KPlotObject::linePen() const 00147 { 00148 return d->linePen; 00149 } 00150 00151 void KPlotObject::setLinePen( const QPen &p ) 00152 { 00153 d->linePen = p; 00154 } 00155 00156 const QPen& KPlotObject::barPen() const 00157 { 00158 return d->barPen; 00159 } 00160 00161 void KPlotObject::setBarPen( const QPen &p ) 00162 { 00163 d->barPen = p; 00164 } 00165 00166 const QPen& KPlotObject::labelPen() const 00167 { 00168 return d->labelPen; 00169 } 00170 00171 void KPlotObject::setLabelPen( const QPen &p ) 00172 { 00173 d->labelPen = p; 00174 } 00175 00176 const QBrush KPlotObject::brush() const 00177 { 00178 return d->brush; 00179 } 00180 00181 void KPlotObject::setBrush( const QBrush &b ) 00182 { 00183 d->brush = b; 00184 } 00185 00186 const QBrush KPlotObject::barBrush() const 00187 { 00188 return d->barBrush; 00189 } 00190 00191 void KPlotObject::setBarBrush( const QBrush &b ) 00192 { 00193 d->barBrush = b; 00194 } 00195 00196 QList< KPlotPoint* > KPlotObject::points() const 00197 { 00198 return d->pList; 00199 } 00200 00201 void KPlotObject::addPoint( const QPointF &p, const QString &label, double barWidth ) 00202 { 00203 addPoint( new KPlotPoint( p.x(), p.y(), label, barWidth ) ); 00204 } 00205 00206 void KPlotObject::addPoint( KPlotPoint *p ) 00207 { 00208 if ( !p ) 00209 return; 00210 d->pList.append( p ); 00211 } 00212 00213 void KPlotObject::addPoint( double x, double y, const QString &label, double barWidth ) 00214 { 00215 addPoint( new KPlotPoint( x, y, label, barWidth ) ); 00216 } 00217 00218 void KPlotObject::removePoint( int index ) { 00219 if ( ( index < 0 ) || ( index >= d->pList.count() ) ) { 00220 kWarning() << "KPlotObject::removePoint(): index " << index << " out of range!"; 00221 return; 00222 } 00223 00224 d->pList.removeAt( index ); 00225 } 00226 00227 void KPlotObject::clearPoints() 00228 { 00229 qDeleteAll( d->pList ); 00230 d->pList.clear(); 00231 } 00232 00233 void KPlotObject::draw( QPainter *painter, KPlotWidget *pw ) { 00234 //Order of drawing determines z-distance: Bars in the back, then lines, 00235 //then points, then labels. 00236 00237 if ( d->type & Bars ) { 00238 painter->setPen( barPen() ); 00239 painter->setBrush( barBrush() ); 00240 00241 for ( int i=0; i<d->pList.size(); ++i ) { 00242 double w = 0; 00243 if ( d->pList[i]->barWidth() == 0.0 ) { 00244 if ( i<d->pList.size()-1 ) 00245 w = d->pList[i+1]->x() - d->pList[i]->x(); 00246 //For the last bin, we'll just keep the previous width 00247 00248 } else { 00249 w = d->pList[i]->barWidth(); 00250 } 00251 00252 QPointF pp = d->pList[i]->position(); 00253 QPointF p1( pp.x() - 0.5*w, 0.0 ); 00254 QPointF p2( pp.x() + 0.5*w, pp.y() ); 00255 QPointF sp1 = pw->mapToWidget( p1 ); 00256 QPointF sp2 = pw->mapToWidget( p2 ); 00257 00258 QRectF barRect = QRectF( sp1.x(), sp1.y(), sp2.x()-sp1.x(), sp2.y()-sp1.y() ).normalized(); 00259 painter->drawRect( barRect ); 00260 pw->maskRect( barRect, 0.25 ); 00261 } 00262 } 00263 00264 //Draw lines: 00265 if ( d->type & Lines ) { 00266 painter->setPen( linePen() ); 00267 00268 QPointF Previous = QPointF(); //Initialize to null 00269 00270 foreach ( KPlotPoint *pp, d->pList ) { 00271 //q is the position of the point in screen pixel coordinates 00272 QPointF q = pw->mapToWidget( pp->position() ); 00273 00274 if ( ! Previous.isNull() ) { 00275 painter->drawLine( Previous, q ); 00276 pw->maskAlongLine( Previous, q ); 00277 } 00278 00279 Previous = q; 00280 } 00281 } 00282 00283 //Draw points: 00284 if ( d->type & Points ) { 00285 00286 foreach( KPlotPoint *pp, d->pList ) { 00287 //q is the position of the point in screen pixel coordinates 00288 QPointF q = pw->mapToWidget( pp->position() ); 00289 if ( pw->pixRect().contains( q.toPoint(), false ) ) { 00290 double x1 = q.x() - size(); 00291 double y1 = q.y() - size(); 00292 QRectF qr = QRectF( x1, y1, 2*size(), 2*size() ); 00293 00294 //Mask out this rect in the plot for label avoidance 00295 pw->maskRect( qr, 2.0 ); 00296 00297 painter->setPen( pen() ); 00298 painter->setBrush( brush() ); 00299 00300 switch ( pointStyle() ) { 00301 case Circle: 00302 painter->drawEllipse( qr ); 00303 break; 00304 00305 case Letter: 00306 painter->drawText( qr, Qt::AlignCenter, pp->label().left(1) ); 00307 break; 00308 00309 case Triangle: 00310 { 00311 QPolygonF tri; 00312 tri << QPointF( q.x() - size(), q.y() + size() ) 00313 << QPointF( q.x(), q.y() - size() ) 00314 << QPointF( q.x() + size(), q.y() + size() ); 00315 painter->drawPolygon( tri ); 00316 break; 00317 } 00318 00319 case Square: 00320 painter->drawRect( qr ); 00321 break; 00322 00323 case Pentagon: 00324 { 00325 QPolygonF pent; 00326 pent << QPointF( q.x(), q.y() - size() ) 00327 << QPointF( q.x() + size(), q.y() - 0.309*size() ) 00328 << QPointF( q.x() + 0.588*size(), q.y() + size() ) 00329 << QPointF( q.x() - 0.588*size(), q.y() + size() ) 00330 << QPointF( q.x() - size(), q.y() - 0.309*size() ); 00331 painter->drawPolygon( pent ); 00332 break; 00333 } 00334 00335 case Hexagon: 00336 { 00337 QPolygonF hex; 00338 hex << QPointF( q.x(), q.y() + size() ) 00339 << QPointF( q.x() + size(), q.y() + 0.5*size() ) 00340 << QPointF( q.x() + size(), q.y() - 0.5*size() ) 00341 << QPointF( q.x(), q.y() - size() ) 00342 << QPointF( q.x() - size(), q.y() + 0.5*size() ) 00343 << QPointF( q.x() - size(), q.y() - 0.5*size() ); 00344 painter->drawPolygon( hex ); 00345 break; 00346 } 00347 00348 case Asterisk: 00349 painter->drawLine( q, QPointF( q.x(), q.y() + size() ) ); 00350 painter->drawLine( q, QPointF( q.x() + size(), q.y() + 0.5*size() ) ); 00351 painter->drawLine( q, QPointF( q.x() + size(), q.y() - 0.5*size() ) ); 00352 painter->drawLine( q, QPointF( q.x(), q.y() - size() ) ); 00353 painter->drawLine( q, QPointF( q.x() - size(), q.y() + 0.5*size() ) ); 00354 painter->drawLine( q, QPointF( q.x() - size(), q.y() - 0.5*size() ) ); 00355 break; 00356 00357 case Star: 00358 { 00359 QPolygonF star; 00360 star << QPointF( q.x(), q.y() - size() ) 00361 << QPointF( q.x() + 0.2245*size(), q.y() - 0.309*size() ) 00362 << QPointF( q.x() + size(), q.y() - 0.309*size() ) 00363 << QPointF( q.x() + 0.363*size(), q.y() + 0.118*size() ) 00364 << QPointF( q.x() + 0.588*size(), q.y() + size() ) 00365 << QPointF( q.x(), q.y() + 0.382*size() ) 00366 << QPointF( q.x() - 0.588*size(), q.y() + size() ) 00367 << QPointF( q.x() - 0.363*size(), q.y() + 0.118*size() ) 00368 << QPointF( q.x() - size(), q.y() - 0.309*size() ) 00369 << QPointF( q.x() - 0.2245*size(), q.y() - 0.309*size() ); 00370 painter->drawPolygon( star ); 00371 break; 00372 } 00373 00374 default: 00375 break; 00376 } 00377 } 00378 } 00379 } 00380 00381 //Draw labels 00382 painter->setPen( labelPen() ); 00383 00384 foreach ( KPlotPoint *pp, d->pList ) { 00385 QPoint q = pw->mapToWidget( pp->position() ).toPoint(); 00386 if ( pw->pixRect().contains(q, false) && ! pp->label().isEmpty() ) { 00387 pw->placeLabel( painter, pp ); 00388 } 00389 } 00390 00391 }
KDE 4.6 API Reference