ReverseMapper.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003    */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KD Chart 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 KD Chart licenses may use this file in
00016  ** accordance with the KD Chart 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.kdab.net/kdchart for
00023  **   information about KD Chart Commercial License Agreements.
00024  **
00025  ** Contact info@kdab.net if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 
00030 #include "ReverseMapper.h"
00031 
00032 #include <math.h>
00033 
00034 #include <QRect>
00035 #include <QtDebug>
00036 #include <QPolygonF>
00037 #include <QPainterPath>
00038 #include <QGraphicsScene>
00039 
00040 #include "../KDChartAbstractDiagram.h"
00041 #include "ChartGraphicsItem.h"
00042 
00043 using namespace KDChart;
00044 
00045 ReverseMapper::ReverseMapper()
00046     : m_scene( 0 )
00047     , m_diagram( 0 )
00048 {
00049 }
00050 
00051 ReverseMapper::ReverseMapper( AbstractDiagram* diagram )
00052     : m_scene( 0 )
00053     , m_diagram( diagram )
00054 {
00055 }
00056 
00057 ReverseMapper::~ReverseMapper()
00058 {
00059     delete m_scene; m_scene = 0;
00060 }
00061 
00062 void ReverseMapper::setDiagram( AbstractDiagram* diagram )
00063 {
00064 
00065     m_diagram = diagram;
00066 }
00067 
00068 void ReverseMapper::clear()
00069 {
00070     delete m_scene;
00071     m_scene = new QGraphicsScene();
00072 }
00073 
00074 QModelIndexList ReverseMapper::indexesIn( const QRect& rect ) const
00075 {
00076     Q_ASSERT( m_diagram );
00077     if ( m_scene && m_scene->sceneRect().intersects( rect ) ) {
00078         QList<QGraphicsItem *> items = m_scene->items( rect );
00079         QModelIndexList indexes;
00080         Q_FOREACH( QGraphicsItem* item, items ) {
00081             ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
00082             if ( i ) {
00083                 QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) );
00084                 indexes << index;
00085             }
00086         }
00087         return indexes;
00088     } else {
00089         return QModelIndexList();
00090     }
00091 }
00092 
00093 QModelIndexList ReverseMapper::indexesAt( const QPointF& point ) const
00094 {
00095     Q_ASSERT( m_diagram );
00096     if ( m_scene && m_scene->sceneRect().contains( point ) ) {
00097         QList<QGraphicsItem *> items = m_scene->items( point );
00098         QModelIndexList indexes;
00099         Q_FOREACH( QGraphicsItem* item, items ) {
00100             ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
00101             if ( i ) {
00102                 QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) );
00103                 if( !indexes.contains(index) )
00104                     indexes << index;
00105             }
00106         }
00107         return indexes;
00108     } else {
00109         return QModelIndexList();
00110     }
00111 }
00112 
00113 QPolygonF ReverseMapper::polygon( int row, int column ) const
00114 {
00115     const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() );
00116     return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon() : QPolygon();
00117 }
00118 
00119 QRectF ReverseMapper::boundingRect( int row, int column ) const
00120 {
00121     const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() );
00122     return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon().boundingRect() : QRectF();
00123 }
00124 
00125 void ReverseMapper::addItem( ChartGraphicsItem* item )
00126 {
00127     Q_ASSERT( m_scene );
00128     m_scene->addItem( item );
00129     m_itemMap.insert( m_diagram->model()->index( item->row(), item->column(), m_diagram->rootIndex() ), item );
00130 }
00131 
00132 void ReverseMapper::addRect( int row, int column, const QRectF& rect )
00133 {
00134     addPolygon( row, column, QPolygonF( rect ) );
00135 }
00136 
00137 void ReverseMapper::addPolygon( int row, int column, const QPolygonF& polygon )
00138 {
00139     ChartGraphicsItem* item = new ChartGraphicsItem( row, column );
00140     item->setPolygon( polygon );
00141     addItem( item );
00142 }
00143 
00144 void ReverseMapper::addCircle( int row, int column, const QPointF& location, const QSizeF& diameter )
00145 {
00146     QPainterPath path;
00147     QPointF ossfet( -0.5*diameter.width(), -0.5*diameter.height() );
00148     path.addEllipse( QRectF( location + ossfet, diameter ) );
00149     addPolygon( row, column, QPolygonF( path.toFillPolygon() ) );
00150 }
00151 
00152 void ReverseMapper::addLine( int row, int column, const QPointF& from, const QPointF& to )
00153 {
00154     // that's no line, dude... make a small circle around that point, instead
00155     if( from == to )
00156     {
00157         addCircle( row, column, from, QSizeF( 1.5, 1.5 ) );
00158         return;
00159     }
00160     // lines do not make good polygons to click on. we calculate a 2
00161     // pixel wide rectangle, where the original line is excatly
00162     // centered in.
00163     // make a 3 pixel wide polygon from the line:
00164     static const QPointF pixel( 1.0, 1.0 );
00165     QPointF left, right;
00166     if ( from.x() < to.x() ) {
00167         left = from;
00168         right = to;
00169     } else {
00170         right = from;
00171         left = to;
00172     }
00173     const QPointF lineVector( right - left );
00174     const qreal lineVectorLength = sqrt( lineVector.x() * lineVector.x() + lineVector.y() * lineVector.y() );
00175     const QPointF lineVectorUnit( lineVector / lineVectorLength );
00176     const QPointF normOfLineVectorUnit( -lineVectorUnit.y(), lineVectorUnit.x() );
00177     // now the four polygon end points:
00178     const QPointF one( left - lineVectorUnit + normOfLineVectorUnit );
00179     const QPointF two( left - lineVectorUnit - normOfLineVectorUnit );
00180     const QPointF three( right + lineVectorUnit - normOfLineVectorUnit );
00181     const QPointF four( right + lineVectorUnit + normOfLineVectorUnit );
00182     addPolygon( row, column, QPolygonF() << one << two << three << four );
00183 }

Generated on Thu Mar 4 23:19:13 2010 for KD Chart 2 by  doxygen 1.5.4