Commit 1c4fdc2e authored by Gus Grubba's avatar Gus Grubba
Browse files

First shot at it

parent 2f5324fd
......@@ -99,15 +99,6 @@ SOURCES += \
libs/shapelib/shpopen.c \
libs/shapelib/safileio.c
#
# [REQUIRED] QWT plotting library dependency. Provides plotting capabilities.
#
!MobileBuild {
include(libs/qwt.pri)
DEPENDPATH += libs/qwt
INCLUDEPATH += libs/qwt
}
#
# [REQUIRED] SDL dependency. Provides joystick/gamepad support.
# The SDL is packaged with QGC for the Mac and Windows. Linux support requires installing the SDL
......
######################################################################
# Automatically generated by qmake (2.01a) Wed Feb 10 11:43:43 2010
######################################################################
QWTSRCDIR = libs/qwt
DEPENDPATH += $$QWTSRCDIR
INCLUDEPATH += $$QWTSRCDIR
# Input
HEADERS += $$QWTSRCDIR/qwt.h \
$$QWTSRCDIR/qwt_abstract_legend.h \
$$QWTSRCDIR/qwt_abstract_scale.h \
$$QWTSRCDIR/qwt_abstract_scale_draw.h \
$$QWTSRCDIR/qwt_abstract_slider.h \
$$QWTSRCDIR/qwt_analog_clock.h \
$$QWTSRCDIR/qwt_arrow_button.h \
$$QWTSRCDIR/qwt_clipper.h \
$$QWTSRCDIR/qwt_color_map.h \
$$QWTSRCDIR/qwt_compass.h \
$$QWTSRCDIR/qwt_compass_rose.h \
$$QWTSRCDIR/qwt_counter.h \
$$QWTSRCDIR/qwt_curve_fitter.h \
$$QWTSRCDIR/qwt_dial.h \
$$QWTSRCDIR/qwt_dial_needle.h \
$$QWTSRCDIR/qwt_dyngrid_layout.h \
$$QWTSRCDIR/qwt_event_pattern.h \
$$QWTSRCDIR/qwt_global.h \
$$QWTSRCDIR/qwt_graphic.h \
$$QWTSRCDIR/qwt_interval.h \
$$QWTSRCDIR/qwt_knob.h \
$$QWTSRCDIR/qwt_legend.h \
$$QWTSRCDIR/qwt_legend_data.h \
$$QWTSRCDIR/qwt_legend_label.h \
$$QWTSRCDIR/qwt_magnifier.h \
$$QWTSRCDIR/qwt_math.h \
$$QWTSRCDIR/qwt_null_paintdevice.h \
$$QWTSRCDIR/qwt_painter.h \
$$QWTSRCDIR/qwt_painter_command.h \
$$QWTSRCDIR/qwt_panner.h \
$$QWTSRCDIR/qwt_picker.h \
$$QWTSRCDIR/qwt_picker_machine.h \
$$QWTSRCDIR/qwt_pixel_matrix.h \
$$QWTSRCDIR/qwt_plot.h \
$$QWTSRCDIR/qwt_plot_canvas.h \
$$QWTSRCDIR/qwt_plot_curve.h \
$$QWTSRCDIR/qwt_plot_dict.h \
$$QWTSRCDIR/qwt_plot_grid.h \
$$QWTSRCDIR/qwt_plot_item.h \
$$QWTSRCDIR/qwt_plot_layout.h \
$$QWTSRCDIR/qwt_plot_magnifier.h \
$$QWTSRCDIR/qwt_plot_marker.h \
$$QWTSRCDIR/qwt_plot_panner.h \
$$QWTSRCDIR/qwt_plot_picker.h \
$$QWTSRCDIR/qwt_plot_rasteritem.h \
$$QWTSRCDIR/qwt_plot_scaleitem.h \
$$QWTSRCDIR/qwt_plot_seriesitem.h \
$$QWTSRCDIR/qwt_plot_spectrogram.h \
$$QWTSRCDIR/qwt_plot_svgitem.h \
$$QWTSRCDIR/qwt_plot_zoomer.h \
$$QWTSRCDIR/qwt_point_mapper.h \
$$QWTSRCDIR/qwt_point_data.h \
$$QWTSRCDIR/qwt_raster_data.h \
$$QWTSRCDIR/qwt_round_scale_draw.h \
$$QWTSRCDIR/qwt_scale_div.h \
$$QWTSRCDIR/qwt_scale_draw.h \
$$QWTSRCDIR/qwt_scale_engine.h \
$$QWTSRCDIR/qwt_scale_map.h \
$$QWTSRCDIR/qwt_scale_widget.h \
$$QWTSRCDIR/qwt_series_data.h \
$$QWTSRCDIR/qwt_slider.h \
$$QWTSRCDIR/qwt_spline.h \
$$QWTSRCDIR/qwt_symbol.h \
$$QWTSRCDIR/qwt_text.h \
$$QWTSRCDIR/qwt_text_engine.h \
$$QWTSRCDIR/qwt_text_label.h \
$$QWTSRCDIR/qwt_thermo.h \
$$QWTSRCDIR/qwt_transform.h \
$$QWTSRCDIR/qwt_wheel.h \
$$QWTSRCDIR/qwt_widget_overlay.h
SOURCES += $$QWTSRCDIR/qwt_abstract_legend.cpp \
$$QWTSRCDIR/qwt_abstract_scale.cpp \
$$QWTSRCDIR/qwt_abstract_scale_draw.cpp \
$$QWTSRCDIR/qwt_abstract_slider.cpp \
$$QWTSRCDIR/qwt_analog_clock.cpp \
$$QWTSRCDIR/qwt_arrow_button.cpp \
$$QWTSRCDIR/qwt_clipper.cpp \
$$QWTSRCDIR/qwt_color_map.cpp \
$$QWTSRCDIR/qwt_compass.cpp \
$$QWTSRCDIR/qwt_compass_rose.cpp \
$$QWTSRCDIR/qwt_counter.cpp \
$$QWTSRCDIR/qwt_curve_fitter.cpp \
$$QWTSRCDIR/qwt_dial.cpp \
$$QWTSRCDIR/qwt_dial_needle.cpp \
$$QWTSRCDIR/qwt_dyngrid_layout.cpp \
$$QWTSRCDIR/qwt_event_pattern.cpp \
$$QWTSRCDIR/qwt_graphic.cpp \
$$QWTSRCDIR/qwt_interval.cpp \
$$QWTSRCDIR/qwt_knob.cpp \
$$QWTSRCDIR/qwt_legend.cpp \
$$QWTSRCDIR/qwt_legend_data.cpp \
$$QWTSRCDIR/qwt_legend_label.cpp \
$$QWTSRCDIR/qwt_magnifier.cpp \
$$QWTSRCDIR/qwt_math.cpp \
$$QWTSRCDIR/qwt_null_paintdevice.cpp \
$$QWTSRCDIR/qwt_painter.cpp \
$$QWTSRCDIR/qwt_painter_command.cpp \
$$QWTSRCDIR/qwt_panner.cpp \
$$QWTSRCDIR/qwt_picker.cpp \
$$QWTSRCDIR/qwt_picker_machine.cpp \
$$QWTSRCDIR/qwt_pixel_matrix.cpp \
$$QWTSRCDIR/qwt_plot.cpp \
$$QWTSRCDIR/qwt_plot_axis.cpp \
$$QWTSRCDIR/qwt_plot_canvas.cpp \
$$QWTSRCDIR/qwt_plot_curve.cpp \
$$QWTSRCDIR/qwt_plot_dict.cpp \
$$QWTSRCDIR/qwt_plot_grid.cpp \
$$QWTSRCDIR/qwt_plot_item.cpp \
$$QWTSRCDIR/qwt_plot_layout.cpp \
$$QWTSRCDIR/qwt_plot_magnifier.cpp \
$$QWTSRCDIR/qwt_plot_marker.cpp \
$$QWTSRCDIR/qwt_plot_panner.cpp \
$$QWTSRCDIR/qwt_plot_picker.cpp \
$$QWTSRCDIR/qwt_plot_rasteritem.cpp \
$$QWTSRCDIR/qwt_plot_scaleitem.cpp \
$$QWTSRCDIR/qwt_plot_seriesitem.cpp \
$$QWTSRCDIR/qwt_plot_spectrogram.cpp \
$$QWTSRCDIR/qwt_plot_svgitem.cpp \
$$QWTSRCDIR/qwt_plot_xml.cpp \
$$QWTSRCDIR/qwt_plot_zoomer.cpp \
$$QWTSRCDIR/qwt_point_mapper.cpp \
$$QWTSRCDIR/qwt_point_data.cpp \
$$QWTSRCDIR/qwt_raster_data.cpp \
$$QWTSRCDIR/qwt_round_scale_draw.cpp \
$$QWTSRCDIR/qwt_scale_div.cpp \
$$QWTSRCDIR/qwt_scale_draw.cpp \
$$QWTSRCDIR/qwt_scale_engine.cpp \
$$QWTSRCDIR/qwt_scale_map.cpp \
$$QWTSRCDIR/qwt_scale_widget.cpp \
$$QWTSRCDIR/qwt_series_data.cpp \
$$QWTSRCDIR/qwt_slider.cpp \
$$QWTSRCDIR/qwt_spline.cpp \
$$QWTSRCDIR/qwt_symbol.cpp \
$$QWTSRCDIR/qwt_text.cpp \
$$QWTSRCDIR/qwt_text_engine.cpp \
$$QWTSRCDIR/qwt_text_label.cpp \
$$QWTSRCDIR/qwt_thermo.cpp \
$$QWTSRCDIR/qwt_transform.cpp \
$$QWTSRCDIR/qwt_wheel.cpp \
$$QWTSRCDIR/qwt_widget_overlay.cpp
add_library(qwt
qwt_abstract_legend.cpp
qwt_abstract_scale.cpp
qwt_abstract_scale_draw.cpp
qwt_abstract_slider.cpp
qwt_analog_clock.cpp
qwt_arrow_button.cpp
qwt_clipper.cpp
qwt_color_map.cpp
qwt_compass.cpp
qwt_compass_rose.cpp
qwt_counter.cpp
qwt_curve_fitter.cpp
qwt_dial.cpp
qwt_dial_needle.cpp
qwt_dyngrid_layout.cpp
qwt_event_pattern.cpp
qwt_graphic.cpp
qwt_interval.cpp
qwt_knob.cpp
qwt_legend.cpp
qwt_legend_data.cpp
qwt_legend_label.cpp
qwt_magnifier.cpp
qwt_math.cpp
qwt_null_paintdevice.cpp
qwt_painter.cpp
qwt_painter_command.cpp
qwt_panner.cpp
qwt_picker.cpp
qwt_picker_machine.cpp
qwt_pixel_matrix.cpp
qwt_plot.cpp
qwt_plot_axis.cpp
qwt_plot_canvas.cpp
qwt_plot_curve.cpp
qwt_plot_dict.cpp
qwt_plot_grid.cpp
qwt_plot_item.cpp
qwt_plot_layout.cpp
qwt_plot_magnifier.cpp
qwt_plot_marker.cpp
qwt_plot_panner.cpp
qwt_plot_picker.cpp
qwt_plot_rasteritem.cpp
qwt_plot_scaleitem.cpp
qwt_plot_seriesitem.cpp
qwt_plot_spectrogram.cpp
qwt_plot_svgitem.cpp
qwt_plot_xml.cpp
qwt_plot_zoomer.cpp
qwt_point_data.cpp
qwt_point_mapper.cpp
qwt_raster_data.cpp
qwt_round_scale_draw.cpp
qwt_scale_div.cpp
qwt_scale_draw.cpp
qwt_scale_engine.cpp
qwt_scale_map.cpp
qwt_scale_widget.cpp
qwt_series_data.cpp
qwt_slider.cpp
qwt_spline.cpp
qwt_symbol.cpp
qwt_text.cpp
qwt_text_engine.cpp
qwt_text_label.cpp
qwt_thermo.cpp
qwt_transform.cpp
qwt_wheel.cpp
qwt_widget_overlay.cpp
)
target_link_libraries(qwt
Qt5::Concurrent
Qt5::Core
Qt5::Svg
Qt5::Widgets
)
target_include_directories(qwt INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_H
#define QWT_H
#include "qwt_global.h"
/*!
Some constants for use within Qwt.
*/
namespace Qwt
{
};
#endif
######################################################################
# Automatically generated by qmake (2.01a) Wed Feb 10 11:43:43 2010
######################################################################
QWTSRCDIR = libs/qwt
DEPENDPATH += $$QWTSRCDIR
INCLUDEPATH += $$QWTSRCDIR
# Input
HEADERS += $$QWTSRCDIR/qwt.h \
$$QWTSRCDIR/qwt_abstract_scale.h \
$$QWTSRCDIR/qwt_abstract_scale_draw.h \
$$QWTSRCDIR/qwt_abstract_slider.h \
$$QWTSRCDIR/qwt_analog_clock.h \
$$QWTSRCDIR/qwt_array.h \
$$QWTSRCDIR/qwt_arrow_button.h \
$$QWTSRCDIR/qwt_clipper.h \
$$QWTSRCDIR/qwt_color_map.h \
$$QWTSRCDIR/qwt_compass.h \
$$QWTSRCDIR/qwt_compass_rose.h \
$$QWTSRCDIR/qwt_counter.h \
$$QWTSRCDIR/qwt_curve_fitter.h \
$$QWTSRCDIR/qwt_data.h \
$$QWTSRCDIR/qwt_dial.h \
$$QWTSRCDIR/qwt_dial_needle.h \
$$QWTSRCDIR/qwt_double_interval.h \
$$QWTSRCDIR/qwt_double_range.h \
$$QWTSRCDIR/qwt_double_rect.h \
$$QWTSRCDIR/qwt_dyngrid_layout.h \
$$QWTSRCDIR/qwt_event_pattern.h \
$$QWTSRCDIR/qwt_global.h \
$$QWTSRCDIR/qwt_interval_data.h \
$$QWTSRCDIR/qwt_knob.h \
$$QWTSRCDIR/qwt_layout_metrics.h \
$$QWTSRCDIR/qwt_legend.h \
$$QWTSRCDIR/qwt_legend_item.h \
$$QWTSRCDIR/qwt_legend_itemmanager.h \
$$QWTSRCDIR/qwt_magnifier.h \
$$QWTSRCDIR/qwt_math.h \
$$QWTSRCDIR/qwt_paint_buffer.h \
$$QWTSRCDIR/qwt_painter.h \
$$QWTSRCDIR/qwt_panner.h \
$$QWTSRCDIR/qwt_picker.h \
$$QWTSRCDIR/qwt_picker_machine.h \
$$QWTSRCDIR/qwt_plot.h \
$$QWTSRCDIR/qwt_plot_canvas.h \
$$QWTSRCDIR/qwt_plot_curve.h \
$$QWTSRCDIR/qwt_plot_dict.h \
$$QWTSRCDIR/qwt_plot_grid.h \
$$QWTSRCDIR/qwt_plot_item.h \
$$QWTSRCDIR/qwt_plot_layout.h \
$$QWTSRCDIR/qwt_plot_magnifier.h \
$$QWTSRCDIR/qwt_plot_marker.h \
$$QWTSRCDIR/qwt_plot_panner.h \
$$QWTSRCDIR/qwt_plot_picker.h \
$$QWTSRCDIR/qwt_plot_printfilter.h \
$$QWTSRCDIR/qwt_plot_rasteritem.h \
$$QWTSRCDIR/qwt_plot_scaleitem.h \
$$QWTSRCDIR/qwt_plot_spectrogram.h \
$$QWTSRCDIR/qwt_plot_svgitem.h \
$$QWTSRCDIR/qwt_plot_zoomer.h \
$$QWTSRCDIR/qwt_polygon.h \
$$QWTSRCDIR/qwt_raster_data.h \
$$QWTSRCDIR/qwt_rect.h \
$$QWTSRCDIR/qwt_round_scale_draw.h \
$$QWTSRCDIR/qwt_scale_div.h \
$$QWTSRCDIR/qwt_scale_draw.h \
$$QWTSRCDIR/qwt_scale_engine.h \
$$QWTSRCDIR/qwt_scale_map.h \
$$QWTSRCDIR/qwt_scale_widget.h \
$$QWTSRCDIR/qwt_slider.h \
$$QWTSRCDIR/qwt_spline.h \
$$QWTSRCDIR/qwt_symbol.h \
$$QWTSRCDIR/qwt_text.h \
$$QWTSRCDIR/qwt_text_engine.h \
$$QWTSRCDIR/qwt_text_label.h \
$$QWTSRCDIR/qwt_thermo.h \
$$QWTSRCDIR/qwt_valuelist.h \
$$QWTSRCDIR/qwt_wheel.h
SOURCES += $$QWTSRCDIR/qwt_abstract_scale.cpp \
$$QWTSRCDIR/qwt_abstract_scale_draw.cpp \
$$QWTSRCDIR/qwt_abstract_slider.cpp \
$$QWTSRCDIR/qwt_analog_clock.cpp \
$$QWTSRCDIR/qwt_arrow_button.cpp \
$$QWTSRCDIR/qwt_clipper.cpp \
$$QWTSRCDIR/qwt_color_map.cpp \
$$QWTSRCDIR/qwt_compass.cpp \
$$QWTSRCDIR/qwt_compass_rose.cpp \
$$QWTSRCDIR/qwt_counter.cpp \
$$QWTSRCDIR/qwt_curve_fitter.cpp \
$$QWTSRCDIR/qwt_data.cpp \
$$QWTSRCDIR/qwt_dial.cpp \
$$QWTSRCDIR/qwt_dial_needle.cpp \
$$QWTSRCDIR/qwt_double_interval.cpp \
$$QWTSRCDIR/qwt_double_range.cpp \
$$QWTSRCDIR/qwt_double_rect.cpp \
$$QWTSRCDIR/qwt_dyngrid_layout.cpp \
$$QWTSRCDIR/qwt_event_pattern.cpp \
$$QWTSRCDIR/qwt_interval_data.cpp \
$$QWTSRCDIR/qwt_knob.cpp \
$$QWTSRCDIR/qwt_layout_metrics.cpp \
$$QWTSRCDIR/qwt_legend.cpp \
$$QWTSRCDIR/qwt_legend_item.cpp \
$$QWTSRCDIR/qwt_magnifier.cpp \
$$QWTSRCDIR/qwt_math.cpp \
$$QWTSRCDIR/qwt_paint_buffer.cpp \
$$QWTSRCDIR/qwt_painter.cpp \
$$QWTSRCDIR/qwt_panner.cpp \
$$QWTSRCDIR/qwt_picker.cpp \
$$QWTSRCDIR/qwt_picker_machine.cpp \
$$QWTSRCDIR/qwt_plot.cpp \
$$QWTSRCDIR/qwt_plot_axis.cpp \
$$QWTSRCDIR/qwt_plot_canvas.cpp \
$$QWTSRCDIR/qwt_plot_curve.cpp \
$$QWTSRCDIR/qwt_plot_dict.cpp \
$$QWTSRCDIR/qwt_plot_grid.cpp \
$$QWTSRCDIR/qwt_plot_item.cpp \
$$QWTSRCDIR/qwt_plot_layout.cpp \
$$QWTSRCDIR/qwt_plot_magnifier.cpp \
$$QWTSRCDIR/qwt_plot_marker.cpp \
$$QWTSRCDIR/qwt_plot_panner.cpp \
$$QWTSRCDIR/qwt_plot_picker.cpp \
$$QWTSRCDIR/qwt_plot_print.cpp \
$$QWTSRCDIR/qwt_plot_printfilter.cpp \
$$QWTSRCDIR/qwt_plot_rasteritem.cpp \
$$QWTSRCDIR/qwt_plot_scaleitem.cpp \
$$QWTSRCDIR/qwt_plot_spectrogram.cpp \
$$QWTSRCDIR/qwt_plot_svgitem.cpp \
$$QWTSRCDIR/qwt_plot_xml.cpp \
$$QWTSRCDIR/qwt_plot_zoomer.cpp \
$$QWTSRCDIR/qwt_raster_data.cpp \
$$QWTSRCDIR/qwt_rect.cpp \
$$QWTSRCDIR/qwt_round_scale_draw.cpp \
$$QWTSRCDIR/qwt_scale_div.cpp \
$$QWTSRCDIR/qwt_scale_draw.cpp \
$$QWTSRCDIR/qwt_scale_engine.cpp \
$$QWTSRCDIR/qwt_scale_map.cpp \
$$QWTSRCDIR/qwt_scale_widget.cpp \
$$QWTSRCDIR/qwt_slider.cpp \
$$QWTSRCDIR/qwt_spline.cpp \
$$QWTSRCDIR/qwt_symbol.cpp \
$$QWTSRCDIR/qwt_text.cpp \
$$QWTSRCDIR/qwt_text_engine.cpp \
$$QWTSRCDIR/qwt_text_label.cpp \
$$QWTSRCDIR/qwt_thermo.cpp \
$$QWTSRCDIR/qwt_wheel.cpp
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_abstract_legend.h"
/*!
Constructor
\param parent Parent widget
*/
QwtAbstractLegend::QwtAbstractLegend( QWidget *parent ):
QFrame( parent )
{
}
//! Destructor
QwtAbstractLegend::~QwtAbstractLegend()
{
}
/*!
Return the extent, that is needed for elements to scroll
the legend ( usually scrollbars ),
\param orientation Orientation
\return Extent of the corresponding scroll element
*/
int QwtAbstractLegend::scrollExtent( Qt::Orientation orientation ) const
{
Q_UNUSED( orientation );
return 0;
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_ABSTRACT_LEGEND_H
#define QWT_ABSTRACT_LEGEND_H
#include "qwt_global.h"
#include "qwt_legend_data.h"
#include <qframe.h>
#include <qlist.h>
class QVariant;
/*!
\brief Abstract base class for legend widgets
Legends, that need to be under control of the QwtPlot layout system
need to be derived from QwtAbstractLegend.
\note Other type of legends can be implemented by connecting to
the QwtPlot::legendDataChanged() signal. But as these legends
are unknown to the plot layout system the layout code
( on screen and for QwtPlotRenderer ) need to be organized
in application code.
\sa QwtLegend
*/
class QWT_EXPORT QwtAbstractLegend : public QFrame
{
Q_OBJECT
public:
explicit QwtAbstractLegend( QWidget *parent = NULL );
virtual ~QwtAbstractLegend();
/*!
Render the legend into a given rectangle.
\param painter Painter
\param rect Bounding rectangle
\param fillBackground When true, fill rect with the widget background
\sa renderLegend() is used by QwtPlotRenderer
*/
virtual void renderLegend( QPainter *painter,
const QRectF &rect, bool fillBackground ) const = 0;
//! \return True, when no plot item is inserted
virtual bool isEmpty() const = 0;
virtual int scrollExtent( Qt::Orientation ) const;
public Q_SLOTS:
/*!
\brief Update the entries for a plot item
\param itemInfo Info about an item
\param data List of legend entry attributes for the item
*/
virtual void updateLegend( const QVariant &itemInfo,
const QList<QwtLegendData> &data ) = 0;
};
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_abstract_scale.h"
#include "qwt_scale_engine.h"
#include "qwt_scale_draw.h"
#include "qwt_scale_div.h"
#include "qwt_scale_map.h"
#include "qwt_interval.h"
class QwtAbstractScale::PrivateData
{
public:
PrivateData():
maxMajor( 5 ),
maxMinor( 3 ),
stepSize( 0.0 )
{
scaleEngine = new QwtLinearScaleEngine();
scaleDraw = new QwtScaleDraw();
}
~PrivateData()
{
delete scaleEngine;
delete scaleDraw;
}
QwtScaleEngine *scaleEngine;
QwtAbstractScaleDraw *scaleDraw;
int maxMajor;
int maxMinor;
double stepSize;
};
/*!
Constructor
\param parent Parent widget
Creates a default QwtScaleDraw and a QwtLinearScaleEngine.
The initial scale boundaries are set to [ 0.0, 100.0 ]
The scaleStepSize() is initialized to 0.0, scaleMaxMajor() to 5
and scaleMaxMajor to 3.
*/
QwtAbstractScale::QwtAbstractScale( QWidget *parent ):
QWidget( parent )
{
d_data = new PrivateData;
rescale( 0.0, 100.0, d_data->stepSize );
}
//! Destructor
QwtAbstractScale::~QwtAbstractScale()
{
delete d_data;
}
/*!
Set the lower bound of the scale
\param value Lower bound
\sa lowerBound(), setScale(), setUpperBound()
\note For inverted scales the lower bound
is greater than the upper bound
*/
void QwtAbstractScale::setLowerBound( double value )
{
setScale( value, upperBound() );
}
/*!
\return Lower bound of the scale
\sa setLowerBound(), setScale(), upperBound()
*/
double QwtAbstractScale::lowerBound() const
{
return d_data->scaleDraw->scaleDiv().lowerBound();
}
/*!
Set the upper bound of the scale
\param value Upper bound
\sa upperBound(), setScale(), setLowerBound()
\note For inverted scales the lower bound
is greater than the upper bound
*/
void QwtAbstractScale::setUpperBound( double value )
{
setScale( lowerBound(), value );
}
/*!
\return Upper bound of the scale
\sa setUpperBound(), setScale(), lowerBound()
*/
double QwtAbstractScale::upperBound() const
{
return d_data->scaleDraw->scaleDiv().upperBound();
}
/*!
\brief Specify a scale.
Define a scale by an interval
The ticks are calculated using scaleMaxMinor(),
scaleMaxMajor() and scaleStepSize().
\param lowerBound lower limit of the scale interval
\param upperBound upper limit of the scale interval
\note For inverted scales the lower bound
is greater than the upper bound
*/
void QwtAbstractScale::setScale( double lowerBound, double upperBound )
{
rescale( lowerBound, upperBound, d_data->stepSize );
}
/*!
\brief Specify a scale.
Define a scale by an interval
The ticks are calculated using scaleMaxMinor(),
scaleMaxMajor() and scaleStepSize().
\param interval Interval
*/
void QwtAbstractScale::setScale( const QwtInterval &interval )
{
setScale( interval.minValue(), interval.maxValue() );
}
/*!
\brief Specify a scale.
scaleMaxMinor(), scaleMaxMajor() and scaleStepSize() and have no effect.
\param scaleDiv Scale division
\sa setAutoScale()
*/
void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv )
{
if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
{
#if 1
if ( d_data->scaleEngine )
{
d_data->scaleDraw->setTransformation(
d_data->scaleEngine->transformation() );
}
#endif
d_data->scaleDraw->setScaleDiv( scaleDiv );
scaleChange();
}
}
/*!
\brief Set the maximum number of major tick intervals.
The scale's major ticks are calculated automatically such that
the number of major intervals does not exceed ticks.
The default value is 5.
\param ticks Maximal number of major ticks.
\sa scaleMaxMajor(), setScaleMaxMinor(),
setScaleStepSize(), QwtScaleEngine::divideInterval()
*/
void QwtAbstractScale::setScaleMaxMajor( int ticks )
{
if ( ticks != d_data->maxMajor )
{
d_data->maxMajor = ticks;
updateScaleDraw();
}
}
/*!
\return Maximal number of major tick intervals
\sa setScaleMaxMajor(), scaleMaxMinor()
*/
int QwtAbstractScale::scaleMaxMajor() const
{
return d_data->maxMajor;
}
/*!
\brief Set the maximum number of minor tick intervals
The scale's minor ticks are calculated automatically such that
the number of minor intervals does not exceed ticks.
The default value is 3.
\param ticks Maximal number of minor ticks.
\sa scaleMaxMajor(), setScaleMaxMinor(),
setScaleStepSize(), QwtScaleEngine::divideInterval()
*/
void QwtAbstractScale::setScaleMaxMinor( int ticks )
{
if ( ticks != d_data->maxMinor )
{
d_data->maxMinor = ticks;
updateScaleDraw();
}
}
/*!
\return Maximal number of minor tick intervals
\sa setScaleMaxMinor(), scaleMaxMajor()
*/
int QwtAbstractScale::scaleMaxMinor() const
{
return d_data->maxMinor;
}
/*!
\brief Set the step size used for calculating a scale division
The step size is hint for calculating the intervals for
the major ticks of the scale. A value of 0.0 is interpreted
as no hint.
\param stepSize Hint for the step size of the scale
\sa scaleStepSize(), QwtScaleEngine::divideScale()
\note Position and distance between the major ticks also
depends on scaleMaxMajor().
*/
void QwtAbstractScale::setScaleStepSize( double stepSize )
{
if ( stepSize != d_data->stepSize )
{
d_data->stepSize = stepSize;
updateScaleDraw();
}
}
/*!
\return Hint for the step size of the scale
\sa setScaleStepSize(), QwtScaleEngine::divideScale()
*/
double QwtAbstractScale::scaleStepSize() const
{
return d_data->stepSize;
}
/*!
\brief Set a scale draw
scaleDraw has to be created with new and will be deleted in
the destructor or the next call of setAbstractScaleDraw().
\sa abstractScaleDraw()
*/
void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw )
{
if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw )
return;
if ( d_data->scaleDraw != NULL )
scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() );
delete d_data->scaleDraw;
d_data->scaleDraw = scaleDraw;
}
/*!
\return Scale draw
\sa setAbstractScaleDraw()
*/
QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw()
{
return d_data->scaleDraw;
}
/*!
\return Scale draw
\sa setAbstractScaleDraw()
*/
const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const
{
return d_data->scaleDraw;
}
/*!
\brief Set a scale engine
The scale engine is responsible for calculating the scale division
and provides a transformation between scale and widget coordinates.
scaleEngine has to be created with new and will be deleted in
the destructor or the next call of setScaleEngine.
*/
void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine )
{
if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine )
{
delete d_data->scaleEngine;
d_data->scaleEngine = scaleEngine;
}
}
/*!
\return Scale engine
\sa setScaleEngine()
*/
const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
{
return d_data->scaleEngine;
}
/*!
\return Scale engine
\sa setScaleEngine()
*/
QwtScaleEngine *QwtAbstractScale::scaleEngine()
{
return d_data->scaleEngine;
}
/*!
\return Scale boundaries and positions of the ticks
The scale division might have been assigned explicitly
or calculated implicitly by rescale().
*/
const QwtScaleDiv &QwtAbstractScale::scaleDiv() const
{
return d_data->scaleDraw->scaleDiv();
}
/*!
\return Map to translate between scale and widget coordinates
*/
const QwtScaleMap &QwtAbstractScale::scaleMap() const
{
return d_data->scaleDraw->scaleMap();
}
/*!
Translate a scale value into a widget coordinate
\param value Scale value
\return Corresponding widget coordinate for value
\sa scaleMap(), invTransform()
*/
int QwtAbstractScale::transform( double value ) const
{
return qRound( d_data->scaleDraw->scaleMap().transform( value ) );
}
/*!
Translate a widget coordinate into a scale value
\param value Widget coordinate
\return Corresponding scale coordinate for value
\sa scaleMap(), transform()
*/
double QwtAbstractScale::invTransform( int value ) const
{
return d_data->scaleDraw->scaleMap().invTransform( value );
}
/*!
\return True, when the scale is increasing in opposite direction
to the widget coordinates
*/
bool QwtAbstractScale::isInverted() const
{
return d_data->scaleDraw->scaleMap().isInverting();
}
/*!
\return The boundary with the smaller value
\sa maximum(), lowerBound(), upperBound()
*/
double QwtAbstractScale::minimum() const
{
return qMin( d_data->scaleDraw->scaleDiv().lowerBound(),
d_data->scaleDraw->scaleDiv().upperBound() );
}
/*!
\return The boundary with the larger value
\sa minimum(), lowerBound(), upperBound()
*/
double QwtAbstractScale::maximum() const
{
return qMax( d_data->scaleDraw->scaleDiv().lowerBound(),
d_data->scaleDraw->scaleDiv().upperBound() );
}
//! Notify changed scale
void QwtAbstractScale::scaleChange()
{
}
/*!
Recalculate the scale division and update the scale.
\param lowerBound Lower limit of the scale interval
\param upperBound Upper limit of the scale interval
\param stepSize Major step size
\sa scaleChange()
*/
void QwtAbstractScale::rescale(
double lowerBound, double upperBound, double stepSize )
{
const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale(
lowerBound, upperBound, d_data->maxMajor, d_data->maxMinor, stepSize );
if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
{
#if 1
d_data->scaleDraw->setTransformation(
d_data->scaleEngine->transformation() );
#endif
d_data->scaleDraw->setScaleDiv( scaleDiv );
scaleChange();
}
}
void QwtAbstractScale::updateScaleDraw()
{
rescale( d_data->scaleDraw->scaleDiv().lowerBound(),
d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize );
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_ABSTRACT_SCALE_H
#define QWT_ABSTRACT_SCALE_H
#include "qwt_global.h"
#include <qwidget.h>
class QwtScaleEngine;
class QwtAbstractScaleDraw;
class QwtScaleDiv;
class QwtScaleMap;
class QwtInterval;
/*!
\brief An abstract base class for widgets having a scale
The scale of an QwtAbstractScale is determined by a QwtScaleDiv
definition, that contains the boundaries and the ticks of the scale.
The scale is painted using a QwtScaleDraw object.
The scale division might be assigned explicitly - but usually
it is calculated from the boundaries using a QwtScaleEngine.
The scale engine also decides the type of transformation of the scale
( linear, logarithmic ... ).
*/
class QWT_EXPORT QwtAbstractScale: public QWidget
{
Q_OBJECT
Q_PROPERTY( double lowerBound READ lowerBound WRITE setLowerBound )
Q_PROPERTY( double upperBound READ upperBound WRITE setUpperBound )
Q_PROPERTY( int scaleMaxMajor READ scaleMaxMajor WRITE setScaleMaxMajor )
Q_PROPERTY( int scaleMaxMinor READ scaleMaxMinor WRITE setScaleMaxMinor )
Q_PROPERTY( double scaleStepSize READ scaleStepSize WRITE setScaleStepSize )
public:
QwtAbstractScale( QWidget *parent = NULL );
virtual ~QwtAbstractScale();
void setScale( double lowerBound, double upperBound );
void setScale( const QwtInterval & );
void setScale( const QwtScaleDiv & );
const QwtScaleDiv& scaleDiv() const;
void setLowerBound( double value );
double lowerBound() const;
void setUpperBound( double value );
double upperBound() const;
void setScaleStepSize( double stepSize );
double scaleStepSize() const;
void setScaleMaxMajor( int ticks );
int scaleMaxMinor() const;
void setScaleMaxMinor( int ticks );
int scaleMaxMajor() const;
void setScaleEngine( QwtScaleEngine * );
const QwtScaleEngine *scaleEngine() const;
QwtScaleEngine *scaleEngine();
int transform( double ) const;
double invTransform( int ) const;
bool isInverted() const;
double minimum() const;
double maximum() const;
const QwtScaleMap &scaleMap() const;
protected:
void rescale( double lowerBound,
double upperBound, double stepSize );
void setAbstractScaleDraw( QwtAbstractScaleDraw * );
const QwtAbstractScaleDraw *abstractScaleDraw() const;
QwtAbstractScaleDraw *abstractScaleDraw();
virtual void scaleChange();
private:
void updateScaleDraw();
class PrivateData;
PrivateData *d_data;
};
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_abstract_scale_draw.h"
#include "qwt_math.h"
#include "qwt_text.h"
#include "qwt_painter.h"
#include "qwt_scale_map.h"
#include <qpainter.h>
#include <qpalette.h>
#include <qmap.h>
#include <qlocale.h>
class QwtAbstractScaleDraw::PrivateData
{
public:
PrivateData():
spacing( 4.0 ),
penWidth( 0 ),
minExtent( 0.0 )
{
components = QwtAbstractScaleDraw::Backbone
| QwtAbstractScaleDraw::Ticks
| QwtAbstractScaleDraw::Labels;
tickLength[QwtScaleDiv::MinorTick] = 4.0;
tickLength[QwtScaleDiv::MediumTick] = 6.0;
tickLength[QwtScaleDiv::MajorTick] = 8.0;
}
ScaleComponents components;
QwtScaleMap map;
QwtScaleDiv scaleDiv;
double spacing;
double tickLength[QwtScaleDiv::NTickTypes];
int penWidth;
double minExtent;
QMap<double, QwtText> labelCache;
};
/*!
\brief Constructor
The range of the scale is initialized to [0, 100],
The spacing (distance between ticks and labels) is
set to 4, the tick lengths are set to 4,6 and 8 pixels
*/
QwtAbstractScaleDraw::QwtAbstractScaleDraw()
{
d_data = new QwtAbstractScaleDraw::PrivateData;
}
//! Destructor
QwtAbstractScaleDraw::~QwtAbstractScaleDraw()
{
delete d_data;
}
/*!
En/Disable a component of the scale
\param component Scale component
\param enable On/Off
\sa hasComponent()
*/
void QwtAbstractScaleDraw::enableComponent(
ScaleComponent component, bool enable )
{
if ( enable )
d_data->components |= component;
else
d_data->components &= ~component;
}
/*!
Check if a component is enabled
\param component Component type
\return true, when component is enabled
\sa enableComponent()
*/
bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
{
return ( d_data->components & component );
}
/*!
Change the scale division
\param scaleDiv New scale division
*/
void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &scaleDiv )
{
d_data->scaleDiv = scaleDiv;
d_data->map.setScaleInterval( scaleDiv.lowerBound(), scaleDiv.upperBound() );
d_data->labelCache.clear();
}
/*!
Change the transformation of the scale
\param transformation New scale transformation
*/
void QwtAbstractScaleDraw::setTransformation(
QwtTransform *transformation )
{
d_data->map.setTransformation( transformation );
}
//! \return Map how to translate between scale and pixel values
const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const
{
return d_data->map;
}
//! \return Map how to translate between scale and pixel values
QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
{
return d_data->map;
}
//! \return scale division
const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
{
return d_data->scaleDiv;
}
/*!
\brief Specify the width of the scale pen
\param width Pen width
\sa penWidth()
*/
void QwtAbstractScaleDraw::setPenWidth( int width )
{
if ( width < 0 )
width = 0;
if ( width != d_data->penWidth )
d_data->penWidth = width;
}
/*!
\return Scale pen width
\sa setPenWidth()
*/
int QwtAbstractScaleDraw::penWidth() const
{
return d_data->penWidth;
}
/*!
\brief Draw the scale
\param painter The painter
\param palette Palette, text color is used for the labels,
foreground color for ticks and backbone
*/
void QwtAbstractScaleDraw::draw( QPainter *painter,
const QPalette& palette ) const
{
painter->save();
QPen pen = painter->pen();
pen.setWidth( d_data->penWidth );
pen.setCosmetic( false );
painter->setPen( pen );
if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
{
painter->save();
painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
const QList<double> &majorTicks =
d_data->scaleDiv.ticks( QwtScaleDiv::MajorTick );
for ( int i = 0; i < majorTicks.count(); i++ )
{
const double v = majorTicks[i];
if ( d_data->scaleDiv.contains( v ) )
drawLabel( painter, v );
}
painter->restore();
}
if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
{
painter->save();
QPen pen = painter->pen();
pen.setColor( palette.color( QPalette::WindowText ) );
pen.setCapStyle( Qt::FlatCap );
painter->setPen( pen );
for ( int tickType = QwtScaleDiv::MinorTick;
tickType < QwtScaleDiv::NTickTypes; tickType++ )
{
const QList<double> &ticks = d_data->scaleDiv.ticks( tickType );
for ( int i = 0; i < ticks.count(); i++ )
{
const double v = ticks[i];
if ( d_data->scaleDiv.contains( v ) )
drawTick( painter, v, d_data->tickLength[tickType] );
}
}
painter->restore();
}
if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
{
painter->save();
QPen pen = painter->pen();
pen.setColor( palette.color( QPalette::WindowText ) );
pen.setCapStyle( Qt::FlatCap );
painter->setPen( pen );
drawBackbone( painter );
painter->restore();
}
painter->restore();
}
/*!
\brief Set the spacing between tick and labels
The spacing is the distance between ticks and labels.
The default spacing is 4 pixels.
\param spacing Spacing
\sa spacing()
*/
void QwtAbstractScaleDraw::setSpacing( double spacing )
{
if ( spacing < 0 )
spacing = 0;
d_data->spacing = spacing;
}
/*!
\brief Get the spacing
The spacing is the distance between ticks and labels.
The default spacing is 4 pixels.
\return Spacing
\sa setSpacing()
*/
double QwtAbstractScaleDraw::spacing() const
{
return d_data->spacing;
}
/*!
\brief Set a minimum for the extent
The extent is calculated from the components of the
scale draw. In situations, where the labels are
changing and the layout depends on the extent (f.e scrolling
a scale), setting an upper limit as minimum extent will
avoid jumps of the layout.
\param minExtent Minimum extent
\sa extent(), minimumExtent()
*/
void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
{
if ( minExtent < 0.0 )
minExtent = 0.0;
d_data->minExtent = minExtent;
}
/*!
Get the minimum extent
\return Minimum extent
\sa extent(), setMinimumExtent()
*/
double QwtAbstractScaleDraw::minimumExtent() const
{
return d_data->minExtent;
}
/*!
Set the length of the ticks
\param tickType Tick type
\param length New length
\warning the length is limited to [0..1000]
*/
void QwtAbstractScaleDraw::setTickLength(
QwtScaleDiv::TickType tickType, double length )
{
if ( tickType < QwtScaleDiv::MinorTick ||
tickType > QwtScaleDiv::MajorTick )
{
return;
}
if ( length < 0.0 )
length = 0.0;
const double maxTickLen = 1000.0;
if ( length > maxTickLen )
length = maxTickLen;
d_data->tickLength[tickType] = length;
}
/*!
\return Length of the ticks
\sa setTickLength(), maxTickLength()
*/
double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
{
if ( tickType < QwtScaleDiv::MinorTick ||
tickType > QwtScaleDiv::MajorTick )
{
return 0;
}
return d_data->tickLength[tickType];
}
/*!
\return Length of the longest tick
Useful for layout calculations
\sa tickLength(), setTickLength()
*/
double QwtAbstractScaleDraw::maxTickLength() const
{
double length = 0.0;
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
length = qMax( length, d_data->tickLength[i] );
return length;
}
/*!
\brief Convert a value into its representing label
The value is converted to a plain text using
QLocale().toString(value).
This method is often overloaded by applications to have individual
labels.
\param value Value
\return Label string.
*/
QwtText QwtAbstractScaleDraw::label( double value ) const
{
return QLocale().toString( value );
}
/*!
\brief Convert a value into its representing label and cache it.
The conversion between value and label is called very often
in the layout and painting code. Unfortunately the
calculation of the label sizes might be slow (really slow
for rich text in Qt4), so it's necessary to cache the labels.
\param font Font
\param value Value
\return Tick label
*/
const QwtText &QwtAbstractScaleDraw::tickLabel(
const QFont &font, double value ) const
{
QMap<double, QwtText>::const_iterator it = d_data->labelCache.find( value );
if ( it == d_data->labelCache.end() )
{
QwtText lbl = label( value );
lbl.setRenderFlags( 0 );
lbl.setLayoutAttribute( QwtText::MinimumLayout );
( void )lbl.textSize( font ); // initialize the internal cache
it = d_data->labelCache.insert( value, lbl );
}
return ( *it );
}
/*!
Invalidate the cache used by tickLabel()
The cache is invalidated, when a new QwtScaleDiv is set. If
the labels need to be changed. while the same QwtScaleDiv is set,
invalidateCache() needs to be called manually.
*/
void QwtAbstractScaleDraw::invalidateCache()
{
d_data->labelCache.clear();
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_ABSTRACT_SCALE_DRAW_H
#define QWT_ABSTRACT_SCALE_DRAW_H
#include "qwt_global.h"
#include "qwt_scale_div.h"
#include "qwt_text.h"
class QPalette;
class QPainter;
class QFont;
class QwtTransform;
class QwtScaleMap;
/*!
\brief A abstract base class for drawing scales
QwtAbstractScaleDraw can be used to draw linear or logarithmic scales.
After a scale division has been specified as a QwtScaleDiv object
using setScaleDiv(), the scale can be drawn with the draw() member.
*/
class QWT_EXPORT QwtAbstractScaleDraw
{
public:
/*!
Components of a scale
\sa enableComponent(), hasComponent
*/
enum ScaleComponent
{
//! Backbone = the line where the ticks are located
Backbone = 0x01,
//! Ticks
Ticks = 0x02,
//! Labels
Labels = 0x04
};
//! Scale components
typedef QFlags<ScaleComponent> ScaleComponents;
QwtAbstractScaleDraw();
virtual ~QwtAbstractScaleDraw();
void setScaleDiv( const QwtScaleDiv &s );
const QwtScaleDiv& scaleDiv() const;
void setTransformation( QwtTransform * );
const QwtScaleMap &scaleMap() const;
QwtScaleMap &scaleMap();
void enableComponent( ScaleComponent, bool enable = true );
bool hasComponent( ScaleComponent ) const;
void setTickLength( QwtScaleDiv::TickType, double length );
double tickLength( QwtScaleDiv::TickType ) const;
double maxTickLength() const;
void setSpacing( double margin );
double spacing() const;
void setPenWidth( int width );
int penWidth() const;
virtual void draw( QPainter *, const QPalette & ) const;
virtual QwtText label( double ) const;
/*!
Calculate the extent
The extent is the distance from the baseline to the outermost
pixel of the scale draw in opposite to its orientation.
It is at least minimumExtent() pixels.
\param font Font used for drawing the tick labels
\return Number of pixels
\sa setMinimumExtent(), minimumExtent()
*/
virtual double extent( const QFont &font ) const = 0;
void setMinimumExtent( double );
double minimumExtent() const;
protected:
/*!
Draw a tick
\param painter Painter
\param value Value of the tick
\param len Length of the tick
\sa drawBackbone(), drawLabel()
*/
virtual void drawTick( QPainter *painter, double value, double len ) const = 0;
/*!
Draws the baseline of the scale
\param painter Painter
\sa drawTick(), drawLabel()
*/
virtual void drawBackbone( QPainter *painter ) const = 0;
/*!
Draws the label for a major scale tick
\param painter Painter
\param value Value
\sa drawTick(), drawBackbone()
*/
virtual void drawLabel( QPainter *painter, double value ) const = 0;
void invalidateCache();
const QwtText &tickLabel( const QFont &, double value ) const;
private:
QwtAbstractScaleDraw( const QwtAbstractScaleDraw & );
QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & );
class PrivateData;
PrivateData *d_data;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QwtAbstractScaleDraw::ScaleComponents )
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_abstract_slider.h"
#include "qwt_abstract_scale_draw.h"
#include "qwt_math.h"
#include "qwt_scale_map.h"
#include <qevent.h>
#if QT_VERSION < 0x040601
#define qFabs(x) ::fabs(x)
#endif
static double qwtAlignToScaleDiv(
const QwtAbstractSlider *slider, double value )
{
const QwtScaleDiv &sd = slider->scaleDiv();
const int tValue = slider->transform( value );
if ( tValue == slider->transform( sd.lowerBound() ) )
return sd.lowerBound();
if ( tValue == slider->transform( sd.lowerBound() ) )
return sd.upperBound();
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
{
const QList<double> ticks = sd.ticks( i );
for ( int j = 0; j < ticks.size(); j++ )
{
if ( slider->transform( ticks[ j ] ) == tValue )
return ticks[ j ];
}
}
return value;
}
class QwtAbstractSlider::PrivateData
{
public:
PrivateData():
isScrolling( false ),
isTracking( true ),
pendingValueChanged( false ),
readOnly( false ),
totalSteps( 100 ),
singleSteps( 1 ),
pageSteps( 10 ),
stepAlignment( true ),
isValid( false ),
value( 0.0 ),
wrapping( false ),
invertedControls( false )
{
}
bool isScrolling;
bool isTracking;
bool pendingValueChanged;
bool readOnly;
uint totalSteps;
uint singleSteps;
uint pageSteps;
bool stepAlignment;
bool isValid;
double value;
bool wrapping;
bool invertedControls;
};
/*!
\brief Constructor
The scale is initialized to [0.0, 100.0], the
number of steps is set to 100 with 1 and 10 and single
an page step sizes. Step alignment is enabled.
The initial value is invalid.
\param parent Parent widget
*/
QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ):
QwtAbstractScale( parent )
{
d_data = new QwtAbstractSlider::PrivateData;
setScale( 0.0, 100.0 );
setFocusPolicy( Qt::StrongFocus );
}
//! Destructor
QwtAbstractSlider::~QwtAbstractSlider()
{
delete d_data;
}
/*!
Set the value to be valid/invalid
\param on When true, the value is invalidated
\sa setValue()
*/
void QwtAbstractSlider::setValid( bool on )
{
if ( on != d_data->isValid )
{
d_data->isValid = on;
sliderChange();
Q_EMIT valueChanged( d_data->value );
}
}
//! \return True, when the value is invalid
bool QwtAbstractSlider::isValid() const
{
return d_data->isValid;
}
/*!
En/Disable read only mode
In read only mode the slider can't be controlled by mouse
or keyboard.
\param on Enables in case of true
\sa isReadOnly()
\warning The focus policy is set to Qt::StrongFocus or Qt::NoFocus
*/
void QwtAbstractSlider::setReadOnly( bool on )
{
if ( d_data->readOnly != on )
{
d_data->readOnly = on;
setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
update();
}
}
/*!
In read only mode the slider can't be controlled by mouse
or keyboard.
\return true if read only
\sa setReadOnly()
*/
bool QwtAbstractSlider::isReadOnly() const
{
return d_data->readOnly;
}
/*!
\brief Enables or disables tracking.
If tracking is enabled, the slider emits the valueChanged()
signal while the movable part of the slider is being dragged.
If tracking is disabled, the slider emits the valueChanged() signal
only when the user releases the slider.
Tracking is enabled by default.
\param on \c true (enable) or \c false (disable) tracking.
\sa isTracking(), sliderMoved()
*/
void QwtAbstractSlider::setTracking( bool on )
{
d_data->isTracking = on;
}
/*!
\return True, when tracking has been enabled
\sa setTracking()
*/
bool QwtAbstractSlider::isTracking() const
{
return d_data->isTracking;
}
/*!
Mouse press event handler
\param event Mouse event
*/
void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( !d_data->isValid || lowerBound() == upperBound() )
return;
d_data->isScrolling = isScrollPosition( event->pos() );
if ( d_data->isScrolling )
{
d_data->pendingValueChanged = false;
Q_EMIT sliderPressed();
}
}
/*!
Mouse Move Event handler
\param event Mouse event
*/
void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( d_data->isValid && d_data->isScrolling )
{
double value = scrolledTo( event->pos() );
if ( value != d_data->value )
{
value = boundedValue( value );
if ( d_data->stepAlignment )
{
value = alignedValue( value );
}
else
{
value = qwtAlignToScaleDiv( this, value );
}
if ( value != d_data->value )
{
d_data->value = value;
sliderChange();
Q_EMIT sliderMoved( d_data->value );
if ( d_data->isTracking )
Q_EMIT valueChanged( d_data->value );
else
d_data->pendingValueChanged = true;
}
}
}
}
/*!
Mouse Release Event handler
\param event Mouse event
*/
void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( d_data->isScrolling && d_data->isValid )
{
d_data->isScrolling = false;
if ( d_data->pendingValueChanged )
Q_EMIT valueChanged( d_data->value );
Q_EMIT sliderReleased();
}
}
/*!
Wheel Event handler
In/decreases the value by s number of steps. The direction
depends on the invertedControls() property.
When the control or shift modifier is pressed the wheel delta
( divided by 120 ) is mapped to an increment according to
pageSteps(). Otherwise it is mapped to singleSteps().
\param event Wheel event
*/
void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( !d_data->isValid || d_data->isScrolling )
return;
int numSteps = 0;
if ( ( event->modifiers() & Qt::ControlModifier) ||
( event->modifiers() & Qt::ShiftModifier ) )
{
// one page regardless of delta
numSteps = d_data->pageSteps;
if ( event->delta() < 0 )
numSteps = -numSteps;
}
else
{
const int numTurns = ( event->delta() / 120 );
numSteps = numTurns * d_data->singleSteps;
}
if ( d_data->invertedControls )
numSteps = -numSteps;
const double value = incrementedValue( d_data->value, numSteps );
if ( value != d_data->value )
{
d_data->value = value;
sliderChange();
Q_EMIT sliderMoved( d_data->value );
Q_EMIT valueChanged( d_data->value );
}
}
/*!
Handles key events
QwtAbstractSlider handles the following keys:
- Qt::Key_Left\n
Add/Subtract singleSteps() in direction to lowerBound();
- Qt::Key_Right\n
Add/Subtract singleSteps() in direction to upperBound();
- Qt::Key_Down\n
Subtract singleSteps(), when invertedControls() is false
- Qt::Key_Up\n
Add singleSteps(), when invertedControls() is false
- Qt::Key_PageDown\n
Subtract pageSteps(), when invertedControls() is false
- Qt::Key_PageUp\n
Add pageSteps(), when invertedControls() is false
- Qt::Key_Home\n
Set the value to the minimum()
- Qt::Key_End\n
Set the value to the maximum()
\param event Key event
\sa isReadOnly()
*/
void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( !d_data->isValid || d_data->isScrolling )
return;
int numSteps = 0;
double value = d_data->value;
switch ( event->key() )
{
case Qt::Key_Left:
{
numSteps = -static_cast<int>( d_data->singleSteps );
if ( isInverted() )
numSteps = -numSteps;
break;
}
case Qt::Key_Right:
{
numSteps = d_data->singleSteps;
if ( isInverted() )
numSteps = -numSteps;
break;
}
case Qt::Key_Down:
{
numSteps = -static_cast<int>( d_data->singleSteps );
if ( d_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_Up:
{
numSteps = d_data->singleSteps;
if ( d_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_PageUp:
{
numSteps = d_data->pageSteps;
if ( d_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_PageDown:
{
numSteps = -static_cast<int>( d_data->pageSteps );
if ( d_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_Home:
{
value = minimum();
break;
}
case Qt::Key_End:
{
value = maximum();
break;
}
default:;
{
event->ignore();
}
}
if ( numSteps != 0 )
{
value = incrementedValue( d_data->value, numSteps );
}
if ( value != d_data->value )
{
d_data->value = value;
sliderChange();
Q_EMIT sliderMoved( d_data->value );
Q_EMIT valueChanged( d_data->value );
}
}
/*!
\brief Set the number of steps
The range of the slider is divided into a number of steps from
which the value increments according to user inputs depend.
The default setting is 100.
\param stepCount Number of steps
\sa totalSteps(), setSingleSteps(), setPageSteps()
*/
void QwtAbstractSlider::setTotalSteps( uint stepCount )
{
d_data->totalSteps = stepCount;
}
/*!
\return Number of steps
\sa setTotalSteps(), singleSteps(), pageSteps()
*/
uint QwtAbstractSlider::totalSteps() const
{
return d_data->totalSteps;
}
/*!
\brief Set the number of steps for a single increment
The range of the slider is divided into a number of steps from
which the value increments according to user inputs depend.
\param stepCount Number of steps
\sa singleSteps(), setTotalSteps(), setPageSteps()
*/
void QwtAbstractSlider::setSingleSteps( uint stepCount )
{
d_data->singleSteps = stepCount;
}
/*!
\return Number of steps
\sa setSingleSteps(), totalSteps(), pageSteps()
*/
uint QwtAbstractSlider::singleSteps() const
{
return d_data->singleSteps;
}
/*!
\brief Set the number of steps for a page increment
The range of the slider is divided into a number of steps from
which the value increments according to user inputs depend.
\param stepCount Number of steps
\sa pageSteps(), setTotalSteps(), setSingleSteps()
*/
void QwtAbstractSlider::setPageSteps( uint stepCount )
{
d_data->pageSteps = stepCount;
}
/*!
\return Number of steps
\sa setPageSteps(), totalSteps(), singleSteps()
*/
uint QwtAbstractSlider::pageSteps() const
{
return d_data->pageSteps;
}
/*!
\brief Enable step alignment
When step alignment is enabled values resulting from slider
movements are aligned to the step size.
\param on Enable step alignment when true
\sa stepAlignment()
*/
void QwtAbstractSlider::setStepAlignment( bool on )
{
if ( on != d_data->stepAlignment )
{
d_data->stepAlignment = on;
}
}
/*!
\return True, when step alignment is enabled
\sa setStepAlignment()
*/
bool QwtAbstractSlider::stepAlignment() const
{
return d_data->stepAlignment;
}
/*!
Set the slider to the specified value
\param value New value
\sa setValid(), sliderChange(), valueChanged()
*/
void QwtAbstractSlider::setValue( double value )
{
value = qBound( minimum(), value, maximum() );
const bool changed = ( d_data->value != value ) || !d_data->isValid;
d_data->value = value;
d_data->isValid = true;
if ( changed )
{
sliderChange();
Q_EMIT valueChanged( d_data->value );
}
}
//! Returns the current value.
double QwtAbstractSlider::value() const
{
return d_data->value;
}
/*!
If wrapping is true stepping up from upperBound() value will
take you to the minimum() value and vice versa.
\param on En/Disable wrapping
\sa wrapping()
*/
void QwtAbstractSlider::setWrapping( bool on )
{
d_data->wrapping = on;
}
/*!
\return True, when wrapping is set
\sa setWrapping()
*/
bool QwtAbstractSlider::wrapping() const
{
return d_data->wrapping;
}
/*!
Invert wheel and key events
Usually scrolling the mouse wheel "up" and using keys like page
up will increase the slider's value towards its maximum.
When invertedControls() is enabled the value is scrolled
towards its minimum.
Inverting the controls might be f.e. useful for a vertical slider
with an inverted scale ( decreasing from top to bottom ).
\param on Invert controls, when true
\sa invertedControls(), keyEvent(), wheelEvent()
*/
void QwtAbstractSlider::setInvertedControls( bool on )
{
d_data->invertedControls = on;
}
/*!
\return True, when the controls are inverted
\sa setInvertedControls()
*/
bool QwtAbstractSlider::invertedControls() const
{
return d_data->invertedControls;
}
/*!
Increment the slider
The step size depends on the number of totalSteps()
\param stepCount Number of steps
\sa setTotalSteps(), incrementedValue()
*/
void QwtAbstractSlider::incrementValue( int stepCount )
{
const double value = incrementedValue(
d_data->value, stepCount );
if ( value != d_data->value )
{
d_data->value = value;
sliderChange();
}
}
/*!
Increment a value
\param value Value
\param stepCount Number of steps
\return Incremented value
*/
double QwtAbstractSlider::incrementedValue(
double value, int stepCount ) const
{
if ( d_data->totalSteps == 0 )
return value;
const QwtTransform *transformation =
scaleMap().transformation();
if ( transformation == NULL )
{
const double range = maximum() - minimum();
value += stepCount * range / d_data->totalSteps;
}
else
{
QwtScaleMap map = scaleMap();
map.setPaintInterval( 0, d_data->totalSteps );
// we need equidant steps according to
// paint device coordinates
const double range = transformation->transform( maximum() )
- transformation->transform( minimum() );
const double stepSize = range / d_data->totalSteps;
double v = transformation->transform( value );
v = qRound( v / stepSize ) * stepSize;
v += stepCount * range / d_data->totalSteps;
value = transformation->invTransform( v );
}
value = boundedValue( value );
if ( d_data->stepAlignment )
value = alignedValue( value );
return value;
}
double QwtAbstractSlider::boundedValue( double value ) const
{
const double vmin = minimum();
const double vmax = maximum();
if ( d_data->wrapping && vmin != vmax )
{
const int fullCircle = 360 * 16;
const double pd = scaleMap().pDist();
if ( int( pd / fullCircle ) * fullCircle == pd )
{
// full circle scales: min and max are the same
const double range = vmax - vmin;
if ( value < vmin )
{
value += ::ceil( ( vmin - value ) / range ) * range;
}
else if ( value > vmax )
{
value -= ::ceil( ( value - vmax ) / range ) * range;
}
}
else
{
if ( value < vmin )
value = vmax;
else if ( value > vmax )
value = vmin;
}
}
else
{
value = qBound( vmin, value, vmax );
}
return value;
}
double QwtAbstractSlider::alignedValue( double value ) const
{
if ( d_data->totalSteps == 0 )
return value;
double stepSize;
if ( scaleMap().transformation() == NULL )
{
stepSize = ( maximum() - minimum() ) / d_data->totalSteps;
if ( stepSize > 0.0 )
{
value = lowerBound() +
qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
}
}
else
{
stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps;
if ( stepSize > 0.0 )
{
double v = scaleMap().transform( value );
v = scaleMap().p1() +
qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;
value = scaleMap().invTransform( v );
}
}
if ( qAbs( stepSize ) > 1e-12 )
{
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
{
// correct rounding error if value = 0
value = 0.0;
}
else
{
// correct rounding error at the border
if ( qFuzzyCompare( value, upperBound() ) )
value = upperBound();
else if ( qFuzzyCompare( value, lowerBound() ) )
value = lowerBound();
}
}
return value;
}
/*!
Update the slider according to modifications of the scale
*/
void QwtAbstractSlider::scaleChange()
{
const double value = qBound( minimum(), d_data->value, maximum() );
const bool changed = ( value != d_data->value );
if ( changed )
{
d_data->value = value;
}
if ( d_data->isValid || changed )
Q_EMIT valueChanged( d_data->value );
updateGeometry();
update();
}
//! Calling update()
void QwtAbstractSlider::sliderChange()
{
update();
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_ABSTRACT_SLIDER_H
#define QWT_ABSTRACT_SLIDER_H
#include "qwt_global.h"
#include "qwt_abstract_scale.h"
/*!
\brief An abstract base class for slider widgets with a scale
A slider widget displays a value according to a scale.
The class is designed as a common super class for widgets like
QwtKnob, QwtDial and QwtSlider.
When the slider is nor readOnly() its value can be modified
by keyboard, mouse and wheel inputs.
The range of the slider is divided into a number of steps from
which the value increments according to user inputs depend.
Only for linear scales the number of steps correspond with
a fixed step size.
*/
class QWT_EXPORT QwtAbstractSlider: public QwtAbstractScale
{
Q_OBJECT
Q_PROPERTY( double value READ value WRITE setValue )
Q_PROPERTY( uint totalSteps READ totalSteps WRITE setTotalSteps )
Q_PROPERTY( uint singleSteps READ singleSteps WRITE setSingleSteps )
Q_PROPERTY( uint pageSteps READ pageSteps WRITE setPageSteps )
Q_PROPERTY( bool stepAlignment READ stepAlignment WRITE setStepAlignment )
Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
Q_PROPERTY( bool tracking READ isTracking WRITE setTracking )
Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping )
Q_PROPERTY( bool invertedControls READ invertedControls WRITE setInvertedControls )
public:
explicit QwtAbstractSlider( QWidget *parent = NULL );
virtual ~QwtAbstractSlider();
void setValid( bool );
bool isValid() const;
double value() const;
void setWrapping( bool );
bool wrapping() const;
void setTotalSteps( uint );
uint totalSteps() const;
void setSingleSteps( uint );
uint singleSteps() const;
void setPageSteps( uint );
uint pageSteps() const;
void setStepAlignment( bool );
bool stepAlignment() const;
void setTracking( bool );
bool isTracking() const;
void setReadOnly( bool );
bool isReadOnly() const;
void setInvertedControls( bool );
bool invertedControls() const;
public Q_SLOTS:
void setValue( double val );
Q_SIGNALS:
/*!
\brief Notify a change of value.
When tracking is enabled (default setting),
this signal will be emitted every time the value changes.
\param value New value
\sa setTracking(), sliderMoved()
*/
void valueChanged( double value );
/*!
This signal is emitted when the user presses the
movable part of the slider.
*/
void sliderPressed();
/*!
This signal is emitted when the user releases the
movable part of the slider.
*/
void sliderReleased();
/*!
This signal is emitted when the user moves the
slider with the mouse.
\param value New value
\sa valueChanged()
*/
void sliderMoved( double value );
protected:
virtual void mousePressEvent( QMouseEvent * );
virtual void mouseReleaseEvent( QMouseEvent * );
virtual void mouseMoveEvent( QMouseEvent * );
virtual void keyPressEvent( QKeyEvent * );
virtual void wheelEvent( QWheelEvent * );
/*!
\brief Determine what to do when the user presses a mouse button.
\param pos Mouse position
\retval True, when pos is a valid scroll position
\sa scrolledTo()
*/
virtual bool isScrollPosition( const QPoint &pos ) const = 0;
/*!
\brief Determine the value for a new position of the
movable part of the slider
\param pos Mouse position
\return Value for the mouse position
\sa isScrollPosition()
*/
virtual double scrolledTo( const QPoint &pos ) const = 0;
void incrementValue( int numSteps );
virtual void scaleChange();
protected:
virtual void sliderChange();
double incrementedValue(
double value, int stepCount ) const;
private:
double alignedValue( double ) const;
double boundedValue( double ) const;
class PrivateData;
PrivateData *d_data;
};
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_analog_clock.h"
#include "qwt_round_scale_draw.h"
#include <qmath.h>
#include <qlocale.h>
class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw
{
public:
QwtAnalogClockScaleDraw()
{
setSpacing( 8 );
enableComponent( QwtAbstractScaleDraw::Backbone, false );
setTickLength( QwtScaleDiv::MinorTick, 2 );
setTickLength( QwtScaleDiv::MediumTick, 4 );
setTickLength( QwtScaleDiv::MajorTick, 8 );
setPenWidth( 1 );
}
virtual QwtText label( double value ) const
{
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
value = 60.0 * 60.0 * 12.0;
return QLocale().toString( qRound( value / ( 60.0 * 60.0 ) ) );
}
};
/*!
Constructor
\param parent Parent widget
*/
QwtAnalogClock::QwtAnalogClock( QWidget *parent ):
QwtDial( parent )
{
setWrapping( true );
setReadOnly( true );
setOrigin( 270.0 );
setScaleDraw( new QwtAnalogClockScaleDraw() );
setTotalSteps( 60 );
const int secondsPerHour = 60.0 * 60.0;
QList<double> majorTicks;
QList<double> minorTicks;
for ( int i = 0; i < 12; i++ )
{
majorTicks += i * secondsPerHour;
for ( int j = 1; j < 5; j++ )
minorTicks += i * secondsPerHour + j * secondsPerHour / 5.0;
}
QwtScaleDiv scaleDiv;
scaleDiv.setInterval( 0.0, 12.0 * secondsPerHour );
scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks );
scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks );
setScale( scaleDiv );
QColor knobColor = palette().color( QPalette::Active, QPalette::Text );
knobColor = knobColor.dark( 120 );
QColor handColor;
int width;
for ( int i = 0; i < NHands; i++ )
{
if ( i == SecondHand )
{
width = 2;
handColor = knobColor.dark( 120 );
}
else
{
width = 8;
handColor = knobColor;
}
QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle(
QwtDialSimpleNeedle::Arrow, true, handColor, knobColor );
hand->setWidth( width );
d_hand[i] = NULL;
setHand( static_cast<Hand>( i ), hand );
}
}
//! Destructor
QwtAnalogClock::~QwtAnalogClock()
{
for ( int i = 0; i < NHands; i++ )
delete d_hand[i];
}
/*!
Nop method, use setHand() instead
\sa setHand()
*/
void QwtAnalogClock::setNeedle( QwtDialNeedle * )
{
// no op
return;
}
/*!
Set a clock hand
\param hand Specifies the type of hand
\param needle Hand
\sa hand()
*/
void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle )
{
if ( hand >= 0 && hand < NHands )
{
delete d_hand[hand];
d_hand[hand] = needle;
}
}
/*!
\return Clock hand
\param hd Specifies the type of hand
\sa setHand()
*/
QwtDialNeedle *QwtAnalogClock::hand( Hand hd )
{
if ( hd < 0 || hd >= NHands )
return NULL;
return d_hand[hd];
}
/*!
\return Clock hand
\param hd Specifies the type of hand
\sa setHand()
*/
const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const
{
return const_cast<QwtAnalogClock *>( this )->hand( hd );
}
/*!
\brief Set the current time
*/
void QwtAnalogClock::setCurrentTime()
{
setTime( QTime::currentTime() );
}
/*!
Set a time
\param time Time to display
*/
void QwtAnalogClock::setTime( const QTime &time )
{
if ( time.isValid() )
{
setValue( ( time.hour() % 12 ) * 60.0 * 60.0
+ time.minute() * 60.0 + time.second() );
}
else
setValid( false );
}
/*!
\brief Draw the needle
A clock has no single needle but three hands instead. drawNeedle()
translates value() into directions for the hands and calls
drawHand().
\param painter Painter
\param center Center of the clock
\param radius Maximum length for the hands
\param dir Dummy, not used.
\param colorGroup ColorGroup
\sa drawHand()
*/
void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF &center,
double radius, double dir, QPalette::ColorGroup colorGroup ) const
{
Q_UNUSED( dir );
if ( isValid() )
{
const double hours = value() / ( 60.0 * 60.0 );
const double minutes =
( value() - qFloor(hours) * 60.0 * 60.0 ) / 60.0;
const double seconds = value() - qFloor(hours) * 60.0 * 60.0
- qFloor(minutes) * 60.0;
double angle[NHands];
angle[HourHand] = 360.0 * hours / 12.0;
angle[MinuteHand] = 360.0 * minutes / 60.0;
angle[SecondHand] = 360.0 * seconds / 60.0;
for ( int hand = 0; hand < NHands; hand++ )
{
const double d = 360.0 - angle[hand] - origin();
drawHand( painter, static_cast<Hand>( hand ),
center, radius, d, colorGroup );
}
}
}
/*!
Draw a clock hand
\param painter Painter
\param hd Specify the type of hand
\param center Center of the clock
\param radius Maximum length for the hands
\param direction Direction of the hand in degrees, counter clockwise
\param cg ColorGroup
*/
void QwtAnalogClock::drawHand( QPainter *painter, Hand hd,
const QPointF &center, double radius, double direction,
QPalette::ColorGroup cg ) const
{
const QwtDialNeedle *needle = hand( hd );
if ( needle )
{
if ( hd == HourHand )
radius = qRound( 0.8 * radius );
needle->draw( painter, center, radius, direction, cg );
}
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_ANALOG_CLOCK_H
#define QWT_ANALOG_CLOCK_H
#include "qwt_global.h"
#include "qwt_dial.h"
#include "qwt_dial_needle.h"
#include <qdatetime.h>
/*!
\brief An analog clock
\image html analogclock.png
\par Example
\code
#include <qwt_analog_clock.h>
QwtAnalogClock *clock = new QwtAnalogClock(...);
clock->scaleDraw()->setPenWidth(3);
clock->setLineWidth(6);
clock->setFrameShadow(QwtDial::Sunken);
clock->setTime();
// update the clock every second
QTimer *timer = new QTimer(clock);
timer->connect(timer, SIGNAL(timeout()), clock, SLOT(setCurrentTime()));
timer->start(1000);
\endcode
\note The examples/dials example shows how to use QwtAnalogClock.
*/
class QWT_EXPORT QwtAnalogClock: public QwtDial
{
Q_OBJECT
public:
/*!
Hand type
\sa setHand(), hand()
*/
enum Hand
{
//! Needle displaying the seconds
SecondHand,
//! Needle displaying the minutes
MinuteHand,
//! Needle displaying the hours
HourHand,
//! Number of needles
NHands
};
explicit QwtAnalogClock( QWidget* parent = NULL );
virtual ~QwtAnalogClock();
void setHand( Hand, QwtDialNeedle * );
const QwtDialNeedle *hand( Hand ) const;
QwtDialNeedle *hand( Hand );
public Q_SLOTS:
void setCurrentTime();
void setTime( const QTime & );
protected:
virtual void drawNeedle( QPainter *, const QPointF &,
double radius, double direction, QPalette::ColorGroup ) const;
virtual void drawHand( QPainter *, Hand, const QPointF &,
double radius, double direction, QPalette::ColorGroup ) const;
private:
// use setHand instead
void setNeedle( QwtDialNeedle * );
QwtDialNeedle *d_hand[NHands];
};
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
// vim: expandtab
#ifndef QWT_ARRAY_H
#define QWT_ARRAY_H
#include "qwt_global.h"
/*!
\def QwtArray
*/
#if QT_VERSION < 0x040000
#include <qmemarray.h>
#define QwtArray QMemArray
#else
#include <qvector.h>
#define QwtArray QVector
#endif
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_arrow_button.h"
#include "qwt_math.h"
#include <qpainter.h>
#include <qstyle.h>
#include <qstyleoption.h>
#include <qevent.h>
#include <qapplication.h>
static const int MaxNum = 3;
static const int Margin = 2;
static const int Spacing = 1;
class QwtArrowButton::PrivateData
{
public:
int num;
Qt::ArrowType arrowType;
};
static QStyleOptionButton styleOpt( const QwtArrowButton* btn )
{
QStyleOptionButton option;
option.init( btn );
option.features = QStyleOptionButton::None;
if ( btn->isFlat() )
option.features |= QStyleOptionButton::Flat;
if ( btn->menu() )
option.features |= QStyleOptionButton::HasMenu;
if ( btn->autoDefault() || btn->isDefault() )
option.features |= QStyleOptionButton::AutoDefaultButton;
if ( btn->isDefault() )
option.features |= QStyleOptionButton::DefaultButton;
if ( btn->isDown() )
option.state |= QStyle::State_Sunken;
if ( !btn->isFlat() && !btn->isDown() )
option.state |= QStyle::State_Raised;
return option;
}
/*!
\param num Number of arrows
\param arrowType see Qt::ArrowType in the Qt docs.
\param parent Parent widget
*/
QwtArrowButton::QwtArrowButton( int num,
Qt::ArrowType arrowType, QWidget *parent ):
QPushButton( parent )
{
d_data = new PrivateData;
d_data->num = qBound( 1, num, MaxNum );
d_data->arrowType = arrowType;
setAutoRepeat( true );
setAutoDefault( false );
switch ( d_data->arrowType )
{
case Qt::LeftArrow:
case Qt::RightArrow:
setSizePolicy( QSizePolicy::Expanding,
QSizePolicy::Fixed );
break;
default:
setSizePolicy( QSizePolicy::Fixed,
QSizePolicy::Expanding );
}
}
//! Destructor
QwtArrowButton::~QwtArrowButton()
{
delete d_data;
d_data = NULL;
}
/*!
\brief The direction of the arrows
*/
Qt::ArrowType QwtArrowButton::arrowType() const
{
return d_data->arrowType;
}
/*!
\brief The number of arrows
*/
int QwtArrowButton::num() const
{
return d_data->num;
}
/*!
\return the bounding rectangle for the label
*/
QRect QwtArrowButton::labelRect() const
{
const int m = Margin;
QRect r = rect();
r.setRect( r.x() + m, r.y() + m,
r.width() - 2 * m, r.height() - 2 * m );
if ( isDown() )
{
QStyleOptionButton option = styleOpt( this );
const int ph = style()->pixelMetric(
QStyle::PM_ButtonShiftHorizontal, &option, this );
const int pv = style()->pixelMetric(
QStyle::PM_ButtonShiftVertical, &option, this );
r.translate( ph, pv );
}
return r;
}
/*!
Paint event handler
\param event Paint event
*/
void QwtArrowButton::paintEvent( QPaintEvent *event )
{
QPushButton::paintEvent( event );
QPainter painter( this );
drawButtonLabel( &painter );
}
/*!
\brief Draw the button label
\param painter Painter
\sa The Qt Manual for QPushButton
*/
void QwtArrowButton::drawButtonLabel( QPainter *painter )
{
const bool isVertical = d_data->arrowType == Qt::UpArrow ||
d_data->arrowType == Qt::DownArrow;
const QRect r = labelRect();
QSize boundingSize = labelRect().size();
if ( isVertical )
boundingSize.transpose();
const int w =
( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum;
QSize arrow = arrowSize( Qt::RightArrow,
QSize( w, boundingSize.height() ) );
if ( isVertical )
arrow.transpose();
QRect contentsSize; // aligned rect where to paint all arrows
if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow )
{
contentsSize.setWidth( d_data->num * arrow.width()
+ ( d_data->num - 1 ) * Spacing );
contentsSize.setHeight( arrow.height() );
}
else
{
contentsSize.setWidth( arrow.width() );
contentsSize.setHeight( d_data->num * arrow.height()
+ ( d_data->num - 1 ) * Spacing );
}
QRect arrowRect( contentsSize );
arrowRect.moveCenter( r.center() );
arrowRect.setSize( arrow );
painter->save();
for ( int i = 0; i < d_data->num; i++ )
{
drawArrow( painter, arrowRect, d_data->arrowType );
int dx = 0;
int dy = 0;
if ( isVertical )
dy = arrow.height() + Spacing;
else
dx = arrow.width() + Spacing;
arrowRect.translate( dx, dy );
}
painter->restore();
if ( hasFocus() )
{
QStyleOptionFocusRect option;
option.init( this );
option.backgroundColor = palette().color( QPalette::Window );
style()->drawPrimitive( QStyle::PE_FrameFocusRect,
&option, painter, this );
}
}
/*!
Draw an arrow int a bounding rectangle
\param painter Painter
\param r Rectangle where to paint the arrow
\param arrowType Arrow type
*/
void QwtArrowButton::drawArrow( QPainter *painter,
const QRect &r, Qt::ArrowType arrowType ) const
{
QPolygon pa( 3 );
switch ( arrowType )
{
case Qt::UpArrow:
pa.setPoint( 0, r.bottomLeft() );
pa.setPoint( 1, r.bottomRight() );
pa.setPoint( 2, r.center().x(), r.top() );
break;
case Qt::DownArrow:
pa.setPoint( 0, r.topLeft() );
pa.setPoint( 1, r.topRight() );
pa.setPoint( 2, r.center().x(), r.bottom() );
break;
case Qt::RightArrow:
pa.setPoint( 0, r.topLeft() );
pa.setPoint( 1, r.bottomLeft() );
pa.setPoint( 2, r.right(), r.center().y() );
break;
case Qt::LeftArrow:
pa.setPoint( 0, r.topRight() );
pa.setPoint( 1, r.bottomRight() );
pa.setPoint( 2, r.left(), r.center().y() );
break;
default:
break;
}
painter->save();
painter->setRenderHint( QPainter::Antialiasing, true );
painter->setPen( Qt::NoPen );
painter->setBrush( palette().brush( QPalette::ButtonText ) );
painter->drawPolygon( pa );
painter->restore();
}
/*!
\return a size hint
*/
QSize QwtArrowButton::sizeHint() const
{
const QSize hint = minimumSizeHint();
return hint.expandedTo( QApplication::globalStrut() );
}
/*!
\brief Return a minimum size hint
*/
QSize QwtArrowButton::minimumSizeHint() const
{
const QSize asz = arrowSize( Qt::RightArrow, QSize() );
QSize sz(
2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(),
2 * Margin + asz.height()
);
if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
sz.transpose();
QStyleOption styleOption;
styleOption.init( this );
sz = style()->sizeFromContents( QStyle::CT_PushButton,
&styleOption, sz, this );
return sz;
}
/*!
Calculate the size for a arrow that fits into a rectangle of a given size
\param arrowType Arrow type
\param boundingSize Bounding size
\return Size of the arrow
*/
QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType,
const QSize &boundingSize ) const
{
QSize bs = boundingSize;
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
bs.transpose();
const int MinLen = 2;
const QSize sz = bs.expandedTo(
QSize( MinLen, 2 * MinLen - 1 ) ); // minimum
int w = sz.width();
int h = 2 * w - 1;
if ( h > sz.height() )
{
h = sz.height();
w = ( h + 1 ) / 2;
}
QSize arrSize( w, h );
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
arrSize.transpose();
return arrSize;
}
/*!
\brief autoRepeat for the space keys
*/
void QwtArrowButton::keyPressEvent( QKeyEvent *event )
{
if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
Q_EMIT clicked();
QPushButton::keyPressEvent( event );
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_ARROW_BUTTON_H
#define QWT_ARROW_BUTTON_H
#include "qwt_global.h"
#include <qpushbutton.h>
/*!
\brief Arrow Button
A push button with one or more filled triangles on its front.
An Arrow button can have 1 to 3 arrows in a row, pointing
up, down, left or right.
*/
class QWT_EXPORT QwtArrowButton : public QPushButton
{
public:
explicit QwtArrowButton ( int num, Qt::ArrowType, QWidget *parent = NULL );
virtual ~QwtArrowButton();
Qt::ArrowType arrowType() const;
int num() const;
virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
protected:
virtual void paintEvent( QPaintEvent *event );
virtual void drawButtonLabel( QPainter *p );
virtual void drawArrow( QPainter *,
const QRect &, Qt::ArrowType ) const;
virtual QRect labelRect() const;
virtual QSize arrowSize( Qt::ArrowType,
const QSize &boundingSize ) const;
virtual void keyPressEvent( QKeyEvent * );
private:
class PrivateData;
PrivateData *d_data;
};
#endif
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_clipper.h"
#include "qwt_point_polar.h"
#include <qrect.h>
#include <string.h>
#include <stdlib.h>
#if QT_VERSION < 0x040601
#define qAtan(x) ::atan(x)
#endif
namespace QwtClip
{
// some templates used for inlining
template <class Point, typename T> class LeftEdge;
template <class Point, typename T> class RightEdge;
template <class Point, typename T> class TopEdge;
template <class Point, typename T> class BottomEdge;
template <class Point> class PointBuffer;
}
template <class Point, typename Value>
class QwtClip::LeftEdge
{
public:
inline LeftEdge( Value x1, Value, Value, Value ):
d_x1( x1 )
{
}
inline bool isInside( const Point &p ) const
{
return p.x() >= d_x1;
}
inline Point intersection( const Point &p1, const Point &p2 ) const
{
double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() );
return Point( d_x1, static_cast< Value >( p2.y() + ( d_x1 - p2.x() ) * dy ) );
}
private:
const Value d_x1;
};
template <class Point, typename Value>
class QwtClip::RightEdge
{
public:
inline RightEdge( Value, Value x2, Value, Value ):
d_x2( x2 )
{
}
inline bool isInside( const Point &p ) const
{
return p.x() <= d_x2;
}
inline Point intersection( const Point &p1, const Point &p2 ) const
{
double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() );
return Point( d_x2, static_cast<Value>( p2.y() + ( d_x2 - p2.x() ) * dy ) );
}
private:
const Value d_x2;
};
template <class Point, typename Value>
class QwtClip::TopEdge
{
public:
inline TopEdge( Value, Value, Value y1, Value ):
d_y1( y1 )
{
}
inline bool isInside( const Point &p ) const
{
return p.y() >= d_y1;
}
inline Point intersection( const Point &p1, const Point &p2 ) const
{
double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() );
return Point( static_cast<Value>( p2.x() + ( d_y1 - p2.y() ) * dx ), d_y1 );
}
private:
const Value d_y1;
};
template <class Point, typename Value>
class QwtClip::BottomEdge
{
public:
inline BottomEdge( Value, Value, Value, Value y2 ):
d_y2( y2 )
{
}
inline bool isInside( const Point &p ) const
{
return p.y() <= d_y2;
}
inline Point intersection( const Point &p1, const Point &p2 ) const
{
double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() );
return Point( static_cast<Value>( p2.x() + ( d_y2 - p2.y() ) * dx ), d_y2 );
}
private:
const Value d_y2;
};
template<class Point>
class QwtClip::PointBuffer
{
public:
PointBuffer( int capacity = 0 ):
m_capacity( 0 ),
m_size( 0 ),
m_buffer( NULL )
{
if ( capacity > 0 )
reserve( capacity );
}
~PointBuffer()
{
if ( m_buffer )
::free( m_buffer );
}
inline void setPoints( int numPoints, const Point *points )
{
reserve( numPoints );
m_size = numPoints;
::memcpy( m_buffer, points, m_size * sizeof( Point ) );
}
inline void reset()
{
m_size = 0;
}
inline int size() const
{
return m_size;
}
inline Point *data() const
{
return m_buffer;
}
inline Point &operator[]( int i )
{
return m_buffer[i];
}
inline const Point &operator[]( int i ) const
{
return m_buffer[i];
}
inline void add( const Point &point )
{
if ( m_capacity <= m_size )
reserve( m_size + 1 );
m_buffer[m_size++] = point;
}
private:
inline void reserve( int size )
{
if ( m_capacity == 0 )
m_capacity = 1;
while ( m_capacity < size )
m_capacity *= 2;
m_buffer = static_cast<Point *>(
::realloc( m_buffer, m_capacity * sizeof( Point ) ) );
}
int m_capacity;
int m_size;
Point *m_buffer;
};
using namespace QwtClip;
template <class Polygon, class Rect, class Point, typename T>
class QwtPolygonClipper
{
public:
QwtPolygonClipper( const Rect &clipRect ):
d_clipRect( clipRect )
{
}
Polygon clipPolygon( const Polygon &polygon, bool closePolygon ) const
{
#if 0
if ( d_clipRect.contains( polygon.boundingRect() ) )
return polygon;
#endif
PointBuffer<Point> points1;
PointBuffer<Point> points2( qMin( 256, polygon.size() ) );
points1.setPoints( polygon.size(), polygon.data() );
clipEdge< LeftEdge<Point, T> >( closePolygon, points1, points2 );
clipEdge< RightEdge<Point, T> >( closePolygon, points2, points1 );
clipEdge< TopEdge<Point, T> >( closePolygon, points1, points2 );
clipEdge< BottomEdge<Point, T> >( closePolygon, points2, points1 );
Polygon p;
p.resize( points1.size() );
::memcpy( p.data(), points1.data(), points1.size() * sizeof( Point ) );
return p;
}
private:
template <class Edge>
inline void clipEdge( bool closePolygon,
PointBuffer<Point> &points, PointBuffer<Point> &clippedPoints ) const
{
clippedPoints.reset();
if ( points.size() < 2 )
{
if ( points.size() == 1 )
clippedPoints.add( points[0] );
return;
}
const Edge edge( d_clipRect.x(), d_clipRect.x() + d_clipRect.width(),
d_clipRect.y(), d_clipRect.y() + d_clipRect.height() );
int lastPos, start;
if ( closePolygon )
{
start = 0;
lastPos = points.size() - 1;
}
else
{
start = 1;
lastPos = 0;
if ( edge.isInside( points[0] ) )
clippedPoints.add( points[0] );
}
const uint nPoints = points.size();
for ( uint i = start; i < nPoints; i++ )
{
const Point &p1 = points[i];
const Point &p2 = points[lastPos];
if ( edge.isInside( p1 ) )
{
if ( edge.isInside( p2 ) )
{
clippedPoints.add( p1 );
}
else
{
clippedPoints.add( edge.intersection( p1, p2 ) );
clippedPoints.add( p1 );
}
}
else
{
if ( edge.isInside( p2 ) )
{
clippedPoints.add( edge.intersection( p1, p2 ) );
}
}
lastPos = i;
}
}
const Rect d_clipRect;
};
class QwtCircleClipper
{
public:
QwtCircleClipper( const QRectF &r );
QVector<QwtInterval> clipCircle( const QPointF &, double radius ) const;
private:
enum Edge
{
Left,
Top,
Right,
Bottom,
NEdges
};
QList<QPointF> cuttingPoints(
Edge, const QPointF &pos, double radius ) const;
double toAngle( const QPointF &, const QPointF & ) const;
const QRectF d_rect;
};
QwtCircleClipper::QwtCircleClipper( const QRectF &r ):
d_rect( r )
{
}
QVector<QwtInterval> QwtCircleClipper::clipCircle(
const QPointF &pos, double radius ) const
{
QList<QPointF> points;
for ( int edge = 0; edge < NEdges; edge++ )
points += cuttingPoints( static_cast<Edge>(edge), pos, radius );
QVector<QwtInterval> intv;
if ( points.size() <= 0 )
{
QRectF cRect( 0, 0, 2 * radius, 2 * radius );
cRect.moveCenter( pos );
if ( d_rect.contains( cRect ) )
intv += QwtInterval( 0.0, 2 * M_PI );
}
else
{
QList<double> angles;
for ( int i = 0; i < points.size(); i++ )
angles += toAngle( pos, points[i] );
qSort( angles );
const int in = d_rect.contains( qwtPolar2Pos( pos, radius,
angles[0] + ( angles[1] - angles[0] ) / 2 ) );
if ( in )
{
for ( int i = 0; i < angles.size() - 1; i += 2 )
intv += QwtInterval( angles[i], angles[i+1] );
}
else
{
for ( int i = 1; i < angles.size() - 1; i += 2 )
intv += QwtInterval( angles[i], angles[i+1] );
intv += QwtInterval( angles.last(), angles.first() );
}
}
return intv;
}
double QwtCircleClipper::toAngle(
const QPointF &from, const QPointF &to ) const
{
if ( from.x() == to.x() )
return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0;
const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) );
double angle = qAtan( m );
if ( to.x() > from.x() )
{
if ( to.y() > from.y() )
angle = 2 * M_PI - angle;
}
else
{
if ( to.y() > from.y() )
angle = M_PI + angle;
else
angle = M_PI - angle;
}
return angle;
}
QList<QPointF> QwtCircleClipper::cuttingPoints(
Edge edge, const QPointF &pos, double radius ) const
{
QList<QPointF> points;
if ( edge == Left || edge == Right )
{
const double x = ( edge == Left ) ? d_rect.left() : d_rect.right();
if ( qAbs( pos.x() - x ) < radius )
{
const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.x() - x ) );
const double m_y1 = pos.y() + off;
if ( m_y1 >= d_rect.top() && m_y1 <= d_rect.bottom() )
points += QPointF( x, m_y1 );
const double m_y2 = pos.y() - off;
if ( m_y2 >= d_rect.top() && m_y2 <= d_rect.bottom() )
points += QPointF( x, m_y2 );
}
}
else
{
const double y = ( edge == Top ) ? d_rect.top() : d_rect.bottom();
if ( qAbs( pos.y() - y ) < radius )
{
const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.y() - y ) );
const double x1 = pos.x() + off;
if ( x1 >= d_rect.left() && x1 <= d_rect.right() )
points += QPointF( x1, y );
const double m_x2 = pos.x() - off;
if ( m_x2 >= d_rect.left() && m_x2 <= d_rect.right() )
points += QPointF( m_x2, y );
}
}
return points;
}
/*!
Sutherland-Hodgman polygon clipping
\param clipRect Clip rectangle
\param polygon Polygon
\param closePolygon True, when the polygon is closed
\return Clipped polygon
*/
QPolygon QwtClipper::clipPolygon(
const QRectF &clipRect, const QPolygon &polygon, bool closePolygon )
{
const int minX = qCeil( clipRect.left() );
const int maxX = qFloor( clipRect.right() );
const int minY = qCeil( clipRect.top() );
const int maxY = qFloor( clipRect.bottom() );
const QRect r( minX, minY, maxX - minX, maxY - minY );
QwtPolygonClipper<QPolygon, QRect, QPoint, int> clipper( r );
return clipper.clipPolygon( polygon, closePolygon );
}
/*!
Sutherland-Hodgman polygon clipping
\param clipRect Clip rectangle
\param polygon Polygon
\param closePolygon True, when the polygon is closed
\return Clipped polygon
*/
QPolygon QwtClipper::clipPolygon(
const QRect &clipRect, const QPolygon &polygon, bool closePolygon )
{
QwtPolygonClipper<QPolygon, QRect, QPoint, int> clipper( clipRect );
return clipper.clipPolygon( polygon, closePolygon );
}
/*!
Sutherland-Hodgman polygon clipping
\param clipRect Clip rectangle
\param polygon Polygon
\param closePolygon True, when the polygon is closed
\return Clipped polygon
*/
QPolygonF QwtClipper::clipPolygonF(
const QRectF &clipRect, const QPolygonF &polygon, bool closePolygon )
{
QwtPolygonClipper<QPolygonF, QRectF, QPointF, double> clipper( clipRect );
return clipper.clipPolygon( polygon, closePolygon );
}
/*!
Circle clipping
clipCircle() divides a circle into intervals of angles representing arcs
of the circle. When the circle is completely inside the clip rectangle
an interval [0.0, 2 * M_PI] is returned.
\param clipRect Clip rectangle
\param center Center of the circle
\param radius Radius of the circle
\return Arcs of the circle
*/
QVector<QwtInterval> QwtClipper::clipCircle( const QRectF &clipRect,
const QPointF &center, double radius )
{
QwtCircleClipper clipper( clipRect );
return clipper.clipCircle( center, radius );
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef QWT_CLIPPER_H
#define QWT_CLIPPER_H
#include "qwt_global.h"
#include "qwt_interval.h"
#include <qpolygon.h>
#include <qvector.h>
class QRect;
class QRectF;
/*!
\brief Some clipping algorithms
*/
class QWT_EXPORT QwtClipper
{
public:
static QPolygon clipPolygon( const QRect &,
const QPolygon &, bool closePolygon = false );
static QPolygon clipPolygon( const QRectF &,
const QPolygon &, bool closePolygon = false );
static QPolygonF clipPolygonF( const QRectF &,
const QPolygonF &, bool closePolygon = false );
static QVector<QwtInterval> clipCircle(
const QRectF &, const QPointF &, double radius );
};
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment