/***************************************************************************** * Qwt Examples - Copyright (C) 2002 Uwe Rathmann * This file may be used under the terms of the 3-clause BSD License *****************************************************************************/ #include "BarChart.h" #include #include #include #include #include #include #include #include #include #include namespace { class ScaleDraw : public QwtScaleDraw { public: ScaleDraw( Qt::Orientation orientation, const QStringList& labels ) : m_labels( labels ) { setTickLength( QwtScaleDiv::MinorTick, 0 ); setTickLength( QwtScaleDiv::MediumTick, 0 ); setTickLength( QwtScaleDiv::MajorTick, 2 ); enableComponent( QwtScaleDraw::Backbone, false ); if ( orientation == Qt::Vertical ) { setLabelRotation( -60.0 ); } else { setLabelRotation( -20.0 ); } setLabelAlignment( Qt::AlignLeft | Qt::AlignVCenter ); } virtual QwtText label( double value ) const QWT_OVERRIDE { QwtText lbl; const int index = qRound( value ); if ( index >= 0 && index < m_labels.size() ) { lbl = m_labels[ index ]; } return lbl; } private: const QStringList m_labels; }; class ChartItem : public QwtPlotBarChart { public: ChartItem() : QwtPlotBarChart( "Page Hits" ) { setLegendMode( QwtPlotBarChart::LegendBarTitles ); setLegendIconSize( QSize( 10, 14 ) ); setLayoutPolicy( AutoAdjustSamples ); setLayoutHint( 4.0 ); // minimum width for a single bar setSpacing( 10 ); // spacing between bars } void addDistro( const QString& distro, const QColor& color ) { m_colors += color; m_distros += distro; itemChanged(); } virtual QwtColumnSymbol* specialSymbol( int index, const QPointF& ) const QWT_OVERRIDE { // we want to have individual colors for each bar QwtColumnSymbol* symbol = new QwtColumnSymbol( QwtColumnSymbol::Box ); symbol->setLineWidth( 2 ); symbol->setFrameStyle( QwtColumnSymbol::Raised ); QColor c( Qt::white ); if ( index >= 0 && index < m_colors.size() ) c = m_colors[ index ]; symbol->setPalette( c ); return symbol; } virtual QwtText barTitle( int sampleIndex ) const QWT_OVERRIDE { QwtText title; if ( sampleIndex >= 0 && sampleIndex < m_distros.size() ) title = m_distros[ sampleIndex ]; return title; } private: QList< QColor > m_colors; QList< QString > m_distros; }; } BarChart::BarChart( QWidget* parent ) : QwtPlot( parent ) { const struct { const char* distro; const int hits; QColor color; } pageHits[] = { { "Arch", 1114, QColor( "DodgerBlue" ) }, { "Debian", 1373, QColor( "#d70751" ) }, { "Fedora", 1638, QColor( "SteelBlue" ) }, { "Mageia", 1395, QColor( "Indigo" ) }, { "Mint", 3874, QColor( 183, 255, 183 ) }, { "openSuSE", 1532, QColor( 115, 186, 37 ) }, { "Puppy", 1059, QColor( "LightSkyBlue" ) }, { "Ubuntu", 2391, QColor( "FireBrick" ) } }; setAutoFillBackground( true ); setPalette( QColor( "Linen" ) ); QwtPlotCanvas* canvas = new QwtPlotCanvas(); canvas->setLineWidth( 2 ); canvas->setFrameStyle( QFrame::Box | QFrame::Sunken ); canvas->setBorderRadius( 10 ); QPalette canvasPalette( QColor( "Plum" ) ); canvasPalette.setColor( QPalette::WindowText, QColor( "Indigo" ) ); canvas->setPalette( canvasPalette ); setCanvas( canvas ); setTitle( "DistroWatch Page Hit Ranking, April 2012" ); ChartItem* chartItem = new ChartItem(); QVector< double > samples; for ( uint i = 0; i < sizeof( pageHits ) / sizeof( pageHits[ 0 ] ); i++ ) { m_distros += pageHits[ i ].distro; samples += pageHits[ i ].hits; chartItem->addDistro( pageHits[ i ].distro, pageHits[ i ].color ); } chartItem->setSamples( samples ); chartItem->attach( this ); m_chartItem = chartItem; insertLegend( new QwtLegend() ); setOrientation( 0 ); setAutoReplot( false ); } void BarChart::setOrientation( int o ) { const Qt::Orientation orientation = ( o == 0 ) ? Qt::Vertical : Qt::Horizontal; int axis1 = QwtAxis::XBottom; int axis2 = QwtAxis::YLeft; if ( orientation == Qt::Horizontal ) qSwap( axis1, axis2 ); m_chartItem->setOrientation( orientation ); setAxisTitle( axis1, "Distros" ); setAxisMaxMinor( axis1, 3 ); setAxisScaleDraw( axis1, new ScaleDraw( orientation, m_distros ) ); setAxisTitle( axis2, "Hits per day ( HPD )" ); setAxisMaxMinor( axis2, 3 ); QwtScaleDraw* scaleDraw = new QwtScaleDraw(); scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 4 ); setAxisScaleDraw( axis2, scaleDraw ); plotLayout()->setCanvasMargin( 0 ); replot(); } void BarChart::exportChart() { QwtPlotRenderer renderer; renderer.exportTo( this, "distrowatch.pdf" ); } void BarChart::doScreenShot() { exportPNG( 800, 600 ); } void BarChart::exportPNG( int width, int height ) { const QString fileBase = QString("distrowatch-%2x%3" ).arg( width ).arg( height); const int resolution = qRound( 85.0 * width / 800.0 ); const double mmToInch = 1.0 / 25.4; const int dotsPerMeter = qRound( resolution * mmToInch * 1000.0 ); QImage image( width, height, QImage::Format_ARGB32 ); image.setDotsPerMeterX( dotsPerMeter ); image.setDotsPerMeterY( dotsPerMeter ); image.fill( Qt::transparent ); QPainter painter( &image ); render( &painter, QRectF( 0, 0, width, height ) ); painter.end(); image.save( fileBase + ".png" ); } void BarChart::render( QPainter* painter, const QRectF& targetRect ) { const int r = 20; const QRectF plotRect = targetRect.adjusted( 0.5 * r, 0.5 * r, -0.5 * r, -0.5 * r ); QwtPlotRenderer renderer; if ( qApp->styleSheet().isEmpty() ) { renderer.setDiscardFlag( QwtPlotRenderer::DiscardBackground, true ); painter->save(); painter->setRenderHint( QPainter::Antialiasing, true ); painter->setPen( QPen( Qt::darkGray, 1 ) ); painter->setBrush( QColor( "WhiteSmoke" ) ); painter->drawRoundedRect( targetRect, r, r ); painter->restore(); } renderer.render( this, painter, plotRect ); } #include "moc_BarChart.cpp"