diff --git a/.gitignore b/.gitignore
index ee259ce1c0ce578a5e66fc3b502ee763b63c3074..4f1e63458e11d4ac46344fdb2b1e800c79a5c82c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,7 +21,6 @@ tmp
debug
release
/qgroundcontrol
-mavlinkgen-build-desktop
qgroundcontrol.xcodeproj/**
doc/html
doc/doxy.log
diff --git a/QGCExternalLibs.pri b/QGCExternalLibs.pri
index eaea69384b685a54713558d38c67f2757249af14..cbd86a9c52c87f80485f7f0b2832d2def8947b70 100644
--- a/QGCExternalLibs.pri
+++ b/QGCExternalLibs.pri
@@ -123,34 +123,6 @@ INCLUDEPATH += $$MAVLINKPATH
INCLUDEPATH += $$MAVLINKPATH/common
}
-#
-# [DEPRECATED] MAVLink generator UI. Provides a GUI interface for generating MAVLink dialects.
-# Replaced by mavgenerator.py within the MAVLink project.
-#
-contains(DEFINES, ENABLE_MAVGEN) {
- warning("Including support for MAVLink generator GUI (manual override from command line, CAUTION: deprecated)")
-} else:infile(user_config.pri, DEFINES, ENABLE_MAVGEN) {
- DEFINES += ENABLE_MAVGEN # infile doesn't automatically include everything in the specified file
- warning("Including support for MAVLink generator GUI (manual override from user_config.pri, CAUTION: deprecated)")
-}
-
-contains(DEFINES, ENABLE_MAVGEN) {
- # Rename the macro to be consistent with other QGC feature existance macros.
- DEFINES -= ENABLE_MAVGEN
- DEFINES += QGC_MAVGEN_ENABLED
- DEPENDPATH += \
- src/apps/mavlinkgen
-
- INCLUDEPATH += \
- src/apps/mavlinkgen \
- src/apps/mavlinkgen/ui \
- src/apps/mavlinkgen/generator
-
- include(src/apps/mavlinkgen/mavlinkgen.pri)
-} else {
- message("Skipping support for MAVLink generator GUI (deprecated, see README)")
-}
-
#
# [OPTIONAL] OpenSceneGraph
# Allow the user to override OpenSceneGraph compilation through a DISABLE_OPEN_SCENE_GRAPH
@@ -348,7 +320,9 @@ INCLUDEPATH += \
#
# [REQUIRED] QWT plotting library dependency. Provides plotting capabilities.
#
-include(libs/qwt/qwt.pri)
+include(libs/qwt.pri)
+DEPENDPATH += libs/qwt
+INCLUDEPATH += libs/qwt
#
# [REQUIRED] QSerialPort library. Provides serial port wrapper library.
diff --git a/README.md b/README.md
index 2f1b49674fd8b93b882bb92ccf6e2a7c3f7076d9..a361f27431ae05e03b8b0ff46bc14a4c82f76aca 100644
--- a/README.md
+++ b/README.md
@@ -37,9 +37,6 @@ The QUpgrade module relies on `libudev` on Linux platforms, so be sure to instal
### Specifying MAVLink dialects
The MAVLink dialect compiled by default by QGC is for the ardupilotmega. This will happen if no other dialects are specified. Setting the `MAVLINK_CONF` variable sets the dialects, with more than one specified in a space-separated list. Note that doing this may result in compilation errors as certain dialects may conflict with each other!
-### MAVLink dialect generator
-An add-on is available for QGC that provides a UI for generating MAVLink dialects from within QGC. This feature has been deprecated since identical functionality now exists within the MAVLink project itself. Enable this functionality by specifying the `DEFINES` variable `ENABLE_MAVGEN`.
-
### Opal-RT's RT-LAB simulator
Integration with Opal-RT's RT-LAB simulator can be enabled on Windows by installing RT-LAB 7.2.4. This allows vehicles to be simulated in RT-LAB and communicate directly with QGC on the same computer as if the UAS was actually deployed. This support is enabled by default once the requisite RT-LAB software is installed. Disabling this can be done by adding `DISABLE_RTLAB` to the `DEFINES` variable.
diff --git a/files/flightgear/Aircraft/EasyStar/easystar.xml b/files/flightgear/Aircraft/EasyStar/easystar.xml
index 3477038fef2894d34781562b11588913287261ce..742c6cb6318b5269fb93c35561020a5362a506b3 100644
--- a/files/flightgear/Aircraft/EasyStar/easystar.xml
+++ b/files/flightgear/Aircraft/EasyStar/easystar.xml
@@ -91,7 +91,7 @@
4.0
0
NONE
- FIXED
+ 0
@@ -107,7 +107,7 @@
4.0
0
NONE
- FIXED
+ 0
diff --git a/libs/README.md b/libs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f0f9a48a2a3a9f7adb4f91183aba948430fc9efd
--- /dev/null
+++ b/libs/README.md
@@ -0,0 +1,9 @@
+This folder contains the various required libraries for QGC to compile. They are distributed with the codebase to ease development.
+
+# Qwt
+Qt Widgets for Technical Applications
+Version: 6.1
+Source obtained: `svn checkout svn://svn.code.sf.net/p/qwt/code/branches/qwt-6.1 qwt`
+
+Contents of `/libs/qwt` is the contents of the `/src` directory from the Qwt repository.
+qwt.pri file is custom made to compile all necessary Qwt code in with QGC.
diff --git a/libs/opmapcontrol/src/core/urlfactory.cpp b/libs/opmapcontrol/src/core/urlfactory.cpp
index 0d64b9448570ae44623176bf90fae7e549d39864..9a3f52dcec68dfce87d1be9e068fbcb9df19d25c 100644
--- a/libs/opmapcontrol/src/core/urlfactory.cpp
+++ b/libs/opmapcontrol/src/core/urlfactory.cpp
@@ -3,25 +3,25 @@
*
* @file urlfactory.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
-* @brief
+* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup OPMapWidget
* @{
-*
+*
*****************************************************************************/
-/*
-* 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 3 of the License, or
+/*
+* 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 3 of the License, or
* (at your option) any later version.
-*
-* This program 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 General Public License
+*
+* This program 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 General Public License
* for more details.
-*
-* You should have received a copy of the GNU General Public License along
-* with this program; if not, write to the Free Software Foundation, Inc.,
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "urlfactory.h"
@@ -37,13 +37,13 @@ namespace core {
///
/// timeout for map connections
///
- QNetworkProxyFactory::setUseSystemConfiguration(true);
+ QNetworkProxyFactory::setUseSystemConfiguration(true);
+
-
///
/// Gets or sets the value of the User-agent HTTP header.
///
- UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7";
+ UserAgent = QString("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:%1.0) Gecko/%2%3%4 Firefox/%5.0.%6").arg(QString::number(Random(3,14)), QString::number(Random(QDate().currentDate().year() - 4, QDate().currentDate().year())), QString::number(Random(11,12)), QString::number(Random(10,30)), QString::number(Random(3,14)), QString::number(Random(1,10))).toLatin1();
Timeout = 5 * 1000;
CorrectGoogleVersions=true;
@@ -54,6 +54,10 @@ namespace core {
UrlFactory::~UrlFactory()
{
}
+ int UrlFactory::Random(int low, int high)
+ {
+ return low + qrand() % (high - low);
+ }
QString UrlFactory::TileXYToQuadKey(const int &tileX,const int &tileY,const int &levelOfDetail) const
{
QString quadKey;
@@ -92,7 +96,7 @@ namespace core {
{
static bool versionRetrieved = false;
- if (versionRetrieved)
+ if (versionRetrieved)
{
return;
}
@@ -112,7 +116,7 @@ namespace core {
#ifdef DEBUG_URLFACTORY
qDebug()<<"Correct GoogleVersion";
#endif //DEBUG_URLFACTORY
- //setIsCorrectGoogleVersions(true);
+ setIsCorrectGoogleVersions(true);
QString url = "https://maps.google.com";
qheader.setUrl(QUrl(url));
@@ -131,7 +135,7 @@ namespace core {
return;
}
QString html=QString(reply->readAll());
- QRegExp reg("\"*https://mts0.google.com/vt/lyrs=m@(\\d*)",Qt::CaseInsensitive);
+ QRegExp reg("\"*https://mt0.google.com/vt/lyrs=m@(\\d*)",Qt::CaseInsensitive);
if(reg.indexIn(html)!=-1)
{
QStringList gc=reg.capturedTexts();
@@ -143,7 +147,7 @@ namespace core {
#endif //DEBUG_URLFACTORY
}
- reg = QRegExp("\"*https://mts0.google.com/vt/lyrs=h@(\\d*)",Qt::CaseInsensitive);
+ reg=QRegExp("\"*https://mt0.google.com/vt/lyrs=h@(\\d*)",Qt::CaseInsensitive);
if(reg.indexIn(html)!=-1)
{
QStringList gc=reg.capturedTexts();
@@ -153,7 +157,7 @@ namespace core {
qDebug()<<"TryCorrectGoogleVersions, VersionGoogleLabels: "<deleteLater();
-
+
}
}
@@ -194,7 +198,7 @@ namespace core {
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
TryCorrectGoogleVersions();
-
+
return QString("https://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleMap).arg(language).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
@@ -206,7 +210,6 @@ namespace core {
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
TryCorrectGoogleVersions();
-
return QString("https://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleSatellite).arg(language).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
@@ -218,7 +221,7 @@ namespace core {
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
TryCorrectGoogleVersions();
-
+
return QString("https://%1%2.google.com/%3/lyrs=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleLabels).arg(language).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
@@ -230,7 +233,6 @@ namespace core {
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
TryCorrectGoogleVersions();
-
return QString("https://%1%2.google.com/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleTerrain).arg(language).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
@@ -243,8 +245,8 @@ namespace core {
GetSecGoogleWords(pos, sec1, sec2);
TryCorrectGoogleVersions();
// http://mt0.google.cn/vt/v=w2.101&hl=zh-CN&gl=cn&x=12&y=6&z=4&s=Ga
-
- return QString("http://%1%2.google.cn/%3/lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleMapChina).arg("zh-CN").arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
+
+ return QString("https://%1%2.google.cn/%3/lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleMapChina).arg("zh-CN").arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
case MapType::GoogleSatelliteChina:
@@ -255,9 +257,9 @@ namespace core {
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
// TryCorrectGoogleVersions();
- // http://khm0.google.cn/kh/v=46&x=12&y=6&z=4&s=Ga
+ // https://khm0.google.cn/kh/v=46&x=12&y=6&z=4&s=Ga
- return QString("http://%1%2.google.cn/%3/lyrs=%4&gl=cn&x=%5%6&y=%7&z=%8&s=%9").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleSatelliteChina).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
+ return QString("https://%1%2.google.cn/%3/lyrs=%4&gl=cn&x=%5%6&y=%7&z=%8&s=%9").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleSatelliteChina).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
case MapType::GoogleLabelsChina:
@@ -270,7 +272,7 @@ namespace core {
TryCorrectGoogleVersions();
// http://mt0.google.cn/vt/v=w2t.110&hl=zh-CN&gl=cn&x=12&y=6&z=4&s=Ga
- return QString("http://%1%2.google.cn/%3/imgtp=png32&lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleLabelsChina).arg("zh-CN").arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
+ return QString("https://%1%2.google.cn/%3/imgtp=png32&lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleLabelsChina).arg("zh-CN").arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
case MapType::GoogleTerrainChina:
@@ -281,10 +283,10 @@ namespace core {
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
TryCorrectGoogleVersions();
-
+
// http://mt0.google.cn/vt/v=w2p.110&hl=zh-CN&gl=cn&x=12&y=6&z=4&s=Ga
- return QString("http://%1%2.google.com/%3/lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleTerrainChina).arg("zh-CN").arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
+ return QString("https://%1%2.google.com/%3/lyrs=%4&hl=%5&gl=cn&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleTerrainChina).arg("zh-CN").arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
case MapType::GoogleMapKorea:
@@ -294,7 +296,7 @@ namespace core {
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
-
+
//http://mt3.gmaptiles.co.kr/mt/v=kr1.11&hl=lt&x=109&y=49&z=7&s=
QString ret = QString("https://%1%2.gmaptiles.co.kr/%3/v=%4&hl=%5&x=%6%7&y=%8&z=%9&s=%10").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleMapKorea).arg(language).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
@@ -308,10 +310,10 @@ namespace core {
QString sec1 = ""; // after &x=...
QString sec2 = ""; // after &zoom=...
GetSecGoogleWords(pos, sec1, sec2);
-
+
// http://khm1.google.co.kr/kh/v=54&x=109&y=49&z=7&s=
- return QString("http://%1%2.google.co.kr/%3/v=%4&x=%5%6&y=%7&z=%8&s=%9").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleSatelliteKorea).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
+ return QString("https://%1%2.google.co.kr/%3/v=%4&x=%5%6&y=%7&z=%8&s=%9").arg(server).arg(GetServerNum(pos, 4)).arg(request).arg(VersionGoogleSatelliteKorea).arg(pos.X()).arg(sec1).arg(pos.Y()).arg(zoom).arg(sec2);
}
break;
case MapType::GoogleLabelsKorea:
@@ -502,12 +504,12 @@ namespace core {
QString UrlFactory::MakeGeocoderUrl(QString keywords)
{
QString key = keywords.replace(' ', '+');
- return QString("http://maps.google.com/maps/geo?q=%1&output=csv&key=%2").arg(key).arg(GoogleMapsAPIKey);
+ return QString("https://maps.google.com/maps/geo?q=%1&output=csv&key=%2").arg(key).arg(GoogleMapsAPIKey);
}
QString UrlFactory::MakeReverseGeocoderUrl(internals::PointLatLng &pt,const QString &language)
{
- return QString("http://maps.google.com/maps/geo?hl=%1&ll=%2,%3&output=csv&key=%4").arg(language).arg(QString::number(pt.Lat())).arg(QString::number(pt.Lng())).arg(GoogleMapsAPIKey);
+ return QString("https://maps.google.com/maps/geo?hl=%1&ll=%2,%3&output=csv&key=%4").arg(language).arg(QString::number(pt.Lat())).arg(QString::number(pt.Lng())).arg(GoogleMapsAPIKey);
}
internals::PointLatLng UrlFactory::GetLatLngFromGeodecoder(const QString &keywords, GeoCoderStatusCode::Types &status)
diff --git a/libs/opmapcontrol/src/core/urlfactory.h b/libs/opmapcontrol/src/core/urlfactory.h
index 2f4bfbeb13f49e964001ca0dd7a83f96c8749e84..7ff86ce9b6a9ad31088b26ac8e41785a85bf8c2b 100644
--- a/libs/opmapcontrol/src/core/urlfactory.h
+++ b/libs/opmapcontrol/src/core/urlfactory.h
@@ -61,6 +61,7 @@ namespace core {
Placemark GetPlacemarkFromGeocoder(internals::PointLatLng location);
int Timeout;
private:
+ int Random(int low, int high);
void GetSecGoogleWords(const core::Point &pos, QString &sec1, QString &sec2);
int GetServerNum(const core::Point &pos,const int &max) const;
void TryCorrectGoogleVersions();
diff --git a/libs/opmapcontrol/src/mapwidget/mapripper.cpp b/libs/opmapcontrol/src/mapwidget/mapripper.cpp
index ef376e5a18ee426daca2b353d1ca51de535a5a25..7dc3004ff170004fbc435a886b2f83dfc9ca54f4 100644
--- a/libs/opmapcontrol/src/mapwidget/mapripper.cpp
+++ b/libs/opmapcontrol/src/mapwidget/mapripper.cpp
@@ -52,31 +52,37 @@ namespace mapcontrol
}
void MapRipper::finish()
{
- if(zoomProjection()->GetAreaTileList(area,zoom,0);
- this->start();
- }
- else
- {
- progressForm->close();
- delete progressForm;
- this->deleteLater();
- }
- }
+ if(ret==QMessageBox::Yes || ret == 1)
+ {
+ points.clear();
+ points=core->Projection()->GetAreaTileList(area,zoom,0);
+ this->start();
+ }
+ else
+ {
+ progressForm->close();
+ delete progressForm;
+ this->deleteLater();
+ }
+ }
+ else
+ {
+ progressForm->close();
+ delete progressForm;
+ this->deleteLater();
+ }
}
diff --git a/libs/qwt.pri b/libs/qwt.pri
new file mode 100644
index 0000000000000000000000000000000000000000..ecb19d61fd7a914c9ccfd9e5c0c98703ed917a37
--- /dev/null
+++ b/libs/qwt.pri
@@ -0,0 +1,149 @@
+######################################################################
+# 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
diff --git a/libs/qwt/qwt_abstract_legend.cpp b/libs/qwt/qwt_abstract_legend.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ecaac61d96cedf695909d2288309f2660b9ffdf
--- /dev/null
+++ b/libs/qwt/qwt_abstract_legend.cpp
@@ -0,0 +1,38 @@
+/* -*- 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;
+}
diff --git a/libs/qwt/qwt_abstract_legend.h b/libs/qwt/qwt_abstract_legend.h
new file mode 100644
index 0000000000000000000000000000000000000000..18bd3f4b96855f43bcb36f4f21960055d7bd8bbf
--- /dev/null
+++ b/libs/qwt/qwt_abstract_legend.h
@@ -0,0 +1,71 @@
+/* -*- 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
+#include
+
+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 &data ) = 0;
+};
+
+#endif
diff --git a/libs/qwt/qwt_abstract_scale.cpp b/libs/qwt/qwt_abstract_scale.cpp
index 1f89a45a091ed266d740812debe1152cd73382f3..3018b854ea411bba9e20485fbfa00ec38adb7125 100644
--- a/libs/qwt/qwt_abstract_scale.cpp
+++ b/libs/qwt/qwt_abstract_scale.cpp
@@ -7,26 +7,27 @@
* 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_double_interval.h"
-#include "qwt_abstract_scale.h"
+#include "qwt_interval.h"
class QwtAbstractScale::PrivateData
{
public:
PrivateData():
- maxMajor(5),
- maxMinor(3),
- stepSize(0.0),
- autoScale(true) {
- scaleEngine = new QwtLinearScaleEngine;
+ maxMajor( 5 ),
+ maxMinor( 3 ),
+ stepSize( 0.0 )
+ {
+ scaleEngine = new QwtLinearScaleEngine();
scaleDraw = new QwtScaleDraw();
}
- ~PrivateData() {
+ ~PrivateData()
+ {
delete scaleEngine;
delete scaleDraw;
}
@@ -37,21 +38,25 @@ public:
int maxMajor;
int maxMinor;
double stepSize;
-
- bool autoScale;
};
/*!
Constructor
+ \param parent Parent widget
+
Creates a default QwtScaleDraw and a QwtLinearScaleEngine.
- Autoscaling is enabled, and the stepSize is initialized by 0.0.
+ 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()
+QwtAbstractScale::QwtAbstractScale( QWidget *parent ):
+ QWidget( parent )
{
d_data = new PrivateData;
- rescale(0.0, 100.0);
+ rescale( 0.0, 100.0, d_data->stepSize );
}
//! Destructor
@@ -61,138 +66,166 @@ QwtAbstractScale::~QwtAbstractScale()
}
/*!
- \brief Specify a scale.
+ Set the lower bound of the scale
- Disable autoscaling and define a scale by an interval and a step size
+ \param value Lower bound
- \param vmin lower limit of the scale interval
- \param vmax upper limit of the scale interval
- \param stepSize major step size
- \sa setAutoScale()
+ \sa lowerBound(), setScale(), setUpperBound()
+ \note For inverted scales the lower bound
+ is greater than the upper bound
*/
-void QwtAbstractScale::setScale(double vmin, double vmax, double stepSize)
+void QwtAbstractScale::setLowerBound( double value )
{
- d_data->autoScale = false;
- d_data->stepSize = stepSize;
+ setScale( value, upperBound() );
+}
- rescale(vmin, vmax, stepSize);
+/*!
+ \return Lower bound of the scale
+ \sa setLowerBound(), setScale(), upperBound()
+*/
+double QwtAbstractScale::lowerBound() const
+{
+ return d_data->scaleDraw->scaleDiv().lowerBound();
}
/*!
- \brief Specify a scale.
+ Set the upper bound of the scale
- Disable autoscaling and define a scale by an interval and a step size
+ \param value Upper bound
- \param interval Interval
- \param stepSize major step size
- \sa setAutoScale()
+ \sa upperBound(), setScale(), setLowerBound()
+ \note For inverted scales the lower bound
+ is greater than the upper bound
*/
-void QwtAbstractScale::setScale(const QwtDoubleInterval &interval,
- double stepSize)
+void QwtAbstractScale::setUpperBound( double value )
{
- setScale(interval.minValue(), interval.maxValue(), stepSize);
+ 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.
- Disable autoscaling and define a scale by a scale division
+ Define a scale by an interval
- \param scaleDiv Scale division
- \sa setAutoScale()
+ 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(const QwtScaleDiv &scaleDiv)
+void QwtAbstractScale::setScale( double lowerBound, double upperBound )
{
- d_data->autoScale = false;
-
- if (scaleDiv != d_data->scaleDraw->scaleDiv()) {
- d_data->scaleDraw->setScaleDiv(scaleDiv);
- scaleChange();
- }
+ rescale( lowerBound, upperBound, d_data->stepSize );
}
/*!
- Recalculate the scale division and update the scale draw.
+ \brief Specify a scale.
- \param vmin Lower limit of the scale interval
- \param vmax Upper limit of the scale interval
- \param stepSize Major step size
+ Define a scale by an interval
- \sa scaleChange()
+ The ticks are calculated using scaleMaxMinor(),
+ scaleMaxMajor() and scaleStepSize().
+
+ \param interval Interval
*/
-void QwtAbstractScale::rescale(double vmin, double vmax, double stepSize)
+void QwtAbstractScale::setScale( const QwtInterval &interval )
{
- const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale(
- vmin, vmax, d_data->maxMajor, d_data->maxMinor, stepSize);
-
- if ( scaleDiv != d_data->scaleDraw->scaleDiv() ) {
- d_data->scaleDraw->setTransformation(
- d_data->scaleEngine->transformation());
- d_data->scaleDraw->setScaleDiv(scaleDiv);
- scaleChange();
- }
+ setScale( interval.minValue(), interval.maxValue() );
}
/*!
- \brief Advise the widget to control the scale range internally.
+ \brief Specify a scale.
- Autoscaling is on by default.
- \sa setScale(), autoScale()
+ scaleMaxMinor(), scaleMaxMajor() and scaleStepSize() and have no effect.
+
+ \param scaleDiv Scale division
+ \sa setAutoScale()
*/
-void QwtAbstractScale::setAutoScale()
+void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv )
{
- if (!d_data->autoScale) {
- d_data->autoScale = true;
+ 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();
}
}
-/*!
- \return \c true if autoscaling is enabled
-*/
-bool QwtAbstractScale::autoScale() const
-{
- return d_data->autoScale;
-}
-
/*!
\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 QwtAbstractScaleDraw
+
+ \param ticks Maximal number of major ticks.
+
+ \sa scaleMaxMajor(), setScaleMaxMinor(),
+ setScaleStepSize(), QwtScaleEngine::divideInterval()
*/
-void QwtAbstractScale::setScaleMaxMajor(int ticks)
+void QwtAbstractScale::setScaleMaxMajor( int ticks )
{
- if (ticks != d_data->maxMajor) {
+ 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
- \sa QwtAbstractScaleDraw
+
+ \param ticks Maximal number of minor ticks.
+
+ \sa scaleMaxMajor(), setScaleMaxMinor(),
+ setScaleStepSize(), QwtScaleEngine::divideInterval()
*/
-void QwtAbstractScale::setScaleMaxMinor(int ticks)
+void QwtAbstractScale::setScaleMaxMinor( int ticks )
{
- if ( ticks != d_data->maxMinor) {
+ if ( ticks != d_data->maxMinor )
+ {
d_data->maxMinor = ticks;
updateScaleDraw();
}
}
/*!
- \return Max. number of minor tick intervals
- The default value is 3.
+ \return Maximal number of minor tick intervals
+ \sa setScaleMaxMinor(), scaleMaxMajor()
*/
int QwtAbstractScale::scaleMaxMinor() const
{
@@ -200,27 +233,52 @@ int QwtAbstractScale::scaleMaxMinor() const
}
/*!
- \return Max. number of major tick intervals
- The default value is 5.
+ \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().
*/
-int QwtAbstractScale::scaleMaxMajor() const
+void QwtAbstractScale::setScaleStepSize( double stepSize )
{
- return d_data->maxMajor;
+ 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
- ~QwtAbstractScale or the next call of setAbstractScaleDraw.
+ the destructor or the next call of setAbstractScaleDraw().
+
+ \sa abstractScaleDraw()
*/
-void QwtAbstractScale::setAbstractScaleDraw(QwtAbstractScaleDraw *scaleDraw)
+void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw )
{
if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw )
return;
if ( d_data->scaleDraw != NULL )
- scaleDraw->setScaleDiv(d_data->scaleDraw->scaleDiv());
+ scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() );
delete d_data->scaleDraw;
d_data->scaleDraw = scaleDraw;
@@ -244,32 +302,27 @@ const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const
return d_data->scaleDraw;
}
-void QwtAbstractScale::updateScaleDraw()
-{
- rescale( d_data->scaleDraw->scaleDiv().lBound(),
- d_data->scaleDraw->scaleDiv().hBound(), d_data->stepSize);
-}
-
/*!
\brief Set a scale engine
- The scale engine is responsible for calculating the scale division,
- and in case of auto scaling how to align the scale.
+ 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
- ~QwtAbstractScale or the next call of setScaleEngine.
+ the destructor or the next call of setScaleEngine.
*/
-void QwtAbstractScale::setScaleEngine(QwtScaleEngine *scaleEngine)
+void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine )
{
- if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine ) {
+ if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine )
+ {
delete d_data->scaleEngine;
d_data->scaleEngine = scaleEngine;
}
}
/*!
- \return Scale engine
- \sa setScaleEngine()
+ \return Scale engine
+ \sa setScaleEngine()
*/
const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
{
@@ -277,8 +330,8 @@ const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
}
/*!
- \return Scale engine
- \sa setScaleEngine()
+ \return Scale engine
+ \sa setScaleEngine()
*/
QwtScaleEngine *QwtAbstractScale::scaleEngine()
{
@@ -286,18 +339,111 @@ QwtScaleEngine *QwtAbstractScale::scaleEngine()
}
/*!
- \brief Notify changed scale
+ \return Scale boundaries and positions of the ticks
- Dummy empty implementation, intended to be overloaded by derived classes
-*/
-void QwtAbstractScale::scaleChange()
+ The scale division might have been assigned explicitly
+ or calculated implicitly by rescale().
+ */
+const QwtScaleDiv &QwtAbstractScale::scaleDiv() const
{
+ return d_data->scaleDraw->scaleDiv();
}
/*!
- \return abstractScaleDraw()->scaleMap()
-*/
+ \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 );
+}
diff --git a/libs/qwt/qwt_abstract_scale.h b/libs/qwt/qwt_abstract_scale.h
index dac0aa3f8168a2483b2a3970de1e4602023cb97b..4ed6616aa8441ab3db1f82fd5cfc14a664cdfc21 100644
--- a/libs/qwt/qwt_abstract_scale.h
+++ b/libs/qwt/qwt_abstract_scale.h
@@ -11,50 +11,85 @@
#define QWT_ABSTRACT_SCALE_H
#include "qwt_global.h"
+#include
class QwtScaleEngine;
class QwtAbstractScaleDraw;
class QwtScaleDiv;
class QwtScaleMap;
-class QwtDoubleInterval;
+class QwtInterval;
/*!
- \brief An abstract base class for classes containing a scale
+ \brief An abstract base class for widgets having a scale
- QwtAbstractScale is used to provide classes with a QwtScaleDraw,
- and a QwtScaleDiv. The QwtScaleDiv might be set explicitely
- or calculated by a QwtScaleEngine.
+ 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
+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();
+ QwtAbstractScale( QWidget *parent = NULL );
virtual ~QwtAbstractScale();
- void setScale(double vmin, double vmax, double step = 0.0);
- void setScale(const QwtDoubleInterval &, double step = 0.0);
- void setScale(const QwtScaleDiv &s);
+ void setScale( double lowerBound, double upperBound );
+ void setScale( const QwtInterval & );
+ void setScale( const QwtScaleDiv & );
+
+ const QwtScaleDiv& scaleDiv() const;
- void setAutoScale();
- bool autoScale() const;
+ void setLowerBound( double value );
+ double lowerBound() const;
- void setScaleMaxMajor( int ticks);
+ 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);
+ void setScaleMaxMinor( int ticks );
int scaleMaxMajor() const;
- void setScaleEngine(QwtScaleEngine *);
+ 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 vmin, double vmax, double step = 0.0);
+ void rescale( double lowerBound,
+ double upperBound, double stepSize );
+
+ void setAbstractScaleDraw( QwtAbstractScaleDraw * );
- void setAbstractScaleDraw(QwtAbstractScaleDraw *);
const QwtAbstractScaleDraw *abstractScaleDraw() const;
QwtAbstractScaleDraw *abstractScaleDraw();
diff --git a/libs/qwt/qwt_abstract_scale_draw.cpp b/libs/qwt/qwt_abstract_scale_draw.cpp
index b04f2f5eb44d4a74b5b42e27000ce9e2b9c1af88..20117330393f1be052a9f7813869a5a5ca1834a9 100644
--- a/libs/qwt/qwt_abstract_scale_draw.cpp
+++ b/libs/qwt/qwt_abstract_scale_draw.cpp
@@ -7,39 +7,43 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-// vim: expandtab
-
-#include
-#include
-#include
-#include
+#include "qwt_abstract_scale_draw.h"
#include "qwt_math.h"
#include "qwt_text.h"
#include "qwt_painter.h"
#include "qwt_scale_map.h"
-#include "qwt_scale_draw.h"
+#include
+#include
+#include
+#include
class QwtAbstractScaleDraw::PrivateData
{
public:
PrivateData():
- components(Backbone | Ticks | Labels),
- spacing(4),
- minExtent(0) {
- tickLength[QwtScaleDiv::MinorTick] = 4;
- tickLength[QwtScaleDiv::MediumTick] = 6;
- tickLength[QwtScaleDiv::MajorTick] = 8;
+ 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;
}
- int components;
+ ScaleComponents components;
QwtScaleMap map;
- QwtScaleDiv scldiv;
+ QwtScaleDiv scaleDiv;
- int spacing;
- int tickLength[QwtScaleDiv::NTickTypes];
+ double spacing;
+ double tickLength[QwtScaleDiv::NTickTypes];
+ int penWidth;
- int minExtent;
+ double minExtent;
QMap labelCache;
};
@@ -56,23 +60,11 @@ QwtAbstractScaleDraw::QwtAbstractScaleDraw()
d_data = new QwtAbstractScaleDraw::PrivateData;
}
-//! Copy constructor
-QwtAbstractScaleDraw::QwtAbstractScaleDraw(const QwtAbstractScaleDraw &other)
-{
- d_data = new QwtAbstractScaleDraw::PrivateData(*other.d_data);
-}
-
//! Destructor
QwtAbstractScaleDraw::~QwtAbstractScaleDraw()
{
delete d_data;
}
-//! Assignment operator
-QwtAbstractScaleDraw &QwtAbstractScaleDraw::operator=(const QwtAbstractScaleDraw &other)
-{
- *d_data = *other.d_data;
- return *this;
-}
/*!
En/Disable a component of the scale
@@ -80,10 +72,10 @@ QwtAbstractScaleDraw &QwtAbstractScaleDraw::operator=(const QwtAbstractScaleDraw
\param component Scale component
\param enable On/Off
- \sa QwtAbstractScaleDraw::hasComponent
+ \sa hasComponent()
*/
void QwtAbstractScaleDraw::enableComponent(
- ScaleComponent component, bool enable)
+ ScaleComponent component, bool enable )
{
if ( enable )
d_data->components |= component;
@@ -93,21 +85,24 @@ void QwtAbstractScaleDraw::enableComponent(
/*!
Check if a component is enabled
- \sa QwtAbstractScaleDraw::enableComponent
+
+ \param component Component type
+ \return true, when component is enabled
+ \sa enableComponent()
*/
-bool QwtAbstractScaleDraw::hasComponent(ScaleComponent component) const
+bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
{
- return (d_data->components & component);
+ return ( d_data->components & component );
}
/*!
Change the scale division
- \param sd New scale division
+ \param scaleDiv New scale division
*/
-void QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &sd)
+void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &scaleDiv )
{
- d_data->scldiv = sd;
- d_data->map.setScaleInterval(sd.lBound(), sd.hBound());
+ d_data->scaleDiv = scaleDiv;
+ d_data->map.setScaleInterval( scaleDiv.lowerBound(), scaleDiv.upperBound() );
d_data->labelCache.clear();
}
@@ -116,13 +111,13 @@ void QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &sd)
\param transformation New scale transformation
*/
void QwtAbstractScaleDraw::setTransformation(
- QwtScaleTransformation *transformation)
+ QwtTransform *transformation )
{
- d_data->map.setTransformation(transformation);
+ d_data->map.setTransformation( transformation );
}
//! \return Map how to translate between scale and pixel values
-const QwtScaleMap &QwtAbstractScaleDraw::map() const
+const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const
{
return d_data->map;
}
@@ -136,22 +131,31 @@ QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
//! \return scale division
const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
{
- return d_data->scldiv;
+ return d_data->scaleDiv;
}
-#if QT_VERSION < 0x040000
/*!
- \brief Draw the scale
+ \brief Specify the width of the scale pen
+ \param width Pen width
+ \sa penWidth()
+*/
+void QwtAbstractScaleDraw::setPenWidth( int width )
+{
+ if ( width < 0 )
+ width = 0;
- \param painter The painter
+ if ( width != d_data->penWidth )
+ d_data->penWidth = width;
+}
- \param colorGroup Color group, text color is used for the labels,
- foreground color for ticks and backbone
+/*!
+ \return Scale pen width
+ \sa setPenWidth()
*/
-void QwtAbstractScaleDraw::draw(QPainter *painter,
- const QColorGroup& colorGroup) const
-
-#else
+int QwtAbstractScaleDraw::penWidth() const
+{
+ return d_data->penWidth;
+}
/*!
\brief Draw the scale
@@ -161,70 +165,75 @@ void QwtAbstractScaleDraw::draw(QPainter *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
-#endif
+void QwtAbstractScaleDraw::draw( QPainter *painter,
+ const QPalette& palette ) const
{
- if ( hasComponent(QwtAbstractScaleDraw::Labels) ) {
- painter->save();
+ painter->save();
-#if QT_VERSION < 0x040000
- painter->setPen(colorGroup.text()); // ignore pen style
-#else
- painter->setPen(palette.color(QPalette::Text)); // ignore pen style
-#endif
+ QPen pen = painter->pen();
+ pen.setWidth( d_data->penWidth );
+ pen.setCosmetic( false );
+ painter->setPen( pen );
- const QwtValueList &majorTicks =
- d_data->scldiv.ticks(QwtScaleDiv::MajorTick);
+ if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
+ {
+ painter->save();
+ painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
+
+ const QList &majorTicks =
+ d_data->scaleDiv.ticks( QwtScaleDiv::MajorTick );
- for (int i = 0; i < (int)majorTicks.count(); i++) {
+ for ( int i = 0; i < majorTicks.count(); i++ )
+ {
const double v = majorTicks[i];
- if ( d_data->scldiv.contains(v) )
- drawLabel(painter, majorTicks[i]);
+ if ( d_data->scaleDiv.contains( v ) )
+ drawLabel( painter, v );
}
painter->restore();
}
- if ( hasComponent(QwtAbstractScaleDraw::Ticks) ) {
+ if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
+ {
painter->save();
QPen pen = painter->pen();
-#if QT_VERSION < 0x040000
- pen.setColor(colorGroup.foreground());
-#else
- pen.setColor(palette.color(QPalette::Foreground));
-#endif
- painter->setPen(pen);
+ pen.setColor( palette.color( QPalette::WindowText ) );
+ pen.setCapStyle( Qt::FlatCap );
+
+ painter->setPen( pen );
for ( int tickType = QwtScaleDiv::MinorTick;
- tickType < QwtScaleDiv::NTickTypes; tickType++ ) {
- const QwtValueList &ticks = d_data->scldiv.ticks(tickType);
- for (int i = 0; i < (int)ticks.count(); i++) {
+ tickType < QwtScaleDiv::NTickTypes; tickType++ )
+ {
+ const QList &ticks = d_data->scaleDiv.ticks( tickType );
+ for ( int i = 0; i < ticks.count(); i++ )
+ {
const double v = ticks[i];
- if ( d_data->scldiv.contains(v) )
- drawTick(painter, v, d_data->tickLength[tickType]);
+ if ( d_data->scaleDiv.contains( v ) )
+ drawTick( painter, v, d_data->tickLength[tickType] );
}
}
painter->restore();
}
- if ( hasComponent(QwtAbstractScaleDraw::Backbone) ) {
+ if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
+ {
painter->save();
QPen pen = painter->pen();
-#if QT_VERSION < 0x040000
- pen.setColor(colorGroup.foreground());
-#else
- pen.setColor(palette.color(QPalette::Foreground));
-#endif
- painter->setPen(pen);
+ pen.setColor( palette.color( QPalette::WindowText ) );
+ pen.setCapStyle( Qt::FlatCap );
+
+ painter->setPen( pen );
- drawBackbone(painter);
+ drawBackbone( painter );
painter->restore();
}
+
+ painter->restore();
}
/*!
@@ -235,9 +244,9 @@ void QwtAbstractScaleDraw::draw(QPainter *painter,
\param spacing Spacing
- \sa QwtAbstractScaleDraw::spacing
+ \sa spacing()
*/
-void QwtAbstractScaleDraw::setSpacing(int spacing)
+void QwtAbstractScaleDraw::setSpacing( double spacing )
{
if ( spacing < 0 )
spacing = 0;
@@ -251,9 +260,10 @@ void QwtAbstractScaleDraw::setSpacing(int spacing)
The spacing is the distance between ticks and labels.
The default spacing is 4 pixels.
- \sa QwtAbstractScaleDraw::setSpacing
+ \return Spacing
+ \sa setSpacing()
*/
-int QwtAbstractScaleDraw::spacing() const
+double QwtAbstractScaleDraw::spacing() const
{
return d_data->spacing;
}
@@ -261,7 +271,7 @@ int QwtAbstractScaleDraw::spacing() const
/*!
\brief Set a minimum for the extent
- The extent is calculated from the coomponents of the
+ 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
@@ -271,19 +281,20 @@ int QwtAbstractScaleDraw::spacing() const
\sa extent(), minimumExtent()
*/
-void QwtAbstractScaleDraw::setMinimumExtent(int minExtent)
+void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
{
- if ( minExtent < 0 )
- minExtent = 0;
+ if ( minExtent < 0.0 )
+ minExtent = 0.0;
d_data->minExtent = minExtent;
}
/*!
Get the minimum extent
+ \return Minimum extent
\sa extent(), setMinimumExtent()
*/
-int QwtAbstractScaleDraw::minimumExtent() const
+double QwtAbstractScaleDraw::minimumExtent() const
{
return d_data->minExtent;
}
@@ -297,33 +308,33 @@ int QwtAbstractScaleDraw::minimumExtent() const
\warning the length is limited to [0..1000]
*/
void QwtAbstractScaleDraw::setTickLength(
- QwtScaleDiv::TickType tickType, int length)
+ QwtScaleDiv::TickType tickType, double length )
{
if ( tickType < QwtScaleDiv::MinorTick ||
- tickType > QwtScaleDiv::MajorTick ) {
+ tickType > QwtScaleDiv::MajorTick )
+ {
return;
}
- if ( length < 0 )
- length = 0;
+ if ( length < 0.0 )
+ length = 0.0;
- const int maxTickLen = 1000;
+ const double maxTickLen = 1000.0;
if ( length > maxTickLen )
- length = 1000;
+ length = maxTickLen;
d_data->tickLength[tickType] = length;
}
/*!
- Return the length of the ticks
-
- \sa QwtAbstractScaleDraw::setTickLength,
- QwtAbstractScaleDraw::majTickLength
+ \return Length of the ticks
+ \sa setTickLength(), maxTickLength()
*/
-int QwtAbstractScaleDraw::tickLength(QwtScaleDiv::TickType tickType) const
+double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
{
if ( tickType < QwtScaleDiv::MinorTick ||
- tickType > QwtScaleDiv::MajorTick ) {
+ tickType > QwtScaleDiv::MajorTick )
+ {
return 0;
}
@@ -331,27 +342,34 @@ int QwtAbstractScaleDraw::tickLength(QwtScaleDiv::TickType tickType) const
}
/*!
- The same as QwtAbstractScaleDraw::tickLength(QwtScaleDiv::MajorTick).
+ \return Length of the longest tick
+
+ Useful for layout calculations
+ \sa tickLength(), setTickLength()
*/
-int QwtAbstractScaleDraw::majTickLength() const
+double QwtAbstractScaleDraw::maxTickLength() const
{
- return d_data->tickLength[QwtScaleDiv::MajorTick];
+ 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::system().toString(value).
+ 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
+QwtText QwtAbstractScaleDraw::label( double value ) const
{
- return QLocale::system().toString(value);
+ return QLocale().toString( value );
}
/*!
@@ -368,28 +386,29 @@ QwtText QwtAbstractScaleDraw::label(double value) const
\return Tick label
*/
const QwtText &QwtAbstractScaleDraw::tickLabel(
- const QFont &font, double value) const
+ const QFont &font, double value ) const
{
- QMap::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);
+ QMap::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
+ ( void )lbl.textSize( font ); // initialize the internal cache
- it = d_data->labelCache.insert(value, lbl);
+ it = d_data->labelCache.insert( value, lbl );
}
- return (*it);
+ return ( *it );
}
/*!
- Invalidate the cache used by QwtAbstractScaleDraw::tickLabel
+ 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,
- QwtAbstractScaleDraw::invalidateCache needs to be called manually.
+ invalidateCache() needs to be called manually.
*/
void QwtAbstractScaleDraw::invalidateCache()
{
diff --git a/libs/qwt/qwt_abstract_scale_draw.h b/libs/qwt/qwt_abstract_scale_draw.h
index a2b7895f4c6d6b7bd47ae801f8ac7cd7320fc398..d0f1ec3c3b4d2e78d5af66d411974482809c727d 100644
--- a/libs/qwt/qwt_abstract_scale_draw.h
+++ b/libs/qwt/qwt_abstract_scale_draw.h
@@ -14,15 +14,10 @@
#include "qwt_scale_div.h"
#include "qwt_text.h"
-
-#if QT_VERSION < 0x040000
-class QColorGroup;
-#else
class QPalette;
-#endif
class QPainter;
class QFont;
-class QwtScaleTransformation;
+class QwtTransform;
class QwtScaleMap;
/*!
@@ -31,8 +26,7 @@ class QwtScaleMap;
QwtAbstractScaleDraw can be used to draw linear or logarithmic scales.
After a scale division has been specified as a QwtScaleDiv object
- using QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &s),
- the scale can be drawn with the QwtAbstractScaleDraw::draw() member.
+ using setScaleDiv(), the scale can be drawn with the draw() member.
*/
class QWT_EXPORT QwtAbstractScaleDraw
{
@@ -40,66 +34,66 @@ public:
/*!
Components of a scale
+ \sa enableComponent(), hasComponent
+ */
+ enum ScaleComponent
+ {
+ //! Backbone = the line where the ticks are located
+ Backbone = 0x01,
- - Backbone
- - Ticks
- - Labels
-
- \sa QwtAbstractScaleDraw::enableComponent,
- QwtAbstractScaleDraw::hasComponent
- */
+ //! Ticks
+ Ticks = 0x02,
- enum ScaleComponent {
- Backbone = 1,
- Ticks = 2,
- Labels = 4
+ //! Labels
+ Labels = 0x04
};
+ //! Scale components
+ typedef QFlags ScaleComponents;
+
QwtAbstractScaleDraw();
- QwtAbstractScaleDraw( const QwtAbstractScaleDraw & );
virtual ~QwtAbstractScaleDraw();
- QwtAbstractScaleDraw &operator=(const QwtAbstractScaleDraw &);
-
- void setScaleDiv(const QwtScaleDiv &s);
+ void setScaleDiv( const QwtScaleDiv &s );
const QwtScaleDiv& scaleDiv() const;
- void setTransformation(QwtScaleTransformation *);
- const QwtScaleMap &map() const;
+ void setTransformation( QwtTransform * );
+ const QwtScaleMap &scaleMap() const;
+ QwtScaleMap &scaleMap();
- void enableComponent(ScaleComponent, bool enable = true);
- bool hasComponent(ScaleComponent) const;
+ void enableComponent( ScaleComponent, bool enable = true );
+ bool hasComponent( ScaleComponent ) const;
- void setTickLength(QwtScaleDiv::TickType, int length);
- int tickLength(QwtScaleDiv::TickType) const;
- int majTickLength() const;
+ void setTickLength( QwtScaleDiv::TickType, double length );
+ double tickLength( QwtScaleDiv::TickType ) const;
+ double maxTickLength() const;
- void setSpacing(int margin);
- int spacing() const;
+ void setSpacing( double margin );
+ double spacing() const;
-#if QT_VERSION < 0x040000
- virtual void draw(QPainter *, const QColorGroup &) const;
-#else
- virtual void draw(QPainter *, const QPalette &) const;
-#endif
+ void setPenWidth( int width );
+ int penWidth() const;
+
+ virtual void draw( QPainter *, const QPalette & ) const;
- virtual QwtText label(double) const;
+ virtual QwtText label( double ) const;
/*!
Calculate the extent
- The extent is the distcance from the baseline to the outermost
+ 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 int extent(const QPen &, const QFont &) const = 0;
+ virtual double extent( const QFont &font ) const = 0;
- void setMinimumExtent(int);
- int minimumExtent() const;
-
- QwtScaleMap &scaleMap();
+ void setMinimumExtent( double );
+ double minimumExtent() const;
protected:
/*!
@@ -107,11 +101,11 @@ protected:
\param painter Painter
\param value Value of the tick
- \param len Lenght of the tick
+ \param len Length of the tick
\sa drawBackbone(), drawLabel()
*/
- virtual void drawTick(QPainter *painter, double value, int len) const = 0;
+ virtual void drawTick( QPainter *painter, double value, double len ) const = 0;
/*!
Draws the baseline of the scale
@@ -119,7 +113,7 @@ protected:
\sa drawTick(), drawLabel()
*/
- virtual void drawBackbone(QPainter *painter) const = 0;
+ virtual void drawBackbone( QPainter *painter ) const = 0;
/*!
Draws the label for a major scale tick
@@ -127,19 +121,21 @@ protected:
\param painter Painter
\param value Value
- \sa drawTick, drawBackbone
+ \sa drawTick(), drawBackbone()
*/
- virtual void drawLabel(QPainter *painter, double value) const = 0;
+ virtual void drawLabel( QPainter *painter, double value ) const = 0;
void invalidateCache();
- const QwtText &tickLabel(const QFont &, double value) const;
+ const QwtText &tickLabel( const QFont &, double value ) const;
private:
- int operator==(const QwtAbstractScaleDraw &) const;
- int operator!=(const QwtAbstractScaleDraw &) const;
+ QwtAbstractScaleDraw( const QwtAbstractScaleDraw & );
+ QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & );
class PrivateData;
PrivateData *d_data;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS( QwtAbstractScaleDraw::ScaleComponents )
+
#endif
diff --git a/libs/qwt/qwt_abstract_slider.cpp b/libs/qwt/qwt_abstract_slider.cpp
index 0f4dcb2bb2001b1f8bc17b88d0623e364bdc65a5..7bac22e613ae6460b426348a8a34590e8fe050cc 100644
--- a/libs/qwt/qwt_abstract_slider.cpp
+++ b/libs/qwt/qwt_abstract_slider.cpp
@@ -7,84 +7,149 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-#include
-#include
#include "qwt_abstract_slider.h"
+#include "qwt_abstract_scale_draw.h"
#include "qwt_math.h"
+#include "qwt_scale_map.h"
+#include
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120
+#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 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():
- scrollMode(ScrNone),
- mouseOffset(0.0),
- tracking(true),
- tmrID(0),
- updTime(150),
- mass(0.0),
- readOnly(false) {
+ 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 )
+ {
}
- int scrollMode;
- double mouseOffset;
- int direction;
- int tracking;
-
- int tmrID;
- int updTime;
- int timerTick;
- QTime time;
- double speed;
- double mass;
- Qt::Orientation orientation;
+ 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
+ \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 orientation Orientation
- \param parent Parent widget
+ \param parent Parent widget
*/
-QwtAbstractSlider::QwtAbstractSlider(
- Qt::Orientation orientation, QWidget *parent):
- QWidget(parent, NULL)
+QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ):
+ QwtAbstractScale( parent )
{
d_data = new QwtAbstractSlider::PrivateData;
- d_data->orientation = orientation;
-#if QT_VERSION >= 0x040000
- using namespace Qt;
-#endif
- setFocusPolicy(TabFocus);
+ setScale( 0.0, 100.0 );
+ setFocusPolicy( Qt::StrongFocus );
}
//! Destructor
QwtAbstractSlider::~QwtAbstractSlider()
{
- if(d_data->tmrID)
- killTimer(d_data->tmrID);
-
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 readOnly Enables in case of true
+ \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 readOnly)
+void QwtAbstractSlider::setReadOnly( bool on )
{
- d_data->readOnly = readOnly;
- update();
+ if ( d_data->readOnly != on )
+ {
+ d_data->readOnly = on;
+ setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
+
+ update();
+ }
}
/*!
@@ -100,452 +165,658 @@ bool QwtAbstractSlider::isReadOnly() const
}
/*!
- \brief Set the orientation.
- \param o Orientation. Allowed values are
- Qt::Horizontal and Qt::Vertical.
-*/
-void QwtAbstractSlider::setOrientation(Qt::Orientation o)
-{
- d_data->orientation = o;
-}
+ \brief Enables or disables tracking.
-/*!
- \return Orientation
- \sa setOrientation()
-*/
-Qt::Orientation QwtAbstractSlider::orientation() const
-{
- return d_data->orientation;
-}
+ 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.
-//! Stop updating if automatic scrolling is active
+ Tracking is enabled by default.
+ \param on \c true (enable) or \c false (disable) tracking.
-void QwtAbstractSlider::stopMoving()
+ \sa isTracking(), sliderMoved()
+*/
+void QwtAbstractSlider::setTracking( bool on )
{
- if(d_data->tmrID) {
- killTimer(d_data->tmrID);
- d_data->tmrID = 0;
- }
+ d_data->isTracking = on;
}
/*!
- \brief Specify the update interval for automatic scrolling
- \param t update interval in milliseconds
- \sa getScrollMode()
+ \return True, when tracking has been enabled
+ \sa setTracking()
*/
-void QwtAbstractSlider::setUpdateTime(int t)
+bool QwtAbstractSlider::isTracking() const
{
- if (t < 50)
- t = 50;
- d_data->updTime = t;
+ return d_data->isTracking;
}
-
-//! Mouse press event handler
-void QwtAbstractSlider::mousePressEvent(QMouseEvent *e)
+/*!
+ Mouse press event handler
+ \param event Mouse event
+*/
+void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
{
- if ( isReadOnly() ) {
- e->ignore();
+ if ( isReadOnly() )
+ {
+ event->ignore();
return;
}
- if ( !isValid() )
- return;
-
- const QPoint &p = e->pos();
- d_data->timerTick = 0;
-
- getScrollMode(p, d_data->scrollMode, d_data->direction);
- stopMoving();
+ if ( !d_data->isValid || lowerBound() == upperBound() )
+ return;
- switch(d_data->scrollMode) {
- case ScrPage:
- case ScrTimer:
- d_data->mouseOffset = 0;
- d_data->tmrID = startTimer(qwtMax(250, 2 * d_data->updTime));
- break;
+ d_data->isScrolling = isScrollPosition( event->pos() );
- case ScrMouse:
- d_data->time.start();
- d_data->speed = 0;
- d_data->mouseOffset = getValue(p) - value();
- emit sliderPressed();
- break;
+ if ( d_data->isScrolling )
+ {
+ d_data->pendingValueChanged = false;
- default:
- d_data->mouseOffset = 0;
- d_data->direction = 0;
- break;
+ Q_EMIT sliderPressed();
}
}
-
-//! Emits a valueChanged() signal if necessary
-void QwtAbstractSlider::buttonReleased()
-{
- if ((!d_data->tracking) || (value() != prevValue()))
- emit valueChanged(value());
-}
-
-
-//! Mouse Release Event handler
-void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e)
+/*!
+ Mouse Move Event handler
+ \param event Mouse event
+*/
+void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
{
- if ( isReadOnly() ) {
- e->ignore();
+ if ( isReadOnly() )
+ {
+ event->ignore();
return;
}
- if ( !isValid() )
- return;
- const double inc = step();
-
- switch(d_data->scrollMode) {
- case ScrMouse: {
- setPosition(e->pos());
- d_data->direction = 0;
- d_data->mouseOffset = 0;
- if (d_data->mass > 0.0) {
- const int ms = d_data->time.elapsed();
- if ((fabs(d_data->speed) > 0.0) && (ms < 50))
- d_data->tmrID = startTimer(d_data->updTime);
- } else {
- d_data->scrollMode = ScrNone;
- buttonReleased();
- }
- emit sliderReleased();
+ if ( d_data->isValid && d_data->isScrolling )
+ {
+ double value = scrolledTo( event->pos() );
+ if ( value != d_data->value )
+ {
+ value = boundedValue( value );
- break;
- }
+ if ( d_data->stepAlignment )
+ {
+ value = alignedValue( value );
+ }
+ else
+ {
+ value = qwtAlignToScaleDiv( this, value );
+ }
- case ScrDirect: {
- setPosition(e->pos());
- d_data->direction = 0;
- d_data->mouseOffset = 0;
- d_data->scrollMode = ScrNone;
- buttonReleased();
- break;
- }
+ if ( value != d_data->value )
+ {
+ d_data->value = value;
- case ScrPage: {
- stopMoving();
- if (!d_data->timerTick)
- QwtDoubleRange::incPages(d_data->direction);
- d_data->timerTick = 0;
- buttonReleased();
- d_data->scrollMode = ScrNone;
- break;
- }
+ sliderChange();
- case ScrTimer: {
- stopMoving();
- if (!d_data->timerTick)
- QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc);
- d_data->timerTick = 0;
- buttonReleased();
- d_data->scrollMode = ScrNone;
- break;
- }
+ Q_EMIT sliderMoved( d_data->value );
- default: {
- d_data->scrollMode = ScrNone;
- buttonReleased();
- }
+ if ( d_data->isTracking )
+ Q_EMIT valueChanged( d_data->value );
+ else
+ d_data->pendingValueChanged = true;
+ }
+ }
}
}
-
/*!
- Move the slider to a specified point, adjust the value
- and emit signals if necessary.
+ Mouse Release Event handler
+ \param event Mouse event
*/
-void QwtAbstractSlider::setPosition(const QPoint &p)
+void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
{
- QwtDoubleRange::fitValue(getValue(p) - d_data->mouseOffset);
-}
+ if ( isReadOnly() )
+ {
+ event->ignore();
+ return;
+ }
+ if ( d_data->isScrolling && d_data->isValid )
+ {
+ d_data->isScrolling = false;
-/*!
- \brief Enables or disables tracking.
+ if ( d_data->pendingValueChanged )
+ Q_EMIT valueChanged( d_data->value );
- If tracking is enabled, the slider emits a
- valueChanged() signal whenever its value
- changes (the default behaviour). If tracking
- is disabled, the value changed() signal will only
- be emitted if:
- - the user releases the mouse
- button and the value has changed or
-
- at the end of automatic scrolling.
- Tracking is enabled by default.
- \param enable \c true (enable) or \c false (disable) tracking.
-*/
-void QwtAbstractSlider::setTracking(bool enable)
-{
- d_data->tracking = enable;
+ Q_EMIT sliderReleased();
+ }
}
/*!
- Mouse Move Event handler
- \param e Mouse event
+ 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::mouseMoveEvent(QMouseEvent *e)
+void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
{
- if ( isReadOnly() ) {
- e->ignore();
+ if ( isReadOnly() )
+ {
+ event->ignore();
return;
}
- if ( !isValid() )
+ if ( !d_data->isValid || d_data->isScrolling )
return;
- if (d_data->scrollMode == ScrMouse ) {
- setPosition(e->pos());
- if (d_data->mass > 0.0) {
- double ms = double(d_data->time.elapsed());
- if (ms < 1.0)
- ms = 1.0;
- d_data->speed = (exactValue() - exactPrevValue()) / ms;
- d_data->time.start();
- }
- if (value() != prevValue())
- emit sliderMoved(value());
- }
-}
+ int numSteps = 0;
-/*!
- Wheel Event handler
- \param e Whell event
-*/
-void QwtAbstractSlider::wheelEvent(QWheelEvent *e)
-{
- if ( isReadOnly() ) {
- e->ignore();
- return;
+ 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 ( !isValid() )
- return;
+ if ( d_data->invertedControls )
+ numSteps = -numSteps;
- int mode = ScrNone, direction = 0;
+ const double value = incrementedValue( d_data->value, numSteps );
+ if ( value != d_data->value )
+ {
+ d_data->value = value;
+ sliderChange();
- // Give derived classes a chance to say ScrNone
- getScrollMode(e->pos(), mode, direction);
- if ( mode != ScrNone ) {
- const int inc = e->delta() / WHEEL_DELTA;
- QwtDoubleRange::incPages(inc);
- if (value() != prevValue())
- emit sliderMoved(value());
+ Q_EMIT sliderMoved( d_data->value );
+ Q_EMIT valueChanged( d_data->value );
}
}
/*!
Handles key events
- - Key_Down, KeyLeft\n
- Decrement by 1
- - Key_Up, Key_Right\n
- Increment by 1
-
- \param e Key event
+ 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 *e)
+void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
{
- if ( isReadOnly() ) {
- e->ignore();
+ if ( isReadOnly() )
+ {
+ event->ignore();
return;
}
- if ( !isValid() )
+ if ( !d_data->isValid || d_data->isScrolling )
return;
- int increment = 0;
- switch ( e->key() ) {
- case Qt::Key_Down:
- if ( orientation() == Qt::Vertical )
- increment = -1;
- break;
- case Qt::Key_Up:
- if ( orientation() == Qt::Vertical )
- increment = 1;
- break;
- case Qt::Key_Left:
- if ( orientation() == Qt::Horizontal )
- increment = -1;
- break;
- case Qt::Key_Right:
- if ( orientation() == Qt::Horizontal )
- increment = 1;
- break;
- default:
- ;
- e->ignore();
- }
+ int numSteps = 0;
+ double value = d_data->value;
- if ( increment != 0 ) {
- QwtDoubleRange::incValue(increment);
- if (value() != prevValue())
- emit sliderMoved(value());
- }
-}
+ switch ( event->key() )
+ {
+ case Qt::Key_Left:
+ {
+ numSteps = -static_cast( d_data->singleSteps );
+ if ( isInverted() )
+ numSteps = -numSteps;
-/*!
- Qt timer event
- \param e Timer event
-*/
-void QwtAbstractSlider::timerEvent(QTimerEvent *)
-{
- const double inc = step();
-
- switch (d_data->scrollMode) {
- case ScrMouse: {
- if (d_data->mass > 0.0) {
- d_data->speed *= exp( - double(d_data->updTime) * 0.001 / d_data->mass );
- const double newval =
- exactValue() + d_data->speed * double(d_data->updTime);
- QwtDoubleRange::fitValue(newval);
- // stop if d_data->speed < one step per second
- if (fabs(d_data->speed) < 0.001 * fabs(step())) {
- d_data->speed = 0;
- stopMoving();
- buttonReleased();
- }
+ break;
+ }
+ case Qt::Key_Right:
+ {
+ numSteps = d_data->singleSteps;
+ if ( isInverted() )
+ numSteps = -numSteps;
- } else
- stopMoving();
- break;
- }
+ break;
+ }
+ case Qt::Key_Down:
+ {
+ numSteps = -static_cast( d_data->singleSteps );
+ if ( d_data->invertedControls )
+ numSteps = -numSteps;
+ break;
+ }
+ case Qt::Key_Up:
+ {
+ numSteps = d_data->singleSteps;
+ if ( d_data->invertedControls )
+ numSteps = -numSteps;
- case ScrPage: {
- QwtDoubleRange::incPages(d_data->direction);
- if (!d_data->timerTick) {
- killTimer(d_data->tmrID);
- d_data->tmrID = startTimer(d_data->updTime);
+ break;
}
- break;
- }
- case ScrTimer: {
- QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc);
- if (!d_data->timerTick) {
- killTimer(d_data->tmrID);
- d_data->tmrID = startTimer(d_data->updTime);
+ case Qt::Key_PageUp:
+ {
+ numSteps = d_data->pageSteps;
+ if ( d_data->invertedControls )
+ numSteps = -numSteps;
+ break;
+ }
+ case Qt::Key_PageDown:
+ {
+ numSteps = -static_cast( 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();
}
- break;
}
- default: {
- stopMoving();
- break;
+
+ 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 );
}
+}
- d_data->timerTick = 1;
+/*!
+ \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;
+}
/*!
- Notify change of value
+ \brief Set the number of steps for a single increment
- This function can be reimplemented by derived classes
- in order to keep track of changes, i.e. repaint the widget.
- The default implementation emits a valueChanged() signal
- if tracking is enabled.
-*/
-void QwtAbstractSlider::valueChange()
+ 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 )
{
- if (d_data->tracking)
- emit valueChanged(value());
-}
+ d_data->singleSteps = stepCount;
+}
/*!
- \brief Set the slider's mass for flywheel effect.
+ \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;
+}
- If the slider's mass is greater then 0, it will continue
- to move after the mouse button has been released. Its speed
- decreases with time at a rate depending on the slider's mass.
- A large mass means that it will continue to move for a
- long time.
+/*!
+ \return Number of steps
+ \sa setPageSteps(), totalSteps(), singleSteps()
+ */
+uint QwtAbstractSlider::pageSteps() const
+{
+ return d_data->pageSteps;
+}
- Derived widgets may overload this function to make it public.
+/*!
+ \brief Enable step alignment
- \param val New mass in kg
+ When step alignment is enabled values resulting from slider
+ movements are aligned to the step size.
- \bug If the mass is smaller than 1g, it is set to zero.
- The maximal mass is limited to 100kg.
- \sa mass()
+ \param on Enable step alignment when true
+ \sa stepAlignment()
*/
-void QwtAbstractSlider::setMass(double val)
+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
{
- if (val < 0.001)
- d_data->mass = 0.0;
- else if (val > 100.0)
- d_data->mass = 100.0;
- else
- d_data->mass = val;
+ return d_data->stepAlignment;
}
/*!
- \return mass
- \sa setMass()
+ Set the slider to the specified value
+
+ \param value New value
+ \sa setValid(), sliderChange(), valueChanged()
*/
-double QwtAbstractSlider::mass() const
+void QwtAbstractSlider::setValue( double value )
{
- return d_data->mass;
+ 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;
+}
/*!
- \brief Move the slider to a specified value
+ If wrapping is true stepping up from upperBound() value will
+ take you to the minimum() value and vice versa.
- This function can be used to move the slider to a value
- which is not an integer multiple of the step size.
- \param val new value
- \sa fitValue()
+ \param on En/Disable wrapping
+ \sa wrapping()
*/
-void QwtAbstractSlider::setValue(double val)
+void QwtAbstractSlider::setWrapping( bool on )
+{
+ d_data->wrapping = on;
+}
+
+/*!
+ \return True, when wrapping is set
+ \sa setWrapping()
+ */
+bool QwtAbstractSlider::wrapping() const
{
- if (d_data->scrollMode == ScrMouse)
- stopMoving();
- QwtDoubleRange::setValue(val);
+ 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;
+}
/*!
- \brief Set the slider's value to the nearest integer multiple
- of the step size.
+ Increment the slider
- \param valeu Value
- \sa setValue(), incValue()
-*/
-void QwtAbstractSlider::fitValue(double value)
+ The step size depends on the number of totalSteps()
+
+ \param stepCount Number of steps
+ \sa setTotalSteps(), incrementedValue()
+ */
+void QwtAbstractSlider::incrementValue( int stepCount )
{
- if (d_data->scrollMode == ScrMouse)
- stopMoving();
- QwtDoubleRange::fitValue(value);
+ const double value = incrementedValue(
+ d_data->value, stepCount );
+
+ if ( value != d_data->value )
+ {
+ d_data->value = value;
+ sliderChange();
+ }
}
/*!
- \brief Increment the value by a specified number of steps
- \param steps number of steps
- \sa setValue()
-*/
-void QwtAbstractSlider::incValue(int steps)
+ 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->scrollMode == ScrMouse)
- stopMoving();
- QwtDoubleRange::incValue(steps);
+ 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;
}
-void QwtAbstractSlider::setMouseOffset(double offset)
+double QwtAbstractSlider::alignedValue( double value ) const
{
- d_data->mouseOffset = offset;
+ 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;
}
-double QwtAbstractSlider::mouseOffset() const
+/*!
+ Update the slider according to modifications of the scale
+ */
+void QwtAbstractSlider::scaleChange()
{
- return d_data->mouseOffset;
+ 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();
}
-int QwtAbstractSlider::scrollMode() const
+//! Calling update()
+void QwtAbstractSlider::sliderChange()
{
- return d_data->scrollMode;
+ update();
}
diff --git a/libs/qwt/qwt_abstract_slider.h b/libs/qwt/qwt_abstract_slider.h
index 3a4a48fe435347f953d2ff8d09af0d728e024f30..c91dcb60486ee4ec5af1a40b3744389f6090d813 100644
--- a/libs/qwt/qwt_abstract_slider.h
+++ b/libs/qwt/qwt_abstract_slider.h
@@ -10,112 +10,95 @@
#ifndef QWT_ABSTRACT_SLIDER_H
#define QWT_ABSTRACT_SLIDER_H
-#include
#include "qwt_global.h"
-#include "qwt_double_range.h"
+#include "qwt_abstract_scale.h"
/*!
- \brief An abstract base class for slider widgets
-
- QwtAbstractSlider is a base class for
- slider widgets. It handles mouse events
- and updates the slider's value accordingly. Derived classes
- only have to implement the getValue() and
- getScrollMode() members, and should react to a
- valueChange(), which normally requires repainting.
+ \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 QWidget, public QwtDoubleRange
+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 valid READ isValid WRITE setValid )
- Q_PROPERTY( double mass READ mass WRITE setMass )
-#ifndef Q_MOC_RUN // Qt3 moc
-#define QWT_PROPERTY Q_PROPERTY
- Q_PROPERTY( Orientation orientation
- READ orientation WRITE setOrientation )
-#else // Qt4 moc
-// MOC_SKIP_BEGIN
- Q_PROPERTY( Qt::Orientation orientation
- READ orientation WRITE setOrientation )
-// MOC_SKIP_END
-#endif
+ 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:
- /*!
- Scroll mode
- \sa getScrollMode()
- */
- enum ScrollMode {
- ScrNone,
- ScrMouse,
- ScrTimer,
- ScrDirect,
- ScrPage
- };
-
- explicit QwtAbstractSlider(Qt::Orientation, QWidget *parent = NULL);
+ explicit QwtAbstractSlider( QWidget *parent = NULL );
virtual ~QwtAbstractSlider();
- void setUpdateTime(int t);
- void stopMoving();
- void setTracking(bool enable);
+ void setValid( bool );
+ bool isValid() const;
- virtual void setMass(double val);
- virtual double mass() const;
+ double value() const;
-#if QT_VERSION >= 0x040000
- virtual void setOrientation(Qt::Orientation o);
- Qt::Orientation orientation() const;
-#else
- virtual void setOrientation(Orientation o);
- Orientation orientation() const;
-#endif
+ void setWrapping( bool );
+ bool wrapping() const;
- bool isReadOnly() const;
+ void setTotalSteps( uint );
+ uint totalSteps() const;
- /*
- Wrappers for QwtDblRange::isValid/QwtDblRange::setValid made
- to be available as Q_PROPERTY in the designer.
- */
+ void setSingleSteps( uint );
+ uint singleSteps() const;
- /*!
- \sa QwtDblRange::isValid
- */
- bool isValid() const {
- return QwtDoubleRange::isValid();
- }
+ void setPageSteps( uint );
+ uint pageSteps() const;
- /*!
- \sa QwtDblRange::isValid
- */
- void setValid(bool valid) {
- QwtDoubleRange::setValid(valid);
- }
+ void setStepAlignment( bool );
+ bool stepAlignment() const;
-public slots:
- virtual void setValue(double val);
- virtual void fitValue(double val);
- virtual void incValue(int steps);
+ void setTracking( bool );
+ bool isTracking() const;
+
+ void setReadOnly( bool );
+ bool isReadOnly() const;
- virtual void setReadOnly(bool);
+ void setInvertedControls( bool );
+ bool invertedControls() const;
-signals:
+public Q_SLOTS:
+ void setValue( double val );
+
+Q_SIGNALS:
/*!
\brief Notify a change of value.
- In the default setting
- (tracking enabled), this signal will be emitted every
- time the value changes ( see setTracking() ).
- \param value new 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);
+ void valueChanged( double value );
/*!
This signal is emitted when the user presses the
- movable part of the slider (start ScrMouse Mode).
+ movable part of the slider.
*/
void sliderPressed();
@@ -123,70 +106,59 @@ signals:
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
+
+ \param value New value
+
+ \sa valueChanged()
*/
- void sliderMoved(double value);
+ void sliderMoved( double value );
protected:
- virtual void setPosition(const QPoint &);
- virtual void valueChange();
-
- virtual void timerEvent(QTimerEvent *e);
- virtual void mousePressEvent(QMouseEvent *e);
- virtual void mouseReleaseEvent(QMouseEvent *e);
- virtual void mouseMoveEvent(QMouseEvent *e);
- virtual void keyPressEvent(QKeyEvent *e);
- virtual void wheelEvent(QWheelEvent *e);
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual void wheelEvent( QWheelEvent * );
/*!
- \brief Determine the value corresponding to a specified poind
+ \brief Determine what to do when the user presses a mouse button.
+
+ \param pos Mouse position
- This is an abstract virtual function which is called when
- the user presses or releases a mouse button or moves the
- mouse. It has to be implemented by the derived class.
- \param p point
+ \retval True, when pos is a valid scroll position
+ \sa scrolledTo()
*/
- virtual double getValue(const QPoint & p) = 0;
+ virtual bool isScrollPosition( const QPoint &pos ) const = 0;
+
/*!
- \brief Determine what to do when the user presses a mouse button.
+ \brief Determine the value for a new position of the
+ movable part of the slider
- This function is abstract and has to be implemented by derived classes.
- It is called on a mousePress event. The derived class can determine
- what should happen next in dependence of the position where the mouse
- was pressed by returning scrolling mode and direction. QwtAbstractSlider
- knows the following modes:
- - QwtAbstractSlider::ScrNone
-
- Scrolling switched off. Don't change the value.
-
- QwtAbstractSlider::ScrMouse
-
- Change the value while the user keeps the
- button pressed and moves the mouse.
-
- QwtAbstractSlider::ScrTimer
-
- Automatic scrolling. Increment the value
- in the specified direction as long as
- the user keeps the button pressed.
-
- QwtAbstractSlider::ScrPage
-
- Automatic scrolling. Same as ScrTimer, but
- increment by page size.
-
- \param p point where the mouse was pressed
- \retval scrollMode The scrolling mode
- \retval direction direction: 1, 0, or -1.
+ \param pos Mouse position
+
+ \return Value for the mouse position
+ \sa isScrollPosition()
*/
- virtual void getScrollMode( const QPoint &p,
- int &scrollMode, int &direction) = 0;
+ virtual double scrolledTo( const QPoint &pos ) const = 0;
+
+ void incrementValue( int numSteps );
- void setMouseOffset(double);
- double mouseOffset() const;
+ virtual void scaleChange();
+
+protected:
+ virtual void sliderChange();
- int scrollMode() const;
+ double incrementedValue(
+ double value, int stepCount ) const;
private:
- void buttonReleased();
+ double alignedValue( double ) const;
+ double boundedValue( double ) const;
class PrivateData;
PrivateData *d_data;
diff --git a/libs/qwt/qwt_analog_clock.cpp b/libs/qwt/qwt_analog_clock.cpp
index e42c6b6616ff1a373389fc389bdf07c744d70d14..1d44a95cb2e4cb389926bc6a4139b04128024574 100644
--- a/libs/qwt/qwt_analog_clock.cpp
+++ b/libs/qwt/qwt_analog_clock.cpp
@@ -8,69 +8,94 @@
*****************************************************************************/
#include "qwt_analog_clock.h"
+#include "qwt_round_scale_draw.h"
+#include
+#include
-/*!
- Constructor
- \param parent Parent widget
-*/
-QwtAnalogClock::QwtAnalogClock(QWidget *parent):
- QwtDial(parent)
+class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw
{
- initClock();
-}
+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 ) ) );
+ }
+};
-#if QT_VERSION < 0x040000
/*!
Constructor
\param parent Parent widget
- \param name Object name
*/
-QwtAnalogClock::QwtAnalogClock(QWidget* parent, const char *name):
- QwtDial(parent, name)
+QwtAnalogClock::QwtAnalogClock( QWidget *parent ):
+ QwtDial( parent )
{
- initClock();
-}
-#endif
+ setWrapping( true );
+ setReadOnly( true );
-void QwtAnalogClock::initClock()
-{
- setWrapping(true);
- setReadOnly(true);
+ setOrigin( 270.0 );
+ setScaleDraw( new QwtAnalogClockScaleDraw() );
+
+ setTotalSteps( 60 );
+
+ const int secondsPerHour = 60.0 * 60.0;
- setOrigin(270.0);
- setRange(0.0, 60.0 * 60.0 * 12.0); // seconds
- setScale(-1, 5, 60.0 * 60.0);
+ QList majorTicks;
+ QList minorTicks;
- setScaleOptions(ScaleTicks | ScaleLabel);
- setScaleTicks(1, 0, 8);
- scaleDraw()->setSpacing(8);
+ for ( int i = 0; i < 12; i++ )
+ {
+ majorTicks += i * secondsPerHour;
- QColor knobColor =
-#if QT_VERSION < 0x040000
- palette().color(QPalette::Active, QColorGroup::Text);
-#else
- palette().color(QPalette::Active, QPalette::Text);
-#endif
- knobColor = knobColor.dark(120);
+ 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 ) {
+ for ( int i = 0; i < NHands; i++ )
+ {
+ if ( i == SecondHand )
+ {
width = 2;
- handColor = knobColor.dark(120);
- } else {
+ handColor = knobColor.dark( 120 );
+ }
+ else
+ {
width = 8;
handColor = knobColor;
}
QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle(
- QwtDialSimpleNeedle::Arrow, true, handColor, knobColor);
- hand->setWidth(width);
+ QwtDialSimpleNeedle::Arrow, true, handColor, knobColor );
+ hand->setWidth( width );
d_hand[i] = NULL;
- setHand((Hand)i, hand);
+ setHand( static_cast( i ), hand );
}
}
@@ -82,24 +107,25 @@ QwtAnalogClock::~QwtAnalogClock()
}
/*!
- Nop method, use setHand instead
- \sa QwtAnalogClock::setHand
+ Nop method, use setHand() instead
+ \sa setHand()
*/
-void QwtAnalogClock::setNeedle(QwtDialNeedle *)
+void QwtAnalogClock::setNeedle( QwtDialNeedle * )
{
// no op
return;
}
/*!
- Set a clockhand
+ Set a clock hand
\param hand Specifies the type of hand
\param needle Hand
- \sa QwtAnalogClock::hand()
+ \sa hand()
*/
-void QwtAnalogClock::setHand(Hand hand, QwtDialNeedle *needle)
+void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle )
{
- if ( hand >= 0 || hand < NHands ) {
+ if ( hand >= 0 && hand < NHands )
+ {
delete d_hand[hand];
d_hand[hand] = needle;
}
@@ -108,9 +134,9 @@ void QwtAnalogClock::setHand(Hand hand, QwtDialNeedle *needle)
/*!
\return Clock hand
\param hd Specifies the type of hand
- \sa QwtAnalogClock::setHand
+ \sa setHand()
*/
-QwtDialNeedle *QwtAnalogClock::hand(Hand hd)
+QwtDialNeedle *QwtAnalogClock::hand( Hand hd )
{
if ( hd < 0 || hd >= NHands )
return NULL;
@@ -121,81 +147,75 @@ QwtDialNeedle *QwtAnalogClock::hand(Hand hd)
/*!
\return Clock hand
\param hd Specifies the type of hand
- \sa QwtAnalogClock::setHand
+ \sa setHand()
*/
-const QwtDialNeedle *QwtAnalogClock::hand(Hand hd) const
+const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const
{
- return ((QwtAnalogClock *)this)->hand(hd);
+ return const_cast( this )->hand( hd );
}
/*!
\brief Set the current time
-
- This is the same as QwtAnalogClock::setTime(), but Qt < 3.0
- can't handle default parameters for slots.
*/
void QwtAnalogClock::setCurrentTime()
{
- setTime(QTime::currentTime());
+ 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);
-}
-
-/*!
- Find the scale label for a given value
-
- \param value Value
- \return Label
-*/
-QwtText QwtAnalogClock::scaleLabel(double value) const
+void QwtAnalogClock::setTime( const QTime &time )
{
- if ( value == 0.0 )
- value = 60.0 * 60.0 * 12.0;
-
- return QString::number(int(value / (60.0 * 60.0)));
+ 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
+ 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 direction Dummy, not used.
- \param cg ColorGroup
+ \param dir Dummy, not used.
+ \param colorGroup ColorGroup
- \sa QwtAnalogClock::drawHand()
+ \sa drawHand()
*/
-void QwtAnalogClock::drawNeedle(QPainter *painter, const QPoint ¢er,
- int radius, double, QPalette::ColorGroup cg) const
+void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF ¢er,
+ double radius, double dir, QPalette::ColorGroup colorGroup ) const
{
- if ( isValid() ) {
- const double hours = value() / (60.0 * 60.0);
- const double minutes = (value() - (int)hours * 60.0 * 60.0) / 60.0;
- const double seconds = value() - (int)hours * 60.0 * 60.0
- - (int)minutes * 60.0;
-
- drawHand(painter, HourHand, center, radius,
- 360.0 - (origin() + 360.0 * hours / 12.0), cg);
- drawHand(painter, MinuteHand, center, radius,
- 360.0 - (origin() + 360.0 * minutes / 60.0), cg);
- drawHand(painter, SecondHand, center, radius,
- 360.0 - (origin() + 360.0 * seconds / 60.0), cg);
+ 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 ),
+ center, radius, d, colorGroup );
+ }
}
}
@@ -209,15 +229,16 @@ void QwtAnalogClock::drawNeedle(QPainter *painter, const QPoint ¢er,
\param direction Direction of the hand in degrees, counter clockwise
\param cg ColorGroup
*/
-void QwtAnalogClock::drawHand(QPainter *painter, Hand hd,
- const QPoint ¢er, int radius, double direction,
- QPalette::ColorGroup cg) const
+void QwtAnalogClock::drawHand( QPainter *painter, Hand hd,
+ const QPointF ¢er, double radius, double direction,
+ QPalette::ColorGroup cg ) const
{
- const QwtDialNeedle *needle = hand(hd);
- if ( needle ) {
+ const QwtDialNeedle *needle = hand( hd );
+ if ( needle )
+ {
if ( hd == HourHand )
- radius = qRound(0.8 * radius);
+ radius = qRound( 0.8 * radius );
- needle->draw(painter, center, radius, direction, cg);
+ needle->draw( painter, center, radius, direction, cg );
}
}
diff --git a/libs/qwt/qwt_analog_clock.h b/libs/qwt/qwt_analog_clock.h
index a660a9d4eed8cec478f69d622c75ea911604e13b..ffe27e2cdbfe64e78564b18b108df98eba2c1ef2 100644
--- a/libs/qwt/qwt_analog_clock.h
+++ b/libs/qwt/qwt_analog_clock.h
@@ -10,10 +10,10 @@
#ifndef QWT_ANALOG_CLOCK_H
#define QWT_ANALOG_CLOCK_H
-#include
#include "qwt_global.h"
#include "qwt_dial.h"
#include "qwt_dial_needle.h"
+#include
/*!
\brief An analog clock
@@ -21,7 +21,8 @@
\image html analogclock.png
\par Example
- \verbatim #include
+ \code
+ #include
QwtAnalogClock *clock = new QwtAnalogClock(...);
clock->scaleDraw()->setPenWidth(3);
@@ -34,10 +35,7 @@
timer->connect(timer, SIGNAL(timeout()), clock, SLOT(setCurrentTime()));
timer->start(1000);
- \endverbatim
-
- Qwt is missing a set of good looking hands.
- Contributions are very welcome.
+ \endcode
\note The examples/dials example shows how to use QwtAnalogClock.
*/
@@ -51,41 +49,43 @@ public:
Hand type
\sa setHand(), hand()
*/
-
- enum 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);
-#if QT_VERSION < 0x040000
- explicit QwtAnalogClock(QWidget* parent, const char *name);
-#endif
+ explicit QwtAnalogClock( QWidget* parent = NULL );
virtual ~QwtAnalogClock();
- virtual void setHand(Hand, QwtDialNeedle *);
- const QwtDialNeedle *hand(Hand) const;
- QwtDialNeedle *hand(Hand);
+ void setHand( Hand, QwtDialNeedle * );
-public slots:
+ const QwtDialNeedle *hand( Hand ) const;
+ QwtDialNeedle *hand( Hand );
+
+public Q_SLOTS:
void setCurrentTime();
- void setTime(const QTime & = QTime::currentTime());
+ void setTime( const QTime & );
protected:
- virtual QwtText scaleLabel(double) const;
-
- virtual void drawNeedle(QPainter *, const QPoint &,
- int radius, double direction, QPalette::ColorGroup) const;
+ virtual void drawNeedle( QPainter *, const QPointF &,
+ double radius, double direction, QPalette::ColorGroup ) const;
- virtual void drawHand(QPainter *, Hand, const QPoint &,
- int radius, double direction, QPalette::ColorGroup) const;
+ virtual void drawHand( QPainter *, Hand, const QPointF &,
+ double radius, double direction, QPalette::ColorGroup ) const;
private:
- virtual void setNeedle(QwtDialNeedle *);
- void initClock();
+ // use setHand instead
+ void setNeedle( QwtDialNeedle * );
QwtDialNeedle *d_hand[NHands];
};
diff --git a/libs/qwt/qwt_arrow_button.cpp b/libs/qwt/qwt_arrow_button.cpp
index d51c445ad9afcf10a742d97415adab29f4409404..bd20f91e9cb662d5023c037a7d1f992aa4479346 100644
--- a/libs/qwt/qwt_arrow_button.cpp
+++ b/libs/qwt/qwt_arrow_button.cpp
@@ -7,12 +7,13 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
+#include "qwt_arrow_button.h"
+#include "qwt_math.h"
#include
#include
+#include
#include
-#include "qwt_math.h"
-#include "qwt_polygon.h"
-#include "qwt_arrow_button.h"
+#include
static const int MaxNum = 3;
static const int Margin = 2;
@@ -25,56 +26,53 @@ public:
Qt::ArrowType arrowType;
};
-
-#if QT_VERSION >= 0x040000
-#include
-static QStyleOptionButton styleOpt(const QwtArrowButton* btn)
+static QStyleOptionButton styleOpt( const QwtArrowButton* btn )
{
QStyleOptionButton option;
- option.init(btn);
+ option.init( btn );
option.features = QStyleOptionButton::None;
- if (btn->isFlat())
+ if ( btn->isFlat() )
option.features |= QStyleOptionButton::Flat;
- if (btn->menu())
+ if ( btn->menu() )
option.features |= QStyleOptionButton::HasMenu;
- if (btn->autoDefault() || btn->isDefault())
+ if ( btn->autoDefault() || btn->isDefault() )
option.features |= QStyleOptionButton::AutoDefaultButton;
- if (btn->isDefault())
+ if ( btn->isDefault() )
option.features |= QStyleOptionButton::DefaultButton;
- if (btn->isDown())
+ if ( btn->isDown() )
option.state |= QStyle::State_Sunken;
- if (!btn->isFlat() && !btn->isDown())
+ if ( !btn->isFlat() && !btn->isDown() )
option.state |= QStyle::State_Raised;
return option;
}
-#endif
/*!
\param num Number of arrows
- \param arrowType see Qt::ArowType in the Qt docs.
+ \param arrowType see Qt::ArrowType in the Qt docs.
\param parent Parent widget
*/
-QwtArrowButton::QwtArrowButton(int num,
- Qt::ArrowType arrowType, QWidget *parent):
- QPushButton(parent)
+QwtArrowButton::QwtArrowButton( int num,
+ Qt::ArrowType arrowType, QWidget *parent ):
+ QPushButton( parent )
{
d_data = new PrivateData;
- d_data->num = qwtLim(num, 1, MaxNum);
+ 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);
+ 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 );
}
}
@@ -102,60 +100,51 @@ int QwtArrowButton::num() const
}
/*!
- \return the bounding rect for the label
+ \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() ) {
- int ph, pv;
-#if QT_VERSION < 0x040000
- ph = style().pixelMetric(
- QStyle::PM_ButtonShiftHorizontal, this);
- pv = style().pixelMetric(
- QStyle::PM_ButtonShiftVertical, this);
- r.moveBy(ph, pv);
-#else
- QStyleOptionButton option = styleOpt(this);
- ph = style()->pixelMetric(
- QStyle::PM_ButtonShiftHorizontal, &option, this);
- pv = style()->pixelMetric(
- QStyle::PM_ButtonShiftVertical, &option, this);
- r.translate(ph, pv);
-#endif
+ 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;
}
-#if QT_VERSION >= 0x040000
/*!
Paint event handler
\param event Paint event
*/
-void QwtArrowButton::paintEvent(QPaintEvent *event)
+void QwtArrowButton::paintEvent( QPaintEvent *event )
{
- QPushButton::paintEvent(event);
- QPainter painter(this);
- drawButtonLabel(&painter);
+ QPushButton::paintEvent( event );
+ QPainter painter( this );
+ drawButtonLabel( &painter );
}
-#endif
/*!
\brief Draw the button label
\param painter Painter
- \sa The Qt Manual on QPushButton
+ \sa The Qt Manual for QPushButton
*/
-void QwtArrowButton::drawButtonLabel(QPainter *painter)
+void QwtArrowButton::drawButtonLabel( QPainter *painter )
{
const bool isVertical = d_data->arrowType == Qt::UpArrow ||
- d_data->arrowType == Qt::DownArrow;
+ d_data->arrowType == Qt::DownArrow;
const QRect r = labelRect();
QSize boundingSize = labelRect().size();
@@ -163,32 +152,36 @@ void QwtArrowButton::drawButtonLabel(QPainter *painter)
boundingSize.transpose();
const int w =
- (boundingSize.width() - (MaxNum - 1) * Spacing) / MaxNum;
+ ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum;
- QSize arrow = arrowSize(Qt::RightArrow,
- QSize(w, boundingSize.height()));
+ 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);
+ 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);
+ 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);
+ for ( int i = 0; i < d_data->num; i++ )
+ {
+ drawArrow( painter, arrowRect, d_data->arrowType );
int dx = 0;
int dy = 0;
@@ -198,77 +191,66 @@ void QwtArrowButton::drawButtonLabel(QPainter *painter)
else
dx = arrow.width() + Spacing;
-#if QT_VERSION >= 0x040000
- arrowRect.translate(dx, dy);
-#else
- arrowRect.moveBy(dx, dy);
-#endif
+ arrowRect.translate( dx, dy );
}
painter->restore();
- if ( hasFocus() ) {
-#if QT_VERSION >= 0x040000
+ if ( hasFocus() )
+ {
QStyleOptionFocusRect option;
- option.init(this);
- option.backgroundColor = palette().color(QPalette::Background);
-
- style()->drawPrimitive(QStyle::PE_FrameFocusRect,
- &option, painter, this);
-#else
- const QRect focusRect =
- style().subRect(QStyle::SR_PushButtonFocusRect, this);
- style().drawPrimitive(QStyle::PE_FocusRect, painter,
- focusRect, colorGroup());
-#endif
+ option.init( this );
+ option.backgroundColor = palette().color( QPalette::Window );
+
+ style()->drawPrimitive( QStyle::PE_FrameFocusRect,
+ &option, painter, this );
}
}
/*!
- Draw an arrow int a bounding rect
+ 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
+void QwtArrowButton::drawArrow( QPainter *painter,
+ const QRect &r, Qt::ArrowType arrowType ) const
{
- QwtPolygon 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;
+ 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();
-#if QT_VERSION < 0x040000
- painter->setPen(colorGroup().buttonText());
- painter->setBrush(colorGroup().brush(QColorGroup::ButtonText));
-#else
- painter->setPen(palette().color(QPalette::ButtonText));
- painter->setBrush(palette().brush(QPalette::ButtonText));
-#endif
- painter->drawPolygon(pa);
+
+ painter->setRenderHint( QPainter::Antialiasing, true );
+ painter->setPen( Qt::NoPen );
+ painter->setBrush( palette().brush( QPalette::ButtonText ) );
+ painter->drawPolygon( pa );
+
painter->restore();
}
@@ -277,7 +259,8 @@ void QwtArrowButton::drawArrow(QPainter *painter,
*/
QSize QwtArrowButton::sizeHint() const
{
- return minimumSizeHint();
+ const QSize hint = minimumSizeHint();
+ return hint.expandedTo( QApplication::globalStrut() );
}
/*!
@@ -285,43 +268,34 @@ QSize QwtArrowButton::sizeHint() const
*/
QSize QwtArrowButton::minimumSizeHint() const
{
- const QSize asz = arrowSize(Qt::RightArrow, QSize());
+ const QSize asz = arrowSize( Qt::RightArrow, QSize() );
QSize sz(
- 2 * Margin + (MaxNum - 1) * Spacing + MaxNum * asz.width(),
+ 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();
-#if QT_VERSION >= 0x040000
QStyleOption styleOption;
- styleOption.init(this);
-
- const QSize hsz = style()->sizeFromContents(QStyle::CT_PushButton,
- &styleOption, sz, this);
-#if QT_VERSION < 0x040300
- if ( hsz.width() != 80 ) // avoid a bug in the Cleanlooks style
-#endif
- sz = hsz;
+ styleOption.init( this );
-#else
- sz = style().sizeFromContents(QStyle::CT_PushButton, this, sz);
-#endif
+ sz = style()->sizeFromContents( QStyle::CT_PushButton,
+ &styleOption, sz, this );
return sz;
}
/*!
- Calculate the size for a arrow that fits into a rect of a given size
+ 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 QwtArrowButton::arrowSize( Qt::ArrowType arrowType,
+ const QSize &boundingSize ) const
{
QSize bs = boundingSize;
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
@@ -329,17 +303,18 @@ QSize QwtArrowButton::arrowSize(Qt::ArrowType arrowType,
const int MinLen = 2;
const QSize sz = bs.expandedTo(
- QSize(MinLen, 2 * MinLen - 1)); // minimum
+ QSize( MinLen, 2 * MinLen - 1 ) ); // minimum
int w = sz.width();
int h = 2 * w - 1;
- if ( h > sz.height() ) {
+ if ( h > sz.height() )
+ {
h = sz.height();
- w = (h + 1) / 2;
+ w = ( h + 1 ) / 2;
}
- QSize arrSize(w, h);
+ QSize arrSize( w, h );
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
arrSize.transpose();
@@ -349,10 +324,10 @@ QSize QwtArrowButton::arrowSize(Qt::ArrowType arrowType,
/*!
\brief autoRepeat for the space keys
*/
-void QwtArrowButton::keyPressEvent(QKeyEvent *e)
+void QwtArrowButton::keyPressEvent( QKeyEvent *event )
{
- if ( e->isAutoRepeat() && e->key() == Qt::Key_Space )
- emit clicked();
+ if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
+ Q_EMIT clicked();
- QPushButton::keyPressEvent(e);
+ QPushButton::keyPressEvent( event );
}
diff --git a/libs/qwt/qwt_arrow_button.h b/libs/qwt/qwt_arrow_button.h
index a47d3236f5c9960705a93db0a55d84d1df7c1fbe..ae436fec0f9404726e817b53df4dc11753e8b323 100644
--- a/libs/qwt/qwt_arrow_button.h
+++ b/libs/qwt/qwt_arrow_button.h
@@ -10,8 +10,8 @@
#ifndef QWT_ARROW_BUTTON_H
#define QWT_ARROW_BUTTON_H
-#include
#include "qwt_global.h"
+#include
/*!
\brief Arrow Button
@@ -23,7 +23,7 @@
class QWT_EXPORT QwtArrowButton : public QPushButton
{
public:
- explicit QwtArrowButton (int num, Qt::ArrowType, QWidget *parent = NULL);
+ explicit QwtArrowButton ( int num, Qt::ArrowType, QWidget *parent = NULL );
virtual ~QwtArrowButton();
Qt::ArrowType arrowType() const;
@@ -33,18 +33,16 @@ public:
virtual QSize minimumSizeHint() const;
protected:
-#if QT_VERSION >= 0x040000
- virtual void paintEvent(QPaintEvent *event);
-#endif
+ virtual void paintEvent( QPaintEvent *event );
- virtual void drawButtonLabel(QPainter *p);
- virtual void drawArrow(QPainter *,
- const QRect &, Qt::ArrowType) const;
+ 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 QSize arrowSize( Qt::ArrowType,
+ const QSize &boundingSize ) const;
- virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyPressEvent( QKeyEvent * );
private:
class PrivateData;
diff --git a/libs/qwt/qwt_clipper.cpp b/libs/qwt/qwt_clipper.cpp
index 7c25157891a255244dcea4ff21f57a622363756d..51614aa37f1c24f4e42478bb2e9eacf3794b3cb3 100644
--- a/libs/qwt/qwt_clipper.cpp
+++ b/libs/qwt/qwt_clipper.cpp
@@ -7,373 +7,365 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-#include
-#include "qwt_math.h"
#include "qwt_clipper.h"
+#include "qwt_point_polar.h"
+#include
+#include
+#include
-static inline QwtDoubleRect boundingRect(const QwtPolygonF &polygon)
-{
-#if QT_VERSION < 0x040000
- if (polygon.isEmpty())
- return QwtDoubleRect(0, 0, 0, 0);
-
- register const QwtDoublePoint *pd = polygon.data();
-
- double minx, maxx, miny, maxy;
- minx = maxx = pd->x();
- miny = maxy = pd->y();
- pd++;
-
- for (uint i = 1; i < polygon.size(); i++, pd++) {
- if (pd->x() < minx)
- minx = pd->x();
- else if (pd->x() > maxx)
- maxx = pd->x();
- if (pd->y() < miny)
- miny = pd->y();
- else if (pd->y() > maxy)
- maxy = pd->y();
- }
- return QwtDoubleRect(minx, miny, maxx - minx, maxy - miny);
-#else
- return polygon.boundingRect();
+#if QT_VERSION < 0x040601
+#define qAtan(x) ::atan(x)
#endif
-}
-enum Edge {
- Left,
- Top,
- Right,
- Bottom,
- NEdges
-};
+namespace QwtClip
+{
+ // some templates used for inlining
+ template class LeftEdge;
+ template class RightEdge;
+ template class TopEdge;
+ template class BottomEdge;
-class QwtPolygonClipper: public QRect
+ template class PointBuffer;
+}
+
+template
+class QwtClip::LeftEdge
{
public:
- QwtPolygonClipper(const QRect &r);
+ inline LeftEdge( Value x1, Value, Value, Value ):
+ d_x1( x1 )
+ {
+ }
- QwtPolygon clipPolygon(const QwtPolygon &) const;
+ 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:
- void clipEdge(Edge, const QwtPolygon &, QwtPolygon &) const;
- bool insideEdge(const QPoint &, Edge edge) const;
- QPoint intersectEdge(const QPoint &p1,
- const QPoint &p2, Edge edge) const;
-
- void addPoint(QwtPolygon &, uint pos, const QPoint &point) const;
+ const Value d_x1;
};
-class QwtPolygonClipperF: public QwtDoubleRect
+template
+class QwtClip::RightEdge
{
public:
- QwtPolygonClipperF(const QwtDoubleRect &r);
- QwtPolygonF clipPolygon(const QwtPolygonF &) const;
+ inline RightEdge( Value, Value x2, Value, Value ):
+ d_x2( x2 )
+ {
+ }
-private:
- void clipEdge(Edge, const QwtPolygonF &, QwtPolygonF &) const;
- bool insideEdge(const QwtDoublePoint &, Edge edge) const;
- QwtDoublePoint intersectEdge(const QwtDoublePoint &p1,
- const QwtDoublePoint &p2, Edge edge) const;
+ 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( p2.y() + ( d_x2 - p2.x() ) * dy ) );
+ }
- void addPoint(QwtPolygonF &, uint pos, const QwtDoublePoint &point) const;
+private:
+ const Value d_x2;
};
-#if QT_VERSION >= 0x040000
-class QwtCircleClipper: public QwtDoubleRect
+template
+class QwtClip::TopEdge
{
public:
- QwtCircleClipper(const QwtDoubleRect &r);
- QwtArray clipCircle(
- const QwtDoublePoint &, double radius) const;
+ 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( p2.x() + ( d_y1 - p2.y() ) * dx ), d_y1 );
+ }
private:
- QList cuttingPoints(
- Edge, const QwtDoublePoint &pos, double radius) const;
- double toAngle(const QwtDoublePoint &, const QwtDoublePoint &) const;
+ const Value d_y1;
};
-#endif
-QwtPolygonClipper::QwtPolygonClipper(const QRect &r):
- QRect(r)
+template
+class QwtClip::BottomEdge
{
-}
+public:
+ inline BottomEdge( Value, Value, Value, Value y2 ):
+ d_y2( y2 )
+ {
+ }
-inline void QwtPolygonClipper::addPoint(
- QwtPolygon &pa, uint pos, const QPoint &point) const
-{
- if ( uint(pa.size()) <= pos )
- pa.resize(pos + 5);
+ inline bool isInside( const Point &p ) const
+ {
+ return p.y() <= d_y2;
+ }
- pa.setPoint(pos, point);
-}
+ 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( p2.x() + ( d_y2 - p2.y() ) * dx ), d_y2 );
+ }
+
+private:
+ const Value d_y2;
+};
-//! Sutherland-Hodgman polygon clipping
-QwtPolygon QwtPolygonClipper::clipPolygon(const QwtPolygon &pa) const
+template
+class QwtClip::PointBuffer
{
- if ( contains( pa.boundingRect() ) )
- return pa;
+public:
+ PointBuffer( int capacity = 0 ):
+ m_capacity( 0 ),
+ m_size( 0 ),
+ m_buffer( NULL )
+ {
+ if ( capacity > 0 )
+ reserve( capacity );
+ }
- QwtPolygon cpa(pa.size());
+ ~PointBuffer()
+ {
+ if ( m_buffer )
+ ::free( m_buffer );
+ }
- clipEdge((Edge)0, pa, cpa);
+ inline void setPoints( int numPoints, const Point *points )
+ {
+ reserve( numPoints );
- for ( uint edge = 1; edge < NEdges; edge++ ) {
- const QwtPolygon rpa = cpa;
-#if QT_VERSION < 0x040000
- cpa.detach();
-#endif
- clipEdge((Edge)edge, rpa, cpa);
+ m_size = numPoints;
+ ::memcpy( m_buffer, points, m_size * sizeof( Point ) );
}
- return cpa;
-}
-
-bool QwtPolygonClipper::insideEdge(const QPoint &p, Edge edge) const
-{
- switch(edge) {
- case Left:
- return p.x() > left();
- case Top:
- return p.y() > top();
- case Right:
- return p.x() < right();
- case Bottom:
- return p.y() < bottom();
- default:
- break;
+ inline void reset()
+ {
+ m_size = 0;
}
- return false;
-}
+ inline int size() const
+ {
+ return m_size;
+ }
-QPoint QwtPolygonClipper::intersectEdge(const QPoint &p1,
- const QPoint &p2, Edge edge ) const
-{
- int x=0, y=0;
- double m = 0;
-
- const double dy = p2.y() - p1.y();
- const double dx = p2.x() - p1.x();
-
- switch ( edge ) {
- case Left:
- x = left();
- m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
- y = p1.y() + int(dy * m);
- break;
- case Top:
- y = top();
- m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
- x = p1.x() + int(dx * m);
- break;
- case Right:
- x = right();
- m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
- y = p1.y() + int(dy * m);
- break;
- case Bottom:
- y = bottom();
- m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
- x = p1.x() + int(dx * m);
- break;
- default:
- break;
+ inline Point *data() const
+ {
+ return m_buffer;
}
- return QPoint(x,y);
-}
+ inline Point &operator[]( int i )
+ {
+ return m_buffer[i];
+ }
-void QwtPolygonClipper::clipEdge(Edge edge,
- const QwtPolygon &pa, QwtPolygon &cpa) const
-{
- if ( pa.count() == 0 ) {
- cpa.resize(0);
- return;
+ inline const Point &operator[]( int i ) const
+ {
+ return m_buffer[i];
}
- unsigned int count = 0;
-
- QPoint p1 = pa.point(0);
- if ( insideEdge(p1, edge) )
- addPoint(cpa, count++, p1);
-
- const uint nPoints = pa.size();
- for ( uint i = 1; i < nPoints; i++ ) {
- const QPoint p2 = pa.point(i);
- if ( insideEdge(p2, edge) ) {
- if ( insideEdge(p1, edge) )
- addPoint(cpa, count++, p2);
- else {
- addPoint(cpa, count++, intersectEdge(p1, p2, edge));
- addPoint(cpa, count++, p2);
- }
- } else {
- if ( insideEdge(p1, edge) )
- addPoint(cpa, count++, intersectEdge(p1, p2, edge));
- }
- p1 = p2;
+ inline void add( const Point &point )
+ {
+ if ( m_capacity <= m_size )
+ reserve( m_size + 1 );
+
+ m_buffer[m_size++] = point;
}
- cpa.resize(count);
-}
-QwtPolygonClipperF::QwtPolygonClipperF(const QwtDoubleRect &r):
- QwtDoubleRect(r)
-{
-}
+private:
+ inline void reserve( int size )
+ {
+ if ( m_capacity == 0 )
+ m_capacity = 1;
-inline void QwtPolygonClipperF::addPoint(QwtPolygonF &pa, uint pos, const QwtDoublePoint &point) const
-{
- if ( uint(pa.size()) <= pos )
- pa.resize(pos + 5);
+ while ( m_capacity < size )
+ m_capacity *= 2;
- pa[(int)pos] = point;
-}
+ m_buffer = static_cast(
+ ::realloc( m_buffer, m_capacity * sizeof( Point ) ) );
+ }
-//! Sutherland-Hodgman polygon clipping
-QwtPolygonF QwtPolygonClipperF::clipPolygon(const QwtPolygonF &pa) const
-{
- if ( contains( ::boundingRect(pa) ) )
- return pa;
+ int m_capacity;
+ int m_size;
+ Point *m_buffer;
+};
- QwtPolygonF cpa(pa.size());
+using namespace QwtClip;
- clipEdge((Edge)0, pa, cpa);
+template
+class QwtPolygonClipper
+{
+public:
+ QwtPolygonClipper( const Rect &clipRect ):
+ d_clipRect( clipRect )
+ {
+ }
- for ( uint edge = 1; edge < NEdges; edge++ ) {
- const QwtPolygonF rpa = cpa;
-#if QT_VERSION < 0x040000
- cpa.detach();
+ Polygon clipPolygon( const Polygon &polygon, bool closePolygon ) const
+ {
+#if 0
+ if ( d_clipRect.contains( polygon.boundingRect() ) )
+ return polygon;
#endif
- clipEdge((Edge)edge, rpa, cpa);
- }
- return cpa;
-}
+ PointBuffer points1;
+ PointBuffer points2( qMin( 256, polygon.size() ) );
-bool QwtPolygonClipperF::insideEdge(const QwtDoublePoint &p, Edge edge) const
-{
- switch(edge) {
- case Left:
- return p.x() > left();
- case Top:
- return p.y() > top();
- case Right:
- return p.x() < right();
- case Bottom:
- return p.y() < bottom();
- default:
- break;
- }
+ points1.setPoints( polygon.size(), polygon.data() );
- return false;
-}
+ clipEdge< LeftEdge >( closePolygon, points1, points2 );
+ clipEdge< RightEdge >( closePolygon, points2, points1 );
+ clipEdge< TopEdge >( closePolygon, points1, points2 );
+ clipEdge< BottomEdge >( closePolygon, points2, points1 );
-QwtDoublePoint QwtPolygonClipperF::intersectEdge(const QwtDoublePoint &p1,
- const QwtDoublePoint &p2, Edge edge ) const
-{
- double x=0.0, y=0.0;
- double m = 0;
-
- const double dy = p2.y() - p1.y();
- const double dx = p2.x() - p1.x();
-
- switch ( edge ) {
- case Left:
- x = left();
- m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
- y = p1.y() + int(dy * m);
- break;
- case Top:
- y = top();
- m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
- x = p1.x() + int(dx * m);
- break;
- case Right:
- x = right();
- m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx);
- y = p1.y() + int(dy * m);
- break;
- case Bottom:
- y = bottom();
- m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy);
- x = p1.x() + int(dx * m);
- break;
- default:
- break;
+ Polygon p;
+ p.resize( points1.size() );
+ ::memcpy( p.data(), points1.data(), points1.size() * sizeof( Point ) );
+
+ return p;
}
- return QwtDoublePoint(x,y);
-}
+private:
+ template
+ inline void clipEdge( bool closePolygon,
+ PointBuffer &points, PointBuffer &clippedPoints ) const
+ {
+ clippedPoints.reset();
+
+ if ( points.size() < 2 )
+ {
+ if ( points.size() == 1 )
+ clippedPoints.add( points[0] );
+ return;
+ }
-void QwtPolygonClipperF::clipEdge(Edge edge,
- const QwtPolygonF &pa, QwtPolygonF &cpa) const
-{
- if ( pa.count() == 0 ) {
- cpa.resize(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;
- unsigned int count = 0;
-
- QwtDoublePoint p1 = pa[0];
- if ( insideEdge(p1, edge) )
- addPoint(cpa, count++, p1);
-
- const uint nPoints = pa.size();
- for ( uint i = 1; i < nPoints; i++ ) {
- const QwtDoublePoint p2 = pa[(int)i];
- if ( insideEdge(p2, edge) ) {
- if ( insideEdge(p1, edge) )
- addPoint(cpa, count++, p2);
- else {
- addPoint(cpa, count++, intersectEdge(p1, p2, edge));
- addPoint(cpa, count++, p2);
+ 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 ) );
+ }
}
- } else {
- if ( insideEdge(p1, edge) )
- addPoint(cpa, count++, intersectEdge(p1, p2, edge));
+ lastPos = i;
}
- p1 = p2;
}
- cpa.resize(count);
-}
-#if QT_VERSION >= 0x040000
+ const Rect d_clipRect;
+};
+
+class QwtCircleClipper
+{
+public:
+ QwtCircleClipper( const QRectF &r );
+ QVector clipCircle( const QPointF &, double radius ) const;
+
+private:
+ enum Edge
+ {
+ Left,
+ Top,
+ Right,
+ Bottom,
+
+ NEdges
+ };
+
+ QList cuttingPoints(
+ Edge, const QPointF &pos, double radius ) const;
+
+ double toAngle( const QPointF &, const QPointF & ) const;
+
+ const QRectF d_rect;
+};
+
-QwtCircleClipper::QwtCircleClipper(const QwtDoubleRect &r):
- QwtDoubleRect(r)
+QwtCircleClipper::QwtCircleClipper( const QRectF &r ):
+ d_rect( r )
{
}
-QwtArray QwtCircleClipper::clipCircle(
- const QwtDoublePoint &pos, double radius) const
+QVector QwtCircleClipper::clipCircle(
+ const QPointF &pos, double radius ) const
{
- QList points;
+ QList points;
for ( int edge = 0; edge < NEdges; edge++ )
- points += cuttingPoints((Edge)edge, pos, radius);
-
- QwtArray intv;
- if ( points.size() <= 0 ) {
- QwtDoubleRect cRect(0, 0, 2 * radius, 2* radius);
- cRect.moveCenter(pos);
- if ( contains(cRect) )
- intv += QwtDoubleInterval(0.0, 2 * M_PI);
- } else {
+ points += cuttingPoints( static_cast(edge), pos, radius );
+
+ QVector 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 angles;
for ( int i = 0; i < points.size(); i++ )
- angles += toAngle(pos, points[i]);
- qSort(angles);
-
- const int in = contains(qwtPolar2Pos(pos, radius,
- angles[0] + (angles[1] - angles[0]) / 2));
- if ( in ) {
- for ( int i = 0; i < angles.size() - 1; i += 2)
- intv += QwtDoubleInterval(angles[i], angles[i+1]);
- } else {
- for ( int i = 1; i < angles.size() - 1; i += 2)
- intv += QwtDoubleInterval(angles[i], angles[i+1]);
- intv += QwtDoubleInterval(angles.last(), angles.first());
+ 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() );
}
}
@@ -381,18 +373,21 @@ QwtArray QwtCircleClipper::clipCircle(
}
double QwtCircleClipper::toAngle(
- const QwtDoublePoint &from, const QwtDoublePoint &to) const
+ 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 = qwtAbs((to.y() - from.y()) / (to.x() - from.x()) );
+ const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) );
- double angle = ::atan(m);
- if ( to.x() > from.x() ) {
+ double angle = qAtan( m );
+ if ( to.x() > from.x() )
+ {
if ( to.y() > from.y() )
angle = 2 * M_PI - angle;
- } else {
+ }
+ else
+ {
if ( to.y() > from.y() )
angle = M_PI + angle;
else
@@ -402,58 +397,114 @@ double QwtCircleClipper::toAngle(
return angle;
}
-QList QwtCircleClipper::cuttingPoints(
- Edge edge, const QwtDoublePoint &pos, double radius) const
+QList QwtCircleClipper::cuttingPoints(
+ Edge edge, const QPointF &pos, double radius ) const
{
- QList points;
-
- if ( edge == Left || edge == Right ) {
- const double x = (edge == Left) ? left() : right();
- if ( qwtAbs(pos.x() - x) < radius ) {
- const double off = ::sqrt(qwtSqr(radius) - qwtSqr(pos.x() - x));
- const double y1 = pos.y() + off;
- if ( y1 >= top() && y1 <= bottom() )
- points += QwtDoublePoint(x, y1);
- const double y2 = pos.y() - off;
- if ( y2 >= top() && y2 <= bottom() )
- points += QwtDoublePoint(x, y2);
+ QList 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) ? top() : bottom();
- if ( qwtAbs(pos.y() - y) < radius ) {
- const double off = ::sqrt(qwtSqr(radius) - qwtSqr(pos.y() - y));
+ }
+ 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 >= left() && x1 <= right() )
- points += QwtDoublePoint(x1, y);
- const double x2 = pos.x() - off;
- if ( x2 >= left() && x2 <= right() )
- points += QwtDoublePoint(x2, y);
+ 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;
}
-#endif
-QwtPolygon QwtClipper::clipPolygon(
- const QRect &clipRect, const QwtPolygon &polygon)
+/*!
+ 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 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 clipper(clipRect);
- return clipper.clipPolygon(polygon);
+ QwtPolygonClipper clipper( clipRect );
+ return clipper.clipPolygon( polygon, closePolygon );
}
-QwtPolygonF QwtClipper::clipPolygonF(
- const QwtDoubleRect &clipRect, const QwtPolygonF &polygon)
+/*!
+ 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 )
{
- QwtPolygonClipperF clipper(clipRect);
- return clipper.clipPolygon(polygon);
+ QwtPolygonClipper clipper( clipRect );
+ return clipper.clipPolygon( polygon, closePolygon );
}
-#if QT_VERSION >= 0x040000
-QwtArray QwtClipper::clipCircle(
- const QwtDoubleRect &clipRect,
- const QwtDoublePoint ¢er, double radius)
+/*!
+ 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 QwtClipper::clipCircle( const QRectF &clipRect,
+ const QPointF ¢er, double radius )
{
- QwtCircleClipper clipper(clipRect);
- return clipper.clipCircle(center, radius);
+ QwtCircleClipper clipper( clipRect );
+ return clipper.clipCircle( center, radius );
}
-#endif
diff --git a/libs/qwt/qwt_clipper.h b/libs/qwt/qwt_clipper.h
index b3fe16f90b177e6cb4fe069918b45d96f05a3e45..1b1820bb02b30000bbf395b3a8a1a8a75c21c9c0 100644
--- a/libs/qwt/qwt_clipper.h
+++ b/libs/qwt/qwt_clipper.h
@@ -11,27 +11,30 @@
#define QWT_CLIPPER_H
#include "qwt_global.h"
-#include "qwt_array.h"
-#include "qwt_polygon.h"
-#include "qwt_double_rect.h"
-#include "qwt_double_interval.h"
+#include "qwt_interval.h"
+#include
+#include
class QRect;
+class QRectF;
/*!
- \brief Some clipping algos
+ \brief Some clipping algorithms
*/
class QWT_EXPORT QwtClipper
{
public:
- static QwtPolygon clipPolygon(const QRect &, const QwtPolygon &);
- static QwtPolygonF clipPolygonF(const QwtDoubleRect &, const QwtPolygonF &);
+ static QPolygon clipPolygon( const QRect &,
+ const QPolygon &, bool closePolygon = false );
+ static QPolygon clipPolygon( const QRectF &,
+ const QPolygon &, bool closePolygon = false );
-#if QT_VERSION >= 0x040000
- static QwtArray clipCircle(
- const QwtDoubleRect &, const QwtDoublePoint &, double radius);
-#endif
+ static QPolygonF clipPolygonF( const QRectF &,
+ const QPolygonF &, bool closePolygon = false );
+
+ static QVector clipCircle(
+ const QRectF &, const QPointF &, double radius );
};
#endif
diff --git a/libs/qwt/qwt_color_map.cpp b/libs/qwt/qwt_color_map.cpp
index 3ea3b129e552ba98c5c9676620758db55253f5d6..571c1380dd84cb6fee1800bdb398c08205720b80 100644
--- a/libs/qwt/qwt_color_map.cpp
+++ b/libs/qwt/qwt_color_map.cpp
@@ -7,31 +7,23 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-#include "qwt_array.h"
-#include "qwt_math.h"
-#include "qwt_double_interval.h"
#include "qwt_color_map.h"
-
-#if QT_VERSION < 0x040000
-#include
-typedef QValueVector QwtColorTable;
-#else
-typedef QVector QwtColorTable;
-#endif
+#include "qwt_math.h"
+#include "qwt_interval.h"
+#include
class QwtLinearColorMap::ColorStops
{
public:
- ColorStops() {
-#if QT_VERSION >= 0x040000
- _stops.reserve(256);
-#endif
+ ColorStops()
+ {
+ _stops.reserve( 256 );
}
- void insert(double pos, const QColor &color);
- QRgb rgb(QwtLinearColorMap::Mode, double pos) const;
+ void insert( double pos, const QColor &color );
+ QRgb rgb( QwtLinearColorMap::Mode, double pos ) const;
- QwtArray stops() const;
+ QVector stops() const;
private:
@@ -39,16 +31,18 @@ private:
{
public:
ColorStop():
- pos(0.0),
- rgb(0) {
+ pos( 0.0 ),
+ rgb( 0 )
+ {
};
- ColorStop(double p, const QColor &c):
- pos(p),
- rgb(c.rgb()) {
- r = qRed(rgb);
- g = qGreen(rgb);
- b = qBlue(rgb);
+ ColorStop( double p, const QColor &c ):
+ pos( p ),
+ rgb( c.rgb() )
+ {
+ r = qRed( rgb );
+ g = qGreen( rgb );
+ b = qBlue( rgb );
}
double pos;
@@ -56,11 +50,11 @@ private:
int r, g, b;
};
- inline int findUpper(double pos) const;
- QwtArray _stops;
+ inline int findUpper( double pos ) const;
+ QVector _stops;
};
-void QwtLinearColorMap::ColorStops::insert(double pos, const QColor &color)
+void QwtLinearColorMap::ColorStops::insert( double pos, const QColor &color )
{
// Lookups need to be very fast, insertions are not so important.
// Anyway, a balanced tree is what we need here. TODO ...
@@ -69,53 +63,52 @@ void QwtLinearColorMap::ColorStops::insert(double pos, const QColor &color)
return;
int index;
- if ( _stops.size() == 0 ) {
+ if ( _stops.size() == 0 )
+ {
index = 0;
-#if QT_VERSION < 0x040000
- _stops.resize(1, QGArray::SpeedOptim);
-#else
- _stops.resize(1);
-#endif
- } else {
- index = findUpper(pos);
- if ( index == (int)_stops.size() ||
- qwtAbs(_stops[index].pos - pos) >= 0.001 ) {
-#if QT_VERSION < 0x040000
- _stops.resize(_stops.size() + 1, QGArray::SpeedOptim);
-#else
- _stops.resize(_stops.size() + 1);
-#endif
+ _stops.resize( 1 );
+ }
+ else
+ {
+ index = findUpper( pos );
+ if ( index == _stops.size() ||
+ qAbs( _stops[index].pos - pos ) >= 0.001 )
+ {
+ _stops.resize( _stops.size() + 1 );
for ( int i = _stops.size() - 1; i > index; i-- )
_stops[i] = _stops[i-1];
}
}
- _stops[index] = ColorStop(pos, color);
+ _stops[index] = ColorStop( pos, color );
}
-inline QwtArray QwtLinearColorMap::ColorStops::stops() const
+inline QVector QwtLinearColorMap::ColorStops::stops() const
{
- QwtArray positions(_stops.size());
- for ( int i = 0; i < (int)_stops.size(); i++ )
+ QVector positions( _stops.size() );
+ for ( int i = 0; i < _stops.size(); i++ )
positions[i] = _stops[i].pos;
return positions;
}
-inline int QwtLinearColorMap::ColorStops::findUpper(double pos) const
+inline int QwtLinearColorMap::ColorStops::findUpper( double pos ) const
{
int index = 0;
int n = _stops.size();
const ColorStop *stops = _stops.data();
- while (n > 0) {
+ while ( n > 0 )
+ {
const int half = n >> 1;
const int middle = index + half;
- if ( stops[middle].pos <= pos ) {
+ if ( stops[middle].pos <= pos )
+ {
index = middle + 1;
n -= half + 1;
- } else
+ }
+ else
n = half;
}
@@ -123,33 +116,36 @@ inline int QwtLinearColorMap::ColorStops::findUpper(double pos) const
}
inline QRgb QwtLinearColorMap::ColorStops::rgb(
- QwtLinearColorMap::Mode mode, double pos) const
+ QwtLinearColorMap::Mode mode, double pos ) const
{
if ( pos <= 0.0 )
return _stops[0].rgb;
if ( pos >= 1.0 )
- return _stops[(int)(_stops.size() - 1)].rgb;
+ return _stops[ _stops.size() - 1 ].rgb;
- const int index = findUpper(pos);
- if ( mode == FixedColors ) {
+ const int index = findUpper( pos );
+ if ( mode == FixedColors )
+ {
return _stops[index-1].rgb;
- } else {
+ }
+ else
+ {
const ColorStop &s1 = _stops[index-1];
const ColorStop &s2 = _stops[index];
- const double ratio = (pos - s1.pos) / (s2.pos - s1.pos);
+ const double ratio = ( pos - s1.pos ) / ( s2.pos - s1.pos );
- const int r = s1.r + qRound(ratio * (s2.r - s1.r));
- const int g = s1.g + qRound(ratio * (s2.g - s1.g));
- const int b = s1.b + qRound(ratio * (s2.b - s1.b));
+ const int r = s1.r + qRound( ratio * ( s2.r - s1.r ) );
+ const int g = s1.g + qRound( ratio * ( s2.g - s1.g ) );
+ const int b = s1.b + qRound( ratio * ( s2.b - s1.b ) );
- return qRgb(r, g, b);
+ return qRgb( r, g, b );
}
}
//! Constructor
-QwtColorMap::QwtColorMap(Format format):
- d_format(format)
+QwtColorMap::QwtColorMap( Format format ):
+ d_format( format )
{
}
@@ -167,15 +163,15 @@ QwtColorMap::~QwtColorMap()
\param interval Range for the values
\return A color table, that can be used for a QImage
*/
-QwtColorTable QwtColorMap::colorTable(
- const QwtDoubleInterval &interval) const
+QVector QwtColorMap::colorTable( const QwtInterval &interval ) const
{
- QwtColorTable table(256);
+ QVector table( 256 );
- if ( interval.isValid() ) {
- const double step = interval.width() / (table.size() - 1);
- for ( int i = 0; i < (int) table.size(); i++ )
- table[i] = rgb(interval, interval.minValue() + step * i);
+ if ( interval.isValid() )
+ {
+ const double step = interval.width() / ( table.size() - 1 );
+ for ( int i = 0; i < table.size(); i++ )
+ table[i] = rgb( interval, interval.minValue() + step * i );
}
return table;
@@ -194,21 +190,13 @@ public:
\param format Preferred format of the color map
*/
-QwtLinearColorMap::QwtLinearColorMap(QwtColorMap::Format format):
- QwtColorMap(format)
+QwtLinearColorMap::QwtLinearColorMap( QwtColorMap::Format format ):
+ QwtColorMap( format )
{
d_data = new PrivateData;
d_data->mode = ScaledColors;
- setColorInterval( Qt::blue, Qt::yellow);
-}
-
-//! Copy constructor
-QwtLinearColorMap::QwtLinearColorMap(const QwtLinearColorMap &other):
- QwtColorMap(other)
-{
- d_data = new PrivateData;
- *this = other;
+ setColorInterval( Qt::blue, Qt::yellow );
}
/*!
@@ -216,15 +204,15 @@ QwtLinearColorMap::QwtLinearColorMap(const QwtLinearColorMap &other):
\param color1 Color used for the minimum value of the value interval
\param color2 Color used for the maximum value of the value interval
- \param format Preferred format of the coor map
+ \param format Preferred format for the color map
*/
-QwtLinearColorMap::QwtLinearColorMap(const QColor &color1,
- const QColor &color2, QwtColorMap::Format format):
- QwtColorMap(format)
+QwtLinearColorMap::QwtLinearColorMap( const QColor &color1,
+ const QColor &color2, QwtColorMap::Format format ):
+ QwtColorMap( format )
{
d_data = new PrivateData;
d_data->mode = ScaledColors;
- setColorInterval(color1, color2);
+ setColorInterval( color1, color2 );
}
//! Destructor
@@ -233,24 +221,6 @@ QwtLinearColorMap::~QwtLinearColorMap()
delete d_data;
}
-//! Assignment operator
-QwtLinearColorMap &QwtLinearColorMap::operator=(
- const QwtLinearColorMap &other)
-{
- QwtColorMap::operator=(other);
- *d_data = *other.d_data;
- return *this;
-}
-
-//! Clone the color map
-QwtColorMap *QwtLinearColorMap::copy() const
-{
- QwtLinearColorMap* map = new QwtLinearColorMap();
- *map = *this;
-
- return map;
-}
-
/*!
\brief Set the mode of the color map
@@ -260,7 +230,7 @@ QwtColorMap *QwtLinearColorMap::copy() const
\sa mode()
*/
-void QwtLinearColorMap::setMode(Mode mode)
+void QwtLinearColorMap::setMode( Mode mode )
{
d_data->mode = mode;
}
@@ -285,11 +255,11 @@ QwtLinearColorMap::Mode QwtLinearColorMap::mode() const
\sa color1(), color2()
*/
void QwtLinearColorMap::setColorInterval(
- const QColor &color1, const QColor &color2)
+ const QColor &color1, const QColor &color2 )
{
d_data->colorStops = ColorStops();
- d_data->colorStops.insert(0.0, color1);
- d_data->colorStops.insert(1.0, color2);
+ d_data->colorStops.insert( 0.0, color1 );
+ d_data->colorStops.insert( 1.0, color2 );
}
/*!
@@ -302,16 +272,16 @@ void QwtLinearColorMap::setColorInterval(
\param value Value between [0.0, 1.0]
\param color Color stop
*/
-void QwtLinearColorMap::addColorStop(double value, const QColor& color)
+void QwtLinearColorMap::addColorStop( double value, const QColor& color )
{
if ( value >= 0.0 && value <= 1.0 )
- d_data->colorStops.insert(value, color);
+ d_data->colorStops.insert( value, color );
}
/*!
- Return all positions of color stops in increasing order
+ \return Positions of color stops in increasing order
*/
-QwtArray QwtLinearColorMap::colorStops() const
+QVector QwtLinearColorMap::colorStops() const
{
return d_data->colorStops.stops();
}
@@ -322,7 +292,7 @@ QwtArray QwtLinearColorMap::colorStops() const
*/
QColor QwtLinearColorMap::color1() const
{
- return QColor(d_data->colorStops.rgb(d_data->mode, 0.0));
+ return QColor( d_data->colorStops.rgb( d_data->mode, 0.0 ) );
}
/*!
@@ -331,51 +301,58 @@ QColor QwtLinearColorMap::color1() const
*/
QColor QwtLinearColorMap::color2() const
{
- return QColor(d_data->colorStops.rgb(d_data->mode, 1.0));
+ return QColor( d_data->colorStops.rgb( d_data->mode, 1.0 ) );
}
/*!
- Map a value of a given interval into a rgb value
+ Map a value of a given interval into a RGB value
\param interval Range for all values
- \param value Value to map into a rgb value
+ \param value Value to map into a RGB value
+
+ \return RGB value for value
*/
QRgb QwtLinearColorMap::rgb(
- const QwtDoubleInterval &interval, double value) const
+ const QwtInterval &interval, double value ) const
{
+ if ( qIsNaN(value) )
+ return qRgba(0, 0, 0, 0);
+
const double width = interval.width();
double ratio = 0.0;
if ( width > 0.0 )
- ratio = (value - interval.minValue()) / width;
+ ratio = ( value - interval.minValue() ) / width;
- return d_data->colorStops.rgb(d_data->mode, ratio);
+ return d_data->colorStops.rgb( d_data->mode, ratio );
}
/*!
- Map a value of a given interval into a color index, between 0 and 255
+ \brief Map a value of a given interval into a color index
\param interval Range for all values
\param value Value to map into a color index
+
+ \return Index, between 0 and 255
*/
unsigned char QwtLinearColorMap::colorIndex(
- const QwtDoubleInterval &interval, double value) const
+ const QwtInterval &interval, double value ) const
{
const double width = interval.width();
- if ( width <= 0.0 || value <= interval.minValue() )
+ if ( qIsNaN(value) || width <= 0.0 || value <= interval.minValue() )
return 0;
if ( value >= interval.maxValue() )
- return (unsigned char)255;
+ return 255;
- const double ratio = (value - interval.minValue()) / width;
+ const double ratio = ( value - interval.minValue() ) / width;
unsigned char index;
if ( d_data->mode == FixedColors )
- index = (unsigned char)(ratio * 255); // always floor
+ index = static_cast( ratio * 255 ); // always floor
else
- index = (unsigned char)qRound(ratio * 255);
+ index = static_cast( qRound( ratio * 255 ) );
return index;
}
@@ -392,23 +369,12 @@ public:
Constructor
\param color Color of the map
*/
-QwtAlphaColorMap::QwtAlphaColorMap(const QColor &color):
- QwtColorMap(QwtColorMap::RGB)
+QwtAlphaColorMap::QwtAlphaColorMap( const QColor &color ):
+ QwtColorMap( QwtColorMap::RGB )
{
d_data = new PrivateData;
d_data->color = color;
- d_data->rgb = color.rgb() & qRgba(255, 255, 255, 0);
-}
-
-/*!
- Copy constructor
- \param other Other color map
-*/
-QwtAlphaColorMap::QwtAlphaColorMap(const QwtAlphaColorMap &other):
- QwtColorMap(other)
-{
- d_data = new PrivateData;
- *this = other;
+ d_data->rgb = color.rgb() & qRgba( 255, 255, 255, 0 );
}
//! Destructor
@@ -417,35 +383,13 @@ QwtAlphaColorMap::~QwtAlphaColorMap()
delete d_data;
}
-/*!
- Assignment operator
- \param other Other color map
- \return *this
-*/
-QwtAlphaColorMap &QwtAlphaColorMap::operator=(
- const QwtAlphaColorMap &other)
-{
- QwtColorMap::operator=(other);
- *d_data = *other.d_data;
- return *this;
-}
-
-//! Clone the color map
-QwtColorMap *QwtAlphaColorMap::copy() const
-{
- QwtAlphaColorMap* map = new QwtAlphaColorMap();
- *map = *this;
-
- return map;
-}
-
/*!
Set the color
\param color Color
\sa color()
*/
-void QwtAlphaColorMap::setColor(const QColor &color)
+void QwtAlphaColorMap::setColor( const QColor &color )
{
d_data->color = color;
d_data->rgb = color.rgb();
@@ -466,22 +410,22 @@ QColor QwtAlphaColorMap::color() const
alpha := (value - interval.minValue()) / interval.width();
\param interval Range for all values
- \param value Value to map into a rgb value
- \return rgb value, with an alpha value
+ \param value Value to map into a RGB value
+ \return RGB value, with an alpha value
*/
-QRgb QwtAlphaColorMap::rgb(const QwtDoubleInterval &interval,
- double value) const
+QRgb QwtAlphaColorMap::rgb( const QwtInterval &interval, double value ) const
{
const double width = interval.width();
- if ( width >= 0.0 ) {
- const double ratio = (value - interval.minValue()) / width;
- int alpha = qRound(255 * ratio);
+ if ( !qIsNaN(value) && width >= 0.0 )
+ {
+ const double ratio = ( value - interval.minValue() ) / width;
+ int alpha = qRound( 255 * ratio );
if ( alpha < 0 )
alpha = 0;
if ( alpha > 255 )
alpha = 255;
- return d_data->rgb | (alpha << 24);
+ return d_data->rgb | ( alpha << 24 );
}
return d_data->rgb;
}
@@ -494,7 +438,7 @@ QRgb QwtAlphaColorMap::rgb(const QwtDoubleInterval &interval,
\return Always 0
*/
unsigned char QwtAlphaColorMap::colorIndex(
- const QwtDoubleInterval &, double) const
+ const QwtInterval &, double ) const
{
return 0;
}
diff --git a/libs/qwt/qwt_color_map.h b/libs/qwt/qwt_color_map.h
index 759ac5a5ba57fff658759b0f4e8b5d949fb7b8e0..91a92bd0cc098200f26a6b29de998de34321ec91 100644
--- a/libs/qwt/qwt_color_map.h
+++ b/libs/qwt/qwt_color_map.h
@@ -10,21 +10,10 @@
#ifndef QWT_COLOR_MAP_H
#define QWT_COLOR_MAP_H
-#include
+#include "qwt_global.h"
+#include "qwt_interval.h"
#include
-#if QT_VERSION < 0x040000
-#include
-#else
#include
-#endif
-#include "qwt_array.h"
-#include "qwt_double_interval.h"
-
-#if defined(QWT_TEMPLATEDLL)
-// MOC_SKIP_BEGIN
-template class QWT_EXPORT QwtArray;
-// MOC_SKIP_END
-#endif
/*!
\brief QwtColorMap is used to map values into colors.
@@ -45,67 +34,60 @@ class QWT_EXPORT QwtColorMap
{
public:
/*!
- - RGB\n
- The map is intended to map into QRgb values.
- - Indexed\n
- The map is intended to map into 8 bit values, that
- are indices into the color table.
-
+ Format for color mapping
\sa rgb(), colorIndex(), colorTable()
*/
- enum Format {
+ enum Format
+ {
+ //! The map is intended to map into RGB values.
RGB,
+
+ /*!
+ The map is intended to map into 8 bit values, that
+ are indices into the color table.
+ */
Indexed
};
- QwtColorMap(Format = QwtColorMap::RGB );
+ QwtColorMap( Format = QwtColorMap::RGB );
virtual ~QwtColorMap();
- inline Format format() const;
-
- //! Clone the color map
- virtual QwtColorMap *copy() const = 0;
+ Format format() const;
/*!
- Map a value of a given interval into a rgb value.
+ Map a value of a given interval into a RGB value.
+
\param interval Range for the values
\param value Value
- \return rgb value, corresponding to value
+ \return RGB value, corresponding to value
*/
- virtual QRgb rgb(
- const QwtDoubleInterval &interval, double value) const = 0;
+ virtual QRgb rgb( const QwtInterval &interval,
+ double value ) const = 0;
/*!
Map a value of a given interval into a color index
+
\param interval Range for the values
\param value Value
\return color index, corresponding to value
*/
virtual unsigned char colorIndex(
- const QwtDoubleInterval &interval, double value) const = 0;
+ const QwtInterval &interval, double value ) const = 0;
- QColor color(const QwtDoubleInterval &, double value) const;
-#if QT_VERSION < 0x040000
- virtual QValueVector colorTable(const QwtDoubleInterval &) const;
-#else
- virtual QVector colorTable(const QwtDoubleInterval &) const;
-#endif
+ QColor color( const QwtInterval &, double value ) const;
+ virtual QVector colorTable( const QwtInterval & ) const;
private:
Format d_format;
};
-
/*!
\brief QwtLinearColorMap builds a color map from color stops.
A color stop is a color at a specific position. The valid
range for the positions is [0.0, 1.0]. When mapping a value
- into a color it is translated into this interval. If
- mode() == FixedColors the color is calculated from the next lower
- color stop. If mode() == ScaledColors the color is calculated
- by interpolating the colors of the adjacent stops.
+ into a color it is translated into this interval according to mode().
*/
class QWT_EXPORT QwtLinearColorMap: public QwtColorMap
{
@@ -114,67 +96,66 @@ public:
Mode of color map
\sa setMode(), mode()
*/
- enum Mode {
+ enum Mode
+ {
+ //! Return the color from the next lower color stop
FixedColors,
+
+ //! Interpolating the colors of the adjacent stops.
ScaledColors
};
- QwtLinearColorMap(QwtColorMap::Format = QwtColorMap::RGB);
+ QwtLinearColorMap( QwtColorMap::Format = QwtColorMap::RGB );
QwtLinearColorMap( const QColor &from, const QColor &to,
- QwtColorMap::Format = QwtColorMap::RGB);
-
- QwtLinearColorMap(const QwtLinearColorMap &);
+ QwtColorMap::Format = QwtColorMap::RGB );
virtual ~QwtLinearColorMap();
- QwtLinearColorMap &operator=(const QwtLinearColorMap &);
-
- virtual QwtColorMap *copy() const;
-
- void setMode(Mode);
+ void setMode( Mode );
Mode mode() const;
- void setColorInterval(const QColor &color1, const QColor &color2);
- void addColorStop(double value, const QColor&);
- QwtArray colorStops() const;
+ void setColorInterval( const QColor &color1, const QColor &color2 );
+ void addColorStop( double value, const QColor& );
+ QVector colorStops() const;
QColor color1() const;
QColor color2() const;
- virtual QRgb rgb(const QwtDoubleInterval &, double value) const;
+ virtual QRgb rgb( const QwtInterval &, double value ) const;
virtual unsigned char colorIndex(
- const QwtDoubleInterval &, double value) const;
+ const QwtInterval &, double value ) const;
class ColorStops;
private:
+ // Disabled copy constructor and operator=
+ QwtLinearColorMap( const QwtLinearColorMap & );
+ QwtLinearColorMap &operator=( const QwtLinearColorMap & );
+
class PrivateData;
PrivateData *d_data;
};
/*!
- \brief QwtAlphaColorMap variies the alpha value of a color
+ \brief QwtAlphaColorMap varies the alpha value of a color
*/
class QWT_EXPORT QwtAlphaColorMap: public QwtColorMap
{
public:
- QwtAlphaColorMap(const QColor & = QColor(Qt::gray));
- QwtAlphaColorMap(const QwtAlphaColorMap &);
-
+ QwtAlphaColorMap( const QColor & = QColor( Qt::gray ) );
virtual ~QwtAlphaColorMap();
- QwtAlphaColorMap &operator=(const QwtAlphaColorMap &);
-
- virtual QwtColorMap *copy() const;
-
- void setColor(const QColor &);
+ void setColor( const QColor & );
QColor color() const;
- virtual QRgb rgb(const QwtDoubleInterval &, double value) const;
+ virtual QRgb rgb( const QwtInterval &, double value ) const;
private:
+ QwtAlphaColorMap( const QwtAlphaColorMap & );
+ QwtAlphaColorMap &operator=( const QwtAlphaColorMap & );
+
virtual unsigned char colorIndex(
- const QwtDoubleInterval &, double value) const;
+ const QwtInterval &, double value ) const;
class PrivateData;
PrivateData *d_data;
@@ -194,13 +175,16 @@ private:
color table once and find the color using colorIndex().
*/
inline QColor QwtColorMap::color(
- const QwtDoubleInterval &interval, double value) const
+ const QwtInterval &interval, double value ) const
{
- if ( d_format == RGB ) {
- return QColor( rgb(interval, value) );
- } else {
- const unsigned int index = colorIndex(interval, value);
- return colorTable(interval)[index]; // slow
+ if ( d_format == RGB )
+ {
+ return QColor( rgb( interval, value ) );
+ }
+ else
+ {
+ const unsigned int index = colorIndex( interval, value );
+ return colorTable( interval )[index]; // slow
}
}
diff --git a/libs/qwt/qwt_column_symbol.cpp b/libs/qwt/qwt_column_symbol.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6f0f1a6357635a326f4455c0d075737b264fcfd
--- /dev/null
+++ b/libs/qwt/qwt_column_symbol.cpp
@@ -0,0 +1,293 @@
+/* -*- 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_column_symbol.h"
+#include "qwt_math.h"
+#include "qwt_painter.h"
+#include
+#include
+
+static void qwtDrawBox( QPainter *p, const QRectF &rect,
+ const QPalette &pal, double lw )
+{
+ if ( lw > 0.0 )
+ {
+ if ( rect.width() == 0.0 )
+ {
+ p->setPen( pal.dark().color() );
+ p->drawLine( rect.topLeft(), rect.bottomLeft() );
+ return;
+ }
+
+ if ( rect.height() == 0.0 )
+ {
+ p->setPen( pal.dark().color() );
+ p->drawLine( rect.topLeft(), rect.topRight() );
+ return;
+ }
+
+ lw = qMin( lw, rect.height() / 2.0 - 1.0 );
+ lw = qMin( lw, rect.width() / 2.0 - 1.0 );
+
+ const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 );
+ QPolygonF polygon( outerRect );
+
+ if ( outerRect.width() > 2 * lw &&
+ outerRect.height() > 2 * lw )
+ {
+ const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw );
+ polygon = polygon.subtracted( innerRect );
+ }
+
+ p->setPen( Qt::NoPen );
+
+ p->setBrush( pal.dark() );
+ p->drawPolygon( polygon );
+ }
+
+ const QRectF windowRect = rect.adjusted( lw, lw, -lw + 1, -lw + 1 );
+ if ( windowRect.isValid() )
+ p->fillRect( windowRect, pal.window() );
+}
+
+static void qwtDrawPanel( QPainter *painter, const QRectF &rect,
+ const QPalette &pal, double lw )
+{
+ if ( lw > 0.0 )
+ {
+ if ( rect.width() == 0.0 )
+ {
+ painter->setPen( pal.window().color() );
+ painter->drawLine( rect.topLeft(), rect.bottomLeft() );
+ return;
+ }
+
+ if ( rect.height() == 0.0 )
+ {
+ painter->setPen( pal.window().color() );
+ painter->drawLine( rect.topLeft(), rect.topRight() );
+ return;
+ }
+
+ lw = qMin( lw, rect.height() / 2.0 - 1.0 );
+ lw = qMin( lw, rect.width() / 2.0 - 1.0 );
+
+ const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 );
+ const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw );
+
+ QPolygonF lines[2];
+
+ lines[0] += outerRect.bottomLeft();
+ lines[0] += outerRect.topLeft();
+ lines[0] += outerRect.topRight();
+ lines[0] += innerRect.topRight();
+ lines[0] += innerRect.topLeft();
+ lines[0] += innerRect.bottomLeft();
+
+ lines[1] += outerRect.topRight();
+ lines[1] += outerRect.bottomRight();
+ lines[1] += outerRect.bottomLeft();
+ lines[1] += innerRect.bottomLeft();
+ lines[1] += innerRect.bottomRight();
+ lines[1] += innerRect.topRight();
+
+ painter->setPen( Qt::NoPen );
+
+ painter->setBrush( pal.light() );
+ painter->drawPolygon( lines[0] );
+ painter->setBrush( pal.dark() );
+ painter->drawPolygon( lines[1] );
+ }
+
+ painter->fillRect( rect.adjusted( lw, lw, -lw + 1, -lw + 1 ), pal.window() );
+}
+
+class QwtColumnSymbol::PrivateData
+{
+public:
+ PrivateData():
+ style( QwtColumnSymbol::Box ),
+ frameStyle( QwtColumnSymbol::Raised ),
+ lineWidth( 2 )
+ {
+ palette = QPalette( Qt::gray );
+ }
+
+ QwtColumnSymbol::Style style;
+ QwtColumnSymbol::FrameStyle frameStyle;
+
+ QPalette palette;
+ int lineWidth;
+};
+
+/*!
+ Constructor
+
+ \param style Style of the symbol
+ \sa setStyle(), style(), Style
+*/
+QwtColumnSymbol::QwtColumnSymbol( Style style )
+{
+ d_data = new PrivateData();
+ d_data->style = style;
+}
+
+//! Destructor
+QwtColumnSymbol::~QwtColumnSymbol()
+{
+ delete d_data;
+}
+
+/*!
+ Specify the symbol style
+
+ \param style Style
+ \sa style(), setPalette()
+*/
+void QwtColumnSymbol::setStyle( Style style )
+{
+ d_data->style = style;
+}
+
+/*!
+ \return Current symbol style
+ \sa setStyle()
+*/
+QwtColumnSymbol::Style QwtColumnSymbol::style() const
+{
+ return d_data->style;
+}
+
+/*!
+ Assign a palette for the symbol
+
+ \param palette Palette
+ \sa palette(), setStyle()
+*/
+void QwtColumnSymbol::setPalette( const QPalette &palette )
+{
+ d_data->palette = palette;
+}
+
+/*!
+ \return Current palette
+ \sa setPalette()
+*/
+const QPalette& QwtColumnSymbol::palette() const
+{
+ return d_data->palette;
+}
+
+/*!
+ Set the frame, that is used for the Box style.
+
+ \param frameStyle Frame style
+ \sa frameStyle(), setLineWidth(), setStyle()
+*/
+void QwtColumnSymbol::setFrameStyle( FrameStyle frameStyle )
+{
+ d_data->frameStyle = frameStyle;
+}
+
+/*!
+ \return Current frame style, that is used for the Box style.
+ \sa setFrameStyle(), lineWidth(), setStyle()
+*/
+QwtColumnSymbol::FrameStyle QwtColumnSymbol::frameStyle() const
+{
+ return d_data->frameStyle;
+}
+
+/*!
+ Set the line width of the frame, that is used for the Box style.
+
+ \param width Width
+ \sa lineWidth(), setFrameStyle()
+*/
+void QwtColumnSymbol::setLineWidth( int width )
+{
+ if ( width < 0 )
+ width = 0;
+
+ d_data->lineWidth = width;
+}
+
+/*!
+ \return Line width of the frame, that is used for the Box style.
+ \sa setLineWidth(), frameStyle(), setStyle()
+*/
+int QwtColumnSymbol::lineWidth() const
+{
+ return d_data->lineWidth;
+}
+
+/*!
+ Draw the symbol depending on its style.
+
+ \param painter Painter
+ \param rect Directed rectangle
+
+ \sa drawBox()
+*/
+void QwtColumnSymbol::draw( QPainter *painter,
+ const QwtColumnRect &rect ) const
+{
+ painter->save();
+
+ switch ( d_data->style )
+ {
+ case QwtColumnSymbol::Box:
+ {
+ drawBox( painter, rect );
+ break;
+ }
+ default:;
+ }
+
+ painter->restore();
+}
+
+/*!
+ Draw the symbol when it is in Box style.
+
+ \param painter Painter
+ \param rect Directed rectangle
+
+ \sa draw()
+*/
+void QwtColumnSymbol::drawBox( QPainter *painter,
+ const QwtColumnRect &rect ) const
+{
+ QRectF r = rect.toRect();
+ if ( QwtPainter::roundingAlignment( painter ) )
+ {
+ r.setLeft( qRound( r.left() ) );
+ r.setRight( qRound( r.right() ) );
+ r.setTop( qRound( r.top() ) );
+ r.setBottom( qRound( r.bottom() ) );
+ }
+
+ switch ( d_data->frameStyle )
+ {
+ case QwtColumnSymbol::Raised:
+ {
+ qwtDrawPanel( painter, r, d_data->palette, d_data->lineWidth );
+ break;
+ }
+ case QwtColumnSymbol::Plain:
+ {
+ qwtDrawBox( painter, r, d_data->palette, d_data->lineWidth );
+ break;
+ }
+ default:
+ {
+ painter->fillRect( r, d_data->palette.window() );
+ }
+ }
+}
diff --git a/libs/qwt/qwt_column_symbol.h b/libs/qwt/qwt_column_symbol.h
new file mode 100644
index 0000000000000000000000000000000000000000..918fe4a3ccbc94d83198a6f6f794c2bc88fe5fff
--- /dev/null
+++ b/libs/qwt/qwt_column_symbol.h
@@ -0,0 +1,161 @@
+/* -*- 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_COLUMN_SYMBOL_H
+#define QWT_COLUMN_SYMBOL_H
+
+#include "qwt_global.h"
+#include "qwt_interval.h"
+#include
+#include
+#include
+
+class QPainter;
+class QPalette;
+class QRect;
+class QwtText;
+
+/*!
+ \brief Directed rectangle representing bounding rectangle and orientation
+ of a column.
+*/
+class QWT_EXPORT QwtColumnRect
+{
+public:
+ //! Direction of the column
+ enum Direction
+ {
+ //! From left to right
+ LeftToRight,
+
+ //! From right to left
+ RightToLeft,
+
+ //! From bottom to top
+ BottomToTop,
+
+ //! From top to bottom
+ TopToBottom
+ };
+
+ //! Build an rectangle with invalid intervals directed BottomToTop.
+ QwtColumnRect():
+ direction( BottomToTop )
+ {
+ }
+
+ //! \return A normalized QRect built from the intervals
+ QRectF toRect() const
+ {
+ QRectF r( hInterval.minValue(), vInterval.minValue(),
+ hInterval.maxValue() - hInterval.minValue(),
+ vInterval.maxValue() - vInterval.minValue() );
+ r = r.normalized();
+
+ if ( hInterval.borderFlags() & QwtInterval::ExcludeMinimum )
+ r.adjust( 1, 0, 0, 0 );
+ if ( hInterval.borderFlags() & QwtInterval::ExcludeMaximum )
+ r.adjust( 0, 0, -1, 0 );
+ if ( vInterval.borderFlags() & QwtInterval::ExcludeMinimum )
+ r.adjust( 0, 1, 0, 0 );
+ if ( vInterval.borderFlags() & QwtInterval::ExcludeMaximum )
+ r.adjust( 0, 0, 0, -1 );
+
+ return r;
+ }
+
+ //! \return Orientation
+ Qt::Orientation orientation() const
+ {
+ if ( direction == LeftToRight || direction == RightToLeft )
+ return Qt::Horizontal;
+
+ return Qt::Vertical;
+ }
+
+ //! Interval for the horizontal coordinates
+ QwtInterval hInterval;
+
+ //! Interval for the vertical coordinates
+ QwtInterval vInterval;
+
+ //! Direction
+ Direction direction;
+};
+
+//! A drawing primitive for columns
+class QWT_EXPORT QwtColumnSymbol
+{
+public:
+ /*!
+ Style
+ \sa setStyle(), style()
+ */
+ enum Style
+ {
+ //! No Style, the symbol draws nothing
+ NoStyle = -1,
+
+ /*!
+ The column is painted with a frame depending on the frameStyle()
+ and lineWidth() using the palette().
+ */
+ Box,
+
+ /*!
+ Styles >= QwtColumnSymbol::UserStyle are reserved for derived
+ classes of QwtColumnSymbol that overload draw() with
+ additional application specific symbol types.
+ */
+ UserStyle = 1000
+ };
+
+ /*!
+ Frame Style used in Box style().
+ \sa Style, setFrameStyle(), frameStyle(), setStyle(), setPalette()
+ */
+ enum FrameStyle
+ {
+ //! No frame
+ NoFrame,
+
+ //! A plain frame style
+ Plain,
+
+ //! A raised frame style
+ Raised
+ };
+
+public:
+ QwtColumnSymbol( Style = NoStyle );
+ virtual ~QwtColumnSymbol();
+
+ void setFrameStyle( FrameStyle style );
+ FrameStyle frameStyle() const;
+
+ void setLineWidth( int width );
+ int lineWidth() const;
+
+ void setPalette( const QPalette & );
+ const QPalette &palette() const;
+
+ void setStyle( Style );
+ Style style() const;
+
+ virtual void draw( QPainter *, const QwtColumnRect & ) const;
+
+protected:
+ void drawBox( QPainter *, const QwtColumnRect & ) const;
+
+private:
+ class PrivateData;
+ PrivateData* d_data;
+};
+
+#endif
diff --git a/libs/qwt/qwt_compass.cpp b/libs/qwt/qwt_compass.cpp
index e2ce650408c997dbac07658099c50aa9ff01b0c3..4e2c9ffdf5cee22d7dd36c7646fc62ade59d2fe1 100644
--- a/libs/qwt/qwt_compass.cpp
+++ b/libs/qwt/qwt_compass.cpp
@@ -7,33 +7,126 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-// vim: expandtab
-
-#include
-#include
-#include
-#include
+#include "qwt_compass.h"
+#include "qwt_compass_rose.h"
#include "qwt_math.h"
#include "qwt_scale_draw.h"
-#include "qwt_paint_buffer.h"
#include "qwt_painter.h"
#include "qwt_dial_needle.h"
-#include "qwt_compass_rose.h"
-#include "qwt_compass.h"
+#include
+#include
+#include
+
+/*!
+ \brief Constructor
+
+ Initializes a label map for multiples of 45 degrees
+ */
+QwtCompassScaleDraw::QwtCompassScaleDraw()
+{
+ enableComponent( QwtAbstractScaleDraw::Backbone, false );
+ enableComponent( QwtAbstractScaleDraw::Ticks, false );
+
+ d_labelMap.insert( 0.0, QString::fromLatin1( "N" ) );
+ d_labelMap.insert( 45.0, QString::fromLatin1( "NE" ) );
+ d_labelMap.insert( 90.0, QString::fromLatin1( "E" ) );
+ d_labelMap.insert( 135.0, QString::fromLatin1( "SE" ) );
+ d_labelMap.insert( 180.0, QString::fromLatin1( "S" ) );
+ d_labelMap.insert( 225.0, QString::fromLatin1( "SW" ) );
+ d_labelMap.insert( 270.0, QString::fromLatin1( "W" ) );
+ d_labelMap.insert( 315.0, QString::fromLatin1( "NW" ) );
+
+#if 0
+ d_labelMap.insert( 22.5, QString::fromLatin1( "NNE" ) );
+ d_labelMap.insert( 67.5, QString::fromLatin1( "NEE" ) );
+ d_labelMap.insert( 112.5, QString::fromLatin1( "SEE" ) );
+ d_labelMap.insert( 157.5, QString::fromLatin1( "SSE" ) );
+ d_labelMap.insert( 202.5, QString::fromLatin1( "SSW" ) );
+ d_labelMap.insert( 247.5, QString::fromLatin1( "SWW" ) );
+ d_labelMap.insert( 292.5, QString::fromLatin1( "NWW" ) );
+ d_labelMap.insert( 337.5, QString::fromLatin1( "NNW" ) );
+#endif
+}
+
+/*!
+ \brief Constructor
+
+ \param map Value to label map
+ */
+QwtCompassScaleDraw::QwtCompassScaleDraw( const QMap &map ):
+ d_labelMap( map )
+{
+ enableComponent( QwtAbstractScaleDraw::Backbone, false );
+ enableComponent( QwtAbstractScaleDraw::Ticks, false );
+}
+
+/*!
+ \brief Set a map, mapping values to labels
+ \param map Value to label map
+
+ The values of the major ticks are found by looking into this
+ map. The default map consists of the labels N, NE, E, SE, S, SW, W, NW.
+
+ \warning The map will have no effect for values that are no major
+ tick values. Major ticks can be changed by QwtScaleDraw::setScale
+
+ \sa labelMap(), scaleDraw(), setScale()
+*/
+void QwtCompassScaleDraw::setLabelMap( const QMap &map )
+{
+ d_labelMap = map;
+}
+
+
+/*!
+ \return map, mapping values to labels
+ \sa setLabelMap()
+*/
+QMap QwtCompassScaleDraw::labelMap() const
+{
+ return d_labelMap;
+}
+
+/*!
+ Map a value to a corresponding label
+
+ \param value Value that will be mapped
+
+ label() looks in the labelMap() for a corresponding label for value
+ or returns an null text.
+
+ \return Label, or QString::null
+ \sa labelMap(), setLabelMap()
+*/
+
+QwtText QwtCompassScaleDraw::label( double value ) const
+{
+ if ( qFuzzyCompare( value + 1.0, 1.0 ) )
+ value = 0.0;
+
+ if ( value < 0.0 )
+ value += 360.0;
+
+ if ( d_labelMap.contains( value ) )
+ return d_labelMap[value];
+
+ return QwtText();
+}
class QwtCompass::PrivateData
{
public:
PrivateData():
- rose(NULL) {
+ rose( NULL )
+ {
}
- ~PrivateData() {
+ ~PrivateData()
+ {
delete rose;
}
QwtCompassRose *rose;
- QMap labelMap;
};
/*!
@@ -45,31 +138,22 @@ public:
mouse and keyboard inputs and has no step size. The default mode
is QwtDial::RotateNeedle.
*/
-QwtCompass::QwtCompass(QWidget* parent):
- QwtDial(parent)
+QwtCompass::QwtCompass( QWidget* parent ):
+ QwtDial( parent )
{
- initCompass();
-}
+ d_data = new PrivateData;
-#if QT_VERSION < 0x040000
+ setScaleDraw( new QwtCompassScaleDraw() );
-/*!
- \brief Constructor
- \param parent Parent widget
- \param name Object name
+ setOrigin( 270.0 );
+ setWrapping( true );
- Create a compass widget with a scale, no needle and no rose.
- The default origin is 270.0 with no valid value. It accepts
- mouse and keyboard inputs and has no step size. The default mode
- is QwtDial::RotateNeedle.
-*/
-QwtCompass::QwtCompass(QWidget* parent, const char *name):
- QwtDial(parent, name)
-{
- initCompass();
-}
+ setScaleMaxMajor( 36 );
+ setScaleMaxMinor( 10 );
-#endif
+ setScale( 0.0, 360.0 ); // degrees as default
+ setTotalSteps( 360 );
+}
//! Destructor
QwtCompass::~QwtCompass()
@@ -77,40 +161,16 @@ QwtCompass::~QwtCompass()
delete d_data;
}
-void QwtCompass::initCompass()
-{
- d_data = new PrivateData;
-
- setScaleOptions(ScaleLabel); // Only labels, no backbone, no ticks
-
- setOrigin(270.0);
- setWrapping(true);
-
- d_data->labelMap.insert(0.0, QString::fromLatin1("N"));
- d_data->labelMap.insert(45.0, QString::fromLatin1("NE"));
- d_data->labelMap.insert(90.0, QString::fromLatin1("E"));
- d_data->labelMap.insert(135.0, QString::fromLatin1("SE"));
- d_data->labelMap.insert(180.0, QString::fromLatin1("S"));
- d_data->labelMap.insert(225.0, QString::fromLatin1("SW"));
- d_data->labelMap.insert(270.0, QString::fromLatin1("W"));
- d_data->labelMap.insert(315.0, QString::fromLatin1("NW"));
-
-#if 0
- d_data->labelMap.insert(22.5, QString::fromLatin1("NNE"));
- d_data->labelMap.insert(67.5, QString::fromLatin1("NEE"));
- d_data->labelMap.insert(112.5, QString::fromLatin1("SEE"));
- d_data->labelMap.insert(157.5, QString::fromLatin1("SSE"));
- d_data->labelMap.insert(202.5, QString::fromLatin1("SSW"));
- d_data->labelMap.insert(247.5, QString::fromLatin1("SWW"));
- d_data->labelMap.insert(292.5, QString::fromLatin1("NWW"));
- d_data->labelMap.insert(337.5, QString::fromLatin1("NNW"));
-#endif
-}
+/*!
+ Draw the contents of the scale
-//! Draw the contents of the scale
-void QwtCompass::drawScaleContents(QPainter *painter,
- const QPoint ¢er, int radius) const
+ \param painter Painter
+ \param center Center of the content circle
+ \param radius Radius of the content circle
+*/
+void QwtCompass::drawScaleContents( QPainter *painter,
+ const QPointF ¢er, double radius ) const
{
QPalette::ColorGroup cg;
if ( isEnabled() )
@@ -119,13 +179,14 @@ void QwtCompass::drawScaleContents(QPainter *painter,
cg = QPalette::Disabled;
double north = origin();
- if ( isValid() ) {
+ if ( isValid() )
+ {
if ( mode() == RotateScale )
north -= value();
}
const int margin = 4;
- drawRose(painter, center, radius - margin, 360.0 - north, cg);
+ drawRose( painter, center, radius - margin, 360.0 - north, cg );
}
/*!
@@ -137,11 +198,11 @@ void QwtCompass::drawScaleContents(QPainter *painter,
\param north Direction pointing north, in degrees counter clockwise
\param cg Color group
*/
-void QwtCompass::drawRose(QPainter *painter, const QPoint ¢er,
- int radius, double north, QPalette::ColorGroup cg) const
+void QwtCompass::drawRose( QPainter *painter, const QPointF ¢er,
+ double radius, double north, QPalette::ColorGroup cg ) const
{
if ( d_data->rose )
- d_data->rose->draw(painter, center, radius, north, cg);
+ d_data->rose->draw( painter, center, radius, north, cg );
}
/*!
@@ -151,9 +212,10 @@ void QwtCompass::drawRose(QPainter *painter, const QPoint ¢er,
set or in ~QwtCompass
\sa rose()
*/
-void QwtCompass::setRose(QwtCompassRose *rose)
+void QwtCompass::setRose( QwtCompassRose *rose )
{
- if ( rose != d_data->rose ) {
+ if ( rose != d_data->rose )
+ {
if ( d_data->rose )
delete d_data->rose;
@@ -189,13 +251,14 @@ QwtCompassRose *QwtCompass::rose()
\sa isReadOnly()
*/
-void QwtCompass::keyPressEvent(QKeyEvent *kev)
+void QwtCompass::keyPressEvent( QKeyEvent *kev )
{
- if (isReadOnly())
+ if ( isReadOnly() )
return;
#if 0
- if ( kev->key() == Key_5 ) {
+ if ( kev->key() == Key_5 )
+ {
invalidate(); // signal ???
return;
}
@@ -203,101 +266,43 @@ void QwtCompass::keyPressEvent(QKeyEvent *kev)
double newValue = value();
- if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 ) {
+ if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 )
+ {
if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 )
return;
- switch (kev->key()) {
- case Qt::Key_6:
- newValue = 180.0 * 0.0;
- break;
- case Qt::Key_3:
- newValue = 180.0 * 0.25;
- break;
- case Qt::Key_2:
- newValue = 180.0 * 0.5;
- break;
- case Qt::Key_1:
- newValue = 180.0 * 0.75;
- break;
- case Qt::Key_4:
- newValue = 180.0 * 1.0;
- break;
- case Qt::Key_7:
- newValue = 180.0 * 1.25;
- break;
- case Qt::Key_8:
- newValue = 180.0 * 1.5;
- break;
- case Qt::Key_9:
- newValue = 180.0 * 1.75;
- break;
+ switch ( kev->key() )
+ {
+ case Qt::Key_6:
+ newValue = 180.0 * 0.0;
+ break;
+ case Qt::Key_3:
+ newValue = 180.0 * 0.25;
+ break;
+ case Qt::Key_2:
+ newValue = 180.0 * 0.5;
+ break;
+ case Qt::Key_1:
+ newValue = 180.0 * 0.75;
+ break;
+ case Qt::Key_4:
+ newValue = 180.0 * 1.0;
+ break;
+ case Qt::Key_7:
+ newValue = 180.0 * 1.25;
+ break;
+ case Qt::Key_8:
+ newValue = 180.0 * 1.5;
+ break;
+ case Qt::Key_9:
+ newValue = 180.0 * 1.75;
+ break;
}
newValue -= origin();
- setValue(newValue);
- } else {
- QwtDial::keyPressEvent(kev);
+ setValue( newValue );
+ }
+ else
+ {
+ QwtDial::keyPressEvent( kev );
}
-}
-
-/*!
- \return map, mapping values to labels
- \sa setLabelMap()
-*/
-const QMap &QwtCompass::labelMap() const
-{
- return d_data->labelMap;
-}
-
-/*!
- \return map, mapping values to labels
- \sa setLabelMap()
-*/
-QMap &QwtCompass::labelMap()
-{
- return d_data->labelMap;
-}
-
-/*!
- \brief Set a map, mapping values to labels
- \param map value to label map
-
- The values of the major ticks are found by looking into this
- map. The default map consists of the labels N, NE, E, SE, S, SW, W, NW.
-
- \warning The map will have no effect for values that are no major
- tick values. Major ticks can be changed by QwtScaleDraw::setScale
-
- \sa labelMap(), scaleDraw(), setScale()
-*/
-void QwtCompass::setLabelMap(const QMap &map)
-{
- d_data->labelMap = map;
-}
-
-/*!
- Map a value to a corresponding label
- \param value Value that will be mapped
- \return Label, or QString::null
-
- label() looks in a map for a corresponding label for value
- or return an null text.
- \sa labelMap(), setLabelMap()
-*/
-
-QwtText QwtCompass::scaleLabel(double value) const
-{
-#if 0
- // better solution ???
- if ( value == -0 )
- value = 0.0;
-#endif
-
- if ( value < 0.0 )
- value += 360.0;
-
- if ( d_data->labelMap.contains(value) )
- return d_data->labelMap[value];
-
- return QwtText();
}
diff --git a/libs/qwt/qwt_compass.h b/libs/qwt/qwt_compass.h
index ed6d06d0a91c823e95fc6bf6d4961820ad14a6ad..b9a3c95bff491a20c0a5ead532e221f722de635e 100644
--- a/libs/qwt/qwt_compass.h
+++ b/libs/qwt/qwt_compass.h
@@ -10,29 +10,38 @@
#ifndef QWT_COMPASS_H
#define QWT_COMPASS_H 1
+#include "qwt_global.h"
+#include "qwt_dial.h"
+#include "qwt_round_scale_draw.h"
#include
#include
-#include "qwt_dial.h"
-#if defined(QWT_TEMPLATEDLL)
+class QwtCompassRose;
+
+/*!
+ \brief A special scale draw made for QwtCompass
-#if defined(QT_NO_STL) || QT_VERSION < 0x040000 || QT_VERSION > 0x040001
-/*
- Unfortunately Qt 4.0.0/Qt 4.0.1 contains uncompilable
- code in the STL adaptors of qmap.h. The declaration below
- instantiates this code resulting in compiler errors.
- If you really need the map to be exported, remove the condition above
- and fix the qmap.h
+ QwtCompassScaleDraw maps values to strings using
+ a special map, that can be modified by the application
+
+ The default map consists of the labels N, NE, E, SE, S, SW, W, NW.
+
+ \sa QwtCompass
*/
-// MOC_SKIP_BEGIN
-template class QWT_EXPORT QMap;
-// MOC_SKIP_END
-#endif
+class QWT_EXPORT QwtCompassScaleDraw: public QwtRoundScaleDraw
+{
+public:
+ explicit QwtCompassScaleDraw();
+ explicit QwtCompassScaleDraw( const QMap &map );
-#endif
+ void setLabelMap( const QMap &map );
+ QMap labelMap() const;
+ virtual QwtText label( double value ) const;
-class QwtCompassRose;
+private:
+ QMap d_labelMap;
+};
/*!
\brief A Compass Widget
@@ -50,34 +59,23 @@ class QWT_EXPORT QwtCompass: public QwtDial
Q_OBJECT
public:
- explicit QwtCompass( QWidget* parent = NULL);
-#if QT_VERSION < 0x040000
- explicit QwtCompass(QWidget* parent, const char *name);
-#endif
+ explicit QwtCompass( QWidget* parent = NULL );
virtual ~QwtCompass();
- void setRose(QwtCompassRose *rose);
+ void setRose( QwtCompassRose *rose );
const QwtCompassRose *rose() const;
QwtCompassRose *rose();
- const QMap &labelMap() const;
- QMap &labelMap();
- void setLabelMap(const QMap &map);
-
protected:
- virtual QwtText scaleLabel(double value) const;
+ virtual void drawRose( QPainter *, const QPointF ¢er,
+ double radius, double north, QPalette::ColorGroup ) const;
- virtual void drawRose(QPainter *, const QPoint ¢er,
- int radius, double north, QPalette::ColorGroup) const;
+ virtual void drawScaleContents( QPainter *,
+ const QPointF ¢er, double radius ) const;
- virtual void drawScaleContents(QPainter *,
- const QPoint ¢er, int radius) const;
-
- virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyPressEvent( QKeyEvent * );
private:
- void initCompass();
-
class PrivateData;
PrivateData *d_data;
};
diff --git a/libs/qwt/qwt_compass_rose.cpp b/libs/qwt/qwt_compass_rose.cpp
index 6e412e4ce9ed1bda513efc5aac41e6c8ea63e6a7..21a35f24443c639db8cfbd69b3c0bcdfd79067ef 100644
--- a/libs/qwt/qwt_compass_rose.cpp
+++ b/libs/qwt/qwt_compass_rose.cpp
@@ -7,48 +7,40 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-#include
-#include
-#include "qwt_math.h"
-#include "qwt_painter.h"
#include "qwt_compass_rose.h"
+#include "qwt_point_polar.h"
+#include "qwt_painter.h"
+#include
-static QPoint cutPoint(QPoint p11, QPoint p12, QPoint p21, QPoint p22)
+static QPointF qwtIntersection(
+ QPointF p11, QPointF p12, QPointF p21, QPointF p22 )
{
- double dx1 = p12.x() - p11.x();
- double dy1 = p12.y() - p11.y();
- double dx2 = p22.x() - p21.x();
- double dy2 = p22.y() - p21.y();
-
- if ( dx1 == 0.0 && dx2 == 0.0 )
- return QPoint();
-
- if ( dx1 == 0.0 ) {
- const double m = dy2 / dx2;
- const double t = p21.y() - m * p21.x();
- return QPoint(p11.x(), qRound(m * p11.x() + t));
- }
+ const QLineF line1( p11, p12 );
+ const QLineF line2( p21, p22 );
- if ( dx2 == 0 ) {
- const double m = dy1 / dx1;
- const double t = p11.y() - m * p11.x();
- return QPoint(p21.x(), qRound(m * p21.x() + t));
- }
-
- const double m1 = dy1 / dx1;
- const double t1 = p11.y() - m1 * p11.x();
+ QPointF pos;
+ if ( line1.intersect( line2, &pos ) == QLineF::NoIntersection )
+ return QPointF();
- const double m2 = dy2 / dx2;
- const double t2 = p21.y() - m2 * p21.x();
-
- if ( m1 == m2 )
- return QPoint();
+ return pos;
+}
- const double x = ( t2 - t1 ) / ( m1 - m2 );
- const double y = t1 + m1 * x;
+class QwtSimpleCompassRose::PrivateData
+{
+public:
+ PrivateData():
+ width( 0.2 ),
+ numThorns( 8 ),
+ numThornLevels( -1 ),
+ shrinkFactor( 0.9 )
+ {
+ }
- return QPoint(qRound(x), qRound(y));
-}
+ double width;
+ int numThorns;
+ int numThornLevels;
+ double shrinkFactor;
+};
/*!
Constructor
@@ -56,31 +48,48 @@ static QPoint cutPoint(QPoint p11, QPoint p12, QPoint p21, QPoint p22)
\param numThorns Number of thorns
\param numThornLevels Number of thorn levels
*/
-QwtSimpleCompassRose::QwtSimpleCompassRose(int numThorns, int numThornLevels):
- d_width(0.2),
- d_numThorns(numThorns),
- d_numThornLevels(numThornLevels),
- d_shrinkFactor(0.9)
+QwtSimpleCompassRose::QwtSimpleCompassRose(
+ int numThorns, int numThornLevels )
{
- const QColor dark(128,128,255);
- const QColor light(192,255,255);
+ d_data = new PrivateData();
+ d_data->numThorns = numThorns;
+ d_data->numThornLevels = numThornLevels;
+
+ const QColor dark( 128, 128, 255 );
+ const QColor light( 192, 255, 255 );
QPalette palette;
- for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
-#if QT_VERSION < 0x040000
- palette.setColor((QPalette::ColorGroup)i,
- QColorGroup::Dark, dark);
- palette.setColor((QPalette::ColorGroup)i,
- QColorGroup::Light, light);
-#else
- palette.setColor((QPalette::ColorGroup)i,
- QPalette::Dark, dark);
- palette.setColor((QPalette::ColorGroup)i,
- QPalette::Light, light);
-#endif
- }
+ palette.setColor( QPalette::Dark, dark );
+ palette.setColor( QPalette::Light, light );
- setPalette(palette);
+ setPalette( palette );
+}
+
+//! Destructor
+QwtSimpleCompassRose::~QwtSimpleCompassRose()
+{
+ delete d_data;
+}
+
+/*!
+ Set the Factor how to shrink the thorns with each level
+ The default value is 0.9.
+
+ \param factor Shrink factor
+ \sa shrinkFactor()
+*/
+void QwtSimpleCompassRose::setShrinkFactor( double factor )
+{
+ d_data->shrinkFactor = factor;
+}
+
+/*!
+ \return Factor how to shrink the thorns with each level
+ \sa setShrinkFactor()
+*/
+double QwtSimpleCompassRose::shrinkFactor() const
+{
+ return d_data->shrinkFactor;
}
/*!
@@ -92,28 +101,14 @@ QwtSimpleCompassRose::QwtSimpleCompassRose(int numThorns, int numThornLevels):
\param north Position
\param cg Color group
*/
-void QwtSimpleCompassRose::draw(QPainter *painter, const QPoint ¢er,
- int radius, double north, QPalette::ColorGroup cg) const
+void QwtSimpleCompassRose::draw( QPainter *painter, const QPointF ¢er,
+ double radius, double north, QPalette::ColorGroup cg ) const
{
-#if QT_VERSION < 0x040000
- QColorGroup colorGroup;
- switch(cg) {
- case QPalette::Disabled:
- colorGroup = palette().disabled();
- case QPalette::Inactive:
- colorGroup = palette().inactive();
- default:
- colorGroup = palette().active();
- }
-
- drawRose(painter, colorGroup, center, radius, north, d_width,
- d_numThorns, d_numThornLevels, d_shrinkFactor);
-#else
QPalette pal = palette();
- pal.setCurrentColorGroup(cg);
- drawRose(painter, pal, center, radius, north, d_width,
- d_numThorns, d_numThornLevels, d_shrinkFactor);
-#endif
+ pal.setCurrentColorGroup( cg );
+
+ drawRose( painter, pal, center, radius, north, d_data->width,
+ d_data->numThorns, d_data->numThornLevels, d_data->shrinkFactor );
}
/*!
@@ -131,13 +126,9 @@ void QwtSimpleCompassRose::draw(QPainter *painter, const QPoint ¢er,
*/
void QwtSimpleCompassRose::drawRose(
QPainter *painter,
-#if QT_VERSION < 0x040000
- const QColorGroup &cg,
-#else
const QPalette &palette,
-#endif
- const QPoint ¢er, int radius, double north, double width,
- int numThorns, int numThornLevels, double shrinkFactor)
+ const QPointF ¢er, double radius, double north, double width,
+ int numThorns, int numThornLevels, double shrinkFactor )
{
if ( numThorns < 4 )
numThorns = 4;
@@ -156,15 +147,17 @@ void QwtSimpleCompassRose::drawRose(
painter->save();
- painter->setPen(Qt::NoPen);
+ painter->setPen( Qt::NoPen );
- for ( int j = 1; j <= numThornLevels; j++ ) {
- double step = pow(2.0, j) * M_PI / (double)numThorns;
+ for ( int j = 1; j <= numThornLevels; j++ )
+ {
+ double step = qPow( 2.0, j ) * M_PI / numThorns;
if ( step > M_PI_2 )
break;
double r = radius;
- for ( int k = 0; k < 3; k++ ) {
+ for ( int k = 0; k < 3; k++ )
+ {
if ( j + k < numThornLevels )
r *= shrinkFactor;
}
@@ -173,37 +166,31 @@ void QwtSimpleCompassRose::drawRose(
if ( 2.0 * M_PI / step > 32 )
leafWidth = 16;
- const double origin = north / 180.0 * M_PI;
+ const double origin = qwtRadians( north );
for ( double angle = origin;
- angle < 2.0 * M_PI + origin; angle += step) {
- const QPoint p = qwtPolar2Pos(center, r, angle);
- QPoint p1 = qwtPolar2Pos(center, leafWidth, angle + M_PI_2);
- QPoint p2 = qwtPolar2Pos(center, leafWidth, angle - M_PI_2);
-
- QwtPolygon pa(3);
- pa.setPoint(0, center);
- pa.setPoint(1, p);
-
- QPoint p3 = qwtPolar2Pos(center, r, angle + step / 2.0);
- p1 = cutPoint(center, p3, p1, p);
- pa.setPoint(2, p1);
-#if QT_VERSION < 0x040000
- painter->setBrush(cg.brush(QColorGroup::Dark));
-#else
- painter->setBrush(palette.brush(QPalette::Dark));
-#endif
- painter->drawPolygon(pa);
-
- QPoint p4 = qwtPolar2Pos(center, r, angle - step / 2.0);
- p2 = cutPoint(center, p4, p2, p);
-
- pa.setPoint(2, p2);
-#if QT_VERSION < 0x040000
- painter->setBrush(cg.brush(QColorGroup::Light));
-#else
- painter->setBrush(palette.brush(QPalette::Light));
-#endif
- painter->drawPolygon(pa);
+ angle < 2.0 * M_PI + origin; angle += step )
+ {
+ const QPointF p = qwtPolar2Pos( center, r, angle );
+ const QPointF p1 = qwtPolar2Pos( center, leafWidth, angle + M_PI_2 );
+ const QPointF p2 = qwtPolar2Pos( center, leafWidth, angle - M_PI_2 );
+ const QPointF p3 = qwtPolar2Pos( center, r, angle + step / 2.0 );
+ const QPointF p4 = qwtPolar2Pos( center, r, angle - step / 2.0 );
+
+ QPainterPath darkPath;
+ darkPath.moveTo( center );
+ darkPath.lineTo( p );
+ darkPath.lineTo( qwtIntersection( center, p3, p1, p ) );
+
+ painter->setBrush( palette.brush( QPalette::Dark ) );
+ painter->drawPath( darkPath );
+
+ QPainterPath lightPath;
+ lightPath.moveTo( center );
+ lightPath.lineTo( p );
+ lightPath.lineTo( qwtIntersection( center, p4, p2, p ) );
+
+ painter->setBrush( palette.brush( QPalette::Light ) );
+ painter->drawPath( lightPath );
}
}
painter->restore();
@@ -215,15 +202,23 @@ void QwtSimpleCompassRose::drawRose(
\param width Width
*/
-
-void QwtSimpleCompassRose::setWidth(double width)
+void QwtSimpleCompassRose::setWidth( double width )
{
- d_width = width;
- if (d_width < 0.03)
- d_width = 0.03;
+ d_data->width = width;
+ if ( d_data->width < 0.03 )
+ d_data->width = 0.03;
+
+ if ( d_data->width > 0.4 )
+ d_data->width = 0.4;
+}
- if (d_width > 0.4)
- d_width = 0.4;
+/*!
+ \return Width of the rose
+ \sa setWidth()
+ */
+double QwtSimpleCompassRose::width() const
+{
+ return d_data->width;
}
/*!
@@ -233,7 +228,7 @@ void QwtSimpleCompassRose::setWidth(double width)
\param numThorns Number of thorns
\sa numThorns(), setNumThornLevels()
*/
-void QwtSimpleCompassRose::setNumThorns(int numThorns)
+void QwtSimpleCompassRose::setNumThorns( int numThorns )
{
if ( numThorns < 4 )
numThorns = 4;
@@ -241,7 +236,7 @@ void QwtSimpleCompassRose::setNumThorns(int numThorns)
if ( numThorns % 4 )
numThorns += 4 - numThorns % 4;
- d_numThorns = numThorns;
+ d_data->numThorns = numThorns;
}
/*!
@@ -250,7 +245,7 @@ void QwtSimpleCompassRose::setNumThorns(int numThorns)
*/
int QwtSimpleCompassRose::numThorns() const
{
- return d_numThorns;
+ return d_data->numThorns;
}
/*!
@@ -259,9 +254,9 @@ int QwtSimpleCompassRose::numThorns() const
\param numThornLevels Number of thorns levels
\sa setNumThorns(), numThornLevels()
*/
-void QwtSimpleCompassRose::setNumThornLevels(int numThornLevels)
+void QwtSimpleCompassRose::setNumThornLevels( int numThornLevels )
{
- d_numThornLevels = numThornLevels;
+ d_data->numThornLevels = numThornLevels;
}
/*!
@@ -270,5 +265,5 @@ void QwtSimpleCompassRose::setNumThornLevels(int numThornLevels)
*/
int QwtSimpleCompassRose::numThornLevels() const
{
- return d_numThornLevels;
+ return d_data->numThornLevels;
}
diff --git a/libs/qwt/qwt_compass_rose.h b/libs/qwt/qwt_compass_rose.h
index a87c4da386f809a5c51117798cee255dad811f20..9b715dfe029d1b90791a5f9e152556c4f4fa12de 100644
--- a/libs/qwt/qwt_compass_rose.h
+++ b/libs/qwt/qwt_compass_rose.h
@@ -10,8 +10,8 @@
#ifndef QWT_COMPASS_ROSE_H
#define QWT_COMPASS_ROSE_H 1
-#include
#include "qwt_global.h"
+#include
class QPainter;
@@ -21,12 +21,18 @@ class QPainter;
class QWT_EXPORT QwtCompassRose
{
public:
+ //! Destructor
virtual ~QwtCompassRose() {};
- virtual void setPalette(const QPalette &p) {
+ //! Assign a palette
+ virtual void setPalette( const QPalette &p )
+ {
d_palette = p;
}
- const QPalette &palette() const {
+
+ //! \return Current palette
+ const QPalette &palette() const
+ {
return d_palette;
}
@@ -39,9 +45,9 @@ public:
\param north Position
\param colorGroup Color group
*/
- virtual void draw(QPainter *painter, const QPoint ¢er,
- int radius, double north,
- QPalette::ColorGroup colorGroup = QPalette::Active) const = 0;
+ virtual void draw( QPainter *painter,
+ const QPointF ¢er, double radius, double north,
+ QPalette::ColorGroup colorGroup = QPalette::Active ) const = 0;
private:
QPalette d_palette;
@@ -53,43 +59,31 @@ private:
class QWT_EXPORT QwtSimpleCompassRose: public QwtCompassRose
{
public:
- QwtSimpleCompassRose(int numThorns = 8, int numThornLevels = -1);
+ QwtSimpleCompassRose( int numThorns = 8, int numThornLevels = -1 );
+ virtual ~QwtSimpleCompassRose();
- void setWidth(double w);
- double width() const {
- return d_width;
- }
+ void setWidth( double w );
+ double width() const;
- void setNumThorns(int count);
+ void setNumThorns( int count );
int numThorns() const;
- void setNumThornLevels(int count);
+ void setNumThornLevels( int count );
int numThornLevels() const;
- void setShrinkFactor(double factor) {
- d_shrinkFactor = factor;
- }
- double shrinkFactor() const {
- return d_shrinkFactor;
- }
+ void setShrinkFactor( double factor );
+ double shrinkFactor() const;
- virtual void draw(QPainter *, const QPoint ¢er, int radius,
- double north, QPalette::ColorGroup = QPalette::Active) const;
+ virtual void draw( QPainter *, const QPointF ¢er, double radius,
+ double north, QPalette::ColorGroup = QPalette::Active ) const;
- static void drawRose(QPainter *,
-#if QT_VERSION < 0x040000
- const QColorGroup &,
-#else
- const QPalette &,
-#endif
- const QPoint ¢er, int radius, double origin, double width,
- int numThorns, int numThornLevels, double shrinkFactor);
+ static void drawRose( QPainter *, const QPalette &,
+ const QPointF ¢er, double radius, double origin, double width,
+ int numThorns, int numThornLevels, double shrinkFactor );
private:
- double d_width;
- int d_numThorns;
- int d_numThornLevels;
- double d_shrinkFactor;
+ class PrivateData;
+ PrivateData *d_data;
};
-#endif // QWT_COMPASS_ROSE_H
+#endif
diff --git a/libs/qwt/qwt_compat.h b/libs/qwt/qwt_compat.h
new file mode 100644
index 0000000000000000000000000000000000000000..c97cf6b9c87b90db9d1806195e3a300d0e0efe9e
--- /dev/null
+++ b/libs/qwt/qwt_compat.h
@@ -0,0 +1,42 @@
+/* -*- 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_COMPAT_H_
+#define _QWT_COMPAT_H_
+
+#include "qwt_global.h"
+#include "qwt_interval.h"
+#include "qwt_point_3d.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+// A couple of definition for Qwt5 compatibility
+
+#define qwtMax qMax
+#define qwtMin qMin
+#define qwtAbs qAbs
+#define qwtRound qRound
+
+#define QwtArray QVector
+
+typedef QList QwtValueList;
+typedef QPointF QwtDoublePoint;
+typedef QSizeF QwtDoubleSize;
+typedef QRectF QwtDoubleRect;
+
+typedef QPolygon QwtPolygon;
+typedef QPolygonF QwtPolygonF;
+typedef QwtInterval QwtDoubleInterval;
+typedef QwtPoint3D QwtDoublePoint3D;
+
+#endif
diff --git a/libs/qwt/qwt_counter.cpp b/libs/qwt/qwt_counter.cpp
index c3236d36c26f1e84137e23263779a8aebe1604a8..31c05c8df33954cd7b98b456b823b5f60f7b5c38 100644
--- a/libs/qwt/qwt_counter.cpp
+++ b/libs/qwt/qwt_counter.cpp
@@ -7,22 +7,26 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-// vim: expandtab
-
+#include "qwt_arrow_button.h"
+#include "qwt_math.h"
+#include "qwt_counter.h"
#include
#include
#include
#include
#include
-#include "qwt_math.h"
-#include "qwt_counter.h"
-#include "qwt_arrow_button.h"
class QwtCounter::PrivateData
{
public:
PrivateData():
- editable(true) {
+ minimum( 0.0 ),
+ maximum( 0.0 ),
+ singleStep( 1.0 ),
+ isValid( false ),
+ value( 0.0 ),
+ wrapping( false )
+ {
increment[Button1] = 1;
increment[Button2] = 10;
increment[Button3] = 100;
@@ -33,27 +37,22 @@ public:
QLineEdit *valueEdit;
int increment[ButtonCnt];
- int nButtons;
+ int numButtons;
- bool editable;
-};
+ double minimum;
+ double maximum;
+ double singleStep;
-/*!
- The default number of buttons is set to 2. The default increments are:
- \li Button 1: 1 step
- \li Button 2: 10 steps
- \li Button 3: 100 steps
+ bool isValid;
+ double value;
- \param parent
- */
-QwtCounter::QwtCounter(QWidget *parent):
- QWidget(parent)
-{
- initCounter();
-}
+ bool wrapping;
+};
-#if QT_VERSION < 0x040000
/*!
+ The counter is initialized with a range is set to [0.0, 1.0] with
+ 0.01 as single step size. The value is invalid.
+
The default number of buttons is set to 2. The default increments are:
\li Button 1: 1 step
\li Button 2: 10 steps
@@ -61,79 +60,68 @@ QwtCounter::QwtCounter(QWidget *parent):
\param parent
*/
-QwtCounter::QwtCounter(QWidget *parent, const char *name):
- QWidget(parent, name)
+QwtCounter::QwtCounter( QWidget *parent ):
+ QWidget( parent )
{
initCounter();
}
-#endif
void QwtCounter::initCounter()
{
d_data = new PrivateData;
-#if QT_VERSION >= 0x040000
- using namespace Qt;
-#endif
-
- QHBoxLayout *layout = new QHBoxLayout(this);
- layout->setSpacing(0);
- layout->setMargin(0);
+ QHBoxLayout *layout = new QHBoxLayout( this );
+ layout->setSpacing( 0 );
+ layout->setMargin( 0 );
- int i;
- for(i = ButtonCnt - 1; i >= 0; i--) {
+ for ( int i = ButtonCnt - 1; i >= 0; i-- )
+ {
QwtArrowButton *btn =
- new QwtArrowButton(i+1, Qt::DownArrow,this);
- btn->setFocusPolicy(NoFocus);
- btn->installEventFilter(this);
- layout->addWidget(btn);
+ new QwtArrowButton( i + 1, Qt::DownArrow, this );
+ btn->setFocusPolicy( Qt::NoFocus );
+ btn->installEventFilter( this );
+ layout->addWidget( btn );
- connect(btn, SIGNAL(released()), SLOT(btnReleased()));
- connect(btn, SIGNAL(clicked()), SLOT(btnClicked()));
+ connect( btn, SIGNAL( released() ), SLOT( btnReleased() ) );
+ connect( btn, SIGNAL( clicked() ), SLOT( btnClicked() ) );
d_data->buttonDown[i] = btn;
}
- d_data->valueEdit = new QLineEdit(this);
- d_data->valueEdit->setReadOnly(false);
- d_data->valueEdit->setValidator(new QDoubleValidator(d_data->valueEdit));
- layout->addWidget(d_data->valueEdit);
-
-#if QT_VERSION >= 0x040000
- connect( d_data->valueEdit, SIGNAL(editingFinished()),
- SLOT(textChanged()) );
-#else
- connect( d_data->valueEdit, SIGNAL(returnPressed()), SLOT(textChanged()) );
- connect( d_data->valueEdit, SIGNAL(lostFocus()), SLOT(textChanged()) );
-#endif
+ d_data->valueEdit = new QLineEdit( this );
+ d_data->valueEdit->setReadOnly( false );
+ d_data->valueEdit->setValidator( new QDoubleValidator( d_data->valueEdit ) );
+ layout->addWidget( d_data->valueEdit );
- layout->setStretchFactor(d_data->valueEdit, 10);
+ connect( d_data->valueEdit, SIGNAL( editingFinished() ),
+ SLOT( textChanged() ) );
- for(i = 0; i < ButtonCnt; i++) {
-#if QT_VERSION >= 0x040000
- using namespace Qt;
-#endif
+ layout->setStretchFactor( d_data->valueEdit, 10 );
+
+ for ( int i = 0; i < ButtonCnt; i++ )
+ {
QwtArrowButton *btn =
- new QwtArrowButton(i+1, Qt::UpArrow, this);
- btn->setFocusPolicy(NoFocus);
- btn->installEventFilter(this);
- layout->addWidget(btn);
+ new QwtArrowButton( i + 1, Qt::UpArrow, this );
+ btn->setFocusPolicy( Qt::NoFocus );
+ btn->installEventFilter( this );
+ layout->addWidget( btn );
- connect(btn, SIGNAL(released()), SLOT(btnReleased()));
- connect(btn, SIGNAL(clicked()), SLOT(btnClicked()));
+ connect( btn, SIGNAL( released() ), SLOT( btnReleased() ) );
+ connect( btn, SIGNAL( clicked() ), SLOT( btnClicked() ) );
d_data->buttonUp[i] = btn;
}
- setNumButtons(2);
- setRange(0.0,1.0,0.001);
- setValue(0.0);
+ setNumButtons( 2 );
+ setRange( 0.0, 1.0 );
+ setSingleStep( 0.001 );
+ setValue( 0.0 );
setSizePolicy(
- QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
- setFocusProxy(d_data->valueEdit);
- setFocusPolicy(StrongFocus);
+ setFocusProxy( d_data->valueEdit );
+ setFocusPolicy( Qt::StrongFocus );
}
//! Destructor
@@ -142,193 +130,265 @@ QwtCounter::~QwtCounter()
delete d_data;
}
+/*!
+ Set the counter to be in valid/invalid state
+
+ When the counter is set to invalid, no numbers are displayed and
+ the buttons are disabled.
+
+ \param on If true the counter will be set as valid
+
+ \sa setValue(), isValid()
+*/
+void QwtCounter::setValid( bool on )
+{
+ if ( on != d_data->isValid )
+ {
+ d_data->isValid = on;
+
+ updateButtons();
+
+ if ( d_data->isValid )
+ {
+ showNumber( value() );
+ Q_EMIT valueChanged( value() );
+ }
+ else
+ {
+ d_data->valueEdit->setText( QString::null );
+ }
+ }
+}
+
+/*!
+ \return True, if the value is valid
+ \sa setValid(), setValue()
+ */
+bool QwtCounter::isValid() const
+{
+ return d_data->isValid;
+}
+
+/*!
+ \brief Allow/disallow the user to manually edit the value
+
+ \param on True disable editing
+ \sa isReadOnly()
+*/
+void QwtCounter::setReadOnly( bool on )
+{
+ d_data->valueEdit->setReadOnly( on );
+}
+
+/*!
+ \return True, when the line line edit is read only. (default is no)
+ \sa setReadOnly()
+ */
+bool QwtCounter::isReadOnly() const
+{
+ return d_data->valueEdit->isReadOnly();
+}
+
/*!
- Sets the minimum width for the buttons
+ \brief Set a new value without adjusting to the step raster
+
+ The state of the counter is set to be valid.
+
+ \param value New value
+
+ \sa isValid(), value(), valueChanged()
+ \warning The value is clipped when it lies outside the range.
*/
-void QwtCounter::polish()
+
+void QwtCounter::setValue( double value )
{
- const int w = d_data->valueEdit->fontMetrics().width("W") + 8;
+ const double vmin = qMin( d_data->minimum, d_data->maximum );
+ const double vmax = qMax( d_data->minimum, d_data->maximum );
+
+ value = qBound( vmin, value, vmax );
+
+ if ( !d_data->isValid || value != d_data->value )
+ {
+ d_data->isValid = true;
+ d_data->value = value;
+
+ showNumber( value );
+ updateButtons();
- for ( int i = 0; i < ButtonCnt; i++ ) {
- d_data->buttonDown[i]->setMinimumWidth(w);
- d_data->buttonUp[i]->setMinimumWidth(w);
+ Q_EMIT valueChanged( value );
}
+}
-#if QT_VERSION < 0x040000
- QWidget::polish();
-#endif
+/*!
+ \return Current value of the counter
+ \sa setValue(), valueChanged()
+ */
+double QwtCounter::value() const
+{
+ return d_data->value;
}
-//! Set from lineedit
-void QwtCounter::textChanged()
+/*!
+ \brief Set the minimum and maximum values
+
+ The maximum is adjusted if necessary to ensure that the range remains valid.
+ The value might be modified to be inside of the range.
+
+ \param min Minimum value
+ \param max Maximum value
+
+ \sa minimum(), maximum()
+ */
+void QwtCounter::setRange( double min, double max )
{
- if ( !d_data->editable )
+ max = qMax( min, max );
+
+ if ( d_data->maximum == max && d_data->minimum == min )
return;
- bool converted = false;
+ d_data->minimum = min;
+ d_data->maximum = max;
- const double value = d_data->valueEdit->text().toDouble(&converted);
- if ( converted )
- setValue( value );
+ setSingleStep( singleStep() );
+
+ const double value = qBound( min, d_data->value, max );
+
+ if ( value != d_data->value )
+ {
+ d_data->value = value;
+
+ if ( d_data->isValid )
+ {
+ showNumber( value );
+ Q_EMIT valueChanged( value );
+ }
+ }
+
+ updateButtons();
}
-/**
- \brief Allow/disallow the user to manually edit the value
+/*!
+ Set the minimum value of the range
- \param editable true enables editing
- \sa editable()
+ \param value Minimum value
+ \sa setRange(), setMaximum(), minimum()
+
+ \note The maximum is adjusted if necessary to ensure that the range remains valid.
*/
-void QwtCounter::setEditable(bool editable)
+void QwtCounter::setMinimum( double value )
{
-#if QT_VERSION >= 0x040000
- using namespace Qt;
-#endif
- if ( editable == d_data->editable )
- return;
+ setRange( value, maximum() );
+}
- d_data->editable = editable;
- d_data->valueEdit->setReadOnly(!editable);
+/*!
+ \return The minimum of the range
+ \sa setRange(), setMinimum(), maximum()
+*/
+double QwtCounter::minimum() const
+{
+ return d_data->minimum;
}
-//! returns whether the line edit is edatble. (default is yes)
-bool QwtCounter::editable() const
+/*!
+ Set the maximum value of the range
+
+ \param value Maximum value
+ \sa setRange(), setMinimum(), maximum()
+*/
+void QwtCounter::setMaximum( double value )
{
- return d_data->editable;
+ setRange( minimum(), value );
}
/*!
- Handle PolishRequest events
+ \return The maximum of the range
+ \sa setRange(), setMaximum(), minimum()
*/
-bool QwtCounter::event ( QEvent * e )
+double QwtCounter::maximum() const
{
-#if QT_VERSION >= 0x040000
- if ( e->type() == QEvent::PolishRequest )
- polish();
-#endif
- return QWidget::event(e);
+ return d_data->maximum;
}
/*!
- Handles key events
+ \brief Set the step size of the counter
- - Ctrl + Qt::Key_Home
- Step to minValue()
- - Ctrl + Qt::Key_End
- Step to maxValue()
- - Qt::Key_Up
- Increment by incSteps(QwtCounter::Button1)
- - Qt::Key_Down
- Decrement by incSteps(QwtCounter::Button1)
- - Qt::Key_PageUp
- Increment by incSteps(QwtCounter::Button2)
- - Qt::Key_PageDown
- Decrement by incSteps(QwtCounter::Button2)
- - Shift + Qt::Key_PageUp
- Increment by incSteps(QwtCounter::Button3)
- - Shift + Qt::Key_PageDown
- Decrement by incSteps(QwtCounter::Button3)
+ A value <= 0.0 disables stepping
+
+ \param stepSize Single step size
+ \sa singleStep()
*/
+void QwtCounter::setSingleStep( double stepSize )
+{
+ d_data->singleStep = qMax( stepSize, 0.0 );
+}
-void QwtCounter::keyPressEvent (QKeyEvent *e)
+/*!
+ \return Single step size
+ \sa setSingleStep()
+ */
+double QwtCounter::singleStep() const
{
- bool accepted = true;
+ return d_data->singleStep;
+}
- switch ( e->key() ) {
- case Qt::Key_Home:
-#if QT_VERSION >= 0x040000
- if ( e->modifiers() & Qt::ControlModifier )
-#else
- if ( e->state() & Qt::ControlButton )
-#endif
- setValue(minValue());
- else
- accepted = false;
- break;
- case Qt::Key_End:
-#if QT_VERSION >= 0x040000
- if ( e->modifiers() & Qt::ControlModifier )
-#else
- if ( e->state() & Qt::ControlButton )
-#endif
- setValue(maxValue());
- else
- accepted = false;
- break;
- case Qt::Key_Up:
- incValue(d_data->increment[0]);
- break;
- case Qt::Key_Down:
- incValue(-d_data->increment[0]);
- break;
- case Qt::Key_PageUp:
- case Qt::Key_PageDown: {
- int increment = d_data->increment[0];
- if ( d_data->nButtons >= 2 )
- increment = d_data->increment[1];
- if ( d_data->nButtons >= 3 ) {
-#if QT_VERSION >= 0x040000
- if ( e->modifiers() & Qt::ShiftModifier )
-#else
- if ( e->state() & Qt::ShiftButton )
-#endif
- increment = d_data->increment[2];
- }
- if ( e->key() == Qt::Key_PageDown )
- increment = -increment;
- incValue(increment);
- break;
- }
- default:
- accepted = false;
- }
+/*!
+ \brief En/Disable wrapping
- if ( accepted ) {
- e->accept();
- return;
- }
+ If wrapping is true stepping up from maximum() value will take
+ you to the minimum() value and vice versa.
- QWidget::keyPressEvent (e);
+ \param on En/Disable wrapping
+ \sa wrapping()
+ */
+void QwtCounter::setWrapping( bool on )
+{
+ d_data->wrapping = on;
}
-void QwtCounter::wheelEvent(QWheelEvent *e)
+/*!
+ \return True, when wrapping is set
+ \sa setWrapping()
+ */
+bool QwtCounter::wrapping() const
{
- e->accept();
+ return d_data->wrapping;
+}
- if ( d_data->nButtons <= 0 )
- return;
+/*!
+ Specify the number of buttons on each side of the label
- int increment = d_data->increment[0];
- if ( d_data->nButtons >= 2 ) {
-#if QT_VERSION >= 0x040000
- if ( e->modifiers() & Qt::ControlModifier )
-#else
- if ( e->state() & Qt::ControlButton )
-#endif
- increment = d_data->increment[1];
- }
- if ( d_data->nButtons >= 3 ) {
-#if QT_VERSION >= 0x040000
- if ( e->modifiers() & Qt::ShiftModifier )
-#else
- if ( e->state() & Qt::ShiftButton )
-#endif
- increment = d_data->increment[2];
- }
+ \param numButtons Number of buttons
+ \sa numButtons()
+*/
+void QwtCounter::setNumButtons( int numButtons )
+{
+ if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt )
+ return;
- for ( int i = 0; i < d_data->nButtons; i++ ) {
- if ( d_data->buttonDown[i]->geometry().contains(e->pos()) ||
- d_data->buttonUp[i]->geometry().contains(e->pos()) ) {
- increment = d_data->increment[i];
+ for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
+ {
+ if ( i < numButtons )
+ {
+ d_data->buttonDown[i]->show();
+ d_data->buttonUp[i]->show();
+ }
+ else
+ {
+ d_data->buttonDown[i]->hide();
+ d_data->buttonUp[i]->hide();
}
}
- const int wheel_delta = 120;
-
- int delta = e->delta();
- if ( delta >= 2 * wheel_delta )
- delta /= 2; // Never saw an abs(delta) < 240
+ d_data->numButtons = numButtons;
+}
- incValue(delta / wheel_delta * increment);
+/*!
+ \return The number of buttons on each side of the widget.
+ \sa setNumButtons()
+*/
+int QwtCounter::numButtons() const
+{
+ return d_data->numButtons;
}
/*!
@@ -336,155 +396,359 @@ void QwtCounter::wheelEvent(QWheelEvent *e)
is incremented or decremented when a specified button
is pushed.
- \param btn One of \c QwtCounter::Button1, \c QwtCounter::Button2,
- \c QwtCounter::Button3
- \param nSteps Number of steps
+ \param button Button index
+ \param numSteps Number of steps
+
+ \sa incSteps()
*/
-void QwtCounter::setIncSteps(QwtCounter::Button btn, int nSteps)
+void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps )
{
- if (( btn >= 0) && (btn < ButtonCnt))
- d_data->increment[btn] = nSteps;
+ if ( button >= 0 && button < QwtCounter::ButtonCnt )
+ d_data->increment[ button ] = numSteps;
}
/*!
- \return the number of steps by which a specified button increments the value
- or 0 if the button is invalid.
- \param btn One of \c QwtCounter::Button1, \c QwtCounter::Button2,
- \c QwtCounter::Button3
+ \return The number of steps by which a specified button increments the value
+ or 0 if the button is invalid.
+ \param button Button index
+
+ \sa setIncSteps()
*/
-int QwtCounter::incSteps(QwtCounter::Button btn) const
+int QwtCounter::incSteps( QwtCounter::Button button ) const
{
- if (( btn >= 0) && (btn < ButtonCnt))
- return d_data->increment[btn];
+ if ( button >= 0 && button < QwtCounter::ButtonCnt )
+ return d_data->increment[ button ];
return 0;
}
+
/*!
- \brief Set a new value
- \param v new value
- Calls QwtDoubleRange::setValue and does all visual updates.
- \sa QwtDoubleRange::setValue
+ Set the number of increment steps for button 1
+ \param nSteps Number of steps
*/
+void QwtCounter::setStepButton1( int nSteps )
+{
+ setIncSteps( QwtCounter::Button1, nSteps );
+}
-void QwtCounter::setValue(double v)
+//! returns the number of increment steps for button 1
+int QwtCounter::stepButton1() const
{
- QwtDoubleRange::setValue(v);
+ return incSteps( QwtCounter::Button1 );
+}
- showNum(value());
- updateButtons();
+/*!
+ Set the number of increment steps for button 2
+ \param nSteps Number of steps
+*/
+void QwtCounter::setStepButton2( int nSteps )
+{
+ setIncSteps( QwtCounter::Button2, nSteps );
+}
+
+//! returns the number of increment steps for button 2
+int QwtCounter::stepButton2() const
+{
+ return incSteps( QwtCounter::Button2 );
}
/*!
- \brief Notify a change of value
+ Set the number of increment steps for button 3
+ \param nSteps Number of steps
*/
-void QwtCounter::valueChange()
+void QwtCounter::setStepButton3( int nSteps )
{
- if ( isValid() )
- showNum(value());
- else
- d_data->valueEdit->setText(QString::null);
+ setIncSteps( QwtCounter::Button3, nSteps );
+}
- updateButtons();
+//! returns the number of increment steps for button 3
+int QwtCounter::stepButton3() const
+{
+ return incSteps( QwtCounter::Button3 );
+}
+
+//! Set from lineedit
+void QwtCounter::textChanged()
+{
+ bool converted = false;
+
+ const double value = d_data->valueEdit->text().toDouble( &converted );
+ if ( converted )
+ setValue( value );
+}
- if ( isValid() )
- emit valueChanged(value());
+/*!
+ Handle QEvent::PolishRequest events
+ \param event Event
+ \return see QWidget::event()
+*/
+bool QwtCounter::event( QEvent *event )
+{
+ if ( event->type() == QEvent::PolishRequest )
+ {
+ const int w = d_data->valueEdit->fontMetrics().width( "W" ) + 8;
+ for ( int i = 0; i < ButtonCnt; i++ )
+ {
+ d_data->buttonDown[i]->setMinimumWidth( w );
+ d_data->buttonUp[i]->setMinimumWidth( w );
+ }
+ }
+
+ return QWidget::event( event );
}
/*!
- \brief Update buttons according to the current value
+ Handle key events
- When the QwtCounter under- or over-flows, the focus is set to the smallest
- up- or down-button and counting is disabled.
+ - Ctrl + Qt::Key_Home\n
+ Step to minimum()
+ - Ctrl + Qt::Key_End\n
+ Step to maximum()
+ - Qt::Key_Up\n
+ Increment by incSteps(QwtCounter::Button1)
+ - Qt::Key_Down\n
+ Decrement by incSteps(QwtCounter::Button1)
+ - Qt::Key_PageUp\n
+ Increment by incSteps(QwtCounter::Button2)
+ - Qt::Key_PageDown\n
+ Decrement by incSteps(QwtCounter::Button2)
+ - Shift + Qt::Key_PageUp\n
+ Increment by incSteps(QwtCounter::Button3)
+ - Shift + Qt::Key_PageDown\n
+ Decrement by incSteps(QwtCounter::Button3)
- Counting is re-enabled on a button release event (mouse or space bar).
+ \param event Key event
*/
-void QwtCounter::updateButtons()
+void QwtCounter::keyPressEvent ( QKeyEvent *event )
{
- if ( isValid() ) {
- // 1. save enabled state of the smallest down- and up-button
- // 2. change enabled state on under- or over-flow
+ bool accepted = true;
- for ( int i = 0; i < ButtonCnt; i++ ) {
- d_data->buttonDown[i]->setEnabled(value() > minValue());
- d_data->buttonUp[i]->setEnabled(value() < maxValue());
+ switch ( event->key() )
+ {
+ case Qt::Key_Home:
+ {
+ if ( event->modifiers() & Qt::ControlModifier )
+ setValue( minimum() );
+ else
+ accepted = false;
+ break;
+ }
+ case Qt::Key_End:
+ {
+ if ( event->modifiers() & Qt::ControlModifier )
+ setValue( maximum() );
+ else
+ accepted = false;
+ break;
+ }
+ case Qt::Key_Up:
+ {
+ incrementValue( d_data->increment[0] );
+ break;
}
- } else {
- for ( int i = 0; i < ButtonCnt; i++ ) {
- d_data->buttonDown[i]->setEnabled(false);
- d_data->buttonUp[i]->setEnabled(false);
+ case Qt::Key_Down:
+ {
+ incrementValue( -d_data->increment[0] );
+ break;
+ }
+ case Qt::Key_PageUp:
+ case Qt::Key_PageDown:
+ {
+ int increment = d_data->increment[0];
+ if ( d_data->numButtons >= 2 )
+ increment = d_data->increment[1];
+ if ( d_data->numButtons >= 3 )
+ {
+ if ( event->modifiers() & Qt::ShiftModifier )
+ increment = d_data->increment[2];
+ }
+ if ( event->key() == Qt::Key_PageDown )
+ increment = -increment;
+ incrementValue( increment );
+ break;
+ }
+ default:
+ {
+ accepted = false;
}
}
+
+ if ( accepted )
+ {
+ event->accept();
+ return;
+ }
+
+ QWidget::keyPressEvent ( event );
}
/*!
- \brief Specify the number of buttons on each side of the label
- \param n Number of buttons
+ Handle wheel events
+ \param event Wheel event
*/
-void QwtCounter::setNumButtons(int n)
+void QwtCounter::wheelEvent( QWheelEvent *event )
{
- if ( n<0 || n>ButtonCnt )
+ event->accept();
+
+ if ( d_data->numButtons <= 0 )
return;
- for ( int i = 0; i < ButtonCnt; i++ ) {
- if ( i < n ) {
- d_data->buttonDown[i]->show();
- d_data->buttonUp[i]->show();
- } else {
- d_data->buttonDown[i]->hide();
- d_data->buttonUp[i]->hide();
+ int increment = d_data->increment[0];
+ if ( d_data->numButtons >= 2 )
+ {
+ if ( event->modifiers() & Qt::ControlModifier )
+ increment = d_data->increment[1];
+ }
+ if ( d_data->numButtons >= 3 )
+ {
+ if ( event->modifiers() & Qt::ShiftModifier )
+ increment = d_data->increment[2];
+ }
+
+ for ( int i = 0; i < d_data->numButtons; i++ )
+ {
+ if ( d_data->buttonDown[i]->geometry().contains( event->pos() ) ||
+ d_data->buttonUp[i]->geometry().contains( event->pos() ) )
+ {
+ increment = d_data->increment[i];
+ }
+ }
+
+ const int wheel_delta = 120;
+
+#if 1
+ int delta = event->delta();
+ if ( delta >= 2 * wheel_delta )
+ delta /= 2; // Never saw an abs(delta) < 240
+#endif
+
+ incrementValue( delta / wheel_delta * increment );
+}
+
+void QwtCounter::incrementValue( int numSteps )
+{
+ const double min = d_data->minimum;
+ const double max = d_data->maximum;
+ double stepSize = d_data->singleStep;
+
+ if ( !d_data->isValid || min >= max || stepSize <= 0.0 )
+ return;
+
+
+#if 1
+ stepSize = qMax( stepSize, 1.0e-10 * ( max - min ) );
+#endif
+
+ double value = d_data->value + numSteps * stepSize;
+
+ if ( d_data->wrapping )
+ {
+ const double range = max - min;
+
+ if ( value < min )
+ {
+ value += ::ceil( ( min - value ) / range ) * range;
}
+ else if ( value > max )
+ {
+ value -= ::ceil( ( value - max ) / range ) * range;
+ }
+ }
+ else
+ {
+ value = qBound( min, value, max );
}
- d_data->nButtons = n;
+ value = min + qRound( ( value - min ) / stepSize ) * stepSize;
+
+ if ( stepSize > 1e-12 )
+ {
+ if ( qFuzzyCompare( value + 1.0, 1.0 ) )
+ {
+ // correct rounding error if value = 0
+ value = 0.0;
+ }
+ else if ( qFuzzyCompare( value, max ) )
+ {
+ // correct rounding error at the border
+ value = max;
+ }
+ }
+
+ if ( value != d_data->value )
+ {
+ d_data->value = value;
+ showNumber( d_data->value );
+ updateButtons();
+
+ Q_EMIT valueChanged( d_data->value );
+ }
}
+
/*!
- \return The number of buttons on each side of the widget.
+ \brief Update buttons according to the current value
+
+ When the QwtCounter under- or over-flows, the focus is set to the smallest
+ up- or down-button and counting is disabled.
+
+ Counting is re-enabled on a button release event (mouse or space bar).
*/
-int QwtCounter::numButtons() const
+void QwtCounter::updateButtons()
{
- return d_data->nButtons;
+ if ( d_data->isValid )
+ {
+ // 1. save enabled state of the smallest down- and up-button
+ // 2. change enabled state on under- or over-flow
+
+ for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
+ {
+ d_data->buttonDown[i]->setEnabled( value() > minimum() );
+ d_data->buttonUp[i]->setEnabled( value() < maximum() );
+ }
+ }
+ else
+ {
+ for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
+ {
+ d_data->buttonDown[i]->setEnabled( false );
+ d_data->buttonUp[i]->setEnabled( false );
+ }
+ }
}
+/*!
+ Display number string
-//! Display number string
-void QwtCounter::showNum(double d)
+ \param number Number
+*/
+void QwtCounter::showNumber( double number )
{
- QString v;
- v.setNum(d);
+ QString text;
+ text.setNum( number );
const int cursorPos = d_data->valueEdit->cursorPosition();
- d_data->valueEdit->setText(v);
- d_data->valueEdit->setCursorPosition(cursorPos);
+ d_data->valueEdit->setText( text );
+ d_data->valueEdit->setCursorPosition( cursorPos );
}
//! Button clicked
void QwtCounter::btnClicked()
{
- for ( int i = 0; i < ButtonCnt; i++ ) {
+ for ( int i = 0; i < ButtonCnt; i++ )
+ {
if ( d_data->buttonUp[i] == sender() )
- incValue(d_data->increment[i]);
+ incrementValue( d_data->increment[i] );
if ( d_data->buttonDown[i] == sender() )
- incValue(-d_data->increment[i]);
+ incrementValue( -d_data->increment[i] );
}
}
//! Button released
void QwtCounter::btnReleased()
{
- emit buttonReleased(value());
-}
-
-/*!
- \brief Notify change of range
-
- This function updates the enabled property of
- all buttons contained in QwtCounter.
-*/
-void QwtCounter::rangeChange()
-{
- updateButtons();
+ Q_EMIT buttonReleased( value() );
}
//! A size hint
@@ -492,112 +756,30 @@ QSize QwtCounter::sizeHint() const
{
QString tmp;
- int w = tmp.setNum(minValue()).length();
- int w1 = tmp.setNum(maxValue()).length();
+ int w = tmp.setNum( minimum() ).length();
+ int w1 = tmp.setNum( maximum() ).length();
if ( w1 > w )
w = w1;
- w1 = tmp.setNum(minValue() + step()).length();
+ w1 = tmp.setNum( minimum() + singleStep() ).length();
if ( w1 > w )
w = w1;
- w1 = tmp.setNum(maxValue() - step()).length();
+ w1 = tmp.setNum( maximum() - singleStep() ).length();
if ( w1 > w )
w = w1;
- tmp.fill('9', w);
+ tmp.fill( '9', w );
- QFontMetrics fm(d_data->valueEdit->font());
- w = fm.width(tmp) + 2;
-#if QT_VERSION >= 0x040000
+ QFontMetrics fm( d_data->valueEdit->font() );
+ w = fm.width( tmp ) + 2;
if ( d_data->valueEdit->hasFrame() )
- w += 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
-#else
- w += 2 * d_data->valueEdit->frameWidth();
-#endif
+ w += 2 * style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
// Now we replace default sizeHint contribution of d_data->valueEdit by
// what we really need.
w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width();
- const int h = qwtMin(QWidget::sizeHint().height(),
- d_data->valueEdit->minimumSizeHint().height());
- return QSize(w, h);
-}
-
-//! returns the step size
-double QwtCounter::step() const
-{
- return QwtDoubleRange::step();
-}
-
-//! sets the step size
-void QwtCounter::setStep(double s)
-{
- QwtDoubleRange::setStep(s);
-}
-
-//! returns the minimum value of the range
-double QwtCounter::minVal() const
-{
- return minValue();
-}
-
-//! sets the minimum value of the range
-void QwtCounter::setMinValue(double m)
-{
- setRange(m, maxValue(), step());
-}
-
-//! returns the maximum value of the range
-double QwtCounter::maxVal() const
-{
- return QwtDoubleRange::maxValue();
-}
-
-//! sets the maximum value of the range
-void QwtCounter::setMaxValue(double m)
-{
- setRange(minValue(), m, step());
-}
-
-//! set the number of increment steps for button 1
-void QwtCounter::setStepButton1(int nSteps)
-{
- setIncSteps(Button1, nSteps);
-}
-
-//! returns the number of increment steps for button 1
-int QwtCounter::stepButton1() const
-{
- return incSteps(Button1);
+ const int h = qMin( QWidget::sizeHint().height(),
+ d_data->valueEdit->minimumSizeHint().height() );
+ return QSize( w, h );
}
-
-//! set the number of increment steps for button 2
-void QwtCounter::setStepButton2(int nSteps)
-{
- setIncSteps(Button2, nSteps);
-}
-
-//! returns the number of increment steps for button 2
-int QwtCounter::stepButton2() const
-{
- return incSteps(Button2);
-}
-
-//! set the number of increment steps for button 3
-void QwtCounter::setStepButton3(int nSteps)
-{
- setIncSteps(Button3, nSteps);
-}
-
-//! returns the number of increment steps for button 3
-int QwtCounter::stepButton3() const
-{
- return incSteps(Button3);
-}
-
-double QwtCounter::value() const
-{
- return QwtDoubleRange::value();
-}
-
diff --git a/libs/qwt/qwt_counter.h b/libs/qwt/qwt_counter.h
index bda399cce3bb4783647044e842afb8f63bec3570..8799eddcac70d692eb0f235e65ba9b76dbea9884 100644
--- a/libs/qwt/qwt_counter.h
+++ b/libs/qwt/qwt_counter.h
@@ -7,14 +7,11 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-// vim: expandtab
-
#ifndef QWT_COUNTER_H
#define QWT_COUNTER_H
-#include
#include "qwt_global.h"
-#include "qwt_double_range.h"
+#include
/*!
\brief The Counter Widget
@@ -24,130 +21,138 @@
of the label which can be used to increment or decrement
the counter's value.
- A Counter has a range from a minimum value to a maximum value
- and a step size. The range can be specified using
- QwtDblRange::setRange().
- The counter's value is an integer multiple of the step size.
- The number of steps by which a button increments or decrements
- the value can be specified using QwtCounter::setIncSteps().
- The number of buttons can be changed with
- QwtCounter::setNumButtons().
-
- Holding the space bar down with focus on a button is the
- fastest method to step through the counter values.
- When the counter underflows/overflows, the focus is set
- to the smallest up/down button and counting is disabled.
- Counting is re-enabled on a button release event (mouse or
- space bar).
+ A counter has a range from a minimum value to a maximum value
+ and a step size. When the wrapping property is set
+ the counter is circular.
+
+ The number of steps by which a button increments or decrements the value
+ can be specified using setIncSteps(). The number of buttons can be
+ changed with setNumButtons().
Example:
\code
-#include "../include/qwt_counter.h>
+#include
-QwtCounter *cnt;
+QwtCounter *counter = new QwtCounter(parent);
-cnt = new QwtCounter(parent, name);
+counter->setRange(0.0, 100.0); // From 0.0 to 100
+counter->setSingleStep( 1.0 ); // Step size 1.0
+counter->setNumButtons(2); // Two buttons each side
+counter->setIncSteps(QwtCounter::Button1, 1); // Button 1 increments 1 step
+counter->setIncSteps(QwtCounter::Button2, 20); // Button 2 increments 20 steps
-cnt->setRange(0.0, 100.0, 1.0); // From 0.0 to 100, step 1.0
-cnt->setNumButtons(2); // Two buttons each side
-cnt->setIncSteps(QwtCounter::Button1, 1); // Button 1 increments 1 step
-cnt->setIncSteps(QwtCounter::Button2, 20); // Button 2 increments 20 steps
-
-connect(cnt, SIGNAL(valueChanged(double)), my_class, SLOT(newValue(double)));
+connect(counter, SIGNAL(valueChanged(double)), myClass, SLOT(newValue(double)));
\endcode
*/
-class QWT_EXPORT QwtCounter : public QWidget, public QwtDoubleRange
+class QWT_EXPORT QwtCounter : public QWidget
{
Q_OBJECT
+ Q_PROPERTY( double value READ value WRITE setValue )
+ Q_PROPERTY( double minimum READ minimum WRITE setMinimum )
+ Q_PROPERTY( double maximum READ maximum WRITE setMaximum )
+ Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep )
+
Q_PROPERTY( int numButtons READ numButtons WRITE setNumButtons )
- Q_PROPERTY( double basicstep READ step WRITE setStep )
- Q_PROPERTY( double minValue READ minVal WRITE setMinValue )
- Q_PROPERTY( double maxValue READ maxVal WRITE setMaxValue )
Q_PROPERTY( int stepButton1 READ stepButton1 WRITE setStepButton1 )
Q_PROPERTY( int stepButton2 READ stepButton2 WRITE setStepButton2 )
Q_PROPERTY( int stepButton3 READ stepButton3 WRITE setStepButton3 )
- Q_PROPERTY( double value READ value WRITE setValue )
- Q_PROPERTY( bool editable READ editable WRITE setEditable )
-public:
- /*!
- Button index
- */
+ Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
+ Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping )
- enum Button {
+public:
+ //! Button index
+ enum Button
+ {
+ //! Button intended for minor steps
Button1,
+
+ //! Button intended for medium steps
Button2,
+
+ //! Button intended for large steps
Button3,
+
+ //! Number of buttons
ButtonCnt
};
- explicit QwtCounter(QWidget *parent = NULL);
-#if QT_VERSION < 0x040000
- explicit QwtCounter(QWidget *parent, const char *name);
-#endif
+ explicit QwtCounter( QWidget *parent = NULL );
virtual ~QwtCounter();
- bool editable() const;
- void setEditable(bool);
+ void setValid( bool );
+ bool isValid() const;
- void setNumButtons(int n);
+ void setWrapping( bool );
+ bool wrapping() const;
+
+ bool isReadOnly() const;
+ void setReadOnly( bool );
+
+ void setNumButtons( int n );
int numButtons() const;
- void setIncSteps(QwtCounter::Button btn, int nSteps);
- int incSteps(QwtCounter::Button btn) const;
+ void setIncSteps( QwtCounter::Button btn, int nSteps );
+ int incSteps( QwtCounter::Button btn ) const;
- virtual void setValue(double);
virtual QSize sizeHint() const;
- virtual void polish();
+ double singleStep() const;
+ void setSingleStep( double s );
+
+ void setRange( double min, double max );
+
+ double minimum() const;
+ void setMinimum( double min );
- // a set of dummies to help the designer
+ double maximum() const;
+ void setMaximum( double max );
- double step() const;
- void setStep(double s);
- double minVal() const;
- void setMinValue(double m);
- double maxVal() const;
- void setMaxValue(double m);
- void setStepButton1(int nSteps);
+ void setStepButton1( int nSteps );
int stepButton1() const;
- void setStepButton2(int nSteps);
+
+ void setStepButton2( int nSteps );
int stepButton2() const;
- void setStepButton3(int nSteps);
+
+ void setStepButton3( int nSteps );
int stepButton3() const;
- virtual double value() const;
-signals:
+ double value() const;
+
+public Q_SLOTS:
+ void setValue( double );
+
+
+Q_SIGNALS:
/*!
This signal is emitted when a button has been released
\param value The new value
*/
- void buttonReleased (double value);
+ void buttonReleased ( double value );
/*!
This signal is emitted when the counter's value has changed
\param value The new value
*/
- void valueChanged (double value);
+ void valueChanged ( double value );
protected:
- virtual bool event(QEvent *);
- virtual void wheelEvent(QWheelEvent *);
- virtual void keyPressEvent(QKeyEvent *);
- virtual void rangeChange();
+ virtual bool event( QEvent * );
+ virtual void wheelEvent( QWheelEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
-private slots:
+private Q_SLOTS:
void btnReleased();
void btnClicked();
void textChanged();
private:
+ void incrementValue( int numSteps );
void initCounter();
void updateButtons();
- void showNum(double);
- virtual void valueChange();
+ void showNumber( double );
class PrivateData;
PrivateData *d_data;
diff --git a/libs/qwt/qwt_curve_fitter.cpp b/libs/qwt/qwt_curve_fitter.cpp
index 05cc82ce88452c9c5c56152c4f1e82b0580abb29..5f09d5d8d07fe310124ae7e8c5d230d4c12bd99b 100644
--- a/libs/qwt/qwt_curve_fitter.cpp
+++ b/libs/qwt/qwt_curve_fitter.cpp
@@ -7,9 +7,15 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
+#include "qwt_curve_fitter.h"
#include "qwt_math.h"
#include "qwt_spline.h"
-#include "qwt_curve_fitter.h"
+#include
+#include
+
+#if QT_VERSION < 0x040601
+#define qFabs(x) ::fabs(x)
+#endif
//! Constructor
QwtCurveFitter::QwtCurveFitter()
@@ -25,8 +31,9 @@ class QwtSplineCurveFitter::PrivateData
{
public:
PrivateData():
- fitMode(QwtSplineCurveFitter::Auto),
- splineSize(250) {
+ fitMode( QwtSplineCurveFitter::Auto ),
+ splineSize( 250 )
+ {
}
QwtSpline spline;
@@ -34,71 +41,110 @@ public:
int splineSize;
};
+//! Constructor
QwtSplineCurveFitter::QwtSplineCurveFitter()
{
d_data = new PrivateData;
}
+//! Destructor
QwtSplineCurveFitter::~QwtSplineCurveFitter()
{
delete d_data;
}
-void QwtSplineCurveFitter::setFitMode(FitMode mode)
+/*!
+ Select the algorithm used for building the spline
+
+ \param mode Mode representing a spline algorithm
+ \sa fitMode()
+*/
+void QwtSplineCurveFitter::setFitMode( FitMode mode )
{
d_data->fitMode = mode;
}
+/*!
+ \return Mode representing a spline algorithm
+ \sa setFitMode()
+*/
QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const
{
return d_data->fitMode;
}
-void QwtSplineCurveFitter::setSpline(const QwtSpline &spline)
+/*!
+ Assign a spline
+
+ \param spline Spline
+ \sa spline()
+*/
+void QwtSplineCurveFitter::setSpline( const QwtSpline &spline )
{
d_data->spline = spline;
d_data->spline.reset();
}
+/*!
+ \return Spline
+ \sa setSpline()
+*/
const QwtSpline &QwtSplineCurveFitter::spline() const
{
return d_data->spline;
}
+/*!
+ \return Spline
+ \sa setSpline()
+*/
QwtSpline &QwtSplineCurveFitter::spline()
{
return d_data->spline;
}
-void QwtSplineCurveFitter::setSplineSize(int splineSize)
+/*!
+ Assign a spline size ( has to be at least 10 points )
+
+ \param splineSize Spline size
+ \sa splineSize()
+*/
+void QwtSplineCurveFitter::setSplineSize( int splineSize )
{
- d_data->splineSize = qwtMax(splineSize, 10);
+ d_data->splineSize = qMax( splineSize, 10 );
}
+/*!
+ \return Spline size
+ \sa setSplineSize()
+*/
int QwtSplineCurveFitter::splineSize() const
{
return d_data->splineSize;
}
-#if QT_VERSION < 0x040000
-QwtArray QwtSplineCurveFitter::fitCurve(
- const QwtArray & points) const
-#else
-QPolygonF QwtSplineCurveFitter::fitCurve(
- const QPolygonF &points) const
-#endif
+/*!
+ Find a curve which has the best fit to a series of data points
+
+ \param points Series of data points
+ \return Curve points
+*/
+QPolygonF QwtSplineCurveFitter::fitCurve( const QPolygonF &points ) const
{
- const int size = (int)points.size();
+ const int size = points.size();
if ( size <= 2 )
return points;
FitMode fitMode = d_data->fitMode;
- if ( fitMode == Auto ) {
+ if ( fitMode == Auto )
+ {
fitMode = Spline;
- const QwtDoublePoint *p = points.data();
- for ( int i = 1; i < size; i++ ) {
- if ( p[i].x() <= p[i-1].x() ) {
+ const QPointF *p = points.data();
+ for ( int i = 1; i < size; i++ )
+ {
+ if ( p[i].x() <= p[i-1].x() )
+ {
fitMode = ParametricSpline;
break;
}
@@ -106,109 +152,302 @@ QPolygonF QwtSplineCurveFitter::fitCurve(
}
if ( fitMode == ParametricSpline )
- return fitParametric(points);
+ return fitParametric( points );
else
- return fitSpline(points);
+ return fitSpline( points );
}
-#if QT_VERSION < 0x040000
-QwtArray QwtSplineCurveFitter::fitSpline(
- const QwtArray &points) const
-#else
-QPolygonF QwtSplineCurveFitter::fitSpline(
- const QPolygonF &points) const
-#endif
+QPolygonF QwtSplineCurveFitter::fitSpline( const QPolygonF &points ) const
{
- d_data->spline.setPoints(points);
+ d_data->spline.setPoints( points );
if ( !d_data->spline.isValid() )
return points;
-#if QT_VERSION < 0x040000
- QwtArray fittedPoints(d_data->splineSize);
-#else
- QPolygonF fittedPoints(d_data->splineSize);
-#endif
+ QPolygonF fittedPoints( d_data->splineSize );
const double x1 = points[0].x();
- const double x2 = points[int(points.size() - 1)].x();
+ const double x2 = points[int( points.size() - 1 )].x();
const double dx = x2 - x1;
- const double delta = dx / (d_data->splineSize - 1);
+ const double delta = dx / ( d_data->splineSize - 1 );
- for (int i = 0; i < d_data->splineSize; i++) {
- QwtDoublePoint &p = fittedPoints[i];
+ for ( int i = 0; i < d_data->splineSize; i++ )
+ {
+ QPointF &p = fittedPoints[i];
const double v = x1 + i * delta;
- const double sv = d_data->spline.value(v);
+ const double sv = d_data->spline.value( v );
- p.setX(qRound(v));
- p.setY(qRound(sv));
+ p.setX( v );
+ p.setY( sv );
}
d_data->spline.reset();
return fittedPoints;
}
-#if QT_VERSION < 0x040000
-QwtArray QwtSplineCurveFitter::fitParametric(
- const QwtArray &points) const
-#else
-QPolygonF QwtSplineCurveFitter::fitParametric(
- const QPolygonF &points) const
-#endif
+QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const
{
int i;
const int size = points.size();
-#if QT_VERSION < 0x040000
- QwtArray fittedPoints(d_data->splineSize);
- QwtArray splinePointsX(size);
- QwtArray splinePointsY(size);
-#else
- QPolygonF fittedPoints(d_data->splineSize);
- QPolygonF splinePointsX(size);
- QPolygonF splinePointsY(size);
-#endif
+ QPolygonF fittedPoints( d_data->splineSize );
+ QPolygonF splinePointsX( size );
+ QPolygonF splinePointsY( size );
- const QwtDoublePoint *p = points.data();
- QwtDoublePoint *spX = splinePointsX.data();
- QwtDoublePoint *spY = splinePointsY.data();
+ const QPointF *p = points.data();
+ QPointF *spX = splinePointsX.data();
+ QPointF *spY = splinePointsY.data();
double param = 0.0;
- for (i = 0; i < size; i++) {
+ for ( i = 0; i < size; i++ )
+ {
const double x = p[i].x();
const double y = p[i].y();
- if ( i > 0 ) {
- const double delta = sqrt( qwtSqr(x - spX[i-1].y())
- + qwtSqr( y - spY[i-1].y() ) );
- param += qwtMax(delta, 1.0);
+ if ( i > 0 )
+ {
+ const double delta = qSqrt( qwtSqr( x - spX[i-1].y() )
+ + qwtSqr( y - spY[i-1].y() ) );
+ param += qMax( delta, 1.0 );
}
- spX[i].setX(param);
- spX[i].setY(x);
- spY[i].setX(param);
- spY[i].setY(y);
+ spX[i].setX( param );
+ spX[i].setY( x );
+ spY[i].setX( param );
+ spY[i].setY( y );
}
- d_data->spline.setPoints(splinePointsX);
+ d_data->spline.setPoints( splinePointsX );
if ( !d_data->spline.isValid() )
return points;
const double deltaX =
- splinePointsX[size - 1].x() / (d_data->splineSize-1);
- for (i = 0; i < d_data->splineSize; i++) {
+ splinePointsX[size - 1].x() / ( d_data->splineSize - 1 );
+ for ( i = 0; i < d_data->splineSize; i++ )
+ {
const double dtmp = i * deltaX;
- fittedPoints[i].setX(qRound(d_data->spline.value(dtmp)));
+ fittedPoints[i].setX( d_data->spline.value( dtmp ) );
}
- d_data->spline.setPoints(splinePointsY);
+ d_data->spline.setPoints( splinePointsY );
if ( !d_data->spline.isValid() )
return points;
const double deltaY =
- splinePointsY[size - 1].x() / (d_data->splineSize-1);
- for (i = 0; i < d_data->splineSize; i++) {
+ splinePointsY[size - 1].x() / ( d_data->splineSize - 1 );
+ for ( i = 0; i < d_data->splineSize; i++ )
+ {
const double dtmp = i * deltaY;
- fittedPoints[i].setY(qRound(d_data->spline.value(dtmp)));
+ fittedPoints[i].setY( d_data->spline.value( dtmp ) );
}
return fittedPoints;
}
+
+class QwtWeedingCurveFitter::PrivateData
+{
+public:
+ PrivateData():
+ tolerance( 1.0 ),
+ chunkSize( 0 )
+ {
+ }
+
+ double tolerance;
+ uint chunkSize;
+};
+
+class QwtWeedingCurveFitter::Line
+{
+public:
+ Line( int i1 = 0, int i2 = 0 ):
+ from( i1 ),
+ to( i2 )
+ {
+ }
+
+ int from;
+ int to;
+};
+
+/*!
+ Constructor
+
+ \param tolerance Tolerance
+ \sa setTolerance(), tolerance()
+*/
+QwtWeedingCurveFitter::QwtWeedingCurveFitter( double tolerance )
+{
+ d_data = new PrivateData;
+ setTolerance( tolerance );
+}
+
+//! Destructor
+QwtWeedingCurveFitter::~QwtWeedingCurveFitter()
+{
+ delete d_data;
+}
+
+/*!
+ Assign the tolerance
+
+ The tolerance is the maximum distance, that is acceptable
+ between the original curve and the smoothed curve.
+
+ Increasing the tolerance will reduce the number of the
+ resulting points.
+
+ \param tolerance Tolerance
+
+ \sa tolerance()
+*/
+void QwtWeedingCurveFitter::setTolerance( double tolerance )
+{
+ d_data->tolerance = qMax( tolerance, 0.0 );
+}
+
+/*!
+ \return Tolerance
+ \sa setTolerance()
+*/
+double QwtWeedingCurveFitter::tolerance() const
+{
+ return d_data->tolerance;
+}
+
+/*!
+ Limit the number of points passed to a run of the algorithm
+
+ The runtime of the Douglas Peucker algorithm increases non linear
+ with the number of points. For a chunk size > 0 the polygon
+ is split into pieces passed to the algorithm one by one.
+
+ \param numPoints Maximum for the number of points passed to the algorithm
+
+ \sa chunkSize()
+*/
+void QwtWeedingCurveFitter::setChunkSize( uint numPoints )
+{
+ if ( numPoints > 0 )
+ numPoints = qMax( numPoints, 3U );
+
+ d_data->chunkSize = numPoints;
+}
+
+/*!
+
+ \return Maximum for the number of points passed to a run
+ of the algorithm - or 0, when unlimited
+ \sa setChunkSize()
+*/
+uint QwtWeedingCurveFitter::chunkSize() const
+{
+ return d_data->chunkSize;
+}
+
+/*!
+ \param points Series of data points
+ \return Curve points
+*/
+QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const
+{
+ QPolygonF fittedPoints;
+
+ if ( d_data->chunkSize == 0 )
+ {
+ fittedPoints = simplify( points );
+ }
+ else
+ {
+ for ( int i = 0; i < points.size(); i += d_data->chunkSize )
+ {
+ const QPolygonF p = points.mid( i, d_data->chunkSize );
+ fittedPoints += simplify( p );
+ }
+ }
+
+ return fittedPoints;
+}
+
+QPolygonF QwtWeedingCurveFitter::simplify( const QPolygonF &points ) const
+{
+ const double toleranceSqr = d_data->tolerance * d_data->tolerance;
+
+ QStack stack;
+ stack.reserve( 500 );
+
+ const QPointF *p = points.data();
+ const int nPoints = points.size();
+
+ QVector usePoint( nPoints, false );
+
+ stack.push( Line( 0, nPoints - 1 ) );
+
+ while ( !stack.isEmpty() )
+ {
+ const Line r = stack.pop();
+
+ // initialize line segment
+ const double vecX = p[r.to].x() - p[r.from].x();
+ const double vecY = p[r.to].y() - p[r.from].y();
+
+ const double vecLength = qSqrt( vecX * vecX + vecY * vecY );
+
+ const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0;
+ const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0;
+
+ double maxDistSqr = 0.0;
+ int nVertexIndexMaxDistance = r.from + 1;
+ for ( int i = r.from + 1; i < r.to; i++ )
+ {
+ //compare to anchor
+ const double fromVecX = p[i].x() - p[r.from].x();
+ const double fromVecY = p[i].y() - p[r.from].y();
+
+ double distToSegmentSqr;
+ if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
+ {
+ distToSegmentSqr = fromVecX * fromVecX + fromVecY * fromVecY;
+ }
+ else
+ {
+ const double toVecX = p[i].x() - p[r.to].x();
+ const double toVecY = p[i].y() - p[r.to].y();
+ const double toVecLength = toVecX * toVecX + toVecY * toVecY;
+
+ const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY );
+ if ( s < 0.0 )
+ {
+ distToSegmentSqr = toVecLength;
+ }
+ else
+ {
+ distToSegmentSqr = qFabs( toVecLength - s * s );
+ }
+ }
+
+ if ( maxDistSqr < distToSegmentSqr )
+ {
+ maxDistSqr = distToSegmentSqr;
+ nVertexIndexMaxDistance = i;
+ }
+ }
+ if ( maxDistSqr <= toleranceSqr )
+ {
+ usePoint[r.from] = true;
+ usePoint[r.to] = true;
+ }
+ else
+ {
+ stack.push( Line( r.from, nVertexIndexMaxDistance ) );
+ stack.push( Line( nVertexIndexMaxDistance, r.to ) );
+ }
+ }
+
+ QPolygonF stripped;
+ for ( int i = 0; i < nPoints; i++ )
+ {
+ if ( usePoint[i] )
+ stripped += p[i];
+ }
+
+ return stripped;
+}
diff --git a/libs/qwt/qwt_curve_fitter.h b/libs/qwt/qwt_curve_fitter.h
index 1ed31e73e10c6dba1bff42cf980150590281ea07..eac376a34d2cc57d26342607002dda1f49bf9b76 100644
--- a/libs/qwt/qwt_curve_fitter.h
+++ b/libs/qwt/qwt_curve_fitter.h
@@ -11,31 +11,11 @@
#define QWT_CURVE_FITTER_H
#include "qwt_global.h"
-#include "qwt_double_rect.h"
+#include
+#include
class QwtSpline;
-#if QT_VERSION >= 0x040000
-#include
-#else
-#include "qwt_array.h"
-#endif
-
-// MOC_SKIP_BEGIN
-
-#if defined(QWT_TEMPLATEDLL)
-
-#if QT_VERSION < 0x040000
-#ifndef QWTARRAY_TEMPLATE_QWTDOUBLEPOINT // by mjo3
-#define QWTARRAY_TEMPLATE_QWTDOUBLEPOINT
-template class QWT_EXPORT QwtArray;
-#endif //end of QWTARRAY_TEMPLATE_QWTDOUBLEPOINT
-#endif
-
-#endif
-
-// MOC_SKIP_END
-
/*!
\brief Abstract base class for a curve fitter
*/
@@ -44,12 +24,13 @@ class QWT_EXPORT QwtCurveFitter
public:
virtual ~QwtCurveFitter();
-#if QT_VERSION < 0x040000
- virtual QwtArray fitCurve(
- const QwtArray&) const = 0;
-#else
- virtual QPolygonF fitCurve(const QPolygonF &) const = 0;
-#endif
+ /*!
+ Find a curve which has the best fit to a series of data points
+
+ \param polygon Series of data points
+ \return Curve points
+ */
+ virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0;
protected:
QwtCurveFitter();
@@ -65,42 +46,91 @@ private:
class QWT_EXPORT QwtSplineCurveFitter: public QwtCurveFitter
{
public:
- enum FitMode {
+ /*!
+ Spline type
+ The default setting is Auto
+ \sa setFitMode(), FitMode()
+ */
+ enum FitMode
+ {
+ /*!
+ Use the default spline algorithm for polygons with
+ increasing x values ( p[i-1] < p[i] ), otherwise use
+ a parametric spline algorithm.
+ */
Auto,
+
+ //! Use a default spline algorithm
Spline,
+
+ //! Use a parametric spline algorithm
ParametricSpline
};
QwtSplineCurveFitter();
virtual ~QwtSplineCurveFitter();
- void setFitMode(FitMode);
+ void setFitMode( FitMode );
FitMode fitMode() const;
- void setSpline(const QwtSpline&);
+ void setSpline( const QwtSpline& );
const QwtSpline &spline() const;
QwtSpline &spline();
- void setSplineSize(int size);
+ void setSplineSize( int size );
int splineSize() const;
-#if QT_VERSION < 0x040000
- virtual QwtArray fitCurve(
- const QwtArray &) const;
-#else
- virtual QPolygonF fitCurve(const QPolygonF &) const;
-#endif
+ virtual QPolygonF fitCurve( const QPolygonF & ) const;
private:
-#if QT_VERSION < 0x040000
- QwtArray fitSpline(
- const QwtArray &) const;
- QwtArray fitParametric(
- const QwtArray &) const;
-#else
- QPolygonF fitSpline(const QPolygonF &) const;
- QPolygonF fitParametric(const QPolygonF &) const;
-#endif
+ QPolygonF fitSpline( const QPolygonF & ) const;
+ QPolygonF fitParametric( const QPolygonF & ) const;
+
+ class PrivateData;
+ PrivateData *d_data;
+};
+
+/*!
+ \brief A curve fitter implementing Douglas and Peucker algorithm
+
+ The purpose of the Douglas and Peucker algorithm is that given a 'curve'
+ composed of line segments to find a curve not too dissimilar but that
+ has fewer points. The algorithm defines 'too dissimilar' based on the
+ maximum distance (tolerance) between the original curve and the
+ smoothed curve.
+
+ The runtime of the algorithm increases non linear ( worst case O( n*n ) )
+ and might be very slow for huge polygons. To avoid performance issues
+ it might be useful to split the polygon ( setChunkSize() ) and to run the algorithm
+ for these smaller parts. The disadvantage of having no interpolation
+ at the borders is for most use cases irrelevant.
+
+ The smoothed curve consists of a subset of the points that defined the
+ original curve.
+
+ In opposite to QwtSplineCurveFitter the Douglas and Peucker algorithm reduces
+ the number of points. By adjusting the tolerance parameter according to the
+ axis scales QwtSplineCurveFitter can be used to implement different
+ level of details to speed up painting of curves of many points.
+*/
+class QWT_EXPORT QwtWeedingCurveFitter: public QwtCurveFitter
+{
+public:
+ QwtWeedingCurveFitter( double tolerance = 1.0 );
+ virtual ~QwtWeedingCurveFitter();
+
+ void setTolerance( double );
+ double tolerance() const;
+
+ void setChunkSize( uint );
+ uint chunkSize() const;
+
+ virtual QPolygonF fitCurve( const QPolygonF & ) const;
+
+private:
+ virtual QPolygonF simplify( const QPolygonF & ) const;
+
+ class Line;
class PrivateData;
PrivateData *d_data;
diff --git a/libs/qwt/qwt_date.cpp b/libs/qwt/qwt_date.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0cf5ca0d2aadbe99960d081525d936d1c393cd2b
--- /dev/null
+++ b/libs/qwt/qwt_date.cpp
@@ -0,0 +1,654 @@
+#include "qwt_date.h"
+#include
+#include
+#include
+#include
+#include
+
+#if QT_VERSION >= 0x050000
+
+typedef qint64 QwtJulianDay;
+static const QwtJulianDay minJulianDayD = Q_INT64_C( -784350574879 );
+static const QwtJulianDay maxJulianDayD = Q_INT64_C( 784354017364 );
+
+#else
+
+// QDate stores the Julian day as unsigned int, but
+// but it is QDate::fromJulianDay( int ). That's why
+// we have the range [ 1, INT_MAX ]
+typedef int QwtJulianDay;
+static const QwtJulianDay minJulianDayD = 1;
+static const QwtJulianDay maxJulianDayD = std::numeric_limits::max();
+
+#endif
+
+static inline Qt::DayOfWeek qwtFirstDayOfWeek()
+{
+#if QT_VERSION >= 0x040800
+ return QLocale().firstDayOfWeek();
+#else
+
+ switch( QLocale().country() )
+ {
+ case QLocale::Maldives:
+ return Qt::Friday;
+
+ case QLocale::Afghanistan:
+ case QLocale::Algeria:
+ case QLocale::Bahrain:
+ case QLocale::Djibouti:
+ case QLocale::Egypt:
+ case QLocale::Eritrea:
+ case QLocale::Ethiopia:
+ case QLocale::Iran:
+ case QLocale::Iraq:
+ case QLocale::Jordan:
+ case QLocale::Kenya:
+ case QLocale::Kuwait:
+ case QLocale::LibyanArabJamahiriya:
+ case QLocale::Morocco:
+ case QLocale::Oman:
+ case QLocale::Qatar:
+ case QLocale::SaudiArabia:
+ case QLocale::Somalia:
+ case QLocale::Sudan:
+ case QLocale::Tunisia:
+ case QLocale::Yemen:
+ return Qt::Saturday;
+
+ case QLocale::AmericanSamoa:
+ case QLocale::Argentina:
+ case QLocale::Azerbaijan:
+ case QLocale::Botswana:
+ case QLocale::Canada:
+ case QLocale::China:
+ case QLocale::FaroeIslands:
+ case QLocale::Georgia:
+ case QLocale::Greenland:
+ case QLocale::Guam:
+ case QLocale::HongKong:
+ case QLocale::Iceland:
+ case QLocale::India:
+ case QLocale::Ireland:
+ case QLocale::Israel:
+ case QLocale::Jamaica:
+ case QLocale::Japan:
+ case QLocale::Kyrgyzstan:
+ case QLocale::Lao:
+ case QLocale::Malta:
+ case QLocale::MarshallIslands:
+ case QLocale::Macau:
+ case QLocale::Mongolia:
+ case QLocale::NewZealand:
+ case QLocale::NorthernMarianaIslands:
+ case QLocale::Pakistan:
+ case QLocale::Philippines:
+ case QLocale::RepublicOfKorea:
+ case QLocale::Singapore:
+ case QLocale::SyrianArabRepublic:
+ case QLocale::Taiwan:
+ case QLocale::Thailand:
+ case QLocale::TrinidadAndTobago:
+ case QLocale::UnitedStates:
+ case QLocale::UnitedStatesMinorOutlyingIslands:
+ case QLocale::USVirginIslands:
+ case QLocale::Uzbekistan:
+ case QLocale::Zimbabwe:
+ return Qt::Sunday;
+
+ default:
+ return Qt::Monday;
+ }
+#endif
+}
+
+static inline void qwtFloorTime(
+ QwtDate::IntervalType intervalType, QDateTime &dt )
+{
+ // when dt is inside the special hour where DST is ending
+ // an hour is no unique. Therefore we have to
+ // use UTC time.
+
+ const Qt::TimeSpec timeSpec = dt.timeSpec();
+
+ if ( timeSpec == Qt::LocalTime )
+ dt = dt.toTimeSpec( Qt::UTC );
+
+ const QTime t = dt.time();
+ switch( intervalType )
+ {
+ case QwtDate::Second:
+ {
+ dt.setTime( QTime( t.hour(), t.minute(), t.second() ) );
+ break;
+ }
+ case QwtDate::Minute:
+ {
+ dt.setTime( QTime( t.hour(), t.minute(), 0 ) );
+ break;
+ }
+ case QwtDate::Hour:
+ {
+ dt.setTime( QTime( t.hour(), 0, 0 ) );
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ( timeSpec == Qt::LocalTime )
+ dt = dt.toTimeSpec( Qt::LocalTime );
+}
+
+static inline QDateTime qwtToTimeSpec(
+ const QDateTime &dt, Qt::TimeSpec spec )
+{
+ if ( dt.timeSpec() == spec )
+ return dt;
+
+ const qint64 jd = dt.date().toJulianDay();
+ if ( jd < 0 || jd >= INT_MAX )
+ {
+ // the conversion between local time and UTC
+ // is internally limited. To avoid
+ // overflows we simply ignore the difference
+ // for those dates
+
+ QDateTime dt2 = dt;
+ dt2.setTimeSpec( spec );
+ return dt2;
+ }
+
+ return dt.toTimeSpec( spec );
+}
+
+static inline double qwtToJulianDay( int year, int month, int day )
+{
+ // code from QDate but using doubles to avoid overflows
+ // for large values
+
+ const int m1 = ( month - 14 ) / 12;
+ const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12;
+ const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 );
+
+ return ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2
+ - ::floor( ( 3 * y1 ) / 4 ) + day - 32075;
+}
+
+static inline qint64 qwtFloorDiv64( qint64 a, int b )
+{
+ if ( a < 0 )
+ a -= b - 1;
+
+ return a / b;
+}
+
+static inline qint64 qwtFloorDiv( int a, int b )
+{
+ if ( a < 0 )
+ a -= b - 1;
+
+ return a / b;
+}
+
+static inline QDate qwtToDate( int year, int month = 1, int day = 1 )
+{
+#if QT_VERSION >= 0x050000
+ return QDate( year, month, day );
+#else
+ if ( year > 100000 )
+ {
+ // code from QDate but using doubles to avoid overflows
+ // for large values
+
+ const int m1 = ( month - 14 ) / 12;
+ const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12;
+ const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 );
+
+ const double jd = ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2
+ - ::floor( ( 3 * y1 ) / 4 ) + day - 32075;
+
+ if ( jd > maxJulianDayD )
+ {
+ qWarning() << "qwtToDate: overflow";
+ return QDate();
+ }
+
+ return QDate::fromJulianDay( static_cast( jd ) );
+ }
+ else
+ {
+ return QDate( year, month, day );
+ }
+#endif
+}
+
+/*!
+ Translate from double to QDateTime
+
+ \param value Number of milliseconds since the epoch,
+ 1970-01-01T00:00:00 UTC
+ \param timeSpec Time specification
+ \return Datetime value
+
+ \sa toDouble(), QDateTime::setMSecsSinceEpoch()
+ \note The return datetime for Qt::OffsetFromUTC will be Qt::UTC
+ */
+QDateTime QwtDate::toDateTime( double value, Qt::TimeSpec timeSpec )
+{
+ const int msecsPerDay = 86400000;
+
+ const double days = static_cast( ::floor( value / msecsPerDay ) );
+
+ const double jd = QwtDate::JulianDayForEpoch + days;
+ if ( ( jd > maxJulianDayD ) || ( jd < minJulianDayD ) )
+ {
+ qWarning() << "QwtDate::toDateTime: overflow";
+ return QDateTime();
+ }
+
+ const QDate d = QDate::fromJulianDay( static_cast( jd ) );
+
+ const int msecs = static_cast( value - days * msecsPerDay );
+
+ static const QTime timeNull( 0, 0, 0, 0 );
+
+ QDateTime dt( d, timeNull.addMSecs( msecs ), Qt::UTC );
+
+ if ( timeSpec == Qt::LocalTime )
+ dt = qwtToTimeSpec( dt, timeSpec );
+
+ return dt;
+}
+
+/*!
+ Translate from QDateTime to double
+
+ \param dateTime Datetime value
+ \return Number of milliseconds since 1970-01-01T00:00:00 UTC has passed.
+
+ \sa toDateTime(), QDateTime::toMSecsSinceEpoch()
+ \warning For values very far below or above 1970-01-01 UTC rounding errors
+ will happen due to the limited significance of a double.
+ */
+double QwtDate::toDouble( const QDateTime &dateTime )
+{
+ const int msecsPerDay = 86400000;
+
+ const QDateTime dt = qwtToTimeSpec( dateTime, Qt::UTC );
+
+ const double days = dt.date().toJulianDay() - QwtDate::JulianDayForEpoch;
+
+ const QTime time = dt.time();
+ const double secs = 3600.0 * time.hour() +
+ 60.0 * time.minute() + time.second();
+
+ return days * msecsPerDay + time.msec() + 1000.0 * secs;
+}
+
+/*!
+ Ceil a datetime according the interval type
+
+ \param dateTime Datetime value
+ \param intervalType Interval type, how to ceil.
+ F.e. when intervalType = QwtDate::Months, the result
+ will be ceiled to the next beginning of a month
+ \return Ceiled datetime
+ \sa floor()
+ */
+QDateTime QwtDate::ceil( const QDateTime &dateTime, IntervalType intervalType )
+{
+ if ( dateTime.date() >= QwtDate::maxDate() )
+ return dateTime;
+
+ QDateTime dt = dateTime;
+
+ switch ( intervalType )
+ {
+ case QwtDate::Millisecond:
+ {
+ break;
+ }
+ case QwtDate::Second:
+ {
+ qwtFloorTime( QwtDate::Second, dt );
+ if ( dt < dateTime )
+ dt.addSecs( 1 );
+
+ break;
+ }
+ case QwtDate::Minute:
+ {
+ qwtFloorTime( QwtDate::Minute, dt );
+ if ( dt < dateTime )
+ dt.addSecs( 60 );
+
+ break;
+ }
+ case QwtDate::Hour:
+ {
+ qwtFloorTime( QwtDate::Hour, dt );
+ if ( dt < dateTime )
+ dt.addSecs( 3600 );
+
+ break;
+ }
+ case QwtDate::Day:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+ if ( dt < dateTime )
+ dt = dt.addDays( 1 );
+
+ break;
+ }
+ case QwtDate::Week:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+ if ( dt < dateTime )
+ dt = dt.addDays( 1 );
+
+ int days = qwtFirstDayOfWeek() - dt.date().dayOfWeek();
+ if ( days < 0 )
+ days += 7;
+
+ dt = dt.addDays( days );
+
+ break;
+ }
+ case QwtDate::Month:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+ dt.setDate( qwtToDate( dateTime.date().year(),
+ dateTime.date().month() ) );
+
+ if ( dt < dateTime )
+ dt.addMonths( 1 );
+
+ break;
+ }
+ case QwtDate::Year:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+
+ const QDate d = dateTime.date();
+
+ int year = d.year();
+ if ( d.month() > 1 || d.day() > 1 || !dateTime.time().isNull() )
+ year++;
+
+ if ( year == 0 )
+ year++; // there is no year 0
+
+ dt.setDate( qwtToDate( year ) );
+ break;
+ }
+ }
+
+ return dt;
+}
+
+/*!
+ Floor a datetime according the interval type
+
+ \param dateTime Datetime value
+ \param intervalType Interval type, how to ceil.
+ F.e. when intervalType = QwtDate::Months,
+ the result will be ceiled to the next
+ beginning of a month
+ \return Floored datetime
+ \sa floor()
+ */
+QDateTime QwtDate::floor( const QDateTime &dateTime,
+ IntervalType intervalType )
+{
+ if ( dateTime.date() <= QwtDate::minDate() )
+ return dateTime;
+
+ QDateTime dt = dateTime;
+
+ switch ( intervalType )
+ {
+ case QwtDate::Millisecond:
+ {
+ break;
+ }
+ case QwtDate::Second:
+ case QwtDate::Minute:
+ case QwtDate::Hour:
+ {
+ qwtFloorTime( intervalType, dt );
+ break;
+ }
+ case QwtDate::Day:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+ break;
+ }
+ case QwtDate::Week:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+
+ int days = dt.date().dayOfWeek() - qwtFirstDayOfWeek();
+ if ( days < 0 )
+ days += 7;
+
+ dt = dt.addDays( -days );
+
+ break;
+ }
+ case QwtDate::Month:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+
+ const QDate date = qwtToDate( dt.date().year(),
+ dt.date().month() );
+ dt.setDate( date );
+
+ break;
+ }
+ case QwtDate::Year:
+ {
+ dt.setTime( QTime( 0, 0 ) );
+
+ const QDate date = qwtToDate( dt.date().year() );
+ dt.setDate( date );
+
+ break;
+ }
+ }
+
+ return dt;
+}
+
+/*!
+ Minimum for the supported date range
+
+ The range of valid dates depends on how QDate stores the
+ Julian day internally.
+
+ - For Qt4 it is "Tue Jan 2 -4713"
+ - For Qt5 it is "Thu Jan 1 -2147483648"
+
+ \return minimum of the date range
+ \sa maxDate()
+ */
+QDate QwtDate::minDate()
+{
+ static QDate date;
+ if ( !date.isValid() )
+ date = QDate::fromJulianDay( minJulianDayD );
+
+ return date;
+}
+
+/*!
+ Maximum for the supported date range
+
+ The range of valid dates depends on how QDate stores the
+ Julian day internally.
+
+ - For Qt4 it is "Tue Jun 3 5874898"
+ - For Qt5 it is "Tue Dec 31 2147483647"
+
+ \return maximum of the date range
+ \sa minDate()
+ \note The maximum differs between Qt4 and Qt5
+ */
+QDate QwtDate::maxDate()
+{
+ static QDate date;
+ if ( !date.isValid() )
+ date = QDate::fromJulianDay( maxJulianDayD );
+
+ return date;
+}
+
+/*!
+ \brief Date of the first day of the first week for a year
+
+ The first day of a week depends on the current locale
+ ( QLocale::firstDayOfWeek() ).
+
+ \param year Year
+ \param type Option how to identify the first week
+ \return First day of week 0
+
+ \sa QLocale::firstDayOfWeek(), weekNumber()
+ */
+QDate QwtDate::dateOfWeek0( int year, Week0Type type )
+{
+ const Qt::DayOfWeek firstDayOfWeek = qwtFirstDayOfWeek();
+
+ QDate dt0( year, 1, 1 );
+
+ // floor to the first day of the week
+ int days = dt0.dayOfWeek() - firstDayOfWeek;
+ if ( days < 0 )
+ days += 7;
+
+ dt0 = dt0.addDays( -days );
+
+ if ( type == QwtDate::FirstThursday )
+ {
+ // according to ISO 8601 the first week is defined
+ // by the first thursday.
+
+ int d = Qt::Thursday - firstDayOfWeek;
+ if ( d < 0 )
+ d += 7;
+
+ if ( dt0.addDays( d ).year() < year )
+ dt0 = dt0.addDays( 7 );
+ }
+
+ return dt0;
+}
+
+/*!
+ Find the week number of a date
+
+ - QwtDate::FirstThursday\n
+ Corresponding to ISO 8601 ( see QDate::weekNumber() ).
+
+ - QwtDate::FirstDay\n
+ Number of weeks that have begun since dateOfWeek0().
+
+ \param date Date
+ \param type Option how to identify the first week
+
+ \return Week number, starting with 1
+ */
+int QwtDate::weekNumber( const QDate &date, Week0Type type )
+{
+ int weekNo;
+
+ if ( type == QwtDate::FirstDay )
+ {
+ const QDate day0 = dateOfWeek0( date.year(), type );
+ weekNo = day0.daysTo( date ) / 7 + 1;
+ }
+ else
+ {
+ weekNo = date.weekNumber();
+ }
+
+ return weekNo;
+}
+
+/*!
+ Offset in seconds from Coordinated Universal Time
+
+ The offset depends on the time specification of dateTime:
+
+ - Qt::UTC
+ 0, dateTime has no offset
+ - Qt::OffsetFromUTC
+ returns dateTime.utcOffset()
+ - Qt::LocalTime:
+ number of seconds from the UTC
+
+ For Qt::LocalTime the offset depends on the timezone and
+ daylight savings.
+
+ \param dateTime Datetime value
+ \return Offset in seconds
+ */
+int QwtDate::utcOffset( const QDateTime &dateTime )
+{
+ int seconds = 0;
+
+ switch( dateTime.timeSpec() )
+ {
+ case Qt::UTC:
+ {
+ break;
+ }
+ case Qt::OffsetFromUTC:
+ {
+ seconds = dateTime.utcOffset();
+ }
+ default:
+ {
+ const QDateTime dt1( dateTime.date(), dateTime.time(), Qt::UTC );
+ seconds = dateTime.secsTo( dt1 );
+ }
+ }
+
+ return seconds;
+}
+
+/*!
+ Translate a datetime into a string
+
+ Beside the format expressions documented in QDateTime::toString()
+ the following expressions are supported:
+
+ - w\n
+ week number: ( 1 - 53 )
+ - ww\n
+ week number with a leading zero ( 01 - 53 )
+
+ \param dateTime Datetime value
+ \param format Format string
+ \param week0Type Specification of week 0
+
+ \return Datetime string
+ \sa QDateTime::toString(), weekNumber(), QwtDateScaleDraw
+ */
+QString QwtDate::toString( const QDateTime &dateTime,
+ const QString & format, Week0Type week0Type )
+{
+ QString weekNo;
+ weekNo.setNum( QwtDate::weekNumber( dateTime.date(), week0Type ) );
+
+ QString weekNoWW;
+ if ( weekNo.length() == 1 )
+ weekNoWW += "0";
+ weekNoWW += weekNo;
+
+ QString fmt = format;
+ fmt.replace( "ww", weekNoWW );
+ fmt.replace( "w", weekNo );
+
+ return dateTime.toString( fmt );
+}
diff --git a/libs/qwt/qwt_date.h b/libs/qwt/qwt_date.h
new file mode 100644
index 0000000000000000000000000000000000000000..30422a1c1c56907f89986b7b79e6e352f8106416
--- /dev/null
+++ b/libs/qwt/qwt_date.h
@@ -0,0 +1,128 @@
+/* -*- 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_DATE_H_
+#define _QWT_DATE_H_
+
+#include "qwt_global.h"
+#include
+
+/*!
+ \brief A collection of methods around date/time values
+
+ Qt offers convenient classes for dealing with date/time values,
+ but Qwt uses coordinate systems that are based on doubles.
+ QwtDate offers methods to translate from QDateTime to double and v.v.
+
+ A double is interpreted as the number of milliseconds since
+ 1970-01-01T00:00:00 Universal Coordinated Time - also known
+ as "The Epoch".
+
+ While the range of the Julian day in Qt4 is limited to [0, MAX_INT],
+ Qt5 stores it as qint64 offering a huge range of valid dates.
+ As the significance of a double is below this ( assuming a
+ fraction of 52 bits ) the translation is not
+ bijective with rounding errors for dates very far from Epoch.
+ For a resolution of 1 ms those start to happen for dates above the
+ year 144683.
+
+ An axis for a date/time interval is expected to be aligned
+ and divided in time/date units like seconds, minutes, ...
+ QwtDate offers several algorithms that are needed to
+ calculate these axes.
+
+ \sa QwtDateScaleEngine, QwtDateScaleDraw, QDate, QTime
+*/
+class QWT_EXPORT QwtDate
+{
+public:
+ /*!
+ How to identify the first week of year differs between
+ countries.
+ */
+ enum Week0Type
+ {
+ /*!
+ According to ISO 8601 the first week of a year is defined
+ as "the week with the year's first Thursday in it".
+
+ FirstThursday corresponds to the numbering that is
+ implemented in QDate::weekNumber().
+ */
+ FirstThursday,
+
+ /*!
+ "The week with January 1.1 in it."
+
+ In the U.S. this definition is more common than
+ FirstThursday.
+ */
+ FirstDay
+ };
+
+ /*!
+ Classification of an time interval
+
+ Time intervals needs to be classified to decide how to
+ align and divide it.
+ */
+ enum IntervalType
+ {
+ //! The interval is related to milliseconds
+ Millisecond,
+
+ //! The interval is related to seconds
+ Second,
+
+ //! The interval is related to minutes
+ Minute,
+
+ //! The interval is related to hours
+ Hour,
+
+ //! The interval is related to days
+ Day,
+
+ //! The interval is related to weeks
+ Week,
+
+ //! The interval is related to months
+ Month,
+
+ //! The interval is related to years
+ Year
+ };
+
+ enum
+ {
+ //! The Julian day of "The Epoch"
+ JulianDayForEpoch = 2440588
+ };
+
+ static QDate minDate();
+ static QDate maxDate();
+
+ static QDateTime toDateTime( double value,
+ Qt::TimeSpec = Qt::UTC );
+
+ static double toDouble( const QDateTime & );
+
+ static QDateTime ceil( const QDateTime &, IntervalType );
+ static QDateTime floor( const QDateTime &, IntervalType );
+
+ static QDate dateOfWeek0( int year, Week0Type );
+ static int weekNumber( const QDate &, Week0Type );
+
+ static int utcOffset( const QDateTime & );
+
+ static QString toString( const QDateTime &,
+ const QString & format, Week0Type );
+};
+
+#endif
diff --git a/libs/qwt/qwt_date_scale_draw.cpp b/libs/qwt/qwt_date_scale_draw.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cfc6dec0b15609bff25c39e1b159f2a710f5dc1
--- /dev/null
+++ b/libs/qwt/qwt_date_scale_draw.cpp
@@ -0,0 +1,269 @@
+#include "qwt_date_scale_draw.h"
+
+class QwtDateScaleDraw::PrivateData
+{
+public:
+ PrivateData( Qt::TimeSpec spec ):
+ timeSpec( spec ),
+ utcOffset( 0 ),
+ week0Type( QwtDate::FirstThursday )
+ {
+ dateFormats[ QwtDate::Millisecond ] = "hh:mm:ss:zzz\nddd dd MMM yyyy";
+ dateFormats[ QwtDate::Second ] = "hh:mm:ss\nddd dd MMM yyyy";
+ dateFormats[ QwtDate::Minute ] = "hh:mm\nddd dd MMM yyyy";
+ dateFormats[ QwtDate::Hour ] = "hh:mm\nddd dd MMM yyyy";
+ dateFormats[ QwtDate::Day ] = "ddd dd MMM yyyy";
+ dateFormats[ QwtDate::Week ] = "Www yyyy";
+ dateFormats[ QwtDate::Month ] = "MMM yyyy";
+ dateFormats[ QwtDate::Year ] = "yyyy";
+ }
+
+ Qt::TimeSpec timeSpec;
+ int utcOffset;
+ QwtDate::Week0Type week0Type;
+ QString dateFormats[ QwtDate::Year + 1 ];
+};
+
+/*!
+ \brief Constructor
+
+ The default setting is to display tick labels for the
+ given time specification. The first week of a year is defined like
+ for QwtDate::FirstThursday.
+
+ \param timeSpec Time specification
+
+ \sa setTimeSpec(), setWeek0Type()
+ */
+QwtDateScaleDraw::QwtDateScaleDraw( Qt::TimeSpec timeSpec )
+{
+ d_data = new PrivateData( timeSpec );
+}
+
+//! Destructor
+QwtDateScaleDraw::~QwtDateScaleDraw()
+{
+ delete d_data;
+}
+
+/*!
+ Set the time specification used for the tick labels
+
+ \param timeSpec Time specification
+ \sa timeSpec(), setUtcOffset(), toDateTime()
+ */
+void QwtDateScaleDraw::setTimeSpec( Qt::TimeSpec timeSpec )
+{
+ d_data->timeSpec = timeSpec;
+}
+
+/*!
+ \return Time specification used for the tick labels
+ \sa setTimeSpec(), utcOffset(), toDateTime()
+ */
+Qt::TimeSpec QwtDateScaleDraw::timeSpec() const
+{
+ return d_data->timeSpec;
+}
+
+/*!
+ Set the offset in seconds from Coordinated Universal Time
+
+ \param seconds Offset in seconds
+
+ \note The offset has no effect beside for the time specification
+ Qt::OffsetFromUTC.
+
+ \sa QDate::utcOffset(), setTimeSpec(), toDateTime()
+ */
+void QwtDateScaleDraw::setUtcOffset( int seconds )
+{
+ d_data->utcOffset = seconds;
+}
+
+/*!
+ \return Offset in seconds from Coordinated Universal Time
+ \note The offset has no effect beside for the time specification
+ Qt::OffsetFromUTC.
+
+ \sa QDate::setUtcOffset(), setTimeSpec(), toDateTime()
+ */
+int QwtDateScaleDraw::utcOffset() const
+{
+ return d_data->utcOffset;
+}
+
+/*!
+ Sets how to identify the first week of a year.
+
+ \param week0Type Mode how to identify the first week of a year
+
+ \sa week0Type().
+ \note week0Type has no effect beside for intervals classified as
+ QwtDate::Week.
+ */
+void QwtDateScaleDraw::setWeek0Type( QwtDate::Week0Type week0Type )
+{
+ d_data->week0Type = week0Type;
+}
+
+/*!
+ \return Setting how to identify the first week of a year.
+ \sa setWeek0Type()
+ */
+QwtDate::Week0Type QwtDateScaleDraw::week0Type() const
+{
+ return d_data->week0Type;
+}
+
+/*!
+ Set the default format string for an datetime interval type
+
+ \param intervalType Interval type
+ \param format Default format string
+
+ \sa dateFormat(), dateFormatOfDate(), QwtDate::toString()
+ */
+void QwtDateScaleDraw::setDateFormat(
+ QwtDate::IntervalType intervalType, const QString &format )
+{
+ if ( intervalType >= QwtDate::Millisecond &&
+ intervalType <= QwtDate::Year )
+ {
+ d_data->dateFormats[ intervalType ] = format;
+ }
+}
+
+/*!
+ \param intervalType Interval type
+ \return Default format string for an datetime interval type
+ \sa setDateFormat(), dateFormatOfDate()
+ */
+QString QwtDateScaleDraw::dateFormat(
+ QwtDate::IntervalType intervalType ) const
+{
+ if ( intervalType >= QwtDate::Millisecond &&
+ intervalType <= QwtDate::Year )
+ {
+ return d_data->dateFormats[ intervalType ];
+ }
+
+ return QString::null;
+}
+
+/*!
+ Format string for the representation of a datetime
+
+ dateFormatOfDate() is intended to be overloaded for
+ situations, where formats are individual for specific
+ datetime values.
+
+ The default setting ignores dateTime and return
+ the default format for the interval type.
+
+ \param dateTime Datetime value
+ \param intervalType Interval type
+ \return Format string
+
+ \sa setDateFormat(), QwtDate::toString()
+ */
+QString QwtDateScaleDraw::dateFormatOfDate( const QDateTime &dateTime,
+ QwtDate::IntervalType intervalType ) const
+{
+ Q_UNUSED( dateTime )
+
+ if ( intervalType >= QwtDate::Millisecond &&
+ intervalType <= QwtDate::Year )
+ {
+ return d_data->dateFormats[ intervalType ];
+ }
+
+ return d_data->dateFormats[ QwtDate::Second ];
+}
+
+/*!
+ \brief Convert a value into its representing label
+
+ The value is converted to a datetime value using toDateTime()
+ and converted to a plain text using QwtDate::toString().
+
+ \param value Value
+ \return Label string.
+
+ \sa dateFormatOfDate()
+*/
+QwtText QwtDateScaleDraw::label( double value ) const
+{
+ const QDateTime dt = toDateTime( value );
+ const QString fmt = dateFormatOfDate(
+ dt, intervalType( scaleDiv() ) );
+
+ return QwtDate::toString( dt, fmt, d_data->week0Type );
+}
+
+/*!
+ Find the less detailed datetime unit, where no rounding
+ errors happen.
+
+ \param scaleDiv Scale division
+ \return Interval type
+
+ \sa dateFormatOfDate()
+ */
+QwtDate::IntervalType QwtDateScaleDraw::intervalType(
+ const QwtScaleDiv &scaleDiv ) const
+{
+ int intvType = QwtDate::Year;
+
+ bool alignedToWeeks = true;
+
+ const QList ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick );
+ for ( int i = 0; i < ticks.size(); i++ )
+ {
+ const QDateTime dt = toDateTime( ticks[i] );
+ for ( int j = QwtDate::Second; j <= intvType; j++ )
+ {
+ const QDateTime dt0 = QwtDate::floor( dt,
+ static_cast( j ) );
+
+ if ( dt0 != dt )
+ {
+ if ( j == QwtDate::Week )
+ {
+ alignedToWeeks = false;
+ }
+ else
+ {
+ intvType = j - 1;
+ break;
+ }
+ }
+ }
+
+ if ( intvType == QwtDate::Millisecond )
+ break;
+ }
+
+ if ( intvType == QwtDate::Week && !alignedToWeeks )
+ intvType = QwtDate::Day;
+
+ return static_cast( intvType );
+}
+
+/*!
+ Translate a double value into a QDateTime object.
+
+ \return QDateTime object initialized with timeSpec() and utcOffset().
+ \sa timeSpec(), utcOffset(), QwtDate::toDateTime()
+ */
+QDateTime QwtDateScaleDraw::toDateTime( double value ) const
+{
+ QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec );
+ if ( d_data->timeSpec == Qt::OffsetFromUTC )
+ {
+ dt = dt.addSecs( d_data->utcOffset );
+ dt.setUtcOffset( d_data->utcOffset );
+ }
+
+ return dt;
+}
diff --git a/libs/qwt/qwt_date_scale_draw.h b/libs/qwt/qwt_date_scale_draw.h
new file mode 100644
index 0000000000000000000000000000000000000000..92589e890f3fa938323436158343344b126def36
--- /dev/null
+++ b/libs/qwt/qwt_date_scale_draw.h
@@ -0,0 +1,77 @@
+#ifndef _QWT_DATE_SCALE_DRAW_H_
+#define _QWT_DATE_SCALE_DRAW_H_ 1
+
+#include "qwt_global.h"
+#include "qwt_scale_draw.h"
+#include "qwt_date.h"
+
+/*!
+ \brief A class for drawing datetime scales
+
+ QwtDateScaleDraw displays values as datetime labels.
+ The format of the labels depends on the alignment of
+ the major tick labels.
+
+ The default format strings are:
+
+ - Millisecond\n
+ "hh:mm:ss:zzz\nddd dd MMM yyyy"
+ - Second\n
+ "hh:mm:ss\nddd dd MMM yyyy"
+ - Minute\n
+ "hh:mm\nddd dd MMM yyyy"
+ - Hour\n
+ "hh:mm\nddd dd MMM yyyy"
+ - Day\n
+ "ddd dd MMM yyyy"
+ - Week\n
+ "Www yyyy"
+ - Month\n
+ "MMM yyyy"
+ - Year\n
+ "yyyy"
+
+ The format strings can be modified using setDateFormat()
+ or individually for each tick label by overloading dateFormatOfDate(),
+
+ Usually QwtDateScaleDraw is used in combination with
+ QwtDateScaleEngine, that calculates scales for datetime
+ intervals.
+
+ \sa QwtDateScaleEngine, QwtPlot::setAxisScaleDraw()
+*/
+class QWT_EXPORT QwtDateScaleDraw: public QwtScaleDraw
+{
+public:
+ QwtDateScaleDraw( Qt::TimeSpec = Qt::LocalTime );
+ virtual ~QwtDateScaleDraw();
+
+ void setDateFormat( QwtDate::IntervalType, const QString & );
+ QString dateFormat( QwtDate::IntervalType ) const;
+
+ void setTimeSpec( Qt::TimeSpec );
+ Qt::TimeSpec timeSpec() const;
+
+ void setUtcOffset( int seconds );
+ int utcOffset() const;
+
+ void setWeek0Type( QwtDate::Week0Type );
+ QwtDate::Week0Type week0Type() const;
+
+ virtual QwtText label( double ) const;
+
+ QDateTime toDateTime( double ) const;
+
+protected:
+ virtual QwtDate::IntervalType
+ intervalType( const QwtScaleDiv & ) const;
+
+ virtual QString dateFormatOfDate( const QDateTime &,
+ QwtDate::IntervalType ) const;
+
+private:
+ class PrivateData;
+ PrivateData *d_data;
+};
+
+#endif
diff --git a/libs/qwt/qwt_date_scale_engine.cpp b/libs/qwt/qwt_date_scale_engine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85c1f175a5ce50fb063c99ec4f93b824d4ace1bc
--- /dev/null
+++ b/libs/qwt/qwt_date_scale_engine.cpp
@@ -0,0 +1,1300 @@
+#include "qwt_date_scale_engine.h"
+#include "qwt_math.h"
+#include "qwt_transform.h"
+#include
+#include
+
+static inline double qwtMsecsForType( QwtDate::IntervalType type )
+{
+ static const double msecs[] =
+ {
+ 1.0,
+ 1000.0,
+ 60.0 * 1000.0,
+ 3600.0 * 1000.0,
+ 24.0 * 3600.0 * 1000.0,
+ 7.0 * 24.0 * 3600.0 * 1000.0,
+ 30.0 * 24.0 * 3600.0 * 1000.0,
+ 365.0 * 24.0 * 3600.0 * 1000.0,
+ };
+
+ if ( type < 0 || type >= static_cast( sizeof( msecs ) / sizeof( msecs[0] ) ) )
+ return 1.0;
+
+ return msecs[ type ];
+}
+
+static inline int qwtAlignValue(
+ double value, double stepSize, bool up )
+{
+ double d = value / stepSize;
+ d = up ? ::ceil( d ) : ::floor( d );
+
+ return static_cast( d * stepSize );
+}
+
+static double qwtIntervalWidth( const QDateTime &minDate,
+ const QDateTime &maxDate, QwtDate::IntervalType intervalType )
+{
+ switch( intervalType )
+ {
+ case QwtDate::Millisecond:
+ {
+ const double secsTo = minDate.secsTo( maxDate );
+ const double msecs = maxDate.time().msec() -
+ minDate.time().msec();
+
+ return secsTo * 1000 + msecs;
+ }
+ case QwtDate::Second:
+ {
+ return minDate.secsTo( maxDate );
+ }
+ case QwtDate::Minute:
+ {
+ const double secsTo = minDate.secsTo( maxDate );
+ return ::floor( secsTo / 60 );
+ }
+ case QwtDate::Hour:
+ {
+ const double secsTo = minDate.secsTo( maxDate );
+ return ::floor( secsTo / 3600 );
+ }
+ case QwtDate::Day:
+ {
+ return minDate.daysTo( maxDate );
+ }
+ case QwtDate::Week:
+ {
+ return ::floor( minDate.daysTo( maxDate ) / 7.0 );
+ }
+ case QwtDate::Month:
+ {
+ const double years =
+ double( maxDate.date().year() ) - minDate.date().year();
+
+ int months = maxDate.date().month() - minDate.date().month();
+ if ( maxDate.date().day() < minDate.date().day() )
+ months--;
+
+ return years * 12 + months;
+ }
+ case QwtDate::Year:
+ {
+ double years =
+ double( maxDate.date().year() ) - minDate.date().year();
+
+ if ( maxDate.date().month() < minDate.date().month() )
+ years -= 1.0;
+
+ return years;
+ }
+ }
+
+ return 0.0;
+}
+
+static double qwtRoundedIntervalWidth(
+ const QDateTime &minDate, const QDateTime &maxDate,
+ QwtDate::IntervalType intervalType )
+{
+ const QDateTime minD = QwtDate::floor( minDate, intervalType );
+ const QDateTime maxD = QwtDate::ceil( maxDate, intervalType );
+
+ return qwtIntervalWidth( minD, maxD, intervalType );
+}
+
+static inline int qwtStepCount( int intervalSize, int maxSteps,
+ const int limits[], size_t numLimits )
+{
+ for ( uint i = 0; i < numLimits; i++ )
+ {
+ const int numSteps = intervalSize / limits[ i ];
+
+ if ( numSteps > 1 && numSteps <= maxSteps &&
+ numSteps * limits[ i ] == intervalSize )
+ {
+ return numSteps;
+ }
+ }
+
+ return 0;
+}
+
+static int qwtStepSize( int intervalSize, int maxSteps, uint base )
+{
+ if ( maxSteps <= 0 )
+ return 0;
+
+ if ( maxSteps > 2 )
+ {
+ for ( int numSteps = maxSteps; numSteps > 1; numSteps-- )
+ {
+ const double stepSize = double( intervalSize ) / numSteps;
+
+ const double p = ::floor( ::log( stepSize ) / ::log( double( base ) ) );
+ const double fraction = qPow( base, p );
+
+ for ( uint n = base; n >= 1; n /= 2 )
+ {
+ if ( qFuzzyCompare( stepSize, n * fraction ) )
+ return qRound( stepSize );
+
+ if ( n == 3 && ( base % 2 ) == 0 )
+ {
+ if ( qFuzzyCompare( stepSize, 2 * fraction ) )
+ return qRound( stepSize );
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int qwtDivideInterval( double intervalSize, int numSteps,
+ const int limits[], size_t numLimits )
+{
+ const int v = qCeil( intervalSize / double( numSteps ) );
+
+ for ( uint i = 0; i < numLimits - 1; i++ )
+ {
+ if ( v <= limits[i] )
+ return limits[i];
+ }
+
+ return limits[ numLimits - 1 ];
+}
+
+static double qwtDivideScale( double intervalSize, int numSteps,
+ QwtDate::IntervalType intervalType )
+{
+ if ( intervalType != QwtDate::Day )
+ {
+ if ( ( intervalSize > numSteps ) &&
+ ( intervalSize <= 2 * numSteps ) )
+ {
+ return 2.0;
+ }
+ }
+
+ double stepSize;
+
+ switch( intervalType )
+ {
+ case QwtDate::Second:
+ case QwtDate::Minute:
+ {
+ static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 };
+
+ stepSize = qwtDivideInterval( intervalSize, numSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ break;
+ }
+ case QwtDate::Hour:
+ {
+ static int limits[] = { 1, 2, 3, 4, 6, 12, 24 };
+
+ stepSize = qwtDivideInterval( intervalSize, numSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ break;
+ }
+ case QwtDate::Day:
+ {
+ const double v = intervalSize / double( numSteps );
+ if ( v <= 5.0 )
+ stepSize = qCeil( v );
+ else
+ stepSize = qCeil( v / 7 ) * 7;
+
+ break;
+ }
+ case QwtDate::Week:
+ {
+ static int limits[] = { 1, 2, 4, 8, 12, 26, 52 };
+
+ stepSize = qwtDivideInterval( intervalSize, numSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ break;
+ }
+ case QwtDate::Month:
+ {
+ static int limits[] = { 1, 2, 3, 4, 6, 12 };
+
+ stepSize = qwtDivideInterval( intervalSize, numSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ break;
+ }
+ case QwtDate::Year:
+ case QwtDate::Millisecond:
+ default:
+ {
+ stepSize = QwtScaleArithmetic::divideInterval(
+ intervalSize, numSteps, 10 );
+ }
+ }
+
+ return stepSize;
+}
+
+static double qwtDivideMajorStep( double stepSize, int maxMinSteps,
+ QwtDate::IntervalType intervalType )
+{
+ double minStepSize = 0.0;
+
+ switch( intervalType )
+ {
+ case QwtDate::Second:
+ {
+ minStepSize = qwtStepSize( stepSize, maxMinSteps, 10 );
+ if ( minStepSize == 0.0 )
+ minStepSize = 0.5 * stepSize;
+
+ break;
+ }
+ case QwtDate::Minute:
+ {
+ static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 };
+
+ int numSteps;
+
+ if ( stepSize > maxMinSteps )
+ {
+ numSteps = qwtStepCount( stepSize, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ }
+ else
+ {
+ numSteps = qwtStepCount( stepSize * 60, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+ }
+
+ if ( numSteps > 0 )
+ minStepSize = double( stepSize ) / numSteps;
+
+ break;
+ }
+ case QwtDate::Hour:
+ {
+ int numSteps = 0;
+
+ if ( stepSize > maxMinSteps )
+ {
+ static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 };
+
+ numSteps = qwtStepCount( stepSize, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+ }
+ else
+ {
+ static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 };
+
+ numSteps = qwtStepCount( stepSize * 60, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+ }
+
+ if ( numSteps > 0 )
+ minStepSize = double( stepSize ) / numSteps;
+
+ break;
+ }
+ case QwtDate::Day:
+ {
+ int numSteps = 0;
+
+ if ( stepSize > maxMinSteps )
+ {
+ static int limits[] = { 1, 2, 3, 7, 14, 28 };
+
+ numSteps = qwtStepCount( stepSize, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+ }
+ else
+ {
+ static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 };
+
+ numSteps = qwtStepCount( stepSize * 24, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+ }
+
+ if ( numSteps > 0 )
+ minStepSize = double( stepSize ) / numSteps;
+
+ break;
+ }
+ case QwtDate::Week:
+ {
+ const int daysInStep = stepSize * 7;
+
+ if ( maxMinSteps >= daysInStep )
+ {
+ // we want to have one tick per day
+ minStepSize = 1.0 / 7.0;
+ }
+ else
+ {
+ // when the stepSize is more than a week we want to
+ // have a tick for each week
+
+ const int stepSizeInWeeks = stepSize;
+
+ if ( stepSizeInWeeks <= maxMinSteps )
+ {
+ minStepSize = 1;
+ }
+ else
+ {
+ minStepSize = QwtScaleArithmetic::divideInterval(
+ stepSizeInWeeks, maxMinSteps, 10 );
+ }
+ }
+ break;
+ }
+ case QwtDate::Month:
+ {
+ // fractions of months doesn't make any sense
+
+ if ( stepSize < maxMinSteps )
+ maxMinSteps = static_cast( stepSize );
+
+ static int limits[] = { 1, 2, 3, 4, 6, 12 };
+
+ int numSteps = qwtStepCount( stepSize, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ if ( numSteps > 0 )
+ minStepSize = double( stepSize ) / numSteps;
+
+ break;
+ }
+ case QwtDate::Year:
+ {
+ if ( stepSize >= maxMinSteps )
+ {
+ minStepSize = QwtScaleArithmetic::divideInterval(
+ stepSize, maxMinSteps, 10 );
+ }
+ else
+ {
+ // something in months
+
+ static int limits[] = { 1, 2, 3, 4, 6, 12 };
+
+ int numSteps = qwtStepCount( 12 * stepSize, maxMinSteps,
+ limits, sizeof( limits ) / sizeof( int ) );
+
+ if ( numSteps > 0 )
+ minStepSize = double( stepSize ) / numSteps;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ( intervalType != QwtDate::Month
+ && minStepSize == 0.0 )
+ {
+ minStepSize = 0.5 * stepSize;
+ }
+
+ return minStepSize;
+}
+
+static QList qwtDstTicks( const QDateTime &dateTime,
+ int secondsMajor, int secondsMinor )
+{
+ if ( secondsMinor <= 0 )
+ QList();
+
+ QDateTime minDate = dateTime.addSecs( -secondsMajor );
+ minDate = QwtDate::floor( minDate, QwtDate::Hour );
+
+ const double utcOffset = QwtDate::utcOffset( dateTime );
+
+ // find the hours where daylight saving time happens
+
+ double dstMin = QwtDate::toDouble( minDate );
+ while ( minDate < dateTime &&
+ QwtDate::utcOffset( minDate ) != utcOffset )
+ {
+ minDate = minDate.addSecs( 3600 );
+ dstMin += 3600 * 1000.0;
+ }
+
+ QList ticks;
+ for ( int i = 0; i < 3600; i += secondsMinor )
+ ticks += dstMin + i * 1000.0;
+
+ return ticks;
+}
+
+static QwtScaleDiv qwtDivideToSeconds(
+ const QDateTime &minDate, const QDateTime &maxDate,
+ double stepSize, int maxMinSteps,
+ QwtDate::IntervalType intervalType )
+{
+ // calculate the min step size
+ double minStepSize = 0;
+
+ if ( maxMinSteps > 1 )
+ {
+ minStepSize = qwtDivideMajorStep( stepSize,
+ maxMinSteps, intervalType );
+ }
+
+ bool daylightSaving = false;
+ if ( minDate.timeSpec() == Qt::LocalTime )
+ {
+ daylightSaving = intervalType > QwtDate::Hour;
+ if ( intervalType == QwtDate::Hour )
+ {
+ daylightSaving = stepSize > 1;
+ }
+ }
+
+ const double s = qwtMsecsForType( intervalType ) / 1000;
+ const int secondsMajor = static_cast( stepSize * s );
+ const double secondsMinor = minStepSize * s;
+
+ // UTC excludes daylight savings. So from the difference
+ // of a date and its UTC counterpart we can find out
+ // the daylight saving hours
+
+ const double utcOffset = QwtDate::utcOffset( minDate );
+ double dstOff = 0;
+
+ QList majorTicks;
+ QList mediumTicks;
+ QList minorTicks;
+
+ for ( QDateTime dt = minDate; dt <= maxDate;
+ dt = dt.addSecs( secondsMajor ) )
+ {
+ if ( !dt.isValid() )
+ break;
+
+ double majorValue = QwtDate::toDouble( dt );
+
+ if ( daylightSaving )
+ {
+ const double offset = utcOffset - QwtDate::utcOffset( dt );
+ majorValue += offset * 1000.0;
+
+ if ( offset > dstOff )
+ {
+ // we add some minor ticks for the DST hour,
+ // otherwise the ticks will be unaligned: 0, 2, 3, 5 ...
+ minorTicks += qwtDstTicks(
+ dt, secondsMajor, qRound( secondsMinor ) );
+ }
+
+ dstOff = offset;
+ }
+
+ if ( majorTicks.isEmpty() || majorTicks.last() != majorValue )
+ majorTicks += majorValue;
+
+ if ( secondsMinor > 0.0 )
+ {
+ const int numMinorSteps = qFloor( secondsMajor / secondsMinor );
+
+ for ( int i = 1; i < numMinorSteps; i++ )
+ {
+ const QDateTime mt = dt.addMSecs(
+ qRound64( i * secondsMinor * 1000 ) );
+
+ double minorValue = QwtDate::toDouble( mt );
+ if ( daylightSaving )
+ {
+ const double offset = utcOffset - QwtDate::utcOffset( mt );
+ minorValue += offset * 1000.0;
+ }
+
+ if ( minorTicks.isEmpty() || minorTicks.last() != minorValue )
+ {
+ const bool isMedium = ( numMinorSteps % 2 == 0 )
+ && ( i != 1 ) && ( i == numMinorSteps / 2 );
+
+ if ( isMedium )
+ mediumTicks += minorValue;
+ else
+ minorTicks += minorValue;
+ }
+ }
+ }
+ }
+
+ QwtScaleDiv scaleDiv;
+
+ scaleDiv.setInterval( QwtDate::toDouble( minDate ),
+ QwtDate::toDouble( maxDate ) );
+
+ scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks );
+ scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks );
+ scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks );
+
+ return scaleDiv;
+}
+
+static QwtScaleDiv qwtDivideToMonths(
+ QDateTime &minDate, const QDateTime &maxDate,
+ double stepSize, int maxMinSteps )
+{
+ // months are intervals with non
+ // equidistant ( in ms ) steps: we have to build the
+ // scale division manually
+
+ int minStepDays = 0;
+ int minStepSize = 0.0;
+
+ if ( maxMinSteps > 1 )
+ {
+ if ( stepSize == 1 )
+ {
+ if ( maxMinSteps >= 30 )
+ minStepDays = 1;
+ else if ( maxMinSteps >= 6 )
+ minStepDays = 5;
+ else if ( maxMinSteps >= 3 )
+ minStepDays = 10;
+
+ minStepDays = 15;
+ }
+ else
+ {
+ minStepSize = qwtDivideMajorStep(
+ stepSize, maxMinSteps, QwtDate::Month );
+ }
+ }
+
+ QList majorTicks;
+ QList mediumTicks;
+ QList minorTicks;
+
+ for ( QDateTime dt = minDate;
+ dt <= maxDate; dt = dt.addMonths( stepSize ) )
+ {
+ if ( !dt.isValid() )
+ break;
+
+ majorTicks += QwtDate::toDouble( dt );
+
+ if ( minStepDays > 0 )
+ {
+ for ( int days = minStepDays;
+ days < 30; days += minStepDays )
+ {
+ const double tick = QwtDate::toDouble( dt.addDays( days ) );
+
+ if ( days == 15 && minStepDays != 15 )
+ mediumTicks += tick;
+ else
+ minorTicks += tick;
+ }
+ }
+ else if ( minStepSize > 0.0 )
+ {
+ const int numMinorSteps = qRound( stepSize / (double) minStepSize );
+
+ for ( int i = 1; i < numMinorSteps; i++ )
+ {
+ const double minorValue =
+ QwtDate::toDouble( dt.addMonths( i * minStepSize ) );
+
+ if ( ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 ) )
+ mediumTicks += minorValue;
+ else
+ minorTicks += minorValue;
+ }
+ }
+ }
+
+ QwtScaleDiv scaleDiv;
+ scaleDiv.setInterval( QwtDate::toDouble( minDate ),
+ QwtDate::toDouble( maxDate ) );
+
+ scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks );
+ scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks );
+ scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks );
+
+ return scaleDiv;
+}
+
+static QwtScaleDiv qwtDivideToYears(
+ const QDateTime &minDate, const QDateTime &maxDate,
+ double stepSize, int maxMinSteps )
+{
+ QList majorTicks;
+ QList mediumTicks;
+ QList minorTicks;
+
+ double minStepSize = 0.0;
+
+ if ( maxMinSteps > 1 )
+ {
+ minStepSize = qwtDivideMajorStep(
+ stepSize, maxMinSteps, QwtDate::Year );
+ }
+
+ int numMinorSteps = 0;
+ if ( minStepSize > 0.0 )
+ numMinorSteps = qFloor( stepSize / minStepSize );
+
+ bool dateBC = minDate.date().year() < -1;
+
+ for ( QDateTime dt = minDate; dt <= maxDate;
+ dt = dt.addYears( stepSize ) )
+ {
+ if ( dateBC && dt.date().year() > 1 )
+ {
+ // there is no year 0 in the Julian calendar
+ dt = dt.addYears( -1 );
+ dateBC = false;
+ }
+
+ if ( !dt.isValid() )
+ break;
+
+ majorTicks += QwtDate::toDouble( dt );
+
+ for ( int i = 1; i < numMinorSteps; i++ )
+ {
+ QDateTime tickDate;
+
+ const double years = qRound( i * minStepSize );
+ if ( years >= INT_MAX / 12 )
+ {
+ tickDate = dt.addYears( years );
+ }
+ else
+ {
+ tickDate = dt.addMonths( qRound( years * 12 ) );
+ }
+
+ const bool isMedium = ( numMinorSteps > 2 ) &&
+ ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 );
+
+ const double minorValue = QwtDate::toDouble( tickDate );
+ if ( isMedium )
+ mediumTicks += minorValue;
+ else
+ minorTicks += minorValue;
+ }
+
+ if ( QwtDate::maxDate().addYears( -stepSize ) < dt.date() )
+ {
+ break;
+ }
+ }
+
+ QwtScaleDiv scaleDiv;
+ scaleDiv.setInterval( QwtDate::toDouble( minDate ),
+ QwtDate::toDouble( maxDate ) );
+
+ scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks );
+ scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks );
+ scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks );
+
+ return scaleDiv;
+}
+
+class QwtDateScaleEngine::PrivateData
+{
+public:
+ PrivateData( Qt::TimeSpec spec ):
+ timeSpec( spec ),
+ utcOffset( 0 ),
+ week0Type( QwtDate::FirstThursday ),
+ maxWeeks( 4 )
+ {
+ }
+
+ Qt::TimeSpec timeSpec;
+ int utcOffset;
+ QwtDate::Week0Type week0Type;
+ int maxWeeks;
+};
+
+
+/*!
+ \brief Constructor
+
+ The engine is initialized to build scales for the
+ given time specification. It classifies intervals > 4 weeks
+ as >= Qt::Month. The first week of a year is defined like
+ for QwtDate::FirstThursday.
+
+ \param timeSpec Time specification
+
+ \sa setTimeSpec(), setMaxWeeks(), setWeek0Type()
+ */
+QwtDateScaleEngine::QwtDateScaleEngine( Qt::TimeSpec timeSpec ):
+ QwtLinearScaleEngine( 10 )
+{
+ d_data = new PrivateData( timeSpec );
+}
+
+//! Destructor
+QwtDateScaleEngine::~QwtDateScaleEngine()
+{
+ delete d_data;
+}
+
+/*!
+ Set the time specification used by the engine
+
+ \param timeSpec Time specification
+ \sa timeSpec(), setUtcOffset(), toDateTime()
+ */
+void QwtDateScaleEngine::setTimeSpec( Qt::TimeSpec timeSpec )
+{
+ d_data->timeSpec = timeSpec;
+}
+
+/*!
+ \return Time specification used by the engine
+ \sa setTimeSpec(), utcOffset(), toDateTime()
+ */
+Qt::TimeSpec QwtDateScaleEngine::timeSpec() const
+{
+ return d_data->timeSpec;
+}
+
+/*!
+ Set the offset in seconds from Coordinated Universal Time
+
+ \param seconds Offset in seconds
+
+ \note The offset has no effect beside for the time specification
+ Qt::OffsetFromUTC.
+
+ \sa QDate::utcOffset(), setTimeSpec(), toDateTime()
+ */
+void QwtDateScaleEngine::setUtcOffset( int seconds )
+{
+ d_data->utcOffset = seconds;
+}
+
+/*!
+ \return Offset in seconds from Coordinated Universal Time
+ \note The offset has no effect beside for the time specification
+ Qt::OffsetFromUTC.
+
+ \sa QDate::setUtcOffset(), setTimeSpec(), toDateTime()
+ */
+int QwtDateScaleEngine::utcOffset() const
+{
+ return d_data->utcOffset;
+}
+
+/*!
+ Sets how to identify the first week of a year.
+
+ \param week0Type Mode how to identify the first week of a year
+
+ \sa week0Type(), setMaxWeeks()
+ \note week0Type has no effect beside for intervals classified as
+ QwtDate::Week.
+ */
+void QwtDateScaleEngine::setWeek0Type( QwtDate::Week0Type week0Type )
+{
+ d_data->week0Type = week0Type;
+}
+
+/*!
+ \return Setting how to identify the first week of a year.
+ \sa setWeek0Type(), maxWeeks()
+ */
+QwtDate::Week0Type QwtDateScaleEngine::week0Type() const
+{
+ return d_data->week0Type;
+}
+
+/*!
+ Set a upper limit for the number of weeks, when an interval
+ can be classified as Qt::Week.
+
+ The default setting is 4 weeks.
+
+ \param weeks Upper limit for the number of weeks
+
+ \note In business charts a year is often devided
+ into weeks [1-52]
+ \sa maxWeeks(), setWeek0Type()
+ */
+void QwtDateScaleEngine::setMaxWeeks( int weeks )
+{
+ d_data->maxWeeks = qMax( weeks, 0 );
+}
+
+/*!
+ \return Upper limit for the number of weeks, when an interval
+ can be classified as Qt::Week.
+ \sa setMaxWeeks(), week0Type()
+ */
+int QwtDateScaleEngine::maxWeeks() const
+{
+ return d_data->maxWeeks;
+}
+
+/*!
+ Classification of a date/time interval division
+
+ \param minDate Minimum ( = earlier ) of the interval
+ \param maxDate Maximum ( = later ) of the interval
+ \param maxSteps Maximum for the number of steps
+
+ \return Interval classification
+ */
+QwtDate::IntervalType QwtDateScaleEngine::intervalType(
+ const QDateTime &minDate, const QDateTime &maxDate,
+ int maxSteps ) const
+{
+ const double jdMin = minDate.date().toJulianDay();
+ const double jdMax = maxDate.date().toJulianDay();
+
+ if ( ( jdMax - jdMin ) / 365 > maxSteps )
+ return QwtDate::Year;
+
+ const int months = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Month );
+ if ( months > maxSteps * 6 )
+ return QwtDate::Year;
+
+ const int days = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Day );
+ const int weeks = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Week );
+
+ if ( weeks > d_data->maxWeeks )
+ {
+ if ( days > 4 * maxSteps * 7 )
+ return QwtDate::Month;
+ }
+
+ if ( days > maxSteps * 7 )
+ return QwtDate::Week;
+
+ const int hours = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Hour );
+ if ( hours > maxSteps * 24 )
+ return QwtDate::Day;
+
+ const int seconds = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Second );
+
+ if ( seconds >= maxSteps * 3600 )
+ return QwtDate::Hour;
+
+ if ( seconds >= maxSteps * 60 )
+ return QwtDate::Minute;
+
+ if ( seconds >= maxSteps )
+ return QwtDate::Second;
+
+ return QwtDate::Millisecond;
+}
+
+/*!
+ Align and divide an interval
+
+ The algorithm aligns and divides the interval into steps.
+
+ Datetime interval divisions are usually not equidistant and the
+ calculated stepSize can only be used as an approximation
+ for the steps calculated by divideScale().
+
+ \param maxNumSteps Max. number of steps
+ \param x1 First limit of the interval (In/Out)
+ \param x2 Second limit of the interval (In/Out)
+ \param stepSize Step size (Out)
+
+ \sa QwtScaleEngine::setAttribute()
+*/
+void QwtDateScaleEngine::autoScale( int maxNumSteps,
+ double &x1, double &x2, double &stepSize ) const
+{
+ stepSize = 0.0;
+
+ QwtInterval interval( x1, x2 );
+ interval = interval.normalized();
+
+ interval.setMinValue( interval.minValue() - lowerMargin() );
+ interval.setMaxValue( interval.maxValue() + upperMargin() );
+
+ if ( testAttribute( QwtScaleEngine::Symmetric ) )
+ interval = interval.symmetrize( reference() );
+
+ if ( testAttribute( QwtScaleEngine::IncludeReference ) )
+ interval = interval.extend( reference() );
+
+ if ( interval.width() == 0.0 )
+ interval = buildInterval( interval.minValue() );
+
+ const QDateTime from = toDateTime( interval.minValue() );
+ const QDateTime to = toDateTime( interval.maxValue() );
+
+ if ( from.isValid() && to.isValid() )
+ {
+ if ( maxNumSteps < 1 )
+ maxNumSteps = 1;
+
+ const QwtDate::IntervalType intvType =
+ intervalType( from, to, maxNumSteps );
+
+ const double width = qwtIntervalWidth( from, to, intvType );
+
+ const double stepWidth = qwtDivideScale( width, maxNumSteps, intvType );
+ if ( stepWidth != 0.0 && !testAttribute( QwtScaleEngine::Floating ) )
+ {
+ const QDateTime d1 = alignDate( from, stepWidth, intvType, false );
+ const QDateTime d2 = alignDate( to, stepWidth, intvType, true );
+
+ interval.setMinValue( QwtDate::toDouble( d1 ) );
+ interval.setMaxValue( QwtDate::toDouble( d2 ) );
+ }
+
+ stepSize = stepWidth * qwtMsecsForType( intvType );
+ }
+
+ x1 = interval.minValue();
+ x2 = interval.maxValue();
+
+ if ( testAttribute( QwtScaleEngine::Inverted ) )
+ {
+ qSwap( x1, x2 );
+ stepSize = -stepSize;
+ }
+}
+
+/*!
+ \brief Calculate a scale division for a date/time interval
+
+ \param x1 First interval limit
+ \param x2 Second interval limit
+ \param maxMajorSteps Maximum for the number of major steps
+ \param maxMinorSteps Maximum number of minor steps
+ \param stepSize Step size. If stepSize == 0, the scaleEngine
+ calculates one.
+ \return Calculated scale division
+*/
+QwtScaleDiv QwtDateScaleEngine::divideScale( double x1, double x2,
+ int maxMajorSteps, int maxMinorSteps, double stepSize ) const
+{
+ if ( maxMajorSteps < 1 )
+ maxMajorSteps = 1;
+
+ const double min = qMin( x1, x2 );
+ const double max = qMax( x1, x2 );
+
+ const QDateTime from = toDateTime( min );
+ const QDateTime to = toDateTime( max );
+
+ if ( from == to )
+ return QwtScaleDiv();
+
+ stepSize = qAbs( stepSize );
+ if ( stepSize > 0.0 )
+ {
+ // as interval types above hours are not equidistant
+ // ( even days might have 23/25 hours because of daylight saving )
+ // the stepSize is used as a hint only
+
+ maxMajorSteps = qCeil( ( max - min ) / stepSize );
+ }
+
+ const QwtDate::IntervalType intvType =
+ intervalType( from, to, maxMajorSteps );
+
+ QwtScaleDiv scaleDiv;
+
+ if ( intvType == QwtDate::Millisecond )
+ {
+ // for milliseconds and below we can use the decimal system
+ scaleDiv = QwtLinearScaleEngine::divideScale( min, max,
+ maxMajorSteps, maxMinorSteps, stepSize );
+ }
+ else
+ {
+ const QDateTime minDate = QwtDate::floor( from, intvType );
+ const QDateTime maxDate = QwtDate::ceil( to, intvType );
+
+ scaleDiv = buildScaleDiv( minDate, maxDate,
+ maxMajorSteps, maxMinorSteps, intvType );
+
+ // scaleDiv has been calculated from an extended interval
+ // adjusted to the step size. We have to shrink it again.
+
+ scaleDiv = scaleDiv.bounded( min, max );
+ }
+
+ if ( x1 > x2 )
+ scaleDiv.invert();
+
+ return scaleDiv;
+}
+
+QwtScaleDiv QwtDateScaleEngine::buildScaleDiv(
+ const QDateTime &minDate, const QDateTime &maxDate,
+ int maxMajorSteps, int maxMinorSteps,
+ QwtDate::IntervalType intervalType ) const
+{
+ // calculate the step size
+ const double stepSize = qwtDivideScale(
+ qwtIntervalWidth( minDate, maxDate, intervalType ),
+ maxMajorSteps, intervalType );
+
+ // align minDate to the step size
+ QDateTime dt0 = alignDate( minDate, stepSize, intervalType, false );
+ if ( !dt0.isValid() )
+ {
+ // the floored date is out of the range of a
+ // QDateTime - we ceil instead.
+ dt0 = alignDate( minDate, stepSize, intervalType, true );
+ }
+
+ QwtScaleDiv scaleDiv;
+
+ if ( intervalType <= QwtDate::Week )
+ {
+ scaleDiv = qwtDivideToSeconds( dt0, maxDate,
+ stepSize, maxMinorSteps, intervalType );
+ }
+ else
+ {
+ if( intervalType == QwtDate::Month )
+ {
+ scaleDiv = qwtDivideToMonths( dt0, maxDate,
+ stepSize, maxMinorSteps );
+ }
+ else if ( intervalType == QwtDate::Year )
+ {
+ scaleDiv = qwtDivideToYears( dt0, maxDate,
+ stepSize, maxMinorSteps );
+ }
+ }
+
+
+ return scaleDiv;
+}
+
+/*!
+ Align a date/time value for a step size
+
+ For Qt::Day alignments there is no "natural day 0" -
+ instead the first day of the year is used to avoid jumping
+ major ticks positions when panning a scale. For other alignments
+ ( f.e according to the first day of the month ) alignDate()
+ has to be overloaded.
+
+ \param dateTime Date/time value
+ \param stepSize Step size
+ \param intervalType Interval type
+ \param up When true dateTime is ceiled - otherwise it is floored
+
+ \return Aligned date/time value
+ */
+QDateTime QwtDateScaleEngine::alignDate(
+ const QDateTime &dateTime, double stepSize,
+ QwtDate::IntervalType intervalType, bool up ) const
+{
+ // what about: (year == 1582 && month == 10 && day > 4 && day < 15) ??
+
+ QDateTime dt = dateTime;
+
+ if ( dateTime.timeSpec() == Qt::OffsetFromUTC )
+ {
+ dt.setUtcOffset( 0 );
+ }
+
+ switch( intervalType )
+ {
+ case QwtDate::Millisecond:
+ {
+ const int ms = qwtAlignValue(
+ dt.time().msec(), stepSize, up ) ;
+
+ dt = QwtDate::floor( dateTime, QwtDate::Second );
+ dt = dt.addMSecs( ms );
+
+ break;
+ }
+ case QwtDate::Second:
+ {
+ int second = dt.time().second();
+ if ( up )
+ {
+ if ( dt.time().msec() > 0 )
+ second++;
+ }
+
+ const int s = qwtAlignValue( second, stepSize, up );
+
+ dt = QwtDate::floor( dt, QwtDate::Minute );
+ dt = dt.addSecs( s );
+
+ break;
+ }
+ case QwtDate::Minute:
+ {
+ int minute = dt.time().minute();
+ if ( up )
+ {
+ if ( dt.time().msec() > 0 || dt.time().second() > 0 )
+ minute++;
+ }
+
+ const int m = qwtAlignValue( minute, stepSize, up );
+
+ dt = QwtDate::floor( dt, QwtDate::Hour );
+ dt = dt.addSecs( m * 60 );
+
+ break;
+ }
+ case QwtDate::Hour:
+ {
+ int hour = dt.time().hour();
+ if ( up )
+ {
+ if ( dt.time().msec() > 0 || dt.time().second() > 0
+ || dt.time().minute() > 0 )
+ {
+ hour++;
+ }
+ }
+ const int h = qwtAlignValue( hour, stepSize, up );
+
+ dt = QwtDate::floor( dt, QwtDate::Day );
+ dt = dt.addSecs( h * 3600 );
+
+ break;
+ }
+ case QwtDate::Day:
+ {
+ // What date do we expect f.e. from an alignment of 5 days ??
+ // Aligning them to the beginning of the year avoids at least
+ // jumping major ticks when panning
+
+ int day = dt.date().dayOfYear();
+ if ( up )
+ {
+ if ( dt.time() > QTime( 0, 0 ) )
+ day++;
+ }
+
+ const int d = qwtAlignValue( day, stepSize, up );
+
+ dt = QwtDate::floor( dt, QwtDate::Year );
+ dt = dt.addDays( d - 1 );
+
+ break;
+ }
+ case QwtDate::Week:
+ {
+ const QDate date = QwtDate::dateOfWeek0(
+ dt.date().year(), d_data->week0Type );
+
+ int numWeeks = date.daysTo( dt.date() ) / 7;
+ if ( up )
+ {
+ if ( dt.time() > QTime( 0, 0 ) ||
+ date.daysTo( dt.date() ) % 7 )
+ {
+ numWeeks++;
+ }
+ }
+
+ const int d = qwtAlignValue( numWeeks, stepSize, up ) * 7;
+
+ dt = QwtDate::floor( dt, QwtDate::Day );
+ dt.setDate( date );
+ dt = dt.addDays( d );
+
+ break;
+ }
+ case QwtDate::Month:
+ {
+ int month = dt.date().month();
+ if ( up )
+ {
+ if ( dt.date().day() > 1 ||
+ dt.time() > QTime( 0, 0 ) )
+ {
+ month++;
+ }
+ }
+
+ const int m = qwtAlignValue( month - 1, stepSize, up );
+
+ dt = QwtDate::floor( dt, QwtDate::Year );
+ dt = dt.addMonths( m );
+
+ break;
+ }
+ case QwtDate::Year:
+ {
+ int year = dateTime.date().year();
+ if ( up )
+ {
+ if ( dateTime.date().dayOfYear() > 1 ||
+ dt.time() > QTime( 0, 0 ) )
+ {
+ year++;
+ }
+ }
+
+ const int y = qwtAlignValue( year, stepSize, up );
+
+ dt = QwtDate::floor( dt, QwtDate::Day );
+ if ( y == 0 )
+ {
+ // there is no year 0 in the Julian calendar
+ dt.setDate( QDate( stepSize, 1, 1 ).addYears( -stepSize ) );
+ }
+ else
+ {
+ dt.setDate( QDate( y, 1, 1 ) );
+ }
+
+ break;
+ }
+ }
+
+ if ( dateTime.timeSpec() == Qt::OffsetFromUTC )
+ {
+ dt.setUtcOffset( dateTime.utcOffset() );
+ }
+
+ return dt;
+}
+
+/*!
+ Translate a double value into a QDateTime object.
+
+ For QDateTime result is bounded by QwtDate::minDate() and QwtDate::maxDate()
+
+ \return QDateTime object initialized with timeSpec() and utcOffset().
+ \sa timeSpec(), utcOffset(), QwtDate::toDateTime()
+ */
+QDateTime QwtDateScaleEngine::toDateTime( double value ) const
+{
+ QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec );
+ if ( !dt.isValid() )
+ {
+ const QDate date = ( value <= 0.0 )
+ ? QwtDate::minDate() : QwtDate::maxDate();
+
+ dt = QDateTime( date, QTime( 0, 0 ), d_data->timeSpec );
+ }
+
+ if ( d_data->timeSpec == Qt::OffsetFromUTC )
+ {
+ dt = dt.addSecs( d_data->utcOffset );
+ dt.setUtcOffset( d_data->utcOffset );
+ }
+
+ return dt;
+}
+
diff --git a/libs/qwt/qwt_date_scale_engine.h b/libs/qwt/qwt_date_scale_engine.h
new file mode 100644
index 0000000000000000000000000000000000000000..db1d0f1342e528c6ef27afe711447a4695220a41
--- /dev/null
+++ b/libs/qwt/qwt_date_scale_engine.h
@@ -0,0 +1,77 @@
+#ifndef _QWT_DATE_SCALE_ENGINE_H_
+#define _QWT_DATE_SCALE_ENGINE_H_ 1
+
+#include "qwt_date.h"
+#include "qwt_scale_engine.h"
+
+/*!
+ \brief A scale engine for date/time values
+
+ QwtDateScaleEngine builds scales from a time intervals.
+ Together with QwtDateScaleDraw it can be used for
+ axes according to date/time values.
+
+ Years, months, weeks, days, hours and minutes are organized
+ in steps with non constant intervals. QwtDateScaleEngine
+ classifies intervals and aligns the boundaries and tick positions
+ according to this classification.
+
+ QwtDateScaleEngine supports representations depending
+ on Qt::TimeSpec specifications. The valid range for scales
+ is limited by the range of QDateTime, that differs
+ between Qt4 and Qt5.
+
+ Datetime values are expected as the number of milliseconds since
+ 1970-01-01T00:00:00 Universal Coordinated Time - also known
+ as "The Epoch", that can be converted to QDateTime using
+ QwtDate::toDateTime().
+
+ \sa QwtDate, QwtPlot::setAxisScaleEngine(),
+ QwtAbstractScale::setScaleEngine()
+*/
+class QWT_EXPORT QwtDateScaleEngine: public QwtLinearScaleEngine
+{
+public:
+ QwtDateScaleEngine( Qt::TimeSpec = Qt::LocalTime );
+ virtual ~QwtDateScaleEngine();
+
+ void setTimeSpec( Qt::TimeSpec );
+ Qt::TimeSpec timeSpec() const;
+
+ void setUtcOffset( int seconds );
+ int utcOffset() const;
+
+ void setWeek0Type( QwtDate::Week0Type );
+ QwtDate::Week0Type week0Type() const;
+
+ void setMaxWeeks( int );
+ int maxWeeks() const;
+
+ virtual void autoScale( int maxNumSteps,
+ double &x1, double &x2, double &stepSize ) const;
+
+ virtual QwtScaleDiv divideScale(
+ double x1, double x2,
+ int maxMajorSteps, int maxMinorSteps,
+ double stepSize = 0.0 ) const;
+
+ virtual QwtDate::IntervalType intervalType(
+ const QDateTime &, const QDateTime &, int maxSteps ) const;
+
+ QDateTime toDateTime( double ) const;
+
+protected:
+ virtual QDateTime alignDate( const QDateTime &, double stepSize,
+ QwtDate::IntervalType, bool up ) const;
+
+private:
+ QwtScaleDiv buildScaleDiv( const QDateTime &, const QDateTime &,
+ int maxMajorSteps, int maxMinorSteps,
+ QwtDate::IntervalType ) const;
+
+private:
+ class PrivateData;
+ PrivateData *d_data;
+};
+
+#endif
diff --git a/libs/qwt/qwt_dial.cpp b/libs/qwt/qwt_dial.cpp
index 35f77b022b7cb6dd6e4f1ffa8f04ba00f53acce5..1440eb14a40ca053683efa3417d764d8c051e54d 100644
--- a/libs/qwt/qwt_dial.cpp
+++ b/libs/qwt/qwt_dial.cpp
@@ -7,45 +7,93 @@
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
-#include
-#include
-#if QT_VERSION >= 0x040000
-#include
-#include
-#endif
-#include
-#include
+#include "qwt_dial.h"
+#include "qwt_dial_needle.h"
#include "qwt_math.h"
#include "qwt_scale_engine.h"
#include "qwt_scale_map.h"
-#include "qwt_paint_buffer.h"
+#include "qwt_round_scale_draw.h"
#include "qwt_painter.h"
-#include "qwt_dial_needle.h"
-#include "qwt_dial.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static inline double qwtAngleDist( double a1, double a2 )
+{
+ double dist = qAbs( a2 - a1 );
+ if ( dist > 360.0 )
+ dist -= 360.0;
+
+ return dist;
+}
+
+static inline bool qwtIsOnArc( double angle, double min, double max )
+{
+ if ( min < max )
+ {
+ return ( angle >= min ) && ( angle <= max );
+ }
+ else
+ {
+ return ( angle >= min ) || ( angle <= max );
+ }
+}
+
+static inline double qwtBoundedAngle( double min, double angle, double max )
+{
+ double from = qwtNormalizeDegrees( min );
+ double to = qwtNormalizeDegrees( max );
+
+ double a;
+
+ if ( qwtIsOnArc( angle, from, to ) )
+ {
+ a = angle;
+ if ( a < min )
+ a += 360.0;
+ }
+ else
+ {
+ if ( qwtAngleDist( angle, from ) <
+ qwtAngleDist( angle, to ) )
+ {
+ a = min;
+ }
+ else
+ {
+ a = max;
+ }
+ }
+
+ return a;
+}
class QwtDial::PrivateData
{
public:
PrivateData():
- visibleBackground(true),
- frameShadow(Sunken),
- lineWidth(0),
- mode(RotateNeedle),
- origin(90.0),
- minScaleArc(0.0),
- maxScaleArc(0.0),
- scaleDraw(0),
- maxMajIntv(36),
- maxMinIntv(10),
- scaleStep(0.0),
- needle(0) {
+ frameShadow( Sunken ),
+ lineWidth( 0 ),
+ mode( RotateNeedle ),
+ origin( 90.0 ),
+ minScaleArc( 0.0 ),
+ maxScaleArc( 0.0 ),
+ needle( NULL ),
+ arcOffset( 0.0 ),
+ mouseOffset( 0.0 )
+ {
}
- ~PrivateData() {
- delete scaleDraw;
+ ~PrivateData()
+ {
delete needle;
}
- bool visibleBackground;
Shadow frameShadow;
int lineWidth;
@@ -55,177 +103,79 @@ public:
double minScaleArc;
double maxScaleArc;
- QwtDialScaleDraw *scaleDraw;
- int maxMajIntv;
- int maxMinIntv;
- double scaleStep;
-
+ double scalePenWidth;
QwtDialNeedle *needle;
- static double previousDir;
-};
-
-double QwtDial::PrivateData::previousDir = -1.0;
-
-/*!
- Constructor
-
- \param parent Parent dial widget
-*/
-QwtDialScaleDraw::QwtDialScaleDraw(QwtDial *parent):
- d_parent(parent),
- d_penWidth(1)
-{
-}
-
-/*!
- Set the pen width used for painting the scale
-
- \param penWidth Pen width
- \sa penWidth(), QwtDial::drawScale()
-*/
-
-void QwtDialScaleDraw::setPenWidth(uint penWidth)
-{
- d_penWidth = penWidth;
-}
+ double arcOffset;
+ double mouseOffset;
-/*!
- \return Pen width used for painting the scale
- \sa setPenWidth, QwtDial::drawScale()
-*/
-uint QwtDialScaleDraw::penWidth() const
-{
- return d_penWidth;
-}
-
-/*!
- Call QwtDial::scaleLabel of the parent dial widget.
-
- \param value Value to display
-
- \sa QwtDial::scaleLabel
-*/
-QwtText QwtDialScaleDraw::label(double value) const
-{
- if ( d_parent == NULL )
- return QwtRoundScaleDraw::label(value);
-
- return d_parent->scaleLabel(value);
-}
+ QPixmap pixmapCache;
+};
/*!
\brief Constructor
\param parent Parent widget
- Create a dial widget with no scale and no needle.
- The default origin is 90.0 with no valid value. It accepts
- mouse and keyboard inputs and has no step size. The default mode
- is QwtDial::RotateNeedle.
-*/
+ Create a dial widget with no needle. The scale is initialized
+ to [ 0.0, 360.0 ] and 360 steps ( QwtAbstractSlider::setTotalSteps() ).
+ The origin of the scale is at 90°,
-QwtDial::QwtDial(QWidget* parent):
- QwtAbstractSlider(Qt::Horizontal, parent)
-{
- initDial();
-}
+ The value is set to 0.0.
-#if QT_VERSION < 0x040000
-/*!
- \brief Constructor
- \param parent Parent widget
- \param name Object name
-
- Create a dial widget with no scale and no needle.
- The default origin is 90.0 with no valid value. It accepts
- mouse and keyboard inputs and has no step size. The default mode
- is QwtDial::RotateNeedle.
+ The default mode is QwtDial::RotateNeedle.
*/
-QwtDial::QwtDial(QWidget* parent, const char *name):
- QwtAbstractSlider(Qt::Horizontal, parent)
-{
- setName(name);
- initDial();
-}
-#endif
-
-void QwtDial::initDial()
+QwtDial::QwtDial( QWidget* parent ):
+ QwtAbstractSlider( parent )
{
d_data = new PrivateData;
-#if QT_VERSION < 0x040000
- setWFlags(Qt::WNoAutoErase);
-#endif
-
-#if QT_VERSION >= 0x040000
- using namespace Qt;
-#endif
- setFocusPolicy(TabFocus);
+ setFocusPolicy( Qt::TabFocus );
QPalette p = palette();
- for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
- const QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
+ for ( int i = 0; i < QPalette::NColorGroups; i++ )
+ {
+ const QPalette::ColorGroup colorGroup =
+ static_cast( i );
// Base: background color of the circle inside the frame.
- // Foreground: background color of the circle inside the scale
-
-#if QT_VERSION < 0x040000
- p.setColor(cg, QColorGroup::Foreground,
- p.color(cg, QColorGroup::Base));
-#else
- p.setColor(cg, QPalette::Foreground,
- p.color(cg, QPalette::Base));
-#endif
+ // WindowText: background color of the circle inside the scale
+
+ p.setColor( colorGroup, QPalette::WindowText,
+ p.color( colorGroup, QPalette::Base ) );
}
- setPalette(p);
+ setPalette( p );
- d_data->scaleDraw = new QwtDialScaleDraw(this);
- d_data->scaleDraw->setRadius(0);
+ QwtRoundScaleDraw* scaleDraw = new QwtRoundScaleDraw();
+ scaleDraw->setRadius( 0 );
- setScaleArc(0.0, 360.0); // scale as a full circle
- setRange(0.0, 360.0, 1.0, 10); // degrees as deafult
-}
+ setScaleDraw( scaleDraw );
-//! Destructor
-QwtDial::~QwtDial()
-{
- delete d_data;
-}
+ setScaleArc( 0.0, 360.0 ); // scale as a full circle
-/*!
- Show/Hide the area outside of the frame
- \param show Show if true, hide if false
+ setScaleMaxMajor( 10 );
+ setScaleMaxMinor( 5 );
- \sa hasVisibleBackground(), setMask()
- \warning When QwtDial is a toplevel widget the window
- border might disappear too.
-*/
-void QwtDial::showBackground(bool show)
-{
- if ( d_data->visibleBackground != show ) {
- d_data->visibleBackground = show;
- updateMask();
- }
+ setValue( 0.0 );
}
-/*!
- true when the area outside of the frame is visible
-
- \sa showBackground(), setMask()
-*/
-bool QwtDial::hasVisibleBackground() const
+//! Destructor
+QwtDial::~QwtDial()
{
- return d_data->visibleBackground;
+ delete d_data;
}
/*!
Sets the frame shadow value from the frame style.
+
\param shadow Frame shadow
\sa setLineWidth(), QFrame::setFrameShadow()
*/
-void QwtDial::setFrameShadow(Shadow shadow)
+void QwtDial::setFrameShadow( Shadow shadow )
{
- if ( shadow != d_data->frameShadow ) {
+ if ( shadow != d_data->frameShadow )
+ {
+ invalidateCache();
+
d_data->frameShadow = shadow;
if ( lineWidth() > 0 )
update();
@@ -234,7 +184,7 @@ void QwtDial::setFrameShadow(Shadow shadow)
/*!
\return Frame shadow
- /sa setFrameShadow(), lineWidth(), QFrame::frameShadow
+ /sa setFrameShadow(), lineWidth(), QFrame::frameShadow()
*/
QwtDial::Shadow QwtDial::frameShadow() const
{
@@ -242,17 +192,20 @@ QwtDial::Shadow QwtDial::frameShadow() const
}
/*!
- Sets the line width
+ Sets the line width of the frame
\param lineWidth Line width
\sa setFrameShadow()
*/
-void QwtDial::setLineWidth(int lineWidth)
+void QwtDial::setLineWidth( int lineWidth )
{
if ( lineWidth < 0 )
lineWidth = 0;
- if ( d_data->lineWidth != lineWidth ) {
+ if ( d_data->lineWidth != lineWidth )
+ {
+ invalidateCache();
+
d_data->lineWidth = lineWidth;
update();
}
@@ -268,65 +221,56 @@ int QwtDial::lineWidth() const
}
/*!
- \return bounding rect of the circle inside the frame
- \sa setLineWidth(), scaleContentsRect(), boundingRect()
+ \return bounding rectangle of the circle inside the frame
+ \sa setLineWidth(), scaleInnerRect(), boundingRect()
*/
-QRect QwtDial::contentsRect() const
+QRect QwtDial::innerRect() const
{
const int lw = lineWidth();
-
- QRect r = boundingRect();
- if ( lw > 0 ) {
- r.setRect(r.x() + lw, r.y() + lw,
- r.width() - 2 * lw, r.height() - 2 * lw);
- }
- return r;
+ return boundingRect().adjusted( lw, lw, -lw, -lw );
}
/*!
- \return bounding rect of the dial including the frame
- \sa setLineWidth(), scaleContentsRect(), contentsRect()
+ \return bounding rectangle of the dial including the frame
+ \sa setLineWidth(), scaleInnerRect(), innerRect()
*/
QRect QwtDial::boundingRect() const
{
- const int radius = qwtMin(width(), height()) / 2;
+ const QRect cr = contentsRect();
+
+ const double dim = qMin( cr.width(), cr.height() );
+
+ QRect inner( 0, 0, dim, dim );
+ inner.moveCenter( cr.center() );
- QRect r(0, 0, 2 * radius, 2 * radius);
- r.moveCenter(rect().center());
- return r;
+ return inner;
}
/*!
- \return rect inside the scale
- \sa setLineWidth(), boundingRect(), contentsRect()
+ \return rectangle inside the scale
+ \sa setLineWidth(), boundingRect(), innerRect()
*/
-QRect QwtDial::scaleContentsRect() const
+QRect QwtDial::scaleInnerRect() const
{
-#if QT_VERSION < 0x040000
- const QPen scalePen(colorGroup().text(), 0, Qt::NoPen);
-#else
- const QPen scalePen(palette().text(), 0, Qt::NoPen);
-#endif
-
- int scaleDist = 0;
- if ( d_data->scaleDraw ) {
- scaleDist = d_data->scaleDraw->extent(scalePen, font());
+ QRect rect = innerRect();
+
+ const QwtAbstractScaleDraw *sd = scaleDraw();
+ if ( sd )
+ {
+ int scaleDist = qCeil( sd->extent( font() ) );
scaleDist++; // margin
+
+ rect.adjust( scaleDist, scaleDist, -scaleDist, -scaleDist );
}
- const QRect rect = contentsRect();
- return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
- rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
+ return rect;
}
/*!
- \brief Change the mode of the meter.
+ \brief Change the mode of the dial.
\param mode New mode
- The value of the meter is indicated by the difference
- between north of the scale and the direction of the needle.
- In case of QwtDial::RotateNeedle north is pointing
- to the origin() and the needle is rotating, in case of
+ In case of QwtDial::RotateNeedle the needle is rotating, in case of
QwtDial::RotateScale, the needle points to origin()
and the scale is rotating.
@@ -334,26 +278,19 @@ QRect QwtDial::scaleContentsRect() const
\sa mode(), setValue(), setOrigin()
*/
-void QwtDial::setMode(Mode mode)
+void QwtDial::setMode( Mode mode )
{
- if ( mode != d_data->mode ) {
+ if ( mode != d_data->mode )
+ {
+ invalidateCache();
+
d_data->mode = mode;
- update();
+ sliderChange();
}
}
/*!
- \return mode of the dial.
-
- The value of the dial is indicated by the difference
- between the origin and the direction of the needle.
- In case of QwtDial::RotateNeedle the scale arc is fixed
- to the origin() and the needle is rotating, in case of
- QwtDial::RotateScale, the needle points to origin()
- and the scale is rotating.
-
- The default mode is QwtDial::RotateNeedle.
-
+ \return Mode of the dial.
\sa setMode(), origin(), setScaleArc(), value()
*/
QwtDial::Mode QwtDial::mode() const
@@ -362,115 +299,72 @@ QwtDial::Mode QwtDial::mode() const
}
/*!
- Sets whether it is possible to step the value from the highest value to
- the lowest value and vice versa to on.
-
- \param wrapping en/disables wrapping
-
- \sa wrapping(), QwtDoubleRange::periodic()
- \note The meaning of wrapping is like the wrapping property of QSpinBox,
- but not like it is used in QDial.
-*/
-void QwtDial::setWrapping(bool wrapping)
+ Invalidate the internal caches used to speed up repainting
+ */
+void QwtDial::invalidateCache()
{
- setPeriodic(wrapping);
+ d_data->pixmapCache = QPixmap();
}
/*!
- wrapping() holds whether it is possible to step the value from the
- highest value to the lowest value and vice versa.
-
- \sa setWrapping(), QwtDoubleRange::setPeriodic()
- \note The meaning of wrapping is like the wrapping property of QSpinBox,
- but not like it is used in QDial.
+ Paint the dial
+ \param event Paint event
*/
-bool QwtDial::wrapping() const
+void QwtDial::paintEvent( QPaintEvent *event )
{
- return periodic();
-}
+ QPainter painter( this );
+ painter.setClipRegion( event->region() );
-/*!
- Resize the dial widget
- \param e Resize event
-*/
-void QwtDial::resizeEvent(QResizeEvent *e)
-{
- QWidget::resizeEvent(e);
+ QStyleOption opt;
+ opt.init(this);
+ style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
- if ( !hasVisibleBackground() )
- updateMask();
-}
+ if ( d_data->mode == QwtDial::RotateScale )
+ {
+ painter.save();
+ painter.setRenderHint( QPainter::Antialiasing, true );
-/*!
- Paint the dial
- \param e Paint event
-*/
-void QwtDial::paintEvent(QPaintEvent *e)
-{
- const QRect &ur = e->rect();
- if ( ur.isValid() ) {
-#if QT_VERSION < 0x040000
- QwtPaintBuffer paintBuffer(this, ur);
- QPainter &painter = *paintBuffer.painter();
-#else
- QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing, true);
-#endif
+ drawContents( &painter );
- painter.save();
- drawContents(&painter);
painter.restore();
+ }
- painter.save();
- drawFrame(&painter);
- painter.restore();
+ const QRect r = contentsRect();
+ if ( r.size() != d_data->pixmapCache.size() )
+ {
+ d_data->pixmapCache = QwtPainter::backingStore( this, r.size() );
+ d_data->pixmapCache.fill( Qt::transparent );
+
+ QPainter p( &d_data->pixmapCache );
+ p.setRenderHint( QPainter::Antialiasing, true );
+ p.translate( -r.topLeft() );
+
+ if ( d_data->mode != QwtDial::RotateScale )
+ drawContents( &p );
- if ( hasFocus() )
- drawFocusIndicator(&painter);
+ if ( lineWidth() > 0 )
+ drawFrame( &p );
+
+ if ( d_data->mode != QwtDial::RotateNeedle )
+ drawNeedle( &p );
}
+
+ painter.drawPixmap( r.topLeft(), d_data->pixmapCache );
+
+ if ( d_data->mode == QwtDial::RotateNeedle )
+ drawNeedle( &painter );
+
+ if ( hasFocus() )
+ drawFocusIndicator( &painter );
}
/*!
- Draw a dotted round circle, if !isReadOnly()
-
+ Draw the focus indicator
\param painter Painter
*/
-void QwtDial::drawFocusIndicator(QPainter *painter) const
+void QwtDial::drawFocusIndicator( QPainter *painter ) const
{
- if ( !isReadOnly() ) {
- QRect focusRect = contentsRect();
-
- const int margin = 2;
- focusRect.setRect(
- focusRect.x() + margin,
- focusRect.y() + margin,
- focusRect.width() - 2 * margin,
- focusRect.height() - 2 * margin);
-
-#if QT_VERSION < 0x040000
- QColor color = colorGroup().color(QColorGroup::Base);
-#else
- QColor color = palette().color(QPalette::Base);
-#endif
- if (color.isValid()) {
- const QColor gray(Qt::gray);
-
- int h, s, v;
-#if QT_VERSION < 0x040000
- color.hsv(&h, &s, &v);
-#else
- color.getHsv(&h, &s, &v);
-#endif
- color = (v > 128) ? gray.dark(120) : gray.light(120);
- } else
- color = Qt::darkGray;
-
- painter->save();
- painter->setBrush(Qt::NoBrush);
- painter->setPen(QPen(color, 0, Qt::DotLine));
- painter->drawEllipse(focusRect);
- painter->restore();
- }
+ QwtPainter::drawFocusRect( painter, this, boundingRect() );
}
/*!
@@ -479,160 +373,60 @@ void QwtDial::drawFocusIndicator(QPainter *painter) const
\param painter Painter
\sa lineWidth(), frameShadow()
*/
-void QwtDial::drawFrame(QPainter *painter)
+void QwtDial::drawFrame( QPainter *painter )
{
- const int lw = lineWidth();
- const int off = (lw + 1) % 2;
-
- QRect r = boundingRect();
- r.setRect(r.x() + lw / 2 - off, r.y() + lw / 2 - off,
- r.width() - lw + off + 1, r.height() - lw + off + 1);
-#if QT_VERSION >= 0x040000
-#ifdef __GNUC__
-#endif
- r.setX(r.x() + 1);
- r.setY(r.y() + 1);
- r.setWidth(r.width() - 2);
- r.setHeight(r.height() - 2);
-#endif
-
- if ( lw > 0 ) {
- switch(d_data->frameShadow) {
- case QwtDial::Raised:
-#if QT_VERSION < 0x040000
- QwtPainter::drawRoundFrame(painter, r,
- lw, colorGroup(), false);
-#else
- QwtPainter::drawRoundFrame(painter, r,
- lw, palette(), false);
-#endif
- break;
- case QwtDial::Sunken:
-#if QT_VERSION < 0x040000
- QwtPainter::drawRoundFrame(painter, r,
- lw, colorGroup(), true);
-#else
- QwtPainter::drawRoundFrame(painter, r,
- lw, palette(), true);
-#endif
- break;
- default: { // Plain
- painter->save();
- painter->setPen(QPen(Qt::black, lw));
- painter->setBrush(Qt::NoBrush);
- painter->drawEllipse(r);
- painter->restore();
- }
- }
- }
+ QwtPainter::drawRoundFrame( painter, boundingRect(),
+ palette(), lineWidth(), d_data->frameShadow );
}
/*!
\brief Draw the contents inside the frame
- QColorGroup::Background is the background color outside of the frame.
- QColorGroup::Base is the background color inside the frame.
- QColorGroup::Foreground is the background color inside the scale.
+ QPalette::Window is the background color outside of the frame.
+ QPalette::Base is the background color inside the frame.
+ QPalette::WindowText is the background color inside the scale.
\param painter Painter
- \sa boundingRect(), contentsRect(),
- scaleContentsRect(), QWidget::setPalette
+
+ \sa boundingRect(), innerRect(),
+ scaleInnerRect(), QWidget::setPalette()
*/
-void QwtDial::drawContents(QPainter *painter) const
+void QwtDial::drawContents( QPainter *painter ) const
{
-#if QT_VERSION < 0x040000
- if ( backgroundMode() == Qt::NoBackground ||
- colorGroup().brush(QColorGroup::Base) !=
- colorGroup().brush(QColorGroup::Background) )
-#else
- if ( testAttribute(Qt::WA_NoSystemBackground) ||
- palette().brush(QPalette::Base) !=
- palette().brush(QPalette::Background) )
-#endif
+ if ( testAttribute( Qt::WA_NoSystemBackground ) ||
+ palette().brush( QPalette::Base ) !=
+ palette().brush( QPalette::Window ) )
{
-
- const QRect br = boundingRect();
+ const QRectF br = boundingRect();
painter->save();
- painter->setPen(Qt::NoPen);
-
-#if QT_VERSION < 0x040000
- painter->setBrush(colorGroup().brush(QColorGroup::Base));
-#else
- painter->setBrush(palette().brush(QPalette::Base));
-#endif
-
- painter->drawEllipse(br);
+ painter->setPen( Qt::NoPen );
+ painter->setBrush( palette().brush( QPalette::Base ) );
+ painter->drawEllipse( br );
painter->restore();
}
-
- const QRect insideScaleRect = scaleContentsRect();
-#if QT_VERSION < 0x040000
- if ( colorGroup().brush(QColorGroup::Foreground) !=
- colorGroup().brush(QColorGroup::Base) )
-#else
- if ( palette().brush(QPalette::Foreground) !=
- palette().brush(QPalette::Base) )
-#endif
+ const QRectF insideScaleRect = scaleInnerRect();
+ if ( palette().brush( QPalette::WindowText ) !=
+ palette().brush( QPalette::Base ) )
{
painter->save();
- painter->setPen(Qt::NoPen);
-
-#if QT_VERSION < 0x040000
- painter->setBrush(colorGroup().brush(QColorGroup::Foreground));
-#else
- painter->setBrush(palette().brush(QPalette::Foreground));
-#endif
-
- painter->drawEllipse(insideScaleRect.x() - 1, insideScaleRect.y() - 1,
- insideScaleRect.width(), insideScaleRect.height() );
-
+ painter->setPen( Qt::NoPen );
+ painter->setBrush( palette().brush( QPalette::WindowText ) );
+ painter->drawEllipse( insideScaleRect );
painter->restore();
}
- const QPoint center = insideScaleRect.center();
- const int radius = insideScaleRect.width() / 2;
+ const QPointF center = insideScaleRect.center();
+ const double radius = 0.5 * insideScaleRect.width();
painter->save();
- drawScaleContents(painter, center, radius);
+ drawScale( painter, center, radius );
painter->restore();
- double direction = d_data->origin;
-
- if (isValid()) {
- direction = d_data->origin + d_data->minScaleArc;
- if ( maxValue() > minValue() && d_data->maxScaleArc > d_data->minScaleArc ) {
- const double ratio =
- (value() - minValue()) / (maxValue() - minValue());
- direction += ratio * (d_data->maxScaleArc - d_data->minScaleArc);
- }
-
- if ( direction >= 360.0 )
- direction -= 360.0;
- }
-
- double origin = d_data->origin;
- if ( mode() == RotateScale ) {
- origin -= direction - d_data->origin;
- direction = d_data->origin;
- }
-
painter->save();
- drawScale(painter, center, radius, origin, d_data->minScaleArc, d_data->maxScaleArc);
+ drawScaleContents( painter, center, radius );
painter->restore();
-
- if ( isValid() ) {
- QPalette::ColorGroup cg;
- if ( isEnabled() )
- cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
- else
- cg = QPalette::Disabled;
-
- painter->save();
- drawNeedle(painter, center, radius, direction, cg);
- painter->restore();
- }
}
/*!
@@ -642,98 +436,96 @@ void QwtDial::drawContents(QPainter *painter) const
\param center Center of the dial
\param radius Length for the needle
\param direction Direction of the needle in degrees, counter clockwise
- \param cg ColorGroup
+ \param colorGroup ColorGroup
*/
-void QwtDial::drawNeedle(QPainter *painter, const QPoint ¢er,
- int radius, double direction, QPalette::ColorGroup cg) const
+void QwtDial::drawNeedle( QPainter *painter, const QPointF ¢er,
+ double radius, double direction, QPalette::ColorGroup colorGroup ) const
{
- if ( d_data->needle ) {
+ if ( d_data->needle )
+ {
direction = 360.0 - direction; // counter clockwise
- d_data->needle->draw(painter, center, radius, direction, cg);
+ d_data->needle->draw( painter, center, radius, direction, colorGroup );
}
}
+void QwtDial::drawNeedle( QPainter *painter ) const
+{
+ if ( !isValid() )
+ return;
+
+ QPalette::ColorGroup colorGroup;
+ if ( isEnabled() )
+ colorGroup = hasFocus() ? QPalette::Active : QPalette::Inactive;
+ else
+ colorGroup = QPalette::Disabled;
+
+ const QRectF sr = scaleInnerRect();
+
+ painter->save();
+ painter->setRenderHint( QPainter::Antialiasing, true );
+ drawNeedle( painter, sr.center(), 0.5 * sr.width(),
+ transform( value() ) + 270.0, colorGroup );
+ painter->restore();
+}
+
/*!
Draw the scale
\param painter Painter
\param center Center of the dial
\param radius Radius of the scale
- \param origin Origin of the scale
- \param minArc Minimum of the arc
- \param maxArc Minimum of the arc
-
- \sa QwtAbstractScaleDraw::setAngleRange
*/
-void QwtDial::drawScale(QPainter *painter, const QPoint ¢er,
- int radius, double origin, double minArc, double maxArc) const
+void QwtDial::drawScale( QPainter *painter,
+ const QPointF ¢er, double radius ) const
{
- if ( d_data->scaleDraw == NULL )
+ QwtRoundScaleDraw *sd = const_cast