kdeui: remove unused classes related to plotting

ksysguard library already has a plotting class (KSignalPlotter) which
should be moved to kdeui library, plasma library also has a plotting
class (SignalPlotter) very similar to the one from ksysguard library
(KGraphicsSignalPlotter)

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-09-27 08:58:04 +03:00
parent 0ac2e1f132
commit 379600e61e
25 changed files with 5 additions and 3058 deletions

View file

@ -224,10 +224,6 @@ install(
KPasteTextAction
KPixmapRegionSelectorDialog
KPixmapRegionSelectorWidget
KPlotAxis
KPlotObject
KPlotPoint
KPlotWidget
KPluginFactory
KPluginInfo
KPluginLoader

View file

@ -1 +0,0 @@
#include "../kplotaxis.h"

View file

@ -1 +0,0 @@
#include "../kplotobject.h"

View file

@ -1 +0,0 @@
#include "../kplotpoint.h"

View file

@ -1 +0,0 @@
#include "../kplotwidget.h"

View file

@ -160,10 +160,6 @@ set(kdeui_LIB_SRCS
paged/kpageview_p.cpp
paged/kpagewidget.cpp
paged/kpagewidgetmodel.cpp
plotting/kplotaxis.cpp
plotting/kplotpoint.cpp
plotting/kplotobject.cpp
plotting/kplotwidget.cpp
shortcuts/kshortcut.cpp
shortcuts/kshortcutschemeshelper.cpp
shortcuts/kstandardshortcut.cpp
@ -504,10 +500,6 @@ install(
paged/kpageview.h
paged/kpagewidget.h
paged/kpagewidgetmodel.h
plotting/kplotwidget.h
plotting/kplotpoint.h
plotting/kplotobject.h
plotting/kplotaxis.h
shortcuts/kshortcut.h
shortcuts/kstandardshortcut.h
shortcuts/kglobalaccel.h

View file

@ -1,20 +0,0 @@
This library provides the KPlot* classes.
KPlotWidget is a QWidget-derived class that provides a virtual baseclass
for easy data-plotting. The idea behind KPlotWidget is that you only have
to specify information in "data units"; i.e., the natural units of the
data being plotted. KPlotWidget automatically converts everything
to screen pixel units.
KPlotWidget draws X and Y axes with tickmarks and tick labels. It
automatically determines how many tickmarks to use and where they should
be, based on the data limits specified for the plot. You change the limits
by calling setLimits( double x1, double x2, double y1, double y2 ).
Data to be plotted are stored using the KPlotObject class. KPlotObject
consists of a QList of QPointF's, each specifying the X,Y coordinates
of a data point. KPlotObject also specifies the "type" of data to be
plotted (POINTS or CURVE or POLYGON or LABEL).
Jason Harris
kstars@30doradus.org

View file

@ -1,200 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2005 Andreas Nicolai <Andreas.Nicolai@gmx.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kplotaxis.h"
#include <math.h> //for log10(), pow(), modf()
#include <kdebug.h>
class KPlotAxis::Private
{
public:
Private( KPlotAxis *qq )
: q( qq )
, m_visible( true )
, m_showTickLabels( false )
, m_labelFmt( 'g' )
, m_labelFieldWidth( 0 )
, m_labelPrec( -1 )
{
}
KPlotAxis *q;
bool m_visible : 1; // Property "visible" defines if Axis is drawn or not.
bool m_showTickLabels : 1;
char m_labelFmt; // Number format for number labels, see QString::arg()
QString m_label; // The label of the axis.
int m_labelFieldWidth; // Field width for number labels, see QString::arg()
int m_labelPrec; // Number precision for number labels, see QString::arg()
QList<double> m_MajorTickMarks, m_MinorTickMarks;
};
KPlotAxis::KPlotAxis( const QString &label )
: d( new Private( this ) )
{
d->m_label = label;
}
KPlotAxis::~KPlotAxis()
{
delete d;
}
bool KPlotAxis::isVisible() const
{
return d->m_visible;
}
void KPlotAxis::setVisible( bool visible )
{
d->m_visible = visible;
}
bool KPlotAxis::areTickLabelsShown() const
{
return d->m_showTickLabels;
}
void KPlotAxis::setTickLabelsShown( bool b )
{
d->m_showTickLabels = b;
}
void KPlotAxis::setLabel( const QString& label )
{
d->m_label = label;
}
QString KPlotAxis::label() const
{
return d->m_label;
}
void KPlotAxis::setTickLabelFormat( char format, int fieldWidth, int precision )
{
d->m_labelFieldWidth = fieldWidth;
d->m_labelFmt = format;
d->m_labelPrec = precision;
}
int KPlotAxis::tickLabelWidth() const
{
return d->m_labelFieldWidth;
}
char KPlotAxis::tickLabelFormat() const
{
return d->m_labelFmt;
}
int KPlotAxis::tickLabelPrecision() const
{
return d->m_labelPrec;
}
void KPlotAxis::setTickMarks( double x0, double length ) {
d->m_MajorTickMarks.clear();
d->m_MinorTickMarks.clear();
//s is the power-of-ten factor of length:
//length = t * s; s = 10^(pwr). e.g., length=350.0 then t=3.5, s = 100.0; pwr = 2.0
double pwr = 0.0;
modf( log10( length ), &pwr );
double s = pow( 10.0, pwr );
double t = length / s;
double TickDistance = 0.0; //The distance between major tickmarks
int NumMajorTicks = 0; //will be between 3 and 5
int NumMinorTicks = 0; //The number of minor ticks between major ticks (will be 4 or 5)
//adjust s and t such that t is between 3 and 5:
if ( t < 3.0 ) {
t *= 10.0;
s /= 10.0;
// t is now between 3 and 30
}
if ( t < 6.0 ) { //accept current values
TickDistance = s;
NumMajorTicks = int( t );
NumMinorTicks = 5;
} else if ( t < 10.0 ) { // adjust by a factor of 2
TickDistance = s * 2.0;
NumMajorTicks = int( t / 2.0 );
NumMinorTicks = 4;
} else if ( t < 20.0 ) { //adjust by a factor of 4
TickDistance = s * 4.0;
NumMajorTicks = int( t / 4.0 );
NumMinorTicks = 4;
} else { //adjust by a factor of 5
TickDistance = s * 5.0;
NumMajorTicks = int( t / 5.0 );
NumMinorTicks = 5;
}
//We have determined the number of tickmarks and their separation
//Now we determine their positions in the Data space.
//Tick0 is the position of a "virtual" tickmark; the first major tickmark
//position beyond the "minimum" edge of the data range.
double Tick0 = x0 - fmod( x0, TickDistance );
if ( x0 < 0.0 ) {
Tick0 -= TickDistance;
NumMajorTicks++;
}
for ( int i=0; i<NumMajorTicks+1; i++ ) {
double xmaj = Tick0 + i*TickDistance;
if ( xmaj >= x0 && xmaj <= x0 + length ) {
d->m_MajorTickMarks.append( xmaj );
}
for ( int j=1; j<NumMinorTicks; j++ ) {
double xmin = xmaj + TickDistance*j/NumMinorTicks;
if ( xmin >= x0 && xmin <= x0 + length )
d->m_MinorTickMarks.append( xmin );
}
}
}
QString KPlotAxis::tickLabel( double val ) const {
if ( d->m_labelFmt == 't' ) {
while ( val < 0.0 ) val += 24.0;
while ( val >= 24.0 ) val -= 24.0;
int h = int(val);
int m = int( 60.*(val - h) );
return QString( "%1:%2" ).arg( h, 2, 10, QLatin1Char('0') ).arg( m, 2, 10, QLatin1Char('0') );
}
return QString( "%1" ).arg( val, d->m_labelFieldWidth, d->m_labelFmt, d->m_labelPrec );
}
QList< double > KPlotAxis::majorTickMarks() const
{
return d->m_MajorTickMarks;
}
QList< double > KPlotAxis::minorTickMarks() const
{
return d->m_MinorTickMarks;
}

View file

@ -1,162 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2005 Andreas Nicolai <Andreas.Nicolai@gmx.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KPLOTAXIS_H
#define KPLOTAXIS_H
#include <kdeui_export.h>
#include <QtCore/qstring.h>
#include <QtCore/qlist.h>
/**
* @short Axis for KPlotWidget
*
* Contains all data for drawing an axis including format specification axis labels.
*
* @author Andreas Nicolai
* @version 1.0
*/
class KDEUI_EXPORT KPlotAxis {
public:
/**
* Constructor, constructs an axis with the label @p label.
*/
explicit KPlotAxis( const QString& label = QString() );
/**
* Destructor.
*/
~KPlotAxis();
/**
* @return whether the axis is visible or not
*/
bool isVisible() const;
/**
* Sets the "visible" property of the axis.
* @param visible if true, this axis will be drawn on the KPlotWidget
*/
void setVisible( bool visible );
/**
* @return whether tick labels will be drawn for this axis
*/
bool areTickLabelsShown() const;
/**
* Determine whether tick labels will be drawn for this axis.
* @param b if true, tick labels will be drawn.
*/
void setTickLabelsShown( bool b );
/**
* Sets the axis label.
* Set the label to an empty string to omit the axis label.
* @param label a string describing the data plotted on the axis.
*/
void setLabel( const QString& label );
/**
* @return the label string for this axis
*/
QString label() const;
/**
* @return the ticklabel string for the given value, rendered according
* to the current format specification.
* @param the value to be rendered as a tick label.
* @sa setTickLabelFormat()
*/
QString tickLabel( double value ) const;
/**
* Set the display format for converting the double value of the
* tick's position to the QString for the tick label.
*
* Normally, the format character is one of 'e', 'E', 'f', 'g', or 'G'
* (see the documentation for QString::arg(double) for details).
*
* In addition, it is possible to set the format character to 't';
* in this case the tickmark value is interpreted as a time in hours,
* and the ticklabel string will be in "hh:mm" clock format.
* Note that when the format character is 't', the fieldWidth and prec
* values are ignored.
*
* @param format the format specification character
* @param fieldWidth the number of characters in the output string.
* If set to 0, the string will be as wide as it needs to be to fully
* render the value.
* @param precision the number of characters following the decimal point.
*/
void setTickLabelFormat( char format = 'g', int fieldWidth = 0, int precision = -1 );
/**
* @return the field width of the tick labels
*/
int tickLabelWidth() const;
/**
* @return the number format of the tick labels
*/
char tickLabelFormat() const;
/**
* @return the number precision of the tick labels
*/
int tickLabelPrecision() const;
/**
* Determine the positions of major and minor tickmarks for this axis.
* @note this function is called by KPlotWidget whenever the plot's
* limits are modified.
* @param x0 the minimum data coordinate of the axis.
* @param length the range covered by the axis, in data units.
* @sa majorTickMarks()
* @sa minorTickMarks()
*/
void setTickMarks( double x0, double length );
/**
* @return the list of coordinates of the major tickmarks for this axis
* @note the positions of tickmarks are automatically computed by setTickMarks().
* @sa setTickMarks()
* @sa minorTickMarks()
*/
QList< double > majorTickMarks() const;
/**
* @return the list with the minor tickmarks
* @note the positions of tickmarks are automatically computed by setTickMarks().
* @sa setTickMarks()
* @sa majorTickMarks()
*/
QList< double > minorTickMarks() const;
private:
class Private;
Private * const d;
Q_DISABLE_COPY( KPlotAxis )
};
#endif // KPLOTAXIS_H

View file

@ -1,392 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kplotobject.h"
#include <QtCore/qalgorithms.h>
#include <QPainter>
#include <QPen>
#include <kdebug.h>
#include "kplotpoint.h"
#include "kplotwidget.h"
class KPlotObject::Private
{
public:
Private( KPlotObject * qq )
: q( qq )
{
}
~Private()
{
qDeleteAll( pList );
}
KPlotObject *q;
QList<KPlotPoint*> pList;
PlotTypes type;
PointStyle pointStyle;
double size;
QPen pen, linePen, barPen, labelPen;
QBrush brush, barBrush;
};
KPlotObject::KPlotObject( const QColor &c, PlotType t, double size, PointStyle ps )
: d( new Private( this ) )
{
//By default, all pens and brushes are set to the given color
setBrush( c );
setBarBrush( c );
setPen( QPen( brush(), 1 ) );
setLinePen( pen() );
setBarPen( pen() );
setLabelPen( pen() );
d->type |= t;
setSize( size );
setPointStyle( ps );
}
KPlotObject::~KPlotObject()
{
delete d;
}
KPlotObject::PlotTypes KPlotObject::plotTypes() const
{
return d->type;
}
void KPlotObject::setShowPoints( bool b )
{
if ( b )
{
d->type |= KPlotObject::Points;
}
else
{
d->type &= ~KPlotObject::Points;
}
}
void KPlotObject::setShowLines( bool b )
{
if ( b )
{
d->type |= KPlotObject::Lines;
}
else
{
d->type &= ~KPlotObject::Lines;
}
}
void KPlotObject::setShowBars( bool b )
{
if ( b )
{
d->type |= KPlotObject::Bars;
}
else
{
d->type &= ~KPlotObject::Bars;
}
}
double KPlotObject::size() const
{
return d->size;
}
void KPlotObject::setSize( double s )
{
d->size = s;
}
KPlotObject::PointStyle KPlotObject::pointStyle() const
{
return d->pointStyle;
}
void KPlotObject::setPointStyle( PointStyle p )
{
d->pointStyle = p;
}
const QPen& KPlotObject::pen() const
{
return d->pen;
}
void KPlotObject::setPen( const QPen &p )
{
d->pen = p;
}
const QPen& KPlotObject::linePen() const
{
return d->linePen;
}
void KPlotObject::setLinePen( const QPen &p )
{
d->linePen = p;
}
const QPen& KPlotObject::barPen() const
{
return d->barPen;
}
void KPlotObject::setBarPen( const QPen &p )
{
d->barPen = p;
}
const QPen& KPlotObject::labelPen() const
{
return d->labelPen;
}
void KPlotObject::setLabelPen( const QPen &p )
{
d->labelPen = p;
}
const QBrush KPlotObject::brush() const
{
return d->brush;
}
void KPlotObject::setBrush( const QBrush &b )
{
d->brush = b;
}
const QBrush KPlotObject::barBrush() const
{
return d->barBrush;
}
void KPlotObject::setBarBrush( const QBrush &b )
{
d->barBrush = b;
}
QList< KPlotPoint* > KPlotObject::points() const
{
return d->pList;
}
void KPlotObject::addPoint( const QPointF &p, const QString &label, double barWidth )
{
addPoint( new KPlotPoint( p.x(), p.y(), label, barWidth ) );
}
void KPlotObject::addPoint( KPlotPoint *p )
{
if ( !p )
return;
d->pList.append( p );
}
void KPlotObject::addPoint( double x, double y, const QString &label, double barWidth )
{
addPoint( new KPlotPoint( x, y, label, barWidth ) );
}
void KPlotObject::removePoint( int index ) {
if ( ( index < 0 ) || ( index >= d->pList.count() ) ) {
kWarning() << "KPlotObject::removePoint(): index " << index << " out of range!";
return;
}
d->pList.removeAt( index );
}
void KPlotObject::clearPoints()
{
qDeleteAll( d->pList );
d->pList.clear();
}
void KPlotObject::draw( QPainter *painter, KPlotWidget *pw ) {
//Order of drawing determines z-distance: Bars in the back, then lines,
//then points, then labels.
if ( d->type & Bars ) {
painter->setPen( barPen() );
painter->setBrush( barBrush() );
double w = 0;
for ( int i=0; i<d->pList.size(); ++i ) {
if ( d->pList[i]->barWidth() == 0.0 ) {
if ( i<d->pList.size()-1 )
w = d->pList[i+1]->x() - d->pList[i]->x();
//For the last bin, we'll just keep the previous width
} else {
w = d->pList[i]->barWidth();
}
QPointF pp = d->pList[i]->position();
QPointF p1( pp.x() - 0.5*w, 0.0 );
QPointF p2( pp.x() + 0.5*w, pp.y() );
QPointF sp1 = pw->mapToWidget( p1 );
QPointF sp2 = pw->mapToWidget( p2 );
QRectF barRect = QRectF( sp1.x(), sp1.y(), sp2.x()-sp1.x(), sp2.y()-sp1.y() ).normalized();
painter->drawRect( barRect );
pw->maskRect( barRect, 0.25 );
}
}
//Draw lines:
if ( d->type & Lines ) {
painter->setPen( linePen() );
QPointF Previous = QPointF(); //Initialize to null
foreach ( KPlotPoint *pp, d->pList ) {
//q is the position of the point in screen pixel coordinates
QPointF q = pw->mapToWidget( pp->position() );
if ( ! Previous.isNull() ) {
painter->drawLine( Previous, q );
pw->maskAlongLine( Previous, q );
}
Previous = q;
}
}
//Draw points:
if ( d->type & Points ) {
foreach( KPlotPoint *pp, d->pList ) {
//q is the position of the point in screen pixel coordinates
QPointF q = pw->mapToWidget( pp->position() );
if ( pw->pixRect().contains( q.toPoint(), false ) ) {
double x1 = q.x() - size();
double y1 = q.y() - size();
QRectF qr = QRectF( x1, y1, 2*size(), 2*size() );
//Mask out this rect in the plot for label avoidance
pw->maskRect( qr, 2.0 );
painter->setPen( pen() );
painter->setBrush( brush() );
switch ( pointStyle() ) {
case Circle:
painter->drawEllipse( qr );
break;
case Letter:
painter->drawText( qr, Qt::AlignCenter, pp->label().left(1) );
break;
case Triangle:
{
QPolygonF tri;
tri << QPointF( q.x() - size(), q.y() + size() )
<< QPointF( q.x(), q.y() - size() )
<< QPointF( q.x() + size(), q.y() + size() );
painter->drawPolygon( tri );
break;
}
case Square:
painter->drawRect( qr );
break;
case Pentagon:
{
QPolygonF pent;
pent << QPointF( q.x(), q.y() - size() )
<< QPointF( q.x() + size(), q.y() - 0.309*size() )
<< QPointF( q.x() + 0.588*size(), q.y() + size() )
<< QPointF( q.x() - 0.588*size(), q.y() + size() )
<< QPointF( q.x() - size(), q.y() - 0.309*size() );
painter->drawPolygon( pent );
break;
}
case Hexagon:
{
QPolygonF hex;
hex << QPointF( q.x(), q.y() + size() )
<< QPointF( q.x() + size(), q.y() + 0.5*size() )
<< QPointF( q.x() + size(), q.y() - 0.5*size() )
<< QPointF( q.x(), q.y() - size() )
<< QPointF( q.x() - size(), q.y() + 0.5*size() )
<< QPointF( q.x() - size(), q.y() - 0.5*size() );
painter->drawPolygon( hex );
break;
}
case Asterisk:
painter->drawLine( q, QPointF( q.x(), q.y() + size() ) );
painter->drawLine( q, QPointF( q.x() + size(), q.y() + 0.5*size() ) );
painter->drawLine( q, QPointF( q.x() + size(), q.y() - 0.5*size() ) );
painter->drawLine( q, QPointF( q.x(), q.y() - size() ) );
painter->drawLine( q, QPointF( q.x() - size(), q.y() + 0.5*size() ) );
painter->drawLine( q, QPointF( q.x() - size(), q.y() - 0.5*size() ) );
break;
case Star:
{
QPolygonF star;
star << QPointF( q.x(), q.y() - size() )
<< QPointF( q.x() + 0.2245*size(), q.y() - 0.309*size() )
<< QPointF( q.x() + size(), q.y() - 0.309*size() )
<< QPointF( q.x() + 0.363*size(), q.y() + 0.118*size() )
<< QPointF( q.x() + 0.588*size(), q.y() + size() )
<< QPointF( q.x(), q.y() + 0.382*size() )
<< QPointF( q.x() - 0.588*size(), q.y() + size() )
<< QPointF( q.x() - 0.363*size(), q.y() + 0.118*size() )
<< QPointF( q.x() - size(), q.y() - 0.309*size() )
<< QPointF( q.x() - 0.2245*size(), q.y() - 0.309*size() );
painter->drawPolygon( star );
break;
}
default:
break;
}
}
}
}
//Draw labels
painter->setPen( labelPen() );
foreach ( KPlotPoint *pp, d->pList ) {
QPoint q = pw->mapToWidget( pp->position() ).toPoint();
if ( pw->pixRect().contains(q, false) && ! pp->label().isEmpty() ) {
pw->placeLabel( painter, pp );
}
}
}

View file

@ -1,280 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KPLOTOBJECT_H
#define KPLOTOBJECT_H
#include <kdeui_export.h>
#include <QtCore/qstring.h>
#include <QtGui/qcolor.h>
#include <QBrush>
#include <QPainter>
#include <QPen>
#include <QPointF>
class KPlotWidget;
class KPlotPoint;
/**
* @class KPlotObject
* @short Encapsulates a data set to be plotted in a KPlotWidget.
*
* Think of a KPlotObject as a set of data displayed as a group in the plot.
* Each KPlotObject consists of a list of KPlotPoints, a "type" controlling
* how the data points are displayed (some combination of Points, Lines, or
* Bars), a color, and a size. There is also a parameter which controls the
* shape of the points used to display the KPlotObject.
*
* @note KPlotObject will take care of the points added to it, so when clearing
* the points list (eg with clearPoints()) any previous reference to a KPlotPoint
* already added to a KPlotObject will be invalid.
*
* @author Jason Harris
* @version 1.1
*/
class KDEUI_EXPORT KPlotObject{
public:
/**
* The type classification of the KPlotObject.
*
* These are bitmask values that can be OR'd together, so that a set
* of points can be represented in the plot in multiple ways.
*
* @note points should be added in order of increasing x-coordinate
* when using Bars.
*/
enum PlotType
{
UnknownType = 0,
Points = 1, ///< each KPlotPoint is represented with a drawn point
Lines = 2, ///< each KPlotPoint is connected with a line
Bars = 4 ///< each KPlotPoint is shown as a vertical bar
};
Q_DECLARE_FLAGS( PlotTypes, PlotType )
/**
* The available shape styles for plotted points.
*/
enum PointStyle
{
NoPoints = 0,
Circle = 1,
Letter = 2,
Triangle = 3,
Square = 4,
Pentagon = 5,
Hexagon = 6,
Asterisk = 7,
Star = 8,
UnknwonPoint
};
/**
* Constructor.
* @param color The color for plotting this object. By default this sets
* the color for Points, Lines and Bars, but there are functions to
* override any of these.
* @param otype the PlotType for this object (Points, Lines or Bars)
* @param size the size to use for plotted points, in pixels
* @param ps The PointStyle describing the shape for plotted points
*/
explicit KPlotObject( const QColor &color = Qt::white, PlotType otype = Points, double size = 2, PointStyle ps = Circle );
/**
* Destructor.
*/
~KPlotObject();
/**
* @return the plot flags of the object
*/
PlotTypes plotTypes() const;
/**
* Set whether points will be drawn for this object
* @param b if true, points will be drawn
*/
void setShowPoints( bool b );
/**
* Set whether lines will be drawn for this object
* @param b if true, lines will be drawn
*/
void setShowLines( bool b );
/**
* Set whether bars will be drawn for this object
* @param b if true, bars will be drawn
*/
void setShowBars( bool b );
/**
* @return the size of the plotted points in this object, in pixels
*/
double size() const;
/**
* Set the size for plotted points in this object, in pixels
* @param s the new size
*/
void setSize( double s );
/**
* @return the style used for drawing the points in this object
*/
PointStyle pointStyle() const;
/**
* Set a new style for drawing the points in this object
* @param p the new style
*/
void setPointStyle( PointStyle p );
/**
* @return the default pen for this Object.
* If no other pens are set, this pen will be used for
* points, lines, bars and labels (this pen is always used for points).
*/
const QPen& pen() const;
/**
* Set the default pen for this object
* @p The pen to use
*/
void setPen( const QPen &p );
/**
* @return the pen to use for drawing lines for this Object.
*/
const QPen& linePen() const;
/**
* Set the pen to use for drawing lines for this object
* @p The pen to use
*/
void setLinePen( const QPen &p );
/**
* @return the pen to use for drawing bars for this Object.
*/
const QPen& barPen() const;
/**
* Set the pen to use for drawing bars for this object
* @p The pen to use
*/
void setBarPen( const QPen &p );
/**
* @return the pen to use for drawing labels for this Object.
*/
const QPen& labelPen() const;
/**
* Set the pen to use for labels for this object
* @p The pen to use
*/
void setLabelPen( const QPen &p );
/**
* @return the default Brush to use for this Object.
*/
const QBrush brush() const;
/**
* Set the default brush to use for this object
* @b The brush to use
*/
void setBrush( const QBrush &b );
/**
* @return the brush to use for filling bars for this Object.
*/
const QBrush barBrush() const;
/**
* Set the brush to use for drawing bars for this object
* @b The brush to use
*/
void setBarBrush( const QBrush &b );
/**
* @return the list of KPlotPoints that make up this object
*/
QList< KPlotPoint* > points() const;
/**
* Add a point to the object's list of points, using input data to construct a KPlotPoint.
* @param p the QPointF to add.
* @param label the optional text label for this point
* @param barWidth the width of the bar, if this object is to be drawn with bars
* @note if @param barWidth is left at its default value of 0.0, then the width will be
* automatically set to the distance between this point and the one to its right.
*/
void addPoint( const QPointF &p, const QString &label = QString(), double barWidth = 0.0 );
/**
* Add a given KPlotPoint to the object's list of points.
* @overload
* @param p pointer to the KPlotPoint to add.
*/
void addPoint( KPlotPoint *p );
/**
* Add a point to the object's list of points, using input data to construct a KPlotPoint.
* @overload
* @param x the X-coordinate of the point to add.
* @param y the Y-coordinate of the point to add.
* @param label the optional text label
* @param barWidth the width of the bar, if this object is to be drawn with bars
* @note if @param barWidth is left at its default value of 0.0, then the width will be
* automatically set to the distance between this point and the one to its right.
*/
void addPoint( double x, double y, const QString &label = QString(), double barWidth = 0.0 );
/**
* Remove the QPointF at position index from the list of points
* @param index the index of the point to be removed.
*/
void removePoint( int index );
/**
* Remove and destroy the points of this object
*/
void clearPoints();
/**
* Draw this KPlotObject on the given QPainter
* @param p The QPainter to draw on
* @param pw the KPlotWidget to draw on (this is needed
* for the KPlotWidget::mapToWidget() function)
*/
void draw( QPainter *p, KPlotWidget *pw );
private:
class Private;
Private * const d;
Q_DISABLE_COPY( KPlotObject )
};
Q_DECLARE_OPERATORS_FOR_FLAGS( KPlotObject::PlotTypes )
#endif

View file

@ -1,111 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kplotpoint.h"
#include <QtCore/qalgorithms.h>
#include <QPainter>
#include <kdebug.h>
class KPlotPoint::Private
{
public:
Private( KPlotPoint * qq, const QPointF &p, const QString &l, double bw )
: q( qq ), point( p ), label( l ), barWidth( bw )
{
}
KPlotPoint *q;
QPointF point;
QString label;
double barWidth;
};
KPlotPoint::KPlotPoint()
: d( new Private( this, QPointF(), QString(), 0.0 ) )
{
}
KPlotPoint::KPlotPoint( double x, double y, const QString &label, double barWidth )
: d( new Private( this, QPointF( x, y ), label, barWidth ) )
{
}
KPlotPoint::KPlotPoint( const QPointF &p, const QString &label, double barWidth )
: d( new Private( this, p, label, barWidth ) )
{
}
KPlotPoint::~KPlotPoint()
{
delete d;
}
QPointF KPlotPoint::position() const
{
return d->point;
}
void KPlotPoint::setPosition( const QPointF &pos )
{
d->point = pos;
}
double KPlotPoint::x() const
{
return d->point.x();
}
void KPlotPoint::setX( double x )
{
d->point.setX( x );
}
double KPlotPoint::y() const
{
return d->point.y();
}
void KPlotPoint::setY( double y )
{
d->point.setY( y );
}
QString KPlotPoint::label() const
{
return d->label;
}
void KPlotPoint::setLabel( const QString &label )
{
d->label = label;
}
double KPlotPoint::barWidth() const
{
return d->barWidth;
}
void KPlotPoint::setBarWidth( double w )
{
d->barWidth = w;
}

View file

@ -1,131 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KPLOTPOINT_H
#define KPLOTPOINT_H
#include <kdeui_export.h>
#include <QtCore/qstring.h>
#include <QPointF>
/**
* @class KPlotPoint
* @short Encapsulates a point in the plot.
* A KPlotPoint consists of X and Y coordinates (in Data units),
* an optional label string, and an optional bar-width,
* The bar-width is only used for plots of type KPlotObject::Bars,
* and it allows the width of each bar to be set manually. If
* bar-widths are omitted, then the widths will be set automatically,
* based on the halfway-mark between adjacent points.
*/
class KDEUI_EXPORT KPlotPoint {
public:
/**
* Default constructor.
*/
explicit KPlotPoint();
/**
* Constructor. Sets the KPlotPoint according to the given arguments
* @param x the X-position for the point, in Data units
* @param y the Y-position for the point, in Data units
* @param label the label string for the point. If the string
* is defined, the point will be labeled in the plot.
* @param width the bar width to use for this point (only used for
* plots of type KPlotObject::Bars)
*/
KPlotPoint( double x, double y, const QString &label = QString(), double width = 0.0 );
/**
* Constructor. Sets the KPlotPoint according to the given arguments
* @param p the position for the point, in Data units
* @param label the label string for the point. If the string
* is defined, the point will be labeled in the plot.
* @param width the bar width to use for this point (only used for
* plots of type KPlotObject::Bars)
*/
explicit KPlotPoint( const QPointF &p, const QString &label = QString(), double width = 0.0 );
/**
* Destructor
*/
~KPlotPoint();
/**
* @return the position of the point, in data units
*/
QPointF position() const;
/**
* Set the position of the point, in data units
* @param pos the new position for the point.
*/
void setPosition( const QPointF &pos );
/**
* @return the X-position of the point, in data units
*/
double x() const;
/**
* Set the X-position of the point, in Data units
*/
void setX( double x );
/**
* @return the Y-position of the point, in data units
*/
double y() const;
/**
* Set the Y-position of the point, in Data units
*/
void setY( double y );
/**
* @return the label for the point
*/
QString label() const;
/**
* Set the label for the point
*/
void setLabel( const QString &label );
/**
* @return the bar-width for the point
*/
double barWidth() const;
/**
* Set the bar-width for the point
*/
void setBarWidth( double w );
private:
class Private;
Private * const d;
Q_DISABLE_COPY( KPlotPoint )
};
#endif

View file

@ -1,971 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kplotwidget.h"
#include "moc_kplotwidget.cpp"
#include <math.h>
#include <kdebug.h>
#include <QtGui/qevent.h>
#include <QHash>
#include <QPainter>
#include <QPixmap>
#include <QToolTip>
#include <QtCore/qalgorithms.h>
#include "kplotaxis.h"
#include "kplotpoint.h"
#include "kplotobject.h"
#define XPADDING 20
#define YPADDING 20
#define BIGTICKSIZE 10
#define SMALLTICKSIZE 4
#define TICKOFFSET 0
class KPlotWidget::Private
{
public:
Private( KPlotWidget *qq )
: q( qq ),
cBackground( Qt::black ), cForeground( Qt::white ), cGrid( Qt::gray ),
showGrid( false ), showObjectToolTip( true ), useAntialias( false )
{
// create the axes and setting their default properties
KPlotAxis *leftAxis = new KPlotAxis();
leftAxis->setTickLabelsShown( true );
axes.insert( LeftAxis, leftAxis );
KPlotAxis *bottomAxis = new KPlotAxis();
bottomAxis->setTickLabelsShown( true );
axes.insert( BottomAxis, bottomAxis );
KPlotAxis *rightAxis = new KPlotAxis();
axes.insert( RightAxis, rightAxis );
KPlotAxis *topAxis = new KPlotAxis();
axes.insert( TopAxis, topAxis );
}
~Private()
{
qDeleteAll( objectList );
qDeleteAll( axes );
}
KPlotWidget *q;
void calcDataRectLimits( double x1, double x2, double y1, double y2 );
/**
* @return a value indicating how well the given rectangle is
* avoiding masked regions in the plot. A higher returned value
* indicates that the rectangle is intersecting a larger portion
* of the masked region, or a portion of the masked region which
* is weighted higher.
* @param r The rectangle to be tested
*/
float rectCost( const QRectF &r ) const;
//Colors
QColor cBackground, cForeground, cGrid;
//draw options
bool showGrid : 1;
bool showObjectToolTip : 1;
bool useAntialias : 1;
//padding
int leftPadding, rightPadding, topPadding, bottomPadding;
// hashmap with the axes we have
QHash<Axis, KPlotAxis*> axes;
// List of KPlotObjects
QList<KPlotObject*> objectList;
// Limits of the plot area in data units
QRectF dataRect, secondDataRect;
// Limits of the plot area in pixel units
QRect pixRect;
//Array holding the mask of "used" regions of the plot
QImage plotMask;
};
KPlotWidget::KPlotWidget( QWidget * parent )
: QFrame( parent ), d( new Private( this ) )
{
setAttribute( Qt::WA_OpaquePaintEvent );
setAttribute( Qt::WA_NoSystemBackground );
d->secondDataRect = QRectF(); //default: no secondary data rect
// sets the default limits
d->calcDataRectLimits( 0.0, 1.0, 0.0, 1.0 );
setDefaultPaddings();
setMinimumSize( 150, 150 );
resize( minimumSizeHint() );
}
KPlotWidget::~KPlotWidget()
{
delete d;
}
QSize KPlotWidget::minimumSizeHint() const
{
return QSize( 150, 150 );
}
QSize KPlotWidget::sizeHint() const
{
return size();
}
void KPlotWidget::setLimits( double x1, double x2, double y1, double y2 )
{
d->calcDataRectLimits( x1, x2, y1, y2 );
update();
}
void KPlotWidget::Private::calcDataRectLimits( double x1, double x2, double y1, double y2 )
{
double XA1, XA2, YA1, YA2;
if (x2<x1) { XA1=x2; XA2=x1; }
else { XA1=x1; XA2=x2; }
if ( y2<y1) { YA1=y2; YA2=y1; }
else { YA1=y1; YA2=y2; }
if ( XA2 == XA1 ) {
kWarning() << "x1 and x2 cannot be equal. Setting x2 = x1 + 1.0";
XA2 = XA1 + 1.0;
}
if ( YA2 == YA1 ) {
kWarning() << "y1 and y2 cannot be equal. Setting y2 = y1 + 1.0";
YA2 = YA1 + 1.0;
}
dataRect = QRectF( XA1, YA1, XA2 - XA1, YA2 - YA1 );
q->axis( LeftAxis )->setTickMarks( dataRect.y(), dataRect.height() );
q->axis( BottomAxis )->setTickMarks( dataRect.x(), dataRect.width() );
if ( secondDataRect.isNull() )
{
q->axis( RightAxis )->setTickMarks( dataRect.y(), dataRect.height() );
q->axis( TopAxis )->setTickMarks( dataRect.x(), dataRect.width() );
}
}
void KPlotWidget::setSecondaryLimits( double x1, double x2, double y1, double y2 ) {
double XA1, XA2, YA1, YA2;
if (x2<x1) { XA1=x2; XA2=x1; }
else { XA1=x1; XA2=x2; }
if ( y2<y1) { YA1=y2; YA2=y1; }
else { YA1=y1; YA2=y2; }
if ( XA2 == XA1 ) {
kWarning() << "x1 and x2 cannot be equal. Setting x2 = x1 + 1.0";
XA2 = XA1 + 1.0;
}
if ( YA2 == YA1 ) {
kWarning() << "y1 and y2 cannot be equal. Setting y2 = y1 + 1.0";
YA2 = YA1 + 1.0;
}
d->secondDataRect = QRectF( XA1, YA1, XA2-XA1, YA2-YA1 );
axis(RightAxis)->setTickMarks( d->secondDataRect.y(), d->secondDataRect.height() );
axis(TopAxis)->setTickMarks( d->secondDataRect.x(), d->secondDataRect.width() );
update();
}
void KPlotWidget::clearSecondaryLimits() {
d->secondDataRect = QRectF();
axis(RightAxis)->setTickMarks( d->dataRect.y(), d->dataRect.height() );
axis(TopAxis)->setTickMarks( d->dataRect.x(), d->dataRect.width() );
update();
}
QRectF KPlotWidget::dataRect() const
{
return d->dataRect;
}
QRectF KPlotWidget::secondaryDataRect() const
{
return d->secondDataRect;
}
void KPlotWidget::addPlotObject( KPlotObject *object )
{
// skip null pointers
if ( !object )
return;
d->objectList.append( object );
update();
}
void KPlotWidget::addPlotObjects( const QList< KPlotObject* >& objects )
{
bool addedsome = false;
foreach ( KPlotObject *o, objects )
{
if ( !o )
continue;
d->objectList.append( o );
addedsome = true;
}
if ( addedsome )
update();
}
QList< KPlotObject* > KPlotWidget::plotObjects() const
{
return d->objectList;
}
void KPlotWidget::removeAllPlotObjects()
{
if ( d->objectList.isEmpty() )
return;
qDeleteAll( d->objectList );
d->objectList.clear();
update();
}
void KPlotWidget::resetPlotMask() {
d->plotMask = QImage( pixRect().size(), QImage::Format_ARGB32 );
QColor fillColor = Qt::black;
fillColor.setAlpha( 128 );
d->plotMask.fill( fillColor.rgb() );
}
void KPlotWidget::resetPlot() {
qDeleteAll( d->objectList );
d->objectList.clear();
clearSecondaryLimits();
d->calcDataRectLimits( 0.0, 1.0, 0.0, 1.0 );
KPlotAxis *a = axis( RightAxis );
a->setLabel( QString() );
a->setTickLabelsShown( false );
a = axis( TopAxis );
a->setLabel( QString() );
a->setTickLabelsShown( false );
axis(KPlotWidget::LeftAxis)->setLabel( QString() );
axis(KPlotWidget::BottomAxis)->setLabel( QString() );
resetPlotMask();
}
void KPlotWidget::replacePlotObject( int i, KPlotObject *o )
{
// skip null pointers and invalid indexes
if ( !o || i < 0 || i >= d->objectList.count() )
return;
d->objectList.replace( i, o );
update();
}
QColor KPlotWidget::backgroundColor() const
{
return d->cBackground;
}
QColor KPlotWidget::foregroundColor() const
{
return d->cForeground;
}
QColor KPlotWidget::gridColor() const
{
return d->cGrid;
}
void KPlotWidget::setBackgroundColor( const QColor &bg ) {
d->cBackground = bg;
update();
}
void KPlotWidget::setForegroundColor( const QColor &fg )
{
d->cForeground = fg;
update();
}
void KPlotWidget::setGridColor( const QColor &gc )
{
d->cGrid = gc;
update();
}
bool KPlotWidget::isGridShown() const
{
return d->showGrid;
}
bool KPlotWidget::isObjectToolTipShown() const
{
return d->showObjectToolTip;
}
bool KPlotWidget::antialiasing() const
{
return d->useAntialias;
}
void KPlotWidget::setAntialiasing( bool b )
{
d->useAntialias = b;
update();
}
void KPlotWidget::setShowGrid( bool show ) {
d->showGrid = show;
update();
}
void KPlotWidget::setObjectToolTipShown( bool show )
{
d->showObjectToolTip = show;
}
KPlotAxis* KPlotWidget::axis( Axis type )
{
QHash<Axis, KPlotAxis*>::Iterator it = d->axes.find( type );
return it != d->axes.end() ? it.value() : 0;
}
const KPlotAxis* KPlotWidget::axis( Axis type ) const
{
QHash<Axis, KPlotAxis*>::ConstIterator it = d->axes.constFind( type );
return it != d->axes.constEnd() ? it.value() : 0;
}
QRect KPlotWidget::pixRect() const
{
return d->pixRect;
}
QList<KPlotPoint*> KPlotWidget::pointsUnderPoint( const QPoint& p ) const {
QList<KPlotPoint*> pts;
foreach ( KPlotObject *po, d->objectList ) {
foreach ( KPlotPoint *pp, po->points() ) {
if ( ( p - mapToWidget( pp->position() ).toPoint() ).manhattanLength() <= 4 )
pts << pp;
}
}
return pts;
}
bool KPlotWidget::event( QEvent* e ) {
if ( e->type() == QEvent::ToolTip ) {
if ( d->showObjectToolTip )
{
QHelpEvent *he = static_cast<QHelpEvent*>( e );
QList<KPlotPoint*> pts = pointsUnderPoint( he->pos() - QPoint( leftPadding(), topPadding() ) - contentsRect().topLeft() );
if ( pts.count() > 0 ) {
QToolTip::showText( he->globalPos(), pts.front()->label(), this );
}
}
e->accept();
return true;
}
else
return QFrame::event( e );
}
void KPlotWidget::resizeEvent( QResizeEvent* e ) {
QFrame::resizeEvent( e );
setPixRect();
resetPlotMask();
}
void KPlotWidget::setPixRect() {
int newWidth = contentsRect().width() - leftPadding() - rightPadding();
int newHeight = contentsRect().height() - topPadding() - bottomPadding();
// PixRect starts at (0,0) because we will translate by leftPadding(), topPadding()
d->pixRect = QRect( 0, 0, newWidth, newHeight );
}
QPointF KPlotWidget::mapToWidget( const QPointF& p ) const
{
float px = d->pixRect.left() + d->pixRect.width() * ( p.x() - d->dataRect.x() ) / d->dataRect.width();
float py = d->pixRect.top() + d->pixRect.height() * ( d->dataRect.y() + d->dataRect.height() - p.y() ) / d->dataRect.height();
return QPointF( px, py );
}
void KPlotWidget::maskRect( const QRectF& rf, float fvalue ) {
QRect r = rf.toRect().intersected( d->pixRect );
int value = int( fvalue );
QColor newColor;
for ( int ix=r.left(); ix<r.right(); ++ix ) {
for ( int iy=r.top(); iy<r.bottom(); ++iy ) {
newColor = QColor( d->plotMask.pixel(ix,iy) );
newColor.setAlpha( 200 );
newColor.setRed( qMin( newColor.red() + value, 255 ) );
d->plotMask.setPixel( ix, iy, newColor.rgba() );
}
}
}
void KPlotWidget::maskAlongLine( const QPointF &p1, const QPointF &p2, float fvalue ) {
if ( ! d->pixRect.contains( p1.toPoint() ) && ! d->pixRect.contains( p2.toPoint() ) ) {
return;
}
int value = int( fvalue );
//Determine slope and zeropoint of line
double m = (p2.y() - p1.y())/(p2.x() - p1.x());
double y0 = p1.y() - m*p1.x();
QColor newColor;
//Mask each pixel along the line joining p1 and p2
if ( m > 1.0 || m < -1.0 ) { //step in y-direction
int y1 = int( p1.y() );
int y2 = int( p2.y() );
if ( y1 > y2 ) {
y1 = int( p2.y() );
y2 = int( p1.y() );
}
for ( int y=y1; y<=y2; ++y ) {
int x = int( (y - y0)/m );
if ( d->pixRect.contains( x, y ) ) {
newColor = QColor( d->plotMask.pixel(x,y) );
newColor.setAlpha( 100 );
newColor.setRed( qMin( newColor.red() + value, 255 ) );
d->plotMask.setPixel( x, y, newColor.rgba() );
}
}
} else { //step in x-direction
int x1 = int( p1.x() );
int x2 = int( p2.x() );
if ( x1 > x2 ) {
x1 = int( p2.x() );
x2 = int( p1.x() );
}
for ( int x=x1; x<=x2; ++x ) {
int y = int( y0 + m*x );
if ( d->pixRect.contains( x, y ) ) {
newColor = QColor( d->plotMask.pixel(x,y) );
newColor.setAlpha( 100 );
newColor.setRed( qMin( newColor.red() + value, 255 ) );
d->plotMask.setPixel( x, y, newColor.rgba() );
}
}
}
}
//Determine optimal placement for a text label for point pp. We want
//the label to be near point pp, but we don't want it to overlap with
//other labels or plot elements. We will use a "downhill simplex"
//algorithm to find a label position that minimizes the pixel values
//in the plotMask image over the label's rect(). The sum of pixel
//values in the label's rect is the "cost" of placing the label there.
//
//Because a downhill simplex follows the local gradient to find low
//values, it can get stuck in local minima. To mitigate this, we will
//iteratively attempt each of the initial path offset directions (up,
//down, right, left) in the order of increasing cost at each location.
void KPlotWidget::placeLabel( QPainter *painter, KPlotPoint *pp ) {
int textFlags = Qt::TextSingleLine | Qt::AlignCenter;
QPointF pos = mapToWidget( pp->position() );
if ( ! d->pixRect.contains( pos.toPoint() ) ) return;
QFontMetricsF fm( painter->font(), painter->device() );
QRectF bestRect = fm.boundingRect( QRectF( pos.x(), pos.y(), 1, 1 ), textFlags, pp->label() );
float xStep = 0.5*bestRect.width();
float yStep = 0.5*bestRect.height();
float maxCost = 0.05 * bestRect.width() * bestRect.height();
float bestCost = d->rectCost( bestRect );
//We will travel along a path defined by the maximum decrease in
//the cost at each step. If this path takes us to a local minimum
//whose cost exceeds maxCost, then we will restart at the
//beginning and select the next-best path. The indices of
//already-tried paths are stored in the TriedPathIndex list.
//
//If we try all four first-step paths and still don't get below
//maxCost, then we'll adopt the local minimum position with the
//best cost (designated as bestBadCost).
int iter = 0;
QList<int> TriedPathIndex;
float bestBadCost = 10000;
QRectF bestBadRect;
//needed to halt iteration from inside the switch
bool flagStop = false;
while ( bestCost > maxCost ) {
//Displace the label up, down, left, right; determine which
//step provides the lowest cost
QRectF upRect = bestRect;
upRect.moveTop( upRect.top() + yStep );
float upCost = d->rectCost( upRect );
QRectF downRect = bestRect;
downRect.moveTop( downRect.top() - yStep );
float downCost = d->rectCost( downRect );
QRectF leftRect = bestRect;
leftRect.moveLeft( leftRect.left() - xStep );
float leftCost = d->rectCost( leftRect );
QRectF rightRect = bestRect;
rightRect.moveLeft( rightRect.left() + xStep );
float rightCost = d->rectCost( rightRect );
//which direction leads to the lowest cost?
QList<float> costList;
costList << upCost << downCost << leftCost << rightCost;
int imin = -1;
for ( int i=0; i<costList.size(); ++i ) {
if ( iter == 0 && TriedPathIndex.contains( i ) ) {
continue; //Skip this first-step path, we already tried it!
}
//If this first-step path doesn't improve the cost,
//skip this direction from now on
if ( iter == 0 && costList[i] >= bestCost ) {
TriedPathIndex.append( i );
continue;
}
if ( costList[i] < bestCost && (imin < 0 || costList[i] < costList[imin]) ) {
imin = i;
}
}
//Make a note that we've tried the current first-step path
if ( iter == 0 && imin >= 0 ) {
TriedPathIndex.append( imin );
}
//Adopt the step that produced the best cost
switch ( imin ) {
case 0: //up
bestRect.moveTop( upRect.top() );
bestCost = upCost;
break;
case 1: //down
bestRect.moveTop( downRect.top() );
bestCost = downCost;
break;
case 2: //left
bestRect.moveLeft( leftRect.left() );
bestCost = leftCost;
break;
case 3: //right
bestRect.moveLeft( rightRect.left() );
bestCost = rightCost;
break;
case -1: //no lower cost found!
//We hit a local minimum. Keep the best of these as bestBadRect
if ( bestCost < bestBadCost ) {
bestBadCost = bestCost;
bestBadRect = bestRect;
}
//If all of the first-step paths have now been searched, we'll
//have to adopt the bestBadRect
if ( TriedPathIndex.size() == 4 ) {
bestRect = bestBadRect;
flagStop = true; //halt iteration
break;
}
//If we haven't yet tried all of the first-step paths, start over
if ( TriedPathIndex.size() < 4 ) {
iter = -1; //anticipating the ++iter below
bestRect = fm.boundingRect( QRectF( pos.x(), pos.y(), 1, 1 ), textFlags, pp->label() );
bestCost = d->rectCost( bestRect );
}
break;
}
//Halt iteration, because we've tried all directions and
//haven't gotten below maxCost (we'll adopt the best
//local minimum found)
if ( flagStop ) {
break;
}
++iter;
}
painter->drawText( bestRect, textFlags, pp->label() );
//Is a line needed to connect the label to the point?
float deltax = pos.x() - bestRect.center().x();
float deltay = pos.y() - bestRect.center().y();
float rbest = sqrt( deltax*deltax + deltay*deltay );
if ( rbest > 20.0 ) {
//Draw a rectangle around the label
painter->setBrush( QBrush() );
//QPen pen = painter->pen();
//pen.setStyle( Qt::DotLine );
//painter->setPen( pen );
painter->drawRoundRect( bestRect );
//Now connect the label to the point with a line.
//The line is drawn from the center of the near edge of the rectangle
float xline = bestRect.center().x();
if ( bestRect.left() > pos.x() )
xline = bestRect.left();
if ( bestRect.right() < pos.x() )
xline = bestRect.right();
float yline = bestRect.center().y();
if ( bestRect.top() > pos.y() )
yline = bestRect.top();
if ( bestRect.bottom() < pos.y() )
yline = bestRect.bottom();
painter->drawLine( QPointF( xline, yline ), pos );
}
//Mask the label's rectangle so other labels won't overlap it.
maskRect( bestRect );
}
float KPlotWidget::Private::rectCost( const QRectF &r ) const
{
if ( ! plotMask.rect().contains( r.toRect() ) ) {
return 10000.;
}
//Compute sum of mask values in the rect r
QImage subMask = plotMask.copy( r.toRect() );
int cost = 0;
for ( int ix=0; ix<subMask.width(); ++ix ) {
for ( int iy=0; iy<subMask.height(); ++iy ) {
cost += QColor( subMask.pixel( ix, iy ) ).red();
}
}
return float(cost);
}
void KPlotWidget::paintEvent( QPaintEvent *e ) {
// let QFrame draw its default stuff (like the frame)
QFrame::paintEvent( e );
QPainter p;
p.begin( this );
p.setRenderHint( QPainter::Antialiasing, d->useAntialias );
p.fillRect( rect(), backgroundColor() );
p.translate( leftPadding() + 0.5, topPadding() + 0.5 );
setPixRect();
p.setClipRect( d->pixRect );
p.setClipping( true );
resetPlotMask();
foreach( KPlotObject *po, d->objectList )
po->draw( &p, this );
//DEBUG: Draw the plot mask
// p.drawImage( 0, 0, d->plotMask );
p.setClipping( false );
drawAxes( &p );
p.end();
}
void KPlotWidget::drawAxes( QPainter *p ) {
if ( d->showGrid ) {
p->setPen( gridColor() );
//Grid lines are placed at locations of primary axes' major tickmarks
//vertical grid lines
foreach ( double xx, axis(BottomAxis)->majorTickMarks() ) {
double px = d->pixRect.width() * (xx - d->dataRect.x()) / d->dataRect.width();
p->drawLine( QPointF( px, 0.0 ), QPointF( px, double(d->pixRect.height()) ) );
}
//horizontal grid lines
foreach( double yy, axis(LeftAxis)->majorTickMarks() ) {
double py = d->pixRect.height() * ( 1.0 - (yy - d->dataRect.y()) / d->dataRect.height() );
p->drawLine( QPointF( 0.0, py ), QPointF( double(d->pixRect.width()), py ) );
}
}
p->setPen( foregroundColor() );
p->setBrush( Qt::NoBrush );
//set small font for tick labels
QFont f = p->font();
int s = f.pointSize();
f.setPointSize( s - 2 );
p->setFont( f );
/*** BottomAxis ***/
KPlotAxis *a = axis(BottomAxis);
if (a->isVisible()) {
//Draw axis line
p->drawLine( 0, d->pixRect.height(), d->pixRect.width(), d->pixRect.height() );
// Draw major tickmarks
foreach( double xx, a->majorTickMarks() ) {
double px = d->pixRect.width() * (xx - d->dataRect.x()) / d->dataRect.width();
if ( px > 0 && px < d->pixRect.width() ) {
p->drawLine( QPointF( px, double(d->pixRect.height() - TICKOFFSET)),
QPointF( px, double(d->pixRect.height() - BIGTICKSIZE - TICKOFFSET)) );
//Draw ticklabel
if ( a->areTickLabelsShown() ) {
QRect r( int(px) - BIGTICKSIZE, d->pixRect.height()+BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, a->tickLabel( xx ) );
}
}
}
// Draw minor tickmarks
foreach ( double xx, a->minorTickMarks() ) {
double px = d->pixRect.width() * (xx - d->dataRect.x()) / d->dataRect.width();
if ( px > 0 && px < d->pixRect.width() ) {
p->drawLine( QPointF( px, double(d->pixRect.height() - TICKOFFSET)),
QPointF( px, double(d->pixRect.height() - SMALLTICKSIZE -TICKOFFSET)) );
}
}
// Draw BottomAxis Label
if ( ! a->label().isEmpty() ) {
QRect r( 0, d->pixRect.height() + 2*YPADDING, d->pixRect.width(), YPADDING );
p->drawText( r, Qt::AlignCenter, a->label() );
}
} //End of BottomAxis
/*** LeftAxis ***/
a = axis(LeftAxis);
if (a->isVisible()) {
//Draw axis line
p->drawLine( 0, 0, 0, d->pixRect.height() );
// Draw major tickmarks
foreach( double yy, a->majorTickMarks() ) {
double py = d->pixRect.height() * ( 1.0 - (yy - d->dataRect.y()) / d->dataRect.height() );
if ( py > 0 && py < d->pixRect.height() ) {
p->drawLine( QPointF( TICKOFFSET, py ), QPointF( double(TICKOFFSET + BIGTICKSIZE), py ) );
//Draw ticklabel
if ( a->areTickLabelsShown() ) {
QRect r( -2*BIGTICKSIZE-SMALLTICKSIZE, int(py)-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
p->drawText( r, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, a->tickLabel( yy ) );
}
}
}
// Draw minor tickmarks
foreach ( double yy, a->minorTickMarks() ) {
double py = d->pixRect.height() * ( 1.0 - (yy - d->dataRect.y()) / d->dataRect.height() );
if ( py > 0 && py < d->pixRect.height() ) {
p->drawLine( QPointF( TICKOFFSET, py ), QPointF( double(TICKOFFSET + SMALLTICKSIZE), py ) );
}
}
//Draw LeftAxis Label. We need to draw the text sideways.
if ( ! a->label().isEmpty() ) {
//store current painter translation/rotation state
p->save();
//translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
p->translate( -3*XPADDING, d->pixRect.height() );
p->rotate( -90.0 );
QRect r( 0, 0, d->pixRect.height(), XPADDING );
p->drawText( r, Qt::AlignCenter, a->label() ); //draw the label, now that we are sideways
p->restore(); //restore translation/rotation state
}
} //End of LeftAxis
//Prepare for top and right axes; we may need the secondary data rect
double x0 = d->dataRect.x();
double y0 = d->dataRect.y();
double dw = d->dataRect.width();
double dh = d->dataRect.height();
if ( secondaryDataRect().isValid() ) {
x0 = secondaryDataRect().x();
y0 = secondaryDataRect().y();
dw = secondaryDataRect().width();
dh = secondaryDataRect().height();
}
/*** TopAxis ***/
a = axis(TopAxis);
if (a->isVisible()) {
//Draw axis line
p->drawLine( 0, 0, d->pixRect.width(), 0 );
// Draw major tickmarks
foreach( double xx, a->majorTickMarks() ) {
double px = d->pixRect.width() * (xx - x0) / dw;
if ( px > 0 && px < d->pixRect.width() ) {
p->drawLine( QPointF( px, TICKOFFSET ), QPointF( px, double(BIGTICKSIZE + TICKOFFSET)) );
//Draw ticklabel
if ( a->areTickLabelsShown() ) {
QRect r( int(px) - BIGTICKSIZE, (int)-1.5*BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, a->tickLabel( xx ) );
}
}
}
// Draw minor tickmarks
foreach ( double xx, a->minorTickMarks() ) {
double px = d->pixRect.width() * (xx - x0) / dw;
if ( px > 0 && px < d->pixRect.width() ) {
p->drawLine( QPointF( px, TICKOFFSET ), QPointF( px, double(SMALLTICKSIZE + TICKOFFSET)) );
}
}
// Draw TopAxis Label
if ( ! a->label().isEmpty() ) {
QRect r( 0, 0 - 3*YPADDING, d->pixRect.width(), YPADDING );
p->drawText( r, Qt::AlignCenter, a->label() );
}
} //End of TopAxis
/*** RightAxis ***/
a = axis(RightAxis);
if (a->isVisible()) {
//Draw axis line
p->drawLine( d->pixRect.width(), 0, d->pixRect.width(), d->pixRect.height() );
// Draw major tickmarks
foreach( double yy, a->majorTickMarks() ) {
double py = d->pixRect.height() * ( 1.0 - (yy - y0) / dh );
if ( py > 0 && py < d->pixRect.height() ) {
p->drawLine( QPointF( double(d->pixRect.width() - TICKOFFSET), py ),
QPointF( double(d->pixRect.width() - TICKOFFSET - BIGTICKSIZE), py ) );
//Draw ticklabel
if ( a->areTickLabelsShown() ) {
QRect r( d->pixRect.width() + SMALLTICKSIZE, int(py)-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
p->drawText( r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, a->tickLabel( yy ) );
}
}
}
// Draw minor tickmarks
foreach ( double yy, a->minorTickMarks() ) {
double py = d->pixRect.height() * ( 1.0 - (yy - y0) / dh );
if ( py > 0 && py < d->pixRect.height() ) {
p->drawLine( QPointF( double(d->pixRect.width() - 0.0), py ),
QPointF( double(d->pixRect.width() - 0.0 - SMALLTICKSIZE), py ) );
}
}
//Draw RightAxis Label. We need to draw the text sideways.
if ( ! a->label().isEmpty() ) {
//store current painter translation/rotation state
p->save();
//translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
p->translate( d->pixRect.width() + 2*XPADDING, d->pixRect.height() );
p->rotate( -90.0 );
QRect r( 0, 0, d->pixRect.height(), XPADDING );
p->drawText( r, Qt::AlignCenter, a->label() ); //draw the label, now that we are sideways
p->restore(); //restore translation/rotation state
}
} //End of RightAxis
}
int KPlotWidget::leftPadding() const
{
if ( d->leftPadding >= 0 )
return d->leftPadding;
const KPlotAxis *a = axis( LeftAxis );
if ( a && a->isVisible() && a->areTickLabelsShown() )
{
return !a->label().isEmpty() ? 3 * XPADDING : 2 * XPADDING;
}
return XPADDING;
}
int KPlotWidget::rightPadding() const
{
if ( d->rightPadding >= 0 )
return d->rightPadding;
const KPlotAxis *a = axis( RightAxis );
if ( a && a->isVisible() && a->areTickLabelsShown() )
{
return !a->label().isEmpty() ? 3 * XPADDING : 2 * XPADDING;
}
return XPADDING;
}
int KPlotWidget::topPadding() const
{
if ( d->topPadding >= 0 )
return d->topPadding;
const KPlotAxis *a = axis( TopAxis );
if ( a && a->isVisible() && a->areTickLabelsShown() )
{
return !a->label().isEmpty() ? 3 * YPADDING : 2 * YPADDING;
}
return YPADDING;
}
int KPlotWidget::bottomPadding() const
{
if ( d->bottomPadding >= 0 )
return d->bottomPadding;
const KPlotAxis *a = axis( BottomAxis );
if ( a && a->isVisible() && a->areTickLabelsShown() )
{
return !a->label().isEmpty() ? 3 * YPADDING : 2 * YPADDING;
}
return YPADDING;
}
void KPlotWidget::setLeftPadding( int padding )
{
d->leftPadding = padding;
}
void KPlotWidget::setRightPadding( int padding )
{
d->rightPadding = padding;
}
void KPlotWidget::setTopPadding( int padding )
{
d->topPadding = padding;
}
void KPlotWidget::setBottomPadding( int padding )
{
d->bottomPadding = padding;
}
void KPlotWidget::setDefaultPaddings()
{
d->leftPadding = -1;
d->rightPadding = -1;
d->topPadding = -1;
d->bottomPadding = -1;
}

View file

@ -1,473 +0,0 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KPLOTWIDGET_H
#define KPLOTWIDGET_H
#include <kdeui_export.h>
#include <QtGui/qframe.h>
class KPlotAxis;
class KPlotObject;
class KPlotPoint;
/**
*@class KPlotWidget
*
*@short Generic data plotting widget.
*
*Widget for drawing plots. The basic idea behind KPlotWidget is that
*you don't have to worry about any transformation from your data's
*natural units to screen pixel coordinates; this is handled internally
*by the widget.
*
*Data to be plotted are represented by one or more instances of
*KPlotObject. KPlotObject contains a list of QPointFs to be plotted
*(again, in the data's natural units), as well as information about how
*the data are to be rendered in the plot (i.e., as separate points or
*connected by lines? With what color and point style? etc). See
*KPlotObject for more information.
*
*KPlotWidget automatically adds axis labels with tickmarks and tick
*labels. These are encapsulated in the KPlotAxis class. All you have
*to do is set the limits of the plotting area in data units, and
*KPlotWidget wil figure out the optimal positions and labels for the
*tickmarks on the axes.
*
*Example of usage:
*
* @code
KPlotWidget *kpw = new KPlotWidget( parent );
// setting our limits for the plot
kpw->setLimits( 1.0, 5.0, 1.0, 25.0 );
// creating a plot object whose points are connected by red lines ...
KPlotObject *kpo = new KPlotObject( Qt::red, KPlotObject::Lines );
// ... adding some points to it ...
for ( float x = 1.0; x <= 5.0; x += 0.1 )
kpo->addPoint( x, x*x );
// ... and adding the object to the plot widget
kpw->addPlotObject( kpo );
* @endcode
*
*@note KPlotWidget will take care of the objects added to it, so when
*clearing the objects list (eg with removeAllPlotObjects()) any previous
*reference to a KPlotObject already added to a KPlotWidget will be invalid.
*
*@author Jason Harris
*@version 1.1
*/
class KDEUI_EXPORT KPlotWidget : public QFrame {
Q_OBJECT
Q_PROPERTY(int leftPadding READ leftPadding)
Q_PROPERTY(int rightPadding READ rightPadding)
Q_PROPERTY(int topPadding READ topPadding)
Q_PROPERTY(int bottomPadding READ bottomPadding)
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
Q_PROPERTY(QColor foregroundColor READ foregroundColor WRITE setForegroundColor)
Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor)
Q_PROPERTY(bool grid READ isGridShown WRITE setShowGrid)
Q_PROPERTY(bool objectToolTip READ isObjectToolTipShown WRITE setObjectToolTipShown)
public:
/**
*@short Constructor.
*@param parent the parent widget
*/
explicit KPlotWidget( QWidget * parent = 0 );
/**
*@short Destructor.
*/
virtual ~KPlotWidget();
/**
* The four types of plot axes.
*/
enum Axis
{
LeftAxis = 0, ///< the left axis
BottomAxis, ///< the bottom axis
RightAxis, ///< the right axis
TopAxis ///< the top axis
};
/**
*@return suggested minimum size for the plot widget
*/
virtual QSize minimumSizeHint() const;
/**
*@return suggested size for the plot widget
*/
virtual QSize sizeHint() const;
/**
* Set new data limits for the plot.
* @param x1 the minimum X value in data units
* @param x2 the maximum X value in data units
* @param y1 the minimum Y value in data units
* @param y2 the maximum Y value in data units
*/
void setLimits( double x1, double x2, double y1, double y2 );
/**
* @short Reset the secondary data limits, which control the
* values displayed along the top and right axes.
*
* All data points are *plotted* using the coordinates
* defined by setLimits(), so this function is only useful for
* showing alternate tickmark labels along the top and right
* edges. For example, if you were plotting temperature on the
* X-axis, you could use Centigrade units for the primary
* (bottom) axis, using setLimits( 0.0, 100.0, 0.0, 1.0 ). If
* you also wanted to show Farenheit units along the secondary
* (top) axis, you would additionally use
* setSecondaryLimits( 32.0, 212.0, 0.0, 1.0 ). The data
* added to the plot would have x-coordinates in Centigrade degrees.
*
* @param x1 the minimum X value in secondary data units
* @param x2 the maximum X value in secondary data units
* @param y1 the minimum Y value in secondary data units
* @param y2 the maximum Y value in secondary data units
* @sa setLimits()
*/
void setSecondaryLimits( double x1, double x2, double y1, double y2 );
/**
* Unset the secondary limits, so the top and right axes
* show the same tickmarks as the bottom and left axes (no tickmark
* labels will be drawn for the top and right axes in this case)
*/
void clearSecondaryLimits();
/**
* @return the rectangle representing the boundaries of the current plot,
* in natural data units.
* @sa setLimits()
*/
QRectF dataRect() const;
/**
* @return the rectangle representing the boundaries of the secondary
* data limits, if they have been set. Otherwise, this function
* behaves the same as dataRect().
* @sa setSecondaryLimits()
*/
QRectF secondaryDataRect() const;
/**
* @return the rectangle representing the boundaries of the current plot,
* in screen pixel units.
*/
QRect pixRect() const;
/**
* Add an item to the list of KPlotObjects to be plotted.
* @note do not use this multiple time if many objects have to be added,
* addPlotObjects() is strongly suggested in this case
* @param object the KPlotObject to be added
*/
void addPlotObject( KPlotObject *object );
/**
* Add more than one KPlotObject at one time.
* @param objects the list of KPlotObjects to be added
*/
void addPlotObjects( const QList< KPlotObject* >& objects );
/**
* @return the current list of plot objects
*/
QList< KPlotObject* > plotObjects() const;
/**
* Remove and delete all items from the list of KPlotObjects
*/
void removeAllPlotObjects();
/**
* Reset the mask used for non-overlapping labels so that all
* regions of the plot area are considered empty.
*/
void resetPlotMask();
/**
* Clear the object list, reset the data limits, and remove axis labels
*/
void resetPlot();
/**
* Replace an item in the KPlotObject list.
* @param i the index of the item to be replaced
* @param o pointer to the replacement KPlotObject
*/
void replacePlotObject( int i, KPlotObject *o );
/**
* @return the background color of the plot.
*
* The default color is black.
*/
QColor backgroundColor() const;
/**
* @return the foreground color, used for axes, tickmarks and associated
* labels.
*
* The default color is white.
*/
QColor foregroundColor() const;
/**
* @return the grid color.
*
* The default color is gray.
*/
QColor gridColor() const;
/**
* Set the background color
* @param bg the new background color
*/
void setBackgroundColor( const QColor &bg );
/**
* Set the foreground color
* @param fg the new foreground color
*/
void setForegroundColor( const QColor &fg );
/**
* Set the grid color
* @param gc the new grid color
*/
void setGridColor( const QColor &gc );
/**
* @return whether the grid lines are shown
* Grid lines are not shown by default.
*/
bool isGridShown() const;
/**
* @return whether the tooltip for the point objects is shown.
* Tooltips are enabled by default.
*/
bool isObjectToolTipShown() const;
/**
* @return whether the antialiasing is active
* Antialiasing is not active by default.
*/
bool antialiasing() const;
/**
* Toggle antialiased drawing.
* @param b if true, the plot graphics will be antialiased.
*/
void setAntialiasing( bool b );
/**
* @return the number of pixels to the left of the plot area.
*
* Padding values are set to -1 by default; if unchanged, this
* function will try to guess a good value, based on whether
* ticklabels and/or axis labels need to be drawn.
*/
int leftPadding() const;
/**
* @return the number of pixels to the right of the plot area.
* Padding values are set to -1 by default; if unchanged, this
* function will try to guess a good value, based on whether
* ticklabels and/or axis labels are to be drawn.
*/
int rightPadding() const;
/**
* @return the number of pixels above the plot area.
* Padding values are set to -1 by default; if unchanged, this
* function will try to guess a good value, based on whether
* ticklabels and/or axis labels are to be drawn.
*/
int topPadding() const;
/**
* @return the number of pixels below the plot area.
* Padding values are set to -1 by default; if unchanged, this
* function will try to guess a good value, based on whether
* ticklabels and/or axis labels are to be drawn.
*/
int bottomPadding() const;
/**
* @short Set the number of pixels to the left of the plot area.
* Set this to -1 to revert to automatic determination of padding values.
*/
void setLeftPadding( int padding );
/**
* @short Set the number of pixels to the right of the plot area.
* Set this to -1 to revert to automatic determination of padding values.
*/
void setRightPadding( int padding );
/**
* @short Set the number of pixels above the plot area.
* Set this to -1 to revert to automatic determination of padding values.
*/
void setTopPadding( int padding );
/**
* @short Set the number of pixels below the plot area.
* Set this to -1 to revert to automatic determination of padding values.
*/
void setBottomPadding( int padding );
/**
* @short Revert all four padding values to -1, so that they will be
* automatically determined.
*/
void setDefaultPaddings();
/**
* @short Map a coordinate @param p from the data rect to the physical
* pixel rect.
* Used mainly when drawing.
* @param p the point to be converted, in natural data units
* @return the coordinate in the pixel coordinate system
*/
QPointF mapToWidget( const QPointF& p ) const;
/**
* Indicate that object labels should try to avoid the given
* rectangle in the plot. The rectangle is in pixel coordinates.
*
* @note You should not normally call this function directly.
* It is called by KPlotObject when points, bars and labels are drawn.
* @param r the rectangle defining the region in the plot that
* text labels should avoid (in pixel coordinates)
* @param value Allows you to determine how strongly the rectangle
* should be avoided. Larger values are avoided more strongly.
*/
void maskRect( const QRectF &r, float value=1.0 );
/**
* Indicate that object labels should try to avoid the line
* joining the two given points (in pixel coordinates).
*
* @note You should not normally call this function directly.
* It is called by KPlotObject when lines are drawn in the plot.
* @param p1 the starting point for the line
* @param p2 the ending point for the line
* @param value Allows you to determine how strongly the line
* should be avoided. Larger values are avoided more strongly.
*/
void maskAlongLine( const QPointF &p1, const QPointF &p2, float value=1.0 );
/**
* Place an object label optimally in the plot. This function will
* attempt to place the label as close as it can to the point to which
* the label belongs, while avoiding overlap with regions of the plot
* that have been masked.
*
* @note You should not normally call this function directly.
* It is called internally in KPlotObject::draw().
*
* @param painter Pointer to the painter on which to draw the label
* @param pp pointer to the KPlotPoint whose label is to be drawn.
*/
void placeLabel( QPainter *painter, KPlotPoint *pp );
/**
* @return the axis of the specified @p type, or 0 if no axis has been set.
* @sa Axis
*/
KPlotAxis* axis( Axis type );
/**
* @return the axis of the specified @p type, or 0 if no axis has been set.
* @sa Axis
*/
const KPlotAxis* axis( Axis type ) const;
public Q_SLOTS:
/**
* Toggle whether grid lines are drawn at major tickmarks.
* @param show if true, grid lines will be drawn.
* @sa isGridShown()
*/
void setShowGrid( bool show );
/**
* Toggle the display of a tooltip for point objects.
* @param show whether show the tooltip.
* @sa isObjectToolTipShown()
*/
void setObjectToolTipShown( bool show );
protected:
/**
* Generic event handler.
*/
virtual bool event( QEvent* );
/**
* The paint event handler, executed when update() or repaint() is called.
*/
virtual void paintEvent( QPaintEvent* );
/**
* The resize event handler, called when the widget is resized.
*/
virtual void resizeEvent( QResizeEvent* );
/**
* Draws the plot axes and axis labels.
* @internal Internal use only; one should simply call update()
* to draw the widget with axes and all objects.
* @param p pointer to the painter on which we are drawing
*/
virtual void drawAxes( QPainter *p );
/**
* Synchronize the PixRect with the current widget size and
* padding settings.
*/
void setPixRect();
/**
* @return a list of points in the plot which are within 4 pixels
* of the screen position given as an argument.
* @param p The screen position from which to check for plot points.
*/
QList<KPlotPoint*> pointsUnderPoint( const QPoint& p ) const;
private:
class Private;
Private * const d;
Q_DISABLE_COPY( KPlotWidget )
};
#endif

View file

@ -152,12 +152,6 @@ if (Q_WS_X11)
target_link_libraries(kdeui-kxerrorhandlertest ${X11_X11_LIB})
endif (Q_WS_X11)
## kplottest
set(kplottest_SRCS testplot_widget.cpp testplot_main.cpp)
kde4_add_manual_test(kplottest ${kplottest_SRCS})
target_link_libraries(kplottest ${KDE4_KDEUI_LIBS})
## kcolorutilsdemo
set(kcolorUtilsDemoSources

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View file

@ -1,42 +0,0 @@
/***************************************************************************
testplot_main.cpp - description
-------------------
begin : Thu Oct 26 2006
copyright : (C) 2006 by Jason Harris
email : kstars@30doradus.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "testplot_widget.h"
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>
int main( int argc, char *argv[] )
{
KAboutData aboutData( "testplot", 0, ki18n("Test KPlotWidget"), "0.1",
ki18n("KPlotWidget test program"),
KAboutData::License_GPL,
ki18n("(c) 2006, Jason Harris"),
ki18n("Performs various tests of KPlotWidget"),
"http://edu.kde.org/");
aboutData.addAuthor(ki18n("Jason Harris"), ki18n("no task"),
"kstars@30doradus.org", "http://edu.kde.org/");
KCmdLineArgs::init( argc, argv, &aboutData );
KApplication a;
TestPlot *tp = new TestPlot(0);
tp->show();
QObject::connect(kapp, SIGNAL(lastWindowClosed()), kapp, SLOT(quit()));
return a.exec();
}

View file

@ -1,195 +0,0 @@
/***************************************************************************
testplot_widget.cpp - description
-------------------
begin : Thu Oct 26 2006
copyright : (C) 2006 by Jason Harris
email : kstars@30doradus.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <math.h>
#include <QtGui/QComboBox>
#include <QtGui/QBoxLayout>
#include <QtGui/QPen>
#include <kdebug.h>
#include "kplotwidget.h"
#include "kplotobject.h"
#include "kplotaxis.h"
#include "testplot_widget.h"
TestPlot::TestPlot( QWidget *p ) : KMainWindow( p ), po1(0), po2(0) {
QWidget *w = new QWidget(this);
vlay = new QVBoxLayout(w);
PlotSelector = new QComboBox( w );
PlotSelector->addItem( "Points plot" );
PlotSelector->addItem( "Lines plot" );
PlotSelector->addItem( "Bars plot" );
PlotSelector->addItem( "Points plot with labels" );
PlotSelector->addItem( "Points, lines and bars" );
PlotSelector->addItem( "Points, lines and bars with labels" );
plot = new KPlotWidget( w );
plot->setMinimumSize( 400,400 );
plot->setAntialiasing( true );
vlay->addWidget( PlotSelector );
vlay->addWidget( plot );
setCentralWidget( w );
connect( PlotSelector, SIGNAL(activated(int)), this, SLOT(slotSelectPlot(int)) );
slotSelectPlot( PlotSelector->currentIndex() );
}
void TestPlot::slotSelectPlot( int n ) {
plot->resetPlot();
switch ( n ) {
case 0: //Points plot
{
plot->setLimits( -6.0, 11.0, -10.0, 110.0 );
po1 = new KPlotObject( Qt::white, KPlotObject::Points, 4, KPlotObject::Asterisk );
po2 = new KPlotObject( Qt::green, KPlotObject::Points, 4, KPlotObject::Triangle );
for ( float x=-5.0; x<=10.0; x+=1.0 ) {
po1->addPoint( x, x*x );
po2->addPoint( x, 50.0 - 5.0*x );
}
plot->addPlotObject( po1 );
plot->addPlotObject( po2 );
plot->update();
break;
}
case 1: //Lines plot
{
plot->setLimits( -0.1, 6.38, -1.1, 1.1 );
plot->setSecondaryLimits( -5.73, 365.55, -1.1, 1.1 );
plot->axis(KPlotWidget::TopAxis)->setTickLabelsShown( true );
plot->axis(KPlotWidget::BottomAxis)->setLabel("Angle [radians]");
plot->axis(KPlotWidget::TopAxis)->setLabel("Angle [degrees]");
po1 = new KPlotObject( Qt::red, KPlotObject::Lines, 2 );
po2 = new KPlotObject( Qt::cyan, KPlotObject::Lines, 2 );
for ( float t=0.0; t<=6.28; t+=0.04 ) {
po1->addPoint( t, sin(t) );
po2->addPoint( t, cos(t) );
}
plot->addPlotObject( po1 );
plot->addPlotObject( po2 );
plot->update();
break;
}
case 2: //Bars plot
{
plot->setLimits( -7.0, 7.0, -5.0, 105.0 );
po1 = new KPlotObject( Qt::white, KPlotObject::Bars, 2 );
po1->setBarBrush( QBrush(Qt::green, Qt::Dense4Pattern) );
for ( float x=-6.5; x<=6.5; x+=0.5 ) {
po1->addPoint( x, 100*exp( -0.5*x*x ), "", 0.5 );
}
plot->addPlotObject( po1 );
plot->update();
break;
}
case 3: //Points plot with labels
{
plot->setLimits( -1.1, 1.1, -1.1, 1.1 );
po1 = new KPlotObject( Qt::yellow, KPlotObject::Points, 10, KPlotObject::Star );
po1->setLabelPen( QPen(Qt::green) );
po1->addPoint( 0.0, 0.8, "North" );
po1->addPoint( 0.57, 0.57, "Northeast" );
po1->addPoint( 0.8, 0.0, "East" );
po1->addPoint( 0.57, -0.57, "Southeast" );
po1->addPoint( 0.0, -0.8, "South" );
po1->addPoint( -0.57, -0.57, "Southwest" );
po1->addPoint( -0.8, 0.0, "West" );
po1->addPoint( -0.57, 0.57, "Northwest" );
plot->addPlotObject( po1 );
plot->update();
break;
}
case 4: //Points, Lines and Bars plot
{
plot->setLimits( -2.1, 2.1, -0.1, 4.1 );
po1 = new KPlotObject( Qt::white, KPlotObject::Points, 10, KPlotObject::Pentagon );
po1->setShowLines( true );
po1->setShowBars( true );
po1->setLabelPen( QPen( QColor( "#AA8800" ) ) );
po1->setLinePen( QPen( Qt::red, 3.0, Qt::DashDotLine ) );
po1->setBarBrush( QBrush( Qt::blue, Qt::BDiagPattern ) );
po1->addPoint( -1.75, 0.5 );
po1->addPoint( -1.25, 1.0 );
po1->addPoint( -0.75, 1.25 );
po1->addPoint( -0.25, 1.5 );
po1->addPoint( 0.25, 2.5 );
po1->addPoint( 0.75, 3.0 );
po1->addPoint( 1.25, 1.5 );
po1->addPoint( 1.75, 1.75 );
plot->addPlotObject( po1 );
update();
break;
}
case 5: //Points, Lines and Bars plot with labels
{
plot->setLimits( -2.1, 2.1, -0.1, 4.1 );
po1 = new KPlotObject( Qt::white, KPlotObject::Points, 10, KPlotObject::Pentagon );
po1->setShowLines( true );
po1->setShowBars( true );
po1->setLabelPen( QPen( QColor( "#AA8800" ) ) );
po1->setLinePen( QPen( Qt::red, 3.0, Qt::DashDotLine ) );
po1->setBarBrush( QBrush( Qt::blue, Qt::BDiagPattern ) );
po1->addPoint( -1.75, 0.5, "A" );
po1->addPoint( -1.25, 1.0, "B" );
po1->addPoint( -0.75, 1.25, "C" );
po1->addPoint( -0.25, 1.5, "D" );
po1->addPoint( 0.25, 2.5, "E" );
po1->addPoint( 0.75, 3.0, "F" );
po1->addPoint( 1.25, 1.5, "G" );
po1->addPoint( 1.75, 1.75, "H" );
plot->addPlotObject( po1 );
update();
break;
}
}
}
#include "moc_testplot_widget.cpp"

View file

@ -1,46 +0,0 @@
/***************************************************************************
testplot_widget.h - description
-------------------
begin : Thu Oct 26 2006
copyright : (C) 2006 by Jason Harris
email : kstars@30doradus.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef TESTPLOT_WIDGET_H
#define TESTPLOT_WIDGET_H
#include <kmainwindow.h>
#include <QComboBox>
#include <QVBoxLayout>
class KPlotWidget;
class KPlotObject;
class TestPlot : public KMainWindow {
Q_OBJECT
public:
TestPlot( QWidget *parent=0 );
~TestPlot() {}
public slots:
void slotSelectPlot( int index );
private:
QVBoxLayout *vlay;
QComboBox *PlotSelector;
KPlotWidget *plot;
KPlotObject *po1, *po2;
};
#endif

View file

@ -198,7 +198,6 @@ void KCompletion::addWeightedItem( const QString& item )
}
addItem( item.left( len ), weight );
return;
}

View file

@ -20,16 +20,15 @@
#include "kxmlguifactory_p.h"
#include "kxmlguiclient.h"
#include "kxmlguibuilder.h"
#include <QtGui/QWidget>
#include <kglobal.h>
#include <kdebug.h>
#include <assert.h>
#include <kcomponentdata.h>
#include <ktoolbar.h>
#include <QWidget>
#include <assert.h>
using namespace KXMLGUI;
void ActionList::plug( QWidget *container, int index ) const

View file

@ -23,10 +23,10 @@
#include <QtCore/QMap>
#include <QtXml/qdom.h>
#include <QStack>
#include <QWidget>
#include <kaction.h>
#include <QWidget>
class KXMLGUIClient;
class KXMLGUIBuilder;

View file

@ -236,12 +236,6 @@ ToolTip=Pixmap Sequence Widget (KDE)
WhatsThis=A simple widget showing a fixed size pixmap sequence.
Group=Display (KDE)
[KPlotWidget]
IncludeFile=kplotwidget.h
ToolTip=A plot widget
WhatsThis=A widget for easily making 2-dimensional plots
Group=Plot (KDE)
[KPushButton]
ToolTip=Improved QPushButton (KDE)
WhatsThis=An improved QPushButton to follow KDE settings