# 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 <math.h>
    00031
    00032 #include <QRect>
    00033 #include <QtDebug>
    00034 #include <QPolygonF>
    00035 #include <QPainterPath>
    00036 #include <QGraphicsScene>
    00037
    00038 #include "ReverseMapper.h"
    00039 #include "../KDChartAbstractDiagram.h"
    00040 #include "ChartGraphicsItem.h"
    00041
    00042 using namespace KDChart;
    00043
    00044 ReverseMapper::ReverseMapper()
    00045     : m_scene( 0 )
    00046     , m_diagram( 0 )
    00047 {
    00048 }
    00049
    00050 ReverseMapper::ReverseMapper( AbstractDiagram* diagram )
    00051     : m_scene( 0 )
    00052     , m_diagram( diagram )
    00053 {
    00054 }
    00055
    00056 ReverseMapper::~ReverseMapper()
    00057 {
    00058     delete m_scene; m_scene = 0;
    00059 }
    00060
    00061 void ReverseMapper::setDiagram( AbstractDiagram* diagram )
    00062 {
    00063
    00064     m_diagram = diagram;
    00065 }
    00066
    00067 void ReverseMapper::clear()
    00068 {
    00069     delete m_scene;
    00070     m_scene = new QGraphicsScene();
    00071 }
    00072
    00073 QModelIndexList ReverseMapper::indexesIn( const QRect& rect ) const
    00074 {
    00075     Q_ASSERT( m_diagram );
    00076     if ( m_scene && m_scene->sceneRect().intersects( rect ) ) {
    00077         QList<QGraphicsItem *> items = m_scene->items( rect );
    00078         QModelIndexList indexes;
    00079         Q_FOREACH( QGraphicsItem* item, items ) {
    00080             ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
    00081             if ( i ) {
    00082                 QModelIndex index ( m_diagram->model()->index( i->row(), i->column() ) );
    00083                 indexes << index;
    00084             }
    00085         }
    00086         return indexes;
    00087     } else {
    00088         return QModelIndexList();
    00089     }
    00090 }
    00091
    00092 QModelIndexList ReverseMapper::indexesAt( const QPointF& point ) const
    00093 {
    00094     Q_ASSERT( m_diagram );
    00095     if ( m_scene && m_scene->sceneRect().contains( point ) ) {
    00096         QList<QGraphicsItem *> items = m_scene->items( point );
    00097         QModelIndexList indexes;
    00098         Q_FOREACH( QGraphicsItem* item, items ) {
    00099             ChartGraphicsItem* i = qgraphicsitem_cast<ChartGraphicsItem*>( item );
    00100             if ( i ) {
    00101                 QModelIndex index ( m_diagram->model()->index( i->row(), i->column() ) );
    00102                 indexes << index;
    00103             }
    00104         }
    00105         return indexes;
    00106     } else {
    00107         return QModelIndexList();
    00108     }
    00109 }
    00110
    00111 void ReverseMapper::addItem( ChartGraphicsItem* item )
    00112 {
    00113     Q_ASSERT( m_scene );
    00114     m_scene->addItem( item );
    00115 }
    00116
    00117 void ReverseMapper::addRect( int row, int column, const QRectF& rect )
    00118 {
    00119     addPolygon( row, column, QPolygonF( rect ) );
    00120 }
    00121
    00122 void ReverseMapper::addPolygon( int row, int column, const QPolygonF& polygon )
    00123 {
    00124     ChartGraphicsItem* item = new ChartGraphicsItem( row, column );
    00125     item->setPolygon( polygon );
    00126     addItem( item );
    00127 }
    00128
    00129 void ReverseMapper::addCircle( int row, int column, const QPointF& location, const QSizeF& diameter )
    00130 {
    00131     QPainterPath path;
    00132     QPointF ossfet( -0.5*diameter.width(), -0.5*diameter.height() );
    00133     path.addEllipse( QRectF( location + ossfet, diameter ) );
    00134     addPolygon( row, column, QPolygonF( path.toFillPolygon() ) );
    00135 }
    00136
    00137 void ReverseMapper::addLine( int row, int column, const QPointF& from, const QPointF& to )
    00138 {
    00139     // lines do not make good polygons to click on. we calculate a 2
    00140     // pixel wide rectangle, where the original line is excatly
    00141     // centered in.
    00142     // make a 3 pixel wide polygon from the line:
    00143     static const QPointF pixel( 1.0, 1.0 );
    00144     QPointF left, right;
    00145     if ( from.x() < to.x() ) {
    00146         left = from;
    00147         right = to;
    00148     } else {
    00149         right = from;
    00150         left = to;
    00151     }
    00152     const QPointF lineVector( right - left );
    00153     const qreal lineVectorLength = sqrt( lineVector.x() * lineVector.x() + lineVector.y() * lineVector.y() );
    00154     const QPointF lineVectorUnit( lineVector / lineVectorLength );
    00155     const QPointF normOfLineVectorUnit( -lineVectorUnit.y(), lineVectorUnit.x() );
    00156     // now the four polygon end points:
    00157     const QPointF one( left - lineVectorUnit + normOfLineVectorUnit );
    00158     const QPointF two( left - lineVectorUnit - normOfLineVectorUnit );
    00159     const QPointF three( right + lineVectorUnit - normOfLineVectorUnit );
    00160     const QPointF four( right + lineVectorUnit + normOfLineVectorUnit );
    00161     addPolygon( row, column, QPolygonF() << one << two << three << four );
    00162 }