KD Chart 2  [rev.2.5]
ReverseMapper.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2012 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
00020 **
00021 **********************************************************************/
00022 
00023 #include "ReverseMapper.h"
00024 
00025 #include <math.h>
00026 
00027 #include <QRect>
00028 #include <QtDebug>
00029 #include <QPolygonF>
00030 #include <QPainterPath>
00031 #include <QGraphicsScene>
00032 
00033 #include "KDChartAbstractDiagram.h"
00034 #include "ChartGraphicsItem.h"
00035 
00036 using namespace KDChart;
00037 
00038 ReverseMapper::ReverseMapper()
00039     : m_scene( 0 )
00040     , m_diagram( 0 )
00041 {
00042 }
00043 
00044 ReverseMapper::ReverseMapper( AbstractDiagram* diagram )
00045     : m_scene( 0 )
00046     , m_diagram( diagram )
00047 {
00048 }
00049 
00050 ReverseMapper::~ReverseMapper()
00051 {
00052     delete m_scene; m_scene = 0;
00053 }
00054 
00055 void ReverseMapper::setDiagram( AbstractDiagram* diagram )
00056 {
00057 
00058     m_diagram = diagram;
00059 }
00060 
00061 void ReverseMapper::clear()
00062 {
00063     m_itemMap.clear();
00064     delete m_scene;
00065     m_scene = new QGraphicsScene();
00066 }
00067 
00068 QModelIndexList ReverseMapper::indexesIn( const QRect& rect ) const
00069 {
00070     Q_ASSERT( m_diagram );
00071     if ( m_scene && m_scene->sceneRect().intersects( rect ) ) {
00072         QList<QGraphicsItem *> items = m_scene->items( rect );
00073         QModelIndexList indexes;
00074         Q_FOREACH( QGraphicsItem* item, items ) {
00075             ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
00076             if ( i ) {
00077                 QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) ); // checked
00078                 indexes << index;
00079             }
00080         }
00081         return indexes;
00082     } else {
00083         return QModelIndexList();
00084     }
00085 }
00086 
00087 QModelIndexList ReverseMapper::indexesAt( const QPointF& point ) const
00088 {
00089     Q_ASSERT( m_diagram );
00090     if ( m_scene && m_scene->sceneRect().contains( point ) ) {
00091         QList<QGraphicsItem *> items = m_scene->items( point );
00092         QModelIndexList indexes;
00093         Q_FOREACH( QGraphicsItem* item, items ) {
00094             ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
00095             if ( i ) {
00096                 QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) ); // checked
00097                 if( !indexes.contains(index) )
00098                     indexes << index;
00099             }
00100         }
00101         return indexes;
00102     } else {
00103         return QModelIndexList();
00104     }
00105 }
00106 
00107 QPolygonF ReverseMapper::polygon( int row, int column ) const
00108 {
00109     if ( !m_diagram->model()->hasIndex( row, column, m_diagram->rootIndex() ) )
00110         return QPolygon();
00111     const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() ); // checked
00112     return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon() : QPolygon();
00113 }
00114 
00115 QRectF ReverseMapper::boundingRect( int row, int column ) const
00116 {
00117     if ( !m_diagram->model()->hasIndex( row, column, m_diagram->rootIndex() ) )
00118         return QRectF();
00119     const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() ); // checked
00120     return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon().boundingRect() : QRectF();
00121 }
00122 
00123 void ReverseMapper::addItem( ChartGraphicsItem* item )
00124 {
00125     Q_ASSERT( m_scene );
00126     m_scene->addItem( item );
00127     m_itemMap.insert( m_diagram->model()->index( item->row(), item->column(), m_diagram->rootIndex() ), item ); // checked
00128 }
00129 
00130 void ReverseMapper::addRect( int row, int column, const QRectF& rect )
00131 {
00132     addPolygon( row, column, QPolygonF( rect ) );
00133 }
00134 
00135 void ReverseMapper::addPolygon( int row, int column, const QPolygonF& polygon )
00136 {
00137     ChartGraphicsItem* item = new ChartGraphicsItem( row, column );
00138     item->setPolygon( polygon );
00139     addItem( item );
00140 }
00141 
00142 void ReverseMapper::addCircle( int row, int column, const QPointF& location, const QSizeF& diameter )
00143 {
00144     QPainterPath path;
00145     QPointF ossfet( -0.5*diameter.width(), -0.5*diameter.height() );
00146     path.addEllipse( QRectF( location + ossfet, diameter ) );
00147     addPolygon( row, column, QPolygonF( path.toFillPolygon() ) );
00148 }
00149 
00150 void ReverseMapper::addLine( int row, int column, const QPointF& from, const QPointF& to )
00151 {
00152     // that's no line, dude... make a small circle around that point, instead
00153     if( from == to )
00154     {
00155         addCircle( row, column, from, QSizeF( 1.5, 1.5 ) );
00156         return;
00157     }
00158     // lines do not make good polygons to click on. we calculate a 2
00159     // pixel wide rectangle, where the original line is excatly
00160     // centered in.
00161     // make a 3 pixel wide polygon from the line:
00162     static const QPointF pixel( 1.0, 1.0 );
00163     QPointF left, right;
00164     if ( from.x() < to.x() ) {
00165         left = from;
00166         right = to;
00167     } else {
00168         right = from;
00169         left = to;
00170     }
00171     const QPointF lineVector( right - left );
00172     const qreal lineVectorLength = sqrt( lineVector.x() * lineVector.x() + lineVector.y() * lineVector.y() );
00173     const QPointF lineVectorUnit( lineVector / lineVectorLength );
00174     const QPointF normOfLineVectorUnit( -lineVectorUnit.y(), lineVectorUnit.x() );
00175     // now the four polygon end points:
00176     const QPointF one( left - lineVectorUnit + normOfLineVectorUnit );
00177     const QPointF two( left - lineVectorUnit - normOfLineVectorUnit );
00178     const QPointF three( right + lineVectorUnit - normOfLineVectorUnit );
00179     const QPointF four( right + lineVectorUnit + normOfLineVectorUnit );
00180     addPolygon( row, column, QPolygonF() << one << two << three << four );
00181 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/