From c44758c5ad6b585932a196ce1ffd48447a5fdc3e Mon Sep 17 00:00:00 2001 From: Damien Date: Mon, 6 Feb 2012 13:40:52 +0100 Subject: [PATCH] Qwt 6.0.1 Support Upgrade to QWT 6.0.1, but still uses a locally patched copy since support for 8 axes has not been included, despite it being a relatively simple patch. Fixes #634. Fixes #567. --- qwt/.gitignore | 4 + qwt/CHANGES | 111 +- qwt/INSTALL | 130 +- qwt/admin/msvc-qmake.bat | 58 - qwt/admin/no-qt-keywords.sh | 9 - qwt/admin/svn2package.sh | 299 - qwt/designer/.gitignore | 4 - qwt/designer/designer.pro | 149 +- qwt/designer/qwt_designer_plotdialog.cpp | 3 +- qwt/designer/qwt_designer_plotdialog.h | 12 +- qwt/designer/qwt_designer_plugin.cpp | 64 +- qwt/designer/qwt_designer_plugin.h | 48 +- qwt/designer/qwtplugin.cpp | 202 - qwt/designer/qwtplugin.h | 42 - .../resources/qrc_qwt_designer_plugin.cpp | 615 ++ qwt/doc/Doxyfile | 1521 ---- qwt/doc/images/analogclock.png | Bin 12649 -> 0 bytes qwt/doc/images/cpuplot.png | Bin 36517 -> 0 bytes qwt/doc/images/curves.png | Bin 20531 -> 0 bytes qwt/doc/images/dials1.png | Bin 72717 -> 0 bytes qwt/doc/images/dials2.png | Bin 28153 -> 0 bytes qwt/doc/images/graph.png | Bin 13144 -> 0 bytes qwt/doc/images/histogram.png | Bin 12524 -> 0 bytes qwt/doc/images/knob.png | Bin 6411 -> 0 bytes qwt/doc/images/plot.png | Bin 31037 -> 0 bytes qwt/doc/images/radio.png | Bin 19794 -> 0 bytes qwt/doc/images/scatterplot.png | Bin 23882 -> 0 bytes qwt/doc/images/sinus.png | Bin 29788 -> 0 bytes qwt/doc/images/sliders.png | Bin 9308 -> 0 bytes qwt/doc/images/spectrogram1.png | Bin 47416 -> 0 bytes qwt/doc/images/spectrogram2.png | Bin 16812 -> 0 bytes qwt/doc/images/spectrogram3.png | Bin 56165 -> 0 bytes qwt/doc/images/sysinfo.png | Bin 16508 -> 0 bytes qwt/doc/qwt.dox | 161 - qwt/examples/bode/bode.pro | 20 +- qwt/examples/bode/bode_plot.h | 25 - qwt/examples/bode/complexnumber.h | 83 + qwt/examples/bode/cplx.h | 62 - qwt/examples/bode/main.cpp | 13 + .../bode/{bode.cpp => mainwindow.cpp} | 236 +- qwt/examples/bode/{bode.h => mainwindow.h} | 21 +- qwt/examples/bode/{bode_plot.cpp => plot.cpp} | 117 +- qwt/examples/bode/plot.h | 31 + qwt/examples/cpuplot/cpupiemarker.cpp | 19 +- qwt/examples/cpuplot/cpupiemarker.h | 2 +- qwt/examples/cpuplot/cpuplot.cpp | 47 +- qwt/examples/cpuplot/cpuplot.h | 4 +- qwt/examples/cpuplot/cpuplot.pro | 18 +- qwt/examples/cpuplot/cpustat.cpp | 23 +- qwt/examples/cpuplot/cpustat.h | 2 +- qwt/examples/curvdemo1/curvdemo1.cpp | 116 +- qwt/examples/curvdemo1/curvdemo1.pro | 8 +- qwt/examples/curvdemo2/curvdemo2.cpp | 71 +- qwt/examples/curvdemo2/curvdemo2.h | 6 +- qwt/examples/curvdemo2/curvdemo2.pro | 10 +- qwt/examples/data_plot/data_plot.cpp | 147 - qwt/examples/data_plot/data_plot.h | 32 - qwt/examples/data_plot/main.cpp | 62 - qwt/examples/dials/attitude_indicator.cpp | 102 +- qwt/examples/dials/attitude_indicator.h | 13 +- qwt/examples/dials/cockpit_grid.cpp | 39 +- qwt/examples/dials/cockpit_grid.h | 2 +- qwt/examples/dials/compass_grid.cpp | 93 +- qwt/examples/dials/dials.cpp | 7 - qwt/examples/dials/dials.pro | 7 +- qwt/examples/dials/speedo_meter.cpp | 16 +- qwt/examples/dials/speedo_meter.h | 2 +- qwt/examples/event_filter/canvaspicker.cpp | 91 +- qwt/examples/event_filter/colorbar.cpp | 20 +- qwt/examples/event_filter/colorbar.h | 4 +- qwt/examples/event_filter/event_filter.cpp | 13 +- qwt/examples/event_filter/event_filter.pro | 24 +- qwt/examples/event_filter/plot.cpp | 34 +- qwt/examples/event_filter/plot.h | 4 +- qwt/examples/event_filter/scalepicker.cpp | 26 +- qwt/examples/event_filter/scalepicker.h | 2 +- qwt/examples/examples.pri | 70 +- qwt/examples/examples.pro | 68 +- qwt/examples/friedberg/friedberg.pro | 21 + qwt/examples/friedberg/friedberg2007.cpp | 384 + qwt/examples/friedberg/friedberg2007.h | 28 + qwt/examples/friedberg/main.cpp | 57 + qwt/examples/friedberg/plot.cpp | 252 + qwt/examples/friedberg/plot.h | 43 + qwt/examples/histogram/histogram_item.cpp | 283 - qwt/examples/histogram/histogram_item.h | 64 - qwt/examples/histogram/main.cpp | 60 - qwt/examples/many_axes/mainwindow.cpp | 56 - qwt/examples/many_axes/mainwindow.h | 22 - qwt/examples/many_axes/many_axes.cpp | 17 - qwt/examples/many_axes/plot.h | 152 - qwt/examples/navigation/main.cpp | 14 + qwt/examples/navigation/mainwindow.cpp | 183 + qwt/examples/navigation/mainwindow.h | 49 + qwt/examples/navigation/navigation.pro | 21 + qwt/examples/navigation/plot.cpp | 146 + qwt/examples/navigation/plot.h | 26 + qwt/examples/oscilloscope/curvedata.cpp | 27 + qwt/examples/oscilloscope/curvedata.h | 16 + qwt/examples/oscilloscope/knob.cpp | 86 + qwt/examples/oscilloscope/knob.h | 33 + qwt/examples/oscilloscope/main.cpp | 35 + qwt/examples/oscilloscope/mainwindow.cpp | 69 + qwt/examples/oscilloscope/mainwindow.h | 32 + qwt/examples/oscilloscope/oscilloscope.pro | 31 + qwt/examples/oscilloscope/plot.cpp | 232 + qwt/examples/oscilloscope/plot.h | 44 + qwt/examples/oscilloscope/samplingthread.cpp | 54 + qwt/examples/oscilloscope/samplingthread.h | 25 + qwt/examples/oscilloscope/signaldata.cpp | 133 + qwt/examples/oscilloscope/signaldata.h | 33 + qwt/examples/oscilloscope/wheelbox.cpp | 90 + qwt/examples/oscilloscope/wheelbox.h | 36 + qwt/examples/plotmatrix/main.cpp | 59 + qwt/examples/plotmatrix/plotmatrix.cpp | 293 + qwt/examples/plotmatrix/plotmatrix.h | 38 + .../plotmatrix.pro} | 20 +- qwt/examples/radio/ampfrm.cpp | 87 +- qwt/examples/radio/ampfrm.h | 13 +- qwt/examples/radio/mainwindow.cpp | 60 + qwt/examples/radio/mainwindow.h | 13 + qwt/examples/radio/radio.cpp | 32 +- qwt/examples/radio/radio.h | 9 - qwt/examples/radio/radio.pro | 19 +- qwt/examples/radio/tunerfrm.cpp | 61 +- qwt/examples/radio/tunerfrm.h | 16 +- qwt/examples/rasterview/main.cpp | 62 + qwt/examples/rasterview/plot.cpp | 146 + qwt/examples/rasterview/plot.h | 17 + .../rasterview.pro} | 15 +- .../{realtime_plot => realtime}/README | 8 +- .../{realtime_plot => realtime}/clear.xpm | 0 qwt/examples/realtime/incrementalplot.cpp | 105 + qwt/examples/realtime/incrementalplot.h | 25 + .../realtime.cpp => realtime/main.cpp} | 3 - .../mainwindow.cpp | 81 +- .../{realtime_plot => realtime}/mainwindow.h | 17 +- .../randomplot.cpp | 47 +- .../{realtime_plot => realtime}/randomplot.h | 14 +- .../realtime.pro} | 29 +- .../{realtime_plot => realtime}/scrollbar.cpp | 29 +- .../{realtime_plot => realtime}/scrollbar.h | 8 +- .../scrollzoomer.cpp | 85 +- .../scrollzoomer.h | 19 +- .../{realtime_plot => realtime}/start.xpm | 0 .../realtime_plot/incrementalplot.cpp | 122 - qwt/examples/realtime_plot/incrementalplot.h | 46 - qwt/examples/refreshtest/circularbuffer.cpp | 73 + qwt/examples/refreshtest/circularbuffer.h | 35 + qwt/examples/refreshtest/main.cpp | 13 + qwt/examples/refreshtest/mainwindow.cpp | 68 + qwt/examples/refreshtest/mainwindow.h | 22 + qwt/examples/refreshtest/panel.cpp | 264 + qwt/examples/refreshtest/panel.h | 50 + qwt/examples/refreshtest/plot.cpp | 161 + qwt/examples/refreshtest/plot.h | 38 + qwt/examples/refreshtest/refreshtest.pro | 26 + qwt/examples/refreshtest/settings.h | 70 + qwt/examples/simple_plot/simple.cpp | 125 - qwt/examples/sinusplot/sinusplot.cpp | 182 + .../sinusplot.pro} | 11 +- qwt/examples/sliders/sliders.cpp | 58 +- qwt/examples/sliders/sliders.h | 2 +- qwt/examples/sliders/sliders.pro | 11 +- qwt/examples/spectrogram/main.cpp | 48 +- qwt/examples/spectrogram/plot.cpp | 86 +- qwt/examples/spectrogram/plot.h | 5 +- qwt/examples/spectrogram/spectrogram.pro | 12 +- qwt/examples/stylesheets/choco.css | 38 + qwt/examples/svgmap/main.cpp | 29 +- qwt/examples/svgmap/plot.cpp | 48 +- qwt/examples/svgmap/plot.h | 11 +- qwt/examples/svgmap/svgmap.pro | 18 +- qwt/examples/sysinfo/sysinfo.cpp | 131 +- qwt/examples/sysinfo/sysinfo.pro | 8 +- qwt/examples/tvplot/main.cpp | 14 + qwt/examples/tvplot/tvplot.cpp | 124 + qwt/examples/tvplot/tvplot.h | 19 + .../histogram.pro => tvplot/tvplot.pro} | 16 +- qwt/qwt.prf | 56 +- qwt/qwt.pro | 18 +- qwt/qwt.pro.user | 2047 ++++++ qwt/qwtbuild.pri | 69 + qwt/qwtconfig.pri.in | 130 +- qwt/src/.gitignore | 2 - qwt/src/qwt.h | 4 +- qwt/src/qwt_abstract_scale.cpp | 83 +- qwt/src/qwt_abstract_scale.h | 34 +- qwt/src/qwt_abstract_scale_draw.cpp | 260 +- qwt/src/qwt_abstract_scale_draw.h | 114 +- qwt/src/qwt_abstract_slider.cpp | 257 +- qwt/src/qwt_abstract_slider.h | 185 +- qwt/src/qwt_analog_clock.cpp | 117 +- qwt/src/qwt_analog_clock.h | 38 +- qwt/src/qwt_arrow_button.cpp | 241 +- qwt/src/qwt_arrow_button.h | 22 +- qwt/src/qwt_clipper.cpp | 748 +- qwt/src/qwt_clipper.h | 22 +- qwt/src/qwt_color_map.cpp | 279 +- qwt/src/qwt_color_map.h | 119 +- qwt/src/qwt_column_symbol.cpp | 296 + qwt/src/qwt_column_symbol.h | 161 + qwt/src/qwt_compass.cpp | 178 +- qwt/src/qwt_compass.h | 48 +- qwt/src/qwt_compass_rose.cpp | 245 +- qwt/src/qwt_compass_rose.h | 61 +- qwt/src/qwt_compat.h | 40 + qwt/src/qwt_counter.cpp | 440 +- qwt/src/qwt_counter.h | 93 +- qwt/src/qwt_curve_fitter.cpp | 311 +- qwt/src/qwt_curve_fitter.h | 108 +- qwt/src/qwt_data.cpp | 384 - qwt/src/qwt_data.h | 166 - qwt/src/qwt_dial.cpp | 865 +-- qwt/src/qwt_dial.h | 153 +- qwt/src/qwt_dial_needle.cpp | 762 +- qwt/src/qwt_dial_needle.h | 140 +- qwt/src/qwt_double_interval.h | 284 - qwt/src/qwt_double_range.cpp | 350 +- qwt/src/qwt_double_range.h | 42 +- qwt/src/qwt_double_rect.cpp | 605 -- qwt/src/qwt_double_rect.h | 501 -- qwt/src/qwt_dyngrid_layout.cpp | 408 +- qwt/src/qwt_dyngrid_layout.h | 64 +- qwt/src/qwt_event_pattern.cpp | 162 +- qwt/src/qwt_event_pattern.h | 82 +- qwt/src/qwt_global.h | 19 +- ...t_double_interval.cpp => qwt_interval.cpp} | 158 +- qwt/src/qwt_interval.h | 296 + qwt/src/qwt_interval_data.cpp | 90 - qwt/src/qwt_interval_data.h | 90 - qwt/src/qwt_interval_symbol.cpp | 298 + qwt/src/qwt_interval_symbol.h | 86 + qwt/src/qwt_knob.cpp | 596 +- qwt/src/qwt_knob.h | 113 +- qwt/src/qwt_layout_metrics.cpp | 339 - qwt/src/qwt_layout_metrics.h | 169 - qwt/src/qwt_legend.cpp | 487 +- qwt/src/qwt_legend.h | 81 +- qwt/src/qwt_legend_item.cpp | 643 +- qwt/src/qwt_legend_item.h | 86 +- qwt/src/qwt_legend_itemmanager.h | 23 +- qwt/src/qwt_magnifier.cpp | 226 +- qwt/src/qwt_magnifier.h | 42 +- qwt/src/qwt_math.cpp | 26 +- qwt/src/qwt_math.h | 144 +- qwt/src/qwt_matrix_raster_data.cpp | 270 + qwt/src/qwt_matrix_raster_data.h | 71 + qwt/src/qwt_null_paintdevice.cpp | 428 ++ qwt/src/qwt_null_paintdevice.h | 89 + qwt/src/qwt_paint_buffer.cpp | 201 - qwt/src/qwt_paint_buffer.h | 65 - qwt/src/qwt_painter.cpp | 1020 ++- qwt/src/qwt_painter.h | 196 +- qwt/src/qwt_panner.cpp | 341 +- qwt/src/qwt_panner.h | 61 +- qwt/src/qwt_picker.cpp | 934 ++- qwt/src/qwt_picker.h | 363 +- qwt/src/qwt_picker_machine.cpp | 229 +- qwt/src/qwt_picker_machine.h | 117 +- qwt/src/qwt_plot.cpp | 532 +- qwt/src/qwt_plot.h | 255 +- qwt/src/qwt_plot_axis.cpp | 348 +- qwt/src/qwt_plot_canvas.cpp | 1117 ++- qwt/src/qwt_plot_canvas.h | 127 +- qwt/src/qwt_plot_curve.cpp | 1462 ++-- qwt/src/qwt_plot_curve.h | 384 +- qwt/src/qwt_plot_dict.cpp | 126 +- qwt/src/qwt_plot_dict.h | 25 +- qwt/src/qwt_plot_directpainter.cpp | 313 + qwt/src/qwt_plot_directpainter.h | 100 + qwt/src/qwt_plot_grid.cpp | 211 +- qwt/src/qwt_plot_grid.h | 34 +- qwt/src/qwt_plot_histogram.cpp | 648 ++ qwt/src/qwt_plot_histogram.h | 134 + qwt/src/qwt_plot_intervalcurve.cpp | 547 ++ qwt/src/qwt_plot_intervalcurve.h | 130 + qwt/src/qwt_plot_item.cpp | 378 +- qwt/src/qwt_plot_item.h | 111 +- qwt/src/qwt_plot_layout.cpp | 765 +- qwt/src/qwt_plot_layout.h | 89 +- qwt/src/qwt_plot_magnifier.cpp | 57 +- qwt/src/qwt_plot_magnifier.h | 10 +- qwt/src/qwt_plot_marker.cpp | 431 +- qwt/src/qwt_plot_marker.h | 79 +- qwt/src/qwt_plot_panner.cpp | 78 +- qwt/src/qwt_plot_panner.h | 23 +- qwt/src/qwt_plot_picker.cpp | 247 +- qwt/src/qwt_plot_picker.h | 58 +- qwt/src/qwt_plot_print.cpp | 530 -- qwt/src/qwt_plot_printfilter.cpp | 590 -- qwt/src/qwt_plot_printfilter.h | 83 - qwt/src/qwt_plot_rasteritem.cpp | 794 ++- qwt/src/qwt_plot_rasteritem.h | 91 +- qwt/src/qwt_plot_renderer.cpp | 833 +++ qwt/src/qwt_plot_renderer.h | 154 + qwt/src/qwt_plot_rescaler.cpp | 293 +- qwt/src/qwt_plot_rescaler.h | 104 +- qwt/src/qwt_plot_scaleitem.cpp | 227 +- qwt/src/qwt_plot_scaleitem.h | 47 +- qwt/src/qwt_plot_seriesitem.cpp | 89 + qwt/src/qwt_plot_seriesitem.h | 220 + qwt/src/qwt_plot_spectrocurve.cpp | 300 + qwt/src/qwt_plot_spectrocurve.h | 76 + qwt/src/qwt_plot_spectrogram.cpp | 587 +- qwt/src/qwt_plot_spectrogram.h | 84 +- qwt/src/qwt_plot_svgitem.cpp | 182 +- qwt/src/qwt_plot_svgitem.h | 33 +- qwt/src/qwt_plot_xml.cpp | 24 +- qwt/src/qwt_plot_zoomer.cpp | 343 +- qwt/src/qwt_plot_zoomer.h | 98 +- qwt/src/{qwt_array.h => qwt_point_3d.cpp} | 26 +- qwt/src/qwt_point_3d.h | 189 + qwt/src/qwt_point_polar.cpp | 113 + qwt/src/qwt_point_polar.h | 195 + qwt/src/qwt_polygon.h | 35 - qwt/src/qwt_raster_data.cpp | 273 +- qwt/src/qwt_raster_data.h | 106 +- qwt/src/qwt_round_scale_draw.cpp | 217 +- qwt/src/qwt_round_scale_draw.h | 35 +- qwt/src/qwt_sampling_thread.cpp | 106 + qwt/src/qwt_sampling_thread.h | 50 + qwt/src/qwt_scale_div.cpp | 68 +- qwt/src/qwt_scale_div.h | 72 +- qwt/src/qwt_scale_draw.cpp | 638 +- qwt/src/qwt_scale_draw.h | 92 +- qwt/src/qwt_scale_engine.cpp | 658 +- qwt/src/qwt_scale_engine.h | 161 +- qwt/src/qwt_scale_map.cpp | 280 +- qwt/src/qwt_scale_map.h | 119 +- qwt/src/qwt_scale_widget.cpp | 679 +- qwt/src/qwt_scale_widget.h | 105 +- qwt/src/qwt_series_data.cpp | 586 ++ qwt/src/qwt_series_data.h | 442 ++ qwt/src/qwt_slider.cpp | 886 ++- qwt/src/qwt_slider.h | 118 +- qwt/src/qwt_spline.cpp | 259 +- qwt/src/qwt_spline.h | 69 +- qwt/src/qwt_symbol.cpp | 1064 ++- qwt/src/qwt_symbol.h | 170 +- qwt/src/qwt_system_clock.cpp | 364 + qwt/src/qwt_system_clock.h | 49 + qwt/src/qwt_text.cpp | 403 +- qwt/src/qwt_text.h | 163 +- qwt/src/qwt_text_engine.cpp | 286 +- qwt/src/qwt_text_engine.h | 88 +- qwt/src/qwt_text_label.cpp | 116 +- qwt/src/qwt_text_label.h | 31 +- qwt/src/qwt_thermo.cpp | 1131 +-- qwt/src/qwt_thermo.h | 126 +- qwt/src/qwt_valuelist.h | 57 - qwt/src/qwt_wheel.cpp | 726 +- qwt/src/qwt_wheel.h | 65 +- qwt/src/src.pro | 155 +- qwt/textengines/mathml/mathml.pro | 60 +- qwt/textengines/mathml/qtmmlwidget-license | 44 + qwt/textengines/mathml/qtmmlwidget.cpp.diff | 23 - .../mathml/qwt_mathml_text_engine.cpp | 32 +- .../mathml/qwt_mathml_text_engine.h | 21 +- qwt/textengines/mathml/qwt_mml_document.cpp | 6260 +++++++++++++++++ qwt/textengines/mathml/qwt_mml_document.h | 45 + qwt/textengines/mathml/qwtmathml.prf | 37 + qwt/textengines/textengines.pri | 75 +- qwt/textengines/textengines.pro | 10 +- src/Aerolab.cpp | 37 +- src/Aerolab.h | 2 +- src/AerolabWindow.cpp | 6 +- src/AllPlot.cpp | 60 +- src/AllPlot.h | 2 +- src/AllPlotWindow.cpp | 8 +- src/CpintPlot.cpp | 6 +- src/CpintPlot.h | 4 +- src/CriticalPowerWindow.cpp | 17 +- src/ErgFilePlot.cpp | 78 +- src/ErgFilePlot.h | 23 +- src/HrPwPlot.cpp | 18 +- src/HrPwWindow.cpp | 3 - src/LTMCanvasPicker.cpp | 1 + src/LTMChartParser.cpp | 4 +- src/LTMPlot.cpp | 44 +- src/LTMSettings.cpp | 4 +- src/LTMWindow.cpp | 5 +- src/LTMWindow.h | 10 +- src/LogTimeScaleDraw.cpp | 10 +- src/LogTimeScaleEngine.h | 2 + src/MainWindow.cpp | 2 +- src/PerfPlot.cpp | 2 +- src/PerfPlot.h | 8 +- src/PerformanceManagerWindow.cpp | 4 +- src/PfPvPlot.cpp | 13 +- src/PfPvPlot.h | 2 + src/PfPvWindow.cpp | 1 - src/PowerHist.cpp | 6 +- src/PowerHist.h | 19 +- src/RealtimePlot.cpp | 81 +- src/RealtimePlot.h | 74 +- src/RealtimePlotWindow.cpp | 24 +- src/ScatterPlot.cpp | 8 +- src/SmallPlot.cpp | 3 +- src/SpinScanPlot.cpp | 18 +- src/SpinScanPlot.h | 9 +- src/SpinScanPolarPlot.cpp | 19 +- src/SpinScanPolarPlot.h | 9 +- src/SplitActivityWizard.h | 4 +- src/TreeMapWindow.cpp | 2 +- src/WorkoutWizard.cpp | 14 +- 406 files changed, 39317 insertions(+), 25831 deletions(-) delete mode 100644 qwt/admin/msvc-qmake.bat delete mode 100755 qwt/admin/no-qt-keywords.sh delete mode 100755 qwt/admin/svn2package.sh delete mode 100644 qwt/designer/.gitignore delete mode 100644 qwt/designer/qwtplugin.cpp delete mode 100644 qwt/designer/qwtplugin.h create mode 100644 qwt/designer/resources/qrc_qwt_designer_plugin.cpp delete mode 100644 qwt/doc/Doxyfile delete mode 100644 qwt/doc/images/analogclock.png delete mode 100644 qwt/doc/images/cpuplot.png delete mode 100644 qwt/doc/images/curves.png delete mode 100644 qwt/doc/images/dials1.png delete mode 100644 qwt/doc/images/dials2.png delete mode 100644 qwt/doc/images/graph.png delete mode 100644 qwt/doc/images/histogram.png delete mode 100644 qwt/doc/images/knob.png delete mode 100644 qwt/doc/images/plot.png delete mode 100644 qwt/doc/images/radio.png delete mode 100644 qwt/doc/images/scatterplot.png delete mode 100644 qwt/doc/images/sinus.png delete mode 100644 qwt/doc/images/sliders.png delete mode 100644 qwt/doc/images/spectrogram1.png delete mode 100644 qwt/doc/images/spectrogram2.png delete mode 100644 qwt/doc/images/spectrogram3.png delete mode 100644 qwt/doc/images/sysinfo.png delete mode 100644 qwt/doc/qwt.dox delete mode 100644 qwt/examples/bode/bode_plot.h create mode 100644 qwt/examples/bode/complexnumber.h delete mode 100644 qwt/examples/bode/cplx.h create mode 100644 qwt/examples/bode/main.cpp rename qwt/examples/bode/{bode.cpp => mainwindow.cpp} (55%) rename qwt/examples/bode/{bode.h => mainwindow.h} (60%) rename qwt/examples/bode/{bode_plot.cpp => plot.cpp} (55%) create mode 100644 qwt/examples/bode/plot.h delete mode 100644 qwt/examples/data_plot/data_plot.cpp delete mode 100644 qwt/examples/data_plot/data_plot.h delete mode 100644 qwt/examples/data_plot/main.cpp create mode 100644 qwt/examples/friedberg/friedberg.pro create mode 100644 qwt/examples/friedberg/friedberg2007.cpp create mode 100644 qwt/examples/friedberg/friedberg2007.h create mode 100644 qwt/examples/friedberg/main.cpp create mode 100644 qwt/examples/friedberg/plot.cpp create mode 100644 qwt/examples/friedberg/plot.h delete mode 100644 qwt/examples/histogram/histogram_item.cpp delete mode 100644 qwt/examples/histogram/histogram_item.h delete mode 100644 qwt/examples/histogram/main.cpp delete mode 100644 qwt/examples/many_axes/mainwindow.cpp delete mode 100644 qwt/examples/many_axes/mainwindow.h delete mode 100644 qwt/examples/many_axes/many_axes.cpp delete mode 100644 qwt/examples/many_axes/plot.h create mode 100644 qwt/examples/navigation/main.cpp create mode 100644 qwt/examples/navigation/mainwindow.cpp create mode 100644 qwt/examples/navigation/mainwindow.h create mode 100644 qwt/examples/navigation/navigation.pro create mode 100644 qwt/examples/navigation/plot.cpp create mode 100644 qwt/examples/navigation/plot.h create mode 100644 qwt/examples/oscilloscope/curvedata.cpp create mode 100644 qwt/examples/oscilloscope/curvedata.h create mode 100644 qwt/examples/oscilloscope/knob.cpp create mode 100644 qwt/examples/oscilloscope/knob.h create mode 100644 qwt/examples/oscilloscope/main.cpp create mode 100644 qwt/examples/oscilloscope/mainwindow.cpp create mode 100644 qwt/examples/oscilloscope/mainwindow.h create mode 100644 qwt/examples/oscilloscope/oscilloscope.pro create mode 100644 qwt/examples/oscilloscope/plot.cpp create mode 100644 qwt/examples/oscilloscope/plot.h create mode 100644 qwt/examples/oscilloscope/samplingthread.cpp create mode 100644 qwt/examples/oscilloscope/samplingthread.h create mode 100644 qwt/examples/oscilloscope/signaldata.cpp create mode 100644 qwt/examples/oscilloscope/signaldata.h create mode 100644 qwt/examples/oscilloscope/wheelbox.cpp create mode 100644 qwt/examples/oscilloscope/wheelbox.h create mode 100644 qwt/examples/plotmatrix/main.cpp create mode 100644 qwt/examples/plotmatrix/plotmatrix.cpp create mode 100644 qwt/examples/plotmatrix/plotmatrix.h rename qwt/examples/{many_axes/many_axes.pro => plotmatrix/plotmatrix.pro} (61%) create mode 100644 qwt/examples/radio/mainwindow.cpp create mode 100644 qwt/examples/radio/mainwindow.h delete mode 100644 qwt/examples/radio/radio.h create mode 100644 qwt/examples/rasterview/main.cpp create mode 100644 qwt/examples/rasterview/plot.cpp create mode 100644 qwt/examples/rasterview/plot.h rename qwt/examples/{data_plot/data_plot.pro => rasterview/rasterview.pro} (65%) rename qwt/examples/{realtime_plot => realtime}/README (89%) rename qwt/examples/{realtime_plot => realtime}/clear.xpm (100%) create mode 100644 qwt/examples/realtime/incrementalplot.cpp create mode 100644 qwt/examples/realtime/incrementalplot.h rename qwt/examples/{realtime_plot/realtime.cpp => realtime/main.cpp} (75%) rename qwt/examples/{realtime_plot => realtime}/mainwindow.cpp (69%) rename qwt/examples/{realtime_plot => realtime}/mainwindow.h (66%) rename qwt/examples/{realtime_plot => realtime}/randomplot.cpp (68%) rename qwt/examples/{realtime_plot => realtime}/randomplot.h (67%) rename qwt/examples/{realtime_plot/realtime_plot.pro => realtime/realtime.pro} (50%) rename qwt/examples/{realtime_plot => realtime}/scrollbar.cpp (86%) rename qwt/examples/{realtime_plot => realtime}/scrollbar.h (92%) rename qwt/examples/{realtime_plot => realtime}/scrollzoomer.cpp (88%) rename qwt/examples/{realtime_plot => realtime}/scrollzoomer.h (78%) rename qwt/examples/{realtime_plot => realtime}/start.xpm (100%) delete mode 100644 qwt/examples/realtime_plot/incrementalplot.cpp delete mode 100644 qwt/examples/realtime_plot/incrementalplot.h create mode 100644 qwt/examples/refreshtest/circularbuffer.cpp create mode 100644 qwt/examples/refreshtest/circularbuffer.h create mode 100644 qwt/examples/refreshtest/main.cpp create mode 100644 qwt/examples/refreshtest/mainwindow.cpp create mode 100644 qwt/examples/refreshtest/mainwindow.h create mode 100644 qwt/examples/refreshtest/panel.cpp create mode 100644 qwt/examples/refreshtest/panel.h create mode 100644 qwt/examples/refreshtest/plot.cpp create mode 100644 qwt/examples/refreshtest/plot.h create mode 100644 qwt/examples/refreshtest/refreshtest.pro create mode 100644 qwt/examples/refreshtest/settings.h delete mode 100644 qwt/examples/simple_plot/simple.cpp create mode 100644 qwt/examples/sinusplot/sinusplot.cpp rename qwt/examples/{simple_plot/simple_plot.pro => sinusplot/sinusplot.pro} (67%) create mode 100644 qwt/examples/stylesheets/choco.css create mode 100644 qwt/examples/tvplot/main.cpp create mode 100644 qwt/examples/tvplot/tvplot.cpp create mode 100644 qwt/examples/tvplot/tvplot.h rename qwt/examples/{histogram/histogram.pro => tvplot/tvplot.pro} (62%) create mode 100644 qwt/qwt.pro.user create mode 100644 qwt/qwtbuild.pri delete mode 100644 qwt/src/.gitignore create mode 100644 qwt/src/qwt_column_symbol.cpp create mode 100644 qwt/src/qwt_column_symbol.h create mode 100644 qwt/src/qwt_compat.h delete mode 100644 qwt/src/qwt_data.cpp delete mode 100644 qwt/src/qwt_data.h delete mode 100644 qwt/src/qwt_double_interval.h delete mode 100644 qwt/src/qwt_double_rect.cpp delete mode 100644 qwt/src/qwt_double_rect.h rename qwt/src/{qwt_double_interval.cpp => qwt_interval.cpp} (60%) create mode 100644 qwt/src/qwt_interval.h delete mode 100644 qwt/src/qwt_interval_data.cpp delete mode 100644 qwt/src/qwt_interval_data.h create mode 100644 qwt/src/qwt_interval_symbol.cpp create mode 100644 qwt/src/qwt_interval_symbol.h delete mode 100644 qwt/src/qwt_layout_metrics.cpp delete mode 100644 qwt/src/qwt_layout_metrics.h create mode 100644 qwt/src/qwt_matrix_raster_data.cpp create mode 100644 qwt/src/qwt_matrix_raster_data.h create mode 100644 qwt/src/qwt_null_paintdevice.cpp create mode 100644 qwt/src/qwt_null_paintdevice.h delete mode 100644 qwt/src/qwt_paint_buffer.cpp delete mode 100644 qwt/src/qwt_paint_buffer.h create mode 100644 qwt/src/qwt_plot_directpainter.cpp create mode 100644 qwt/src/qwt_plot_directpainter.h create mode 100644 qwt/src/qwt_plot_histogram.cpp create mode 100644 qwt/src/qwt_plot_histogram.h create mode 100644 qwt/src/qwt_plot_intervalcurve.cpp create mode 100644 qwt/src/qwt_plot_intervalcurve.h delete mode 100644 qwt/src/qwt_plot_print.cpp delete mode 100644 qwt/src/qwt_plot_printfilter.cpp delete mode 100644 qwt/src/qwt_plot_printfilter.h create mode 100644 qwt/src/qwt_plot_renderer.cpp create mode 100644 qwt/src/qwt_plot_renderer.h create mode 100644 qwt/src/qwt_plot_seriesitem.cpp create mode 100644 qwt/src/qwt_plot_seriesitem.h create mode 100644 qwt/src/qwt_plot_spectrocurve.cpp create mode 100644 qwt/src/qwt_plot_spectrocurve.h rename qwt/src/{qwt_array.h => qwt_point_3d.cpp} (61%) create mode 100644 qwt/src/qwt_point_3d.h create mode 100644 qwt/src/qwt_point_polar.cpp create mode 100644 qwt/src/qwt_point_polar.h delete mode 100644 qwt/src/qwt_polygon.h create mode 100644 qwt/src/qwt_sampling_thread.cpp create mode 100644 qwt/src/qwt_sampling_thread.h create mode 100644 qwt/src/qwt_series_data.cpp create mode 100644 qwt/src/qwt_series_data.h create mode 100644 qwt/src/qwt_system_clock.cpp create mode 100644 qwt/src/qwt_system_clock.h delete mode 100644 qwt/src/qwt_valuelist.h create mode 100644 qwt/textengines/mathml/qtmmlwidget-license delete mode 100644 qwt/textengines/mathml/qtmmlwidget.cpp.diff create mode 100644 qwt/textengines/mathml/qwt_mml_document.cpp create mode 100644 qwt/textengines/mathml/qwt_mml_document.h create mode 100644 qwt/textengines/mathml/qwtmathml.prf diff --git a/qwt/.gitignore b/qwt/.gitignore index 755e94dd9..78ccff244 100644 --- a/qwt/.gitignore +++ b/qwt/.gitignore @@ -1,2 +1,6 @@ lib qwtconfig.pri +*.so +moc*.cpp +*.obj +*.o diff --git a/qwt/CHANGES b/qwt/CHANGES index adc90fcb0..1538f1500 100644 --- a/qwt/CHANGES +++ b/qwt/CHANGES @@ -1,24 +1,125 @@ +Release 6.0.1 +=================== + +Changes +------- +1) Incompatibilities with Qt < 4.6.1 fixed +2) Reduce warnings with pedantic compiler options +3) Examples fixed +4) Legend identifiers of with symbol and line fixed + +Release 6.0.0 +=================== + +Changes +------- +1) Qt3 support dropped +2) QwtPlot layout/render code ported from int to double + Exported/printed documents in scalable formats like SVG or PDF + are 100% scalable now. +3) Template base classes introduced for curve and curve data + to be reusable in all plot items displaying series of samples. +4) New plot items + - QwtPlotHistogram + - QwtPlotIntervalCurve ( error bars or displaying the area between 2 curves ) + - QwtPlotSpectroCurve ( mapping the z value to a color ) +5) Raster items + - QwtMatrixRasterData introduced + - More accurate rendering + - Several API changes + - Thread support for rendering spectrograms +6) QwtPlot::print moved to QwtPlotRenderer +7) Other new classes + QwtColumnSymbol + QwtDoublePoint3D + QwtIntervalSymbol + QwtPlotDirectPainter + QwtSamplingThread + QwtSystemClock +8) QwtPicker and friends reorganized, + QwtPickerTrackerMachine added for displaying a rubberband for + mouse moves. Enter/Leave added to events, that are handled + by the picker machines. +9) QwtScaleWidget::LayoutFlag added + Introduced to control the direction of vertical axis titles. +10)QwtWeedingCurveFitter added + QwtWeedingCurveFitter is an implementation of the Douglas/Peuker + algorithm, that can be used to reduce the number of curve points. + It can be very useful to improve the performance of painting + curves of many lines ( f.e. by implementing different level of details ). +11)Legend code update for representing different pixmaps for different + types of plot items. +12)Copy operators removed, using pointers instead +13)QwtPolarPoint from qwtpolar added +14)QwtThermo + Optional QwtColorMaps added +15)Interfaces and code of all sliders/dials cleaned up. + QApplication::globalStrut(), styled backgrounds ... + + +Release 5.2.2 +=================== + +Bug Fixes +--------- +1) QwtSplineCurveFitter + Rounding to integers values removed +2) QwtPlot + initial size of 200x200 +3) QwtPlotPrintFilter, QwtPlot::print + handling of background color in QwtPlot::print +4) QwtPlotPrintFilter + Problem with colored plot titles fixed +5) QwtPlotItem + Crash fixed, when changing the z order of attached items +6) QwtLinearScaleEngine, QwtLog10ScaleEngine + Several minor fixes + Release 5.2.1 =================== Bug Fixes --------- -1) QwtScaleDraw +1) Export declarations removed from qwt_valuelist.h to avoid + compiler errors with Qt 4.6 + certain compilers on Windows. +2) QwtScaleDraw Wrong border dist hints for unregular scale divisions fixed + Layout calculation for the tick labels fixed. + The layout was wrong by 1 pixel for top/left/bottom axes. + On a left axis without a title the labels were sometimes cut off. +3) QwtPainter + Splits polylines for all pens to avoid a bottleneck of the + raster paint engine. +4) QwtScaleWidget + Calculation of the colorbar position fixed ( spacing/margin ) +5) QwtPlotCurve + Wrong clipping rect fixed +6) QwtPicker + QwtPicker::setTrackerFont() fixed. + Recursion on the Mac, when constructing the rubberband fixed. + Workaround for a Qt3 bug added that is responsible for left aligning + all tracker texts to the canvas. + +Changes +------- +1) Project files adopted for symbian +2) qwt.pro + CONFIG += ordered added for using make -j + CONFIG += silent added Release 5.2.0 =================== Changes ------- -1) Ported to Qt 4.5.x +1) Ported to Qt 4.5.x 2) Scaling of non cosmetic pens (for printing to devices in high resolution) -3) Clipping of polygons for SVG rendering +3) Clipping of polygons for SVG rendering 4) QwtRect removed use QwtClipper instead 5) QwtPlotRescaler Introduced -6) QwtDoubleInterval +6) QwtDoubleInterval BorderMode introduced 7) QwtPlotCurve Performance of incremental curve painting ( = draw(from, to) ) improved. @@ -38,7 +139,7 @@ Changes counter clockwise scales introduced 15)QwtPlotMarker Vertical text labels -16)doc/qwt-5.2.0.qch added foe browsing the Qwt docs in the Qt assistant +16)doc/qwt-5.2.0.qch added foe browsing the Qwt docs in the Qt assistant Bug Fixes --------- diff --git a/qwt/INSTALL b/qwt/INSTALL index f65118559..f180ef02c 100644 --- a/qwt/INSTALL +++ b/qwt/INSTALL @@ -9,18 +9,14 @@ build a certain project. A project file ends with the suffix "*.pro". Files that end with the suffix "*.pri" are included by the project files and contain definitions, that are common for several project files. -qwtconfig.pri is read by all project files of the Qwt package. -So the first step is to edit qwtconfig.pri to adjust it to your -needs. +qwtconfig.pri and qwtbuild.pri are read by all project files of the Qwt +package. qwtconfig.pri is also read by qwt.prf, when building your +application. So the first step is to edit the *.pri files to adjust +them to your needs. -MathML Extension -================ - -Qwt/Qt4 supports the MathML render engine from the Qt solutions package, -that is only available with a commercial Qt license. - -You need a release of qtmmlwidget >= 2.1. -Copy the files qtmmlwidget.[cpp|h] to textengines/mathml. +The subdirs template of qmake is known to be buggy when using spaces +in path names. So better don't build Qwt below a path name with spaces. +( Otherwise you might have to run qmake in all subdirs manually ). Documentation ========================== @@ -29,12 +25,19 @@ Qwt includes a class documentation, that is available in various formats: - Html files - PDF document -- Qt Compressed Help (*.qch ) for the Qt assistant. +- Qt Compressed Help (*.qch ) for the Qt assistant or creator. + You can load it "Edit Preferences" -> "Documentation" -> "Add..." - Man pages ( UNIX only ) -A) Unix Qt3/Qt4 +Building Qwt ========================== +The easiest way to build Qwt is from the command line - but you insist on +using an IDE don't forget the "make install" step. + +A) Unix +-------- + qmake make make install @@ -57,8 +60,10 @@ qmake make -B) Win32/MSVC Qt3/Qt4 -===================== +B) Win32/MSVC +-------- + +Check that your Qt version has been built with MSVC - not with MinGW ! Please read the qmake documentation how to convert your *.pro files into your development environment. @@ -66,6 +71,7 @@ your *.pro files into your development environment. F.e MSVC with nmake: qmake qwt.pro nmake +nmake install If you didn't enable autobuilding of the examples in qwtconfig.pri you have to build the examples this way: @@ -74,32 +80,28 @@ cd examples qmake examples.pro nmake -admin/msvc-qmake.bat helps users of Visual Studio users to -generate makefiles or project files (.dsp for MSVC-6.0 or vcproj for -MSVC.NET) for Qwt. - -To generate makefiles, type: "admin\msvc-qmake" -To generate project files, type: "admin\msvc-qmake vc" - -When you have built a Qwt DLL you need to add the following -define to your compiler flags: QWT_DLL. - Windows doesn't like mixing of debug and release binaries. Most of the problems with using the Qwt designer plugin are because of trying to load a Qwt debug library into a designer release executable. +It's not possible to load a plugin, that has been built with MinGW +into a Qt Designer/Creator, that has been built with MSVC ( and v.v ). +This is a common reason for problems, when working with prebuild +binaries of the Qt Creator. -C) Win32/MinGW Qt4 -================== +C) Win32/MinGW +-------- -C1) Windows Shell +Check that your Qt version has been built with MinGW - not with MSVC ! -Start a Windows Shell, where Qt4 is initialized. ( F.e. with +Start a Shell, where Qt4 is initialized. ( F.e. with "Programs->Qt by Trolltech ...->Qt 4.x.x Command Prompt" ). +Check if you can execute "make" or something like "mingw32-make". qmake qwt.pro make +make install If you didn't enable autobuilding of the examples in qwtconfig.pri you have to build the examples this way: @@ -107,47 +109,17 @@ you have to build the examples this way: cd examples qmake examples.pro make -make install - -C2) MSYS Shell Qt >= 4.3.0 - -Support for the MSYS Shell has been improved in Qt 4.3.0. -Now building Qwt from the MSYS Shell works exactly like in UNIX or in the -Windows Shell - or at least it should: -because of a bug in Qt 4.3.0 you always have to do a "qmake -r". - -C3) MSYS Shell Qt < 4.3.0 - -For Qt < 4.3.0 you have to set the MINGW_IN_SHELL variable. -make will run into errors with the subdirs target, that can be -ignored (make -i). - -export MINGW_IN_SHELL=1; - -qmake -make -i -make -i install - -If you didn't enable autobuilding of the examples in qwtconfig.pri -you have to build the examples this way: - -cd examples -qmake examples.pro -make -i -make -i install - -C1-C3) - -When you have built a Qwt DLL you need to add QWT_DLL to your compiler -flags. If you are using qmake for your own builds this done by adding -the following line to your profile: "DEFINES += QWT_DLL". Windows doesn't like mixing of debug and release binaries. Most of the problems with using the Qwt designer plugin are because of trying to load a Qwt debug library into a designer release executable. +Don't forget to tell qmake where to find qwt.prf: +qmake -set QMAKEFEATURES ... + D) MacOSX +-------- Well, the Mac is only another Unix system. So read the instructions in A). @@ -158,19 +130,35 @@ following: qmake -spec macx-g++ ... -D) Qtopia Core +D) Qt Embedded +-------- -I only tested Qwt with Qtopia Core in qvfb (Virtual Framebuffer Devivce) +I only tested Qwt with Qt Embedded in qvfb (Virtual Framebuffer Devivce) Emulator on my Linux box. To build Qwt for the emulator was as simple as for a regular Unix build. -qmake -make +F) Symbian +-------- -E) Qtopia (!= Qtopia Core) +I never tried this platform myself. -I once compiled the Qwt library against Qtopia 4.2.0 successfully - but -not more. It should be possible to build and install Qwt, but it's -not done yet. +Using Qwt +=========== + +For building a Qwt application with qmake use the Qwt configuration features +file, that has been installed by "make install". When qmake is able to find +it ( http://doc.qt.nokia.com/4.7/qmake-advanced-usage.html#adding-new-configuration-features ) +you can simply add "CONFIG += qwt" to your application project file. + +If you don't use qmake you have to add the include path to find the Qwt +headers to your compiler flags and the Qwt library to your linker list. +Don't forget to add QWT_DLL to the compiler flags, when you work with a +Qwt-DLLs on Windows. + +For using the designer plugin you have to configure the Qt designer/creator +where to look for plugins. This can be done by setting the QT_PLUGIN_PATH or +using a qt.conf file ( see http://doc.qt.nokia.com/4.7/deployment-plugins.html ). +Beside the plugin the Qwt library itsself also needs to be known to the Designer/Creator +( see LD_LIBRARY_PATH, PATH ... above ). Good luck ! diff --git a/qwt/admin/msvc-qmake.bat b/qwt/admin/msvc-qmake.bat deleted file mode 100644 index 6cc2b7b0a..000000000 --- a/qwt/admin/msvc-qmake.bat +++ /dev/null @@ -1,58 +0,0 @@ -REM Batch file to make all Makefiles or all Visual Studio project files -REM (*.dsp for MSVC-6.0 or *.vcproj for MSVC-7.0) for Qwt with qmake. -REM -REM BUG: the designer plugin *.dsp file may not work; the Makefile does. -REM -REM To make Makefiles, type: msvc-qmake -REM To make project files type: msvc-qmake vc - -REM For the Qwt library: -cd src -qmake -t %1lib% src.pro -cd .. - -REM For the designer plugin: -cd textengines\mathml -qmake -t %1lib mathml.pro -cd ..\.. - -REM For the designer plugin: -cd designer -qmake -t %1lib designer.pro -cd .. - -REM For the examples: -cd examples -cd bode -qmake -t %1app bode.pro -cd ..\cpuplot -qmake -t %1app cpuplot.pro -cd ..\curvdemo1 -qmake -t %1app curvdemo1.pro -cd ..\curvdemo2 -qmake -t %1app curvdemo2.pro -cd ..\data_plot -qmake -t %1app data_plot.pro -cd ..\dials -qmake -t %1app dials.pro -cd ..\event_filter -qmake -t %1app event_filter.pro -cd ..\histogram -qmake -t %1app histogram.pro -cd ..\radio -qmake -t %1app radio.pro -cd ..\realtime_plot -qmake -t %1app realtime_plot.pro -cd ..\simple_plot -qmake -t %1app simple_plot.pro -cd ..\sliders -qmake -t %1app sliders.pro -cd ..\spectrogram -qmake -t %1app spectrogram.pro -cd ..\svgmap -qmake -t %1app svgmap.pro -cd ..\sysinfo -qmake -t %1app sysinfo.pro -cd ..\.. - -REM EOF diff --git a/qwt/admin/no-qt-keywords.sh b/qwt/admin/no-qt-keywords.sh deleted file mode 100755 index 6611bdb0b..000000000 --- a/qwt/admin/no-qt-keywords.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh - -find src -name "qwt_*.h" | xargs grep -l 'signals:' | xargs sed -i "s/signals:/Q_SIGNALS:/" -find src -name "qwt_*.h" | xargs grep -l 'slots:' | xargs sed -i "s/signals:/Q_SLOTS:/" -find src -name "qwt_*.cpp" | xargs grep -l 'emit ' | xargs sed -i "s/emit /Q_EMIT /" - -echo "CONFIG += no_keywords" >> src/src.pro - - diff --git a/qwt/admin/svn2package.sh b/qwt/admin/svn2package.sh deleted file mode 100755 index e58a7984e..000000000 --- a/qwt/admin/svn2package.sh +++ /dev/null @@ -1,299 +0,0 @@ -#! /bin/sh -# -# Generates a Qwt package from sourceforge svn -# -# Usage: svn2package.sh [-b|--branch ] [packagename] -# - -########################## -# usage -########################## - -function usage() { - echo "Usage: $0 [-b|--branch ] [-pdf] [-qch] [packagename]" - exit 1 -} - -################################ -# checkout -################################ - -function checkoutQwt() { - - if [ -x $2 ] - then - rm -r $2 - if [ $? -ne 0 ] - then - exit $? - fi - fi - - svn -q co https://qwt.svn.sourceforge.net/svnroot/qwt/$1/$2 - if [ $? -ne 0 ] - then - echo "Can't access sourceforge SVN" - exit $? - fi - - if [ "$3" != "$2" ] - then - rm -rf $3 - mv $2 $3 - fi -} - -########################## -# cleanQwt dirname -########################## - -function cleanQwt { - - cd $1 - if [ $? -ne 0 ] - then - exit $? - fi - - find . -name .svn -print | xargs rm -r - - rm TODO - rm admin/svn2package.sh - - PROFILES="qwtconfig.pri" - for PROFILE in $PROFILES - do - sed -i -e 's/= debug /= release /' $PROFILE - done - - HEADERS=`find . -type f -name '*.h' -print` - SOURCES=`find . -type f -name '*.cpp' -print` - PROFILES=`find . -type f -name '*.pro' -print` - PRIFILES=`find . -type f -name '*.pri' -print` - - for EXPANDFILE in $HEADERS $SOURCES $PROFILES $PRIFILES - do - expand -4 $EXPANDFILE > $EXPANDFILE.expand - mv $EXPANDFILE.expand $EXPANDFILE - done - - for SRCFILE in $SOURCES $PROFILES $PRIFILES - do - sed -i -e '/#warning/d' $SRCFILE - done - - sed -i -e "s/\$\$VERSION-svn/$VERSION/" qwtconfig.pri - sed -i -e "s/\$\${QwtVersion}-svn/\$\${QwtVersion}/" qwt.prf - - cd - > /dev/null -} - -########################## -# createDocs dirname -########################## - -function createDocs { - - ODIR=`pwd` - - cd $1 - if [ $? -ne 0 ] - then - exit $? - fi - - cp Doxyfile Doxyfile.doc - - sed -i '/PROJECT_NUMBER/d' Doxyfile.doc - echo "PROJECT_NUMBER = $VERSION" >> Doxyfile.doc - - if [ $GENERATE_MAN -ne 0 ] - then - sed -i -e '/GENERATE_MAN/d' -e '/PROJECT_NUMBER/d' Doxyfile.doc - echo 'GENERATE_MAN = YES' >> Doxyfile.doc - fi - - if [ $GENERATE_PDF -ne 0 ] - then - # We need LateX for the qwtdoc.pdf - - sed -i -e '/GENERATE_LATEX/d' -e '/GENERATE_MAN/d' -e '/PROJECT_NUMBER/d' Doxyfile.doc - echo 'GENERATE_LATEX = YES' >> Doxyfile.doc - echo 'GENERATE_MAN = YES' >> Doxyfile.doc - echo "PROJECT_NUMBER = $VERSION" >> Doxyfile.doc - fi - - if [ $GENERATE_QCH -ne 0 ] - then - sed -i -e '/GENERATE_HTMLHELP/d' Doxyfile.doc - echo "GENERATE_HTMLHELP = YES" >> Doxyfile.doc - fi - - cp ../INSTALL ../COPYING ./ - - doxygen Doxyfile.doc > /dev/null - if [ $? -ne 0 ] - then - exit $? - fi - - if [ $GENERATE_QCH -ne 0 ] - then - doxygen2qthelp --namespace=net.sourceforge.qwt-$VERSION --folder=qwt-$VERSION html/index.hhp qwt-$VERSION.qch - rm html/index.hh* - fi - - rm Doxyfile.doc Doxygen.log INSTALL COPYING - rm -r images - - if [ $GENERATE_PDF -ne 0 ] - then - cd latex - make > /dev/null 2>&1 - if [ $? -ne 0 ] - then - exit $? - fi - - cd .. - mkdir pdf - mv latex/refman.pdf pdf/qwtdoc.pdf - - rm -r latex - fi - - cd $ODIR -} - -########################## -# posix2dos filename -########################## - -function posix2dos { - # At least one unix2dos writes to stdout instead of overwriting the input. - # The -q option is always enabled in stdin->stdout mode. - unix2dos <$1 >$1.dos - mv $1.dos $1 -} - -########################## -# prepare4Win dirname -########################## - -function prepare4Win { - - cd $1 - if [ $? -ne 0 ] - then - exit $? - fi - - rm -r doc/man - - # win files, but not uptodate - - BATCHES=`find . -type f -name '*.bat' -print` - HEADERS=`find . -type f -name '*.h' -print` - SOURCES=`find . -type f -name '*.cpp' -print` - PROFILES=`find . -type f -name '*.pro' -print` - PRIFILES=`find . -type f -name '*.pri' -print` - - for FILE in $BATCHES $HEADERS $SOURCES $PROFILES $PRIFILES - do - posix2dos $FILE - done - - cd - > /dev/null -} - -########################## -# prepare4Unix dirname -########################## - -function prepare4Unix { - - cd $1 - if [ $? -ne 0 ] - then - exit $? - fi - - rm -rf admin - - cd - > /dev/null -} - -########################## -# main -########################## - -QWTDIR= -SVNDIR=trunk -BRANCH=qwt -VERSION= -GENERATE_PDF=0 -GENERATE_QCH=0 -GENERATE_MAN=1 - -while [ $# -gt 0 ] ; do - case "$1" in - -h|--help) - usage; exit 1 ;; - -b|--branch) - shift; SVNDIR=branches; BRANCH=$1; shift;; - -pdf) - GENERATE_PDF=1; shift;; - -qch) - GENERATE_QCH=1; shift;; - *) - QWTDIR=qwt-$1 ; VERSION=$1; shift;; - esac -done - -if [ "$QWTDIR" == "" ] -then - usage - exit 2 -fi - -TMPDIR=/tmp/$QWTDIR-tmp - -echo -n "checkout to $TMPDIR ... " -checkoutQwt $SVNDIR $BRANCH $TMPDIR -cleanQwt $TMPDIR -echo done - -echo -n "generate documentation ... " -createDocs $TMPDIR/doc - -if [ $GENERATE_PDF -ne 0 ] -then - mv $TMPDIR/doc/pdf/qwtdoc.pdf $QWTDIR.pdf - rmdir $TMPDIR/doc/pdf -fi - -echo done - - -DIR=`pwd` -echo -n "create packages in $DIR ... " - -cd /tmp - -rm -rf $QWTDIR -cp -a $TMPDIR $QWTDIR -prepare4Unix $QWTDIR -tar cfz $QWTDIR.tgz $QWTDIR -tar cfj $QWTDIR.tar.bz2 $QWTDIR - -rm -rf $QWTDIR -cp -a $TMPDIR $QWTDIR -prepare4Win $QWTDIR -zip -r $QWTDIR.zip $QWTDIR > /dev/null - -rm -rf $TMPDIR $QWTDIR - -mv $QWTDIR.tgz $QWTDIR.tar.bz2 $QWTDIR.zip $DIR/ -echo done - -exit 0 diff --git a/qwt/designer/.gitignore b/qwt/designer/.gitignore deleted file mode 100644 index f30057983..000000000 --- a/qwt/designer/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -moc -obj -plugins -resources diff --git a/qwt/designer/designer.pro b/qwt/designer/designer.pro index 2df4894a1..f1f6e4f8b 100644 --- a/qwt/designer/designer.pro +++ b/qwt/designer/designer.pro @@ -1,135 +1,72 @@ -# -*- mode: sh -*- ########################### +################################################################ # 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 -############################################## +################################################################ -QWT_ROOT = .. +QWT_ROOT = $${PWD}/.. include ( $${QWT_ROOT}/qwtconfig.pri ) +include ( $${QWT_ROOT}/qwtbuild.pri ) -contains(CONFIG, QwtDesigner) { +contains(QWT_CONFIG, QwtDesigner) { - CONFIG += warn_on + CONFIG += qt designer plugin + CONFIG += warn_on - SUFFIX_STR = + TEMPLATE = lib + TARGET = qwt_designer_plugin - VVERSION = $$[QT_VERSION] - isEmpty(VVERSION) { + DESTDIR = plugins/designer - # Qt 3 - debug { - SUFFIX_STR = $${DEBUG_SUFFIX} - } - else { - SUFFIX_STR = $${RELEASE_SUFFIX} - } + INCLUDEPATH += $${QWT_ROOT}/src + DEPENDPATH += $${QWT_ROOT}/src + + contains(QWT_CONFIG, QwtFramework) { + + LIBS += -F$${QWT_ROOT}/lib } else { - CONFIG(debug, debug|release) { - SUFFIX_STR = $${DEBUG_SUFFIX} - } - else { - SUFFIX_STR = $${RELEASE_SUFFIX} + LIBS += -L$${QWT_ROOT}/lib + } + + IPATH = $${INCLUDEPATH} + qtAddLibrary(qwt) + INCLUDEPATH = $${IPATH} + + contains(QWT_CONFIG, QwtDll) { + + win32 { + DEFINES += QT_DLL QWT_DLL } } - TEMPLATE = lib - MOC_DIR = moc - OBJECTS_DIR = obj$${SUFFIX_STR} - DESTDIR = plugins/designer - INCLUDEPATH += $${QWT_ROOT}/src - DEPENDPATH += $${QWT_ROOT}/src + !contains(QWT_CONFIG, QwtPlot) { + DEFINES += NO_QWT_PLOT + } - LIBNAME = qwt$${SUFFIX_STR} - contains(CONFIG, QwtDll) { - win32 { - DEFINES += QT_DLL QWT_DLL - LIBNAME = $${LIBNAME}$${VER_MAJ} - } - } + !contains(QWT_CONFIG, QwtWidgets) { + DEFINES += NO_QWT_WIDGETS + } - !contains(CONFIG, QwtPlot) { - DEFINES += NO_QWT_PLOT - } + HEADERS += qwt_designer_plugin.h + SOURCES += qwt_designer_plugin.cpp - !contains(CONFIG, QwtWidgets) { - DEFINES += NO_QWT_WIDGETS - } + contains(QWT_CONFIG, QwtPlot) { - unix:LIBS += -L$${QWT_ROOT}/lib -l$${LIBNAME} - win32-msvc:LIBS += $${QWT_ROOT}/lib/$${LIBNAME}.lib - win32-msvc.net:LIBS += $${QWT_ROOT}/lib/$${LIBNAME}.lib - win32-msvc2002:LIBS += $${QWT_ROOT}/lib/$${LIBNAME}.lib - win32-msvc2003:LIBS += $${QWT_ROOT}/lib/$${LIBNAME}.lib - win32-msvc2005:LIBS += $${QWT_ROOT}/lib/$${LIBNAME}.lib - win32-msvc2008:LIBS += $${QWT_ROOT}/lib/$${LIBNAME}.lib - win32-g++:LIBS += -L$${QWT_ROOT}/lib -l$${LIBNAME} + HEADERS += qwt_designer_plotdialog.h + SOURCES += qwt_designer_plotdialog.cpp + } - # isEmpty(QT_VERSION) does not work with Qt-4.1.0/MinGW + RESOURCES += qwt_designer_plugin.qrc - VVERSION = $$[QT_VERSION] - isEmpty(VVERSION) { - # Qt 3 - TARGET = qwtplugin$${SUFFIX_STR} - CONFIG += qt plugin - - UI_DIR = ui - - HEADERS += qwtplugin.h - SOURCES += qwtplugin.cpp - - target.path = $(QTDIR)/plugins/designer - INSTALLS += target - - IMAGES += \ - pixmaps/qwtplot.png \ - pixmaps/qwtanalogclock.png \ - pixmaps/qwtcounter.png \ - pixmaps/qwtcompass.png \ - pixmaps/qwtdial.png \ - pixmaps/qwtknob.png \ - pixmaps/qwtscale.png \ - pixmaps/qwtslider.png \ - pixmaps/qwtthermo.png \ - pixmaps/qwtwheel.png \ - pixmaps/qwtwidget.png - - } else { - - # Qt 4 - - TARGET = qwt_designer_plugin$${SUFFIX_STR} - CONFIG += qt designer plugin - - RCC_DIR = resources - - HEADERS += \ - qwt_designer_plugin.h - - SOURCES += \ - qwt_designer_plugin.cpp - - contains(CONFIG, QwtPlot) { - - HEADERS += \ - qwt_designer_plotdialog.h - - SOURCES += \ - qwt_designer_plotdialog.cpp - } - - RESOURCES += \ - qwt_designer_plugin.qrc - - target.path = $$[QT_INSTALL_PLUGINS]/designer - INSTALLS += target - } + target.path = $${QWT_INSTALL_PLUGINS} + INSTALLS += target } else { - TEMPLATE = subdirs # do nothing + TEMPLATE = subdirs # do nothing } diff --git a/qwt/designer/qwt_designer_plotdialog.cpp b/qwt/designer/qwt_designer_plotdialog.cpp index 65793a794..50d62dd80 100644 --- a/qwt/designer/qwt_designer_plotdialog.cpp +++ b/qwt/designer/qwt_designer_plotdialog.cpp @@ -15,7 +15,7 @@ using namespace QwtDesignerPlugin; -PlotDialog::PlotDialog(const QString &properties, QWidget *parent): +PlotDialog::PlotDialog(const QString &properties, QWidget *parent): QDialog(parent) { setWindowTitle("Plot Properties"); @@ -39,4 +39,3 @@ PlotDialog::PlotDialog(const QString &properties, QWidget *parent): mainLayout->addLayout(buttonLayout); setLayout(mainLayout); } - diff --git a/qwt/designer/qwt_designer_plotdialog.h b/qwt/designer/qwt_designer_plotdialog.h index 0de9260a9..b2e150724 100644 --- a/qwt/designer/qwt_designer_plotdialog.h +++ b/qwt/designer/qwt_designer_plotdialog.h @@ -10,27 +10,19 @@ #ifndef QWT_DESIGNER_PLOTDIALOG_H #define QWT_DESIGNER_PLOTDIALOG_H -#include - -#if QT_VERSION < 0x040000 -#ifdef __GNUC__ -#error This code is Qt4 only -#endif -#endif - #include namespace QwtDesignerPlugin { -class PlotDialog: public QDialog +class PlotDialog: public QDialog { Q_OBJECT public: PlotDialog(const QString &properties, QWidget *parent = NULL); -signals: +Q_SIGNALS: void edited(const QString&); }; diff --git a/qwt/designer/qwt_designer_plugin.cpp b/qwt/designer/qwt_designer_plugin.cpp index ea9a2e944..d0bad355d 100644 --- a/qwt/designer/qwt_designer_plugin.cpp +++ b/qwt/designer/qwt_designer_plugin.cpp @@ -42,7 +42,7 @@ using namespace QwtDesignerPlugin; -CustomWidgetInterface::CustomWidgetInterface(QObject *parent): +CustomWidgetInterface::CustomWidgetInterface(QObject *parent): QObject(parent), d_isInitialized(false) { @@ -116,13 +116,13 @@ void CustomWidgetInterface::initialize( #ifndef NO_QWT_PLOT -PlotInterface::PlotInterface(QObject *parent): +PlotInterface::PlotInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtPlot"; d_include = "qwt_plot.h"; d_icon = QPixmap(":/pixmaps/qwtplot.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -144,13 +144,13 @@ QWidget *PlotInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -AnalogClockInterface::AnalogClockInterface(QObject *parent): +AnalogClockInterface::AnalogClockInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtAnalogClock"; d_include = "qwt_analog_clock.h"; d_icon = QPixmap(":/pixmaps/qwtanalogclock.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -175,13 +175,13 @@ QWidget *AnalogClockInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -CompassInterface::CompassInterface(QObject *parent): +CompassInterface::CompassInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtCompass"; d_include = "qwt_compass.h"; d_icon = QPixmap(":/pixmaps/qwtcompass.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -206,13 +206,13 @@ QWidget *CompassInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -CounterInterface::CounterInterface(QObject *parent): +CounterInterface::CounterInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtCounter"; d_include = "qwt_counter.h"; d_icon = QPixmap(":/pixmaps/qwtcounter.png"); - d_domXml = + d_domXml = "\n" "\n"; } @@ -226,13 +226,13 @@ QWidget *CounterInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -DialInterface::DialInterface(QObject *parent): +DialInterface::DialInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtDial"; d_include = "qwt_dial.h"; d_icon = QPixmap(":/pixmaps/qwtdial.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -257,13 +257,13 @@ QWidget *DialInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -KnobInterface::KnobInterface(QObject *parent): +KnobInterface::KnobInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtKnob"; d_include = "qwt_knob.h"; d_icon = QPixmap(":/pixmaps/qwtknob.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -285,13 +285,13 @@ QWidget *KnobInterface::createWidget(QWidget *parent) #ifndef NO_QWT_PLOT -ScaleWidgetInterface::ScaleWidgetInterface(QObject *parent): +ScaleWidgetInterface::ScaleWidgetInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtScaleWidget"; d_include = "qwt_scale_widget.h"; d_icon = QPixmap(":/pixmaps/qwtscale.png"); - d_domXml = + d_domXml = "\n" "\n"; } @@ -305,13 +305,13 @@ QWidget *ScaleWidgetInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -SliderInterface::SliderInterface(QObject *parent): +SliderInterface::SliderInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtSlider"; d_include = "qwt_slider.h"; d_icon = QPixmap(":/pixmaps/qwtslider.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -337,18 +337,14 @@ QWidget *SliderInterface::createWidget(QWidget *parent) #endif -TextLabelInterface::TextLabelInterface(QObject *parent): +TextLabelInterface::TextLabelInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtTextLabel"; d_include = "qwt_text_label.h"; -#ifdef __GNUC__ -#warning QwtTextLabel icon is missing -#endif - d_icon = QPixmap(":/pixmaps/qwtwidget.png"); - d_domXml = + d_domXml = "\n" " \n" " \n" @@ -368,13 +364,13 @@ QWidget *TextLabelInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -ThermoInterface::ThermoInterface(QObject *parent): +ThermoInterface::ThermoInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtThermo"; d_include = "qwt_thermo.h"; d_icon = QPixmap(":/pixmaps/qwtthermo.png"); - d_domXml = + d_domXml = "\n" "\n"; } @@ -388,13 +384,13 @@ QWidget *ThermoInterface::createWidget(QWidget *parent) #ifndef NO_QWT_WIDGETS -WheelInterface::WheelInterface(QObject *parent): +WheelInterface::WheelInterface(QObject *parent): CustomWidgetInterface(parent) { d_name = "QwtWheel"; d_include = "qwt_wheel.h"; d_icon = QPixmap(":/pixmaps/qwtwheel.png"); - d_domXml = + d_domXml = "\n" "\n"; } @@ -406,8 +402,8 @@ QWidget *WheelInterface::createWidget(QWidget *parent) #endif -CustomWidgetCollectionInterface::CustomWidgetCollectionInterface( - QObject *parent): +CustomWidgetCollectionInterface::CustomWidgetCollectionInterface( + QObject *parent): QObject(parent) { #ifndef NO_QWT_PLOT @@ -429,13 +425,13 @@ CustomWidgetCollectionInterface::CustomWidgetCollectionInterface( d_plugins.append(new TextLabelInterface(this)); } -QList +QList CustomWidgetCollectionInterface::customWidgets(void) const { return d_plugins; } -TaskMenuFactory::TaskMenuFactory(QExtensionManager *parent): +TaskMenuFactory::TaskMenuFactory(QExtensionManager *parent): QExtensionFactory(parent) { } @@ -460,11 +456,11 @@ QObject *TaskMenuFactory::createExtension( TaskMenuExtension::TaskMenuExtension(QWidget *widget, QObject *parent): - QObject(parent), + QObject(parent), d_widget(widget) { d_editAction = new QAction(tr("Edit Qwt Attributes ..."), this); - connect(d_editAction, SIGNAL(triggered()), + connect(d_editAction, SIGNAL(triggered()), this, SLOT(editProperties())); } @@ -492,7 +488,7 @@ void TaskMenuExtension::editProperties() if ( qobject_cast(d_widget) ) { PlotDialog dialog(properties); - connect(&dialog, SIGNAL(edited(const QString&)), + connect(&dialog, SIGNAL(edited(const QString&)), SLOT(applyProperties(const QString &))); (void)dialog.exec(); return; diff --git a/qwt/designer/qwt_designer_plugin.h b/qwt/designer/qwt_designer_plugin.h index d631255ad..b181844f9 100644 --- a/qwt/designer/qwt_designer_plugin.h +++ b/qwt/designer/qwt_designer_plugin.h @@ -10,16 +10,6 @@ #ifndef QWT_DESIGNER_PLUGIN_H #define QWT_DESIGNER_PLUGIN_H -#include - -#if QT_VERSION < 0x040000 - -#ifdef __GNUC__ -#error This code is Qt4 only -#endif - -#endif - #include #include #include @@ -27,7 +17,7 @@ namespace QwtDesignerPlugin { -class CustomWidgetInterface: public QObject, +class CustomWidgetInterface: public QObject, public QDesignerCustomWidgetInterface { Q_OBJECT @@ -49,11 +39,11 @@ public: virtual void initialize(QDesignerFormEditorInterface *); protected: - QString d_name; - QString d_include; - QString d_toolTip; - QString d_whatsThis; - QString d_domXml; + QString d_name; + QString d_include; + QString d_toolTip; + QString d_whatsThis; + QString d_domXml; QString d_codeTemplate; QIcon d_icon; @@ -77,7 +67,7 @@ private: }; #ifndef NO_QWT_PLOT -class PlotInterface: public CustomWidgetInterface +class PlotInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -89,7 +79,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class AnalogClockInterface: public CustomWidgetInterface +class AnalogClockInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -101,7 +91,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class CompassInterface: public CustomWidgetInterface +class CompassInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -113,7 +103,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class CounterInterface: public CustomWidgetInterface +class CounterInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -125,7 +115,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class DialInterface: public CustomWidgetInterface +class DialInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -137,7 +127,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class KnobInterface: public CustomWidgetInterface +class KnobInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -149,7 +139,7 @@ public: #endif #ifndef NO_QWT_PLOT -class ScaleWidgetInterface: public CustomWidgetInterface +class ScaleWidgetInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -161,7 +151,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class SliderInterface: public CustomWidgetInterface +class SliderInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -172,7 +162,7 @@ public: }; #endif -class TextLabelInterface: public CustomWidgetInterface +class TextLabelInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -183,7 +173,7 @@ public: }; #ifndef NO_QWT_WIDGETS -class ThermoInterface: public CustomWidgetInterface +class ThermoInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -195,7 +185,7 @@ public: #endif #ifndef NO_QWT_WIDGETS -class WheelInterface: public CustomWidgetInterface +class WheelInterface: public CustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) @@ -214,7 +204,7 @@ public: TaskMenuFactory(QExtensionManager *parent = 0); protected: - QObject *createExtension(QObject *object, + QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const; }; @@ -230,7 +220,7 @@ public: QAction *preferredEditAction() const; QList taskActions() const; -private slots: +private Q_SLOTS: void editProperties(); void applyProperties(const QString &); diff --git a/qwt/designer/qwtplugin.cpp b/qwt/designer/qwtplugin.cpp deleted file mode 100644 index 2ee6f6903..000000000 --- a/qwt/designer/qwtplugin.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#if defined(_MSC_VER) /* MSVC Compiler */ -#pragma warning ( disable : 4786 ) -#endif - -#include -#include -#include -#include - -#include "qwtplugin.h" -#include "qwt_text_label.h" - -#ifndef NO_QWT_PLOT -#include "qwt_plot.h" -#include "qwt_scale_widget.h" -#endif - -#ifndef NO_QWT_WIDGETS -#include "qwt_counter.h" -#include "qwt_wheel.h" -#include "qwt_thermo.h" -#include "qwt_knob.h" -#include "qwt_slider.h" -#include "qwt_analog_clock.h" -#include "qwt_compass.h" -#endif - -namespace -{ - struct Entry - { - Entry() {} - Entry( QString _classname, QString _header, QString _pixmap, - QString _tooltip, QString _whatshis): - classname(_classname), - header(_header), - pixmap(_pixmap), - tooltip(_tooltip), - whatshis(_whatshis) - {} - - QString classname; - QString header; - QString pixmap; - QString tooltip; - QString whatshis; - }; - - QValueList vec; - - const Entry *entry(const QString& str) - { - for ( uint i = 0; i < vec.count(); i++ ) - { - if (str == vec[i].classname) - return &vec[i]; - } - return NULL; - } -} - -QwtPlugin::QwtPlugin() -{ -#ifndef NO_QWT_PLOT - vec.append(Entry("QwtPlot", "qwt_plot.h", - "qwtplot.png", "QwtPlot", "whatsthis")); - vec.append(Entry("QwtScaleWidget", "qwt_scale_widget.h", - "qwtscale.png", "QwtScaleWidget", "whatsthis")); -#endif - -#ifndef NO_QWT_WIDGETS - vec.append(Entry("QwtAnalogClock", "qwt_analog_clock.h", - "qwtanalogclock.png", "QwtAnalogClock", "whatsthis")); - vec.append(Entry("QwtCompass", "qwt_compass.h", - "qwtcompass.png", "QwtCompass", "whatsthis")); - vec.append(Entry("QwtCounter", "qwt_counter.h", - "qwtcounter.png", "QwtCounter", "whatsthis")); - vec.append(Entry("QwtDial", "qwt_dial.h", - "qwtdial.png", "QwtDial", "whatsthis")); - vec.append(Entry("QwtKnob", "qwt_knob.h", - "qwtknob.png", "QwtKnob", "whatsthis")); - vec.append(Entry("QwtSlider", "qwt_slider.h", - "qwtslider.png", "QwtSlider", "whatsthis")); - vec.append(Entry("QwtThermo", "qwt_thermo.h", - "qwtthermo.png", "QwtThermo", "whatsthis")); - vec.append(Entry("QwtWheel", "qwt_wheel.h", - "qwtwheel.png", "QwtWheel", "whatsthis")); -#endif - - vec.append(Entry("QwtTextLabel", "qwt_text_label.h", - "qwtwidget.png", "QwtTextLabel", "whatsthis")); - -} - -QWidget* QwtPlugin::create(const QString &key, - QWidget* parent, const char* name) -{ - QWidget *w = NULL; - -#ifndef NO_QWT_PLOT - if ( key == "QwtPlot" ) - w = new QwtPlot( parent ); - else if ( key == "QwtScaleWidget" ) - w = new QwtScaleWidget( QwtScaleDraw::LeftScale, parent); -#endif - -#ifndef NO_QWT_WIDGETS - if ( key == "QwtAnalogClock" ) - w = new QwtAnalogClock( parent); - else if ( key == "QwtCounter" ) - w = new QwtCounter( parent); - else if ( key == "QwtCompass" ) - w = new QwtCompass( parent); - else if ( key == "QwtDial" ) - w = new QwtDial( parent); - else if ( key == "QwtWheel" ) - w = new QwtWheel( parent); - else if ( key == "QwtThermo" ) - w = new QwtThermo( parent); - else if ( key == "QwtKnob" ) - w = new QwtKnob( parent); - else if ( key == "QwtSlider" ) - w = new QwtSlider( parent); -#endif - - if ( key == "QwtTextLabel" ) - w = new QwtTextLabel( parent); - - if ( w ) - w->setName(name); - - return w; -} - -QStringList QwtPlugin::keys() const -{ - QStringList list; - - for (unsigned i = 0; i < vec.count(); i++) - list += vec[i].classname; - - return list; -} - -QString QwtPlugin::group( const QString& feature ) const -{ - if (entry(feature) != NULL ) - return QString("Qwt"); - return QString::null; -} - -QIconSet QwtPlugin::iconSet( const QString& pmap) const -{ - QString pixmapKey("qwtwidget.png"); - if (entry(pmap) != NULL ) - pixmapKey = entry(pmap)->pixmap; - - const QMimeSource *ms = - QMimeSourceFactory::defaultFactory()->data(pixmapKey); - - QPixmap pixmap; - QImageDrag::decode(ms, pixmap); - - return QIconSet(pixmap); -} - -QString QwtPlugin::includeFile( const QString& feature ) const -{ - if (entry(feature) != NULL) - return entry(feature)->header; - return QString::null; -} - -QString QwtPlugin::toolTip( const QString& feature ) const -{ - if (entry(feature) != NULL ) - return entry(feature)->tooltip; - return QString::null; -} - -QString QwtPlugin::whatsThis( const QString& feature ) const -{ - if (entry(feature) != NULL) - return entry(feature)->whatshis; - return QString::null; -} - -bool QwtPlugin::isContainer( const QString& ) const -{ - return false; -} - -Q_EXPORT_PLUGIN( QwtPlugin ) diff --git a/qwt/designer/qwtplugin.h b/qwt/designer/qwtplugin.h deleted file mode 100644 index 3b78520a1..000000000 --- a/qwt/designer/qwtplugin.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#ifndef QWT_PLUGIN_H -#define QWT_PLUGIN_H - -#include - -#if QT_VERSION >= 0x040000 - -#ifdef __GNUC__ -#error This code is Qt3 only -#endif - -This code is Qt3 only - -#endif - -#include - -class QT_WIDGET_PLUGIN_EXPORT QwtPlugin: public QWidgetPlugin -{ -public: - QwtPlugin(); - - QStringList keys() const; - QWidget* create( const QString &classname, QWidget* parent = 0, const char* name = 0 ); - QString group( const QString& ) const; - QIconSet iconSet( const QString& ) const; - QString includeFile( const QString& ) const; - QString toolTip( const QString& ) const; - QString whatsThis( const QString& ) const; - bool isContainer( const QString& ) const; -}; - -#endif diff --git a/qwt/designer/resources/qrc_qwt_designer_plugin.cpp b/qwt/designer/resources/qrc_qwt_designer_plugin.cpp new file mode 100644 index 000000000..247e0a57e --- /dev/null +++ b/qwt/designer/resources/qrc_qwt_designer_plugin.cpp @@ -0,0 +1,615 @@ +/**************************************************************************** +** Resource object code +** +** Created: Thu Feb 2 22:55:24 2012 +** by: The Resource Compiler for Qt version 4.7.4 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtslider.png + 0x0,0x0,0x1,0xc4, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x6,0x0,0x0,0x0,0xc4,0xb4,0x6c,0x3b, + 0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2,0xa,0x9,0x13,0xa,0x30,0x66, + 0xcc,0x85,0xa0,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0, + 0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41, + 0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x1,0x53,0x49,0x44,0x41,0x54, + 0x78,0xda,0x63,0x60,0x18,0x5,0xc3,0xf,0xfc,0x47,0x2,0x75,0x4b,0xba,0xfe,0x93, + 0xaa,0x9f,0x9,0x9f,0xe4,0xa7,0x6f,0x9f,0x18,0x8e,0x5c,0x3e,0x2,0x66,0xfb,0x54, + 0x5,0x92,0x64,0x38,0x13,0x29,0x8a,0x7,0x85,0xc1,0x2c,0x30,0x6,0xa3,0x3,0xdb, + 0xff,0xff,0xc,0xff,0x21,0x76,0x31,0x62,0x2a,0x3c,0x7d,0xed,0x24,0x3,0x83,0x23, + 0x3b,0xee,0xe0,0x60,0x62,0x66,0xe0,0x16,0x55,0x64,0xf8,0xba,0xe2,0x2a,0x23,0xdc, + 0x60,0x26,0xa0,0xa1,0xff,0x18,0x99,0x18,0xf8,0x85,0x14,0x18,0xd8,0xd8,0x79,0x19, + 0x18,0x81,0x8a,0xb0,0x1,0x31,0x69,0x43,0x1c,0xa6,0x32,0x32,0x30,0xb1,0xb0,0x31, + 0xbc,0xf8,0xf0,0x88,0x41,0xa2,0x2a,0xe1,0xff,0x8b,0xb6,0x5,0x8c,0x60,0x83,0xff, + 0x31,0x32,0x32,0x8,0x89,0xaa,0x32,0x18,0x5a,0xa7,0x30,0xe8,0x2a,0x6a,0x3,0x2d, + 0x67,0xc1,0xd0,0xca,0x2d,0xac,0xcc,0x10,0x10,0xd4,0x8c,0xdd,0xb1,0x40,0x87,0xbc, + 0xff,0xf5,0x9f,0xe1,0xee,0xc5,0x5,0xc,0x92,0x2,0x22,0xc,0xcb,0x61,0x2e,0xe6, + 0x16,0x53,0x66,0x78,0xf7,0xf3,0x13,0xc3,0xb1,0xb3,0x8b,0x19,0x98,0xbf,0x1a,0x33, + 0xb0,0xb3,0xb0,0x32,0x30,0x78,0xd9,0xa3,0x68,0xfe,0xfa,0xe9,0x29,0xc3,0xed,0xab, + 0x6b,0xb0,0x1a,0xcc,0xc9,0xce,0xc1,0xa0,0x2c,0x2e,0xcb,0xe0,0xe0,0x18,0xc8,0x20, + 0x22,0x2a,0x7,0x34,0xb8,0xb,0x62,0xf0,0xd7,0x95,0xd7,0x18,0x25,0x2a,0xe3,0xfe, + 0x4b,0xfc,0xfb,0xce,0x20,0x21,0x20,0xcc,0xc0,0xce,0xca,0x86,0xa1,0x99,0x9d,0x95, + 0x9d,0x41,0x42,0x50,0x4,0xab,0xc1,0x1c,0x40,0x39,0x61,0x1e,0x7e,0x6,0x69,0x49, + 0x25,0x6,0x27,0x15,0x6d,0x46,0x48,0xe0,0xe0,0x0,0xa0,0x8c,0x1,0x4a,0xc7,0x97, + 0xee,0x5e,0x62,0xd8,0x7d,0xe9,0x38,0xc3,0xb9,0x6b,0xc7,0x19,0xb6,0xb4,0xad,0xc7, + 0xa9,0x1e,0x23,0x78,0x88,0x55,0x48,0x2a,0xa0,0x7d,0x3a,0x46,0x7,0x69,0x53,0x2b, + 0x28,0x32,0x18,0x6f,0x98,0xa1,0x97,0xf,0xa4,0x84,0xf1,0x28,0x80,0x3,0x0,0xb9, + 0xf0,0x60,0x59,0x7a,0xd9,0xd8,0x20,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae, + 0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtdial.png + 0x0,0x0,0x1,0xb1, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x2,0x0,0x0,0x0,0x4b,0xd6,0xfb,0x6c, + 0x0,0x0,0x1,0x78,0x49,0x44,0x41,0x54,0x78,0x9c,0x9d,0x94,0x31,0x8e,0xc2,0x30, + 0x10,0x45,0x7,0x67,0x63,0x8d,0x81,0x2b,0x50,0x86,0x3,0xa4,0xa6,0xe2,0x0,0xf4, + 0x5c,0x82,0x9e,0x1b,0x70,0x83,0xb4,0x91,0xb8,0x41,0x2a,0x9a,0x70,0x84,0xa4,0x81, + 0xa,0x21,0x21,0x51,0x50,0x50,0x23,0x41,0x50,0xa4,0x2d,0x7e,0xd6,0xc,0xe,0xc9, + 0x66,0xf7,0x57,0x96,0x3d,0xff,0x79,0x3c,0xc9,0x4c,0x2f,0xcb,0x32,0x12,0x3a,0x1c, + 0xe,0xd4,0xaa,0x20,0x8,0x9c,0x9d,0xaf,0x8f,0xfe,0x3c,0xcf,0x99,0xd9,0x18,0xe3, + 0x79,0x9e,0xc,0x18,0x8d,0x46,0x88,0x91,0xa0,0x9e,0xcd,0x2,0x67,0x69,0x9a,0x6a, + 0xad,0x8d,0x31,0xf3,0xf9,0xdc,0xb9,0x6d,0xbb,0xdd,0x5a,0x90,0xa4,0x54,0x8,0xf8, + 0x93,0x24,0xf1,0x7d,0x7f,0xb1,0x58,0x48,0x67,0x18,0x86,0xf2,0xb1,0x0,0x49,0x8a, + 0xb2,0xfe,0xf5,0x7a,0x5d,0x14,0x5,0xfc,0x61,0x18,0x5a,0x8f,0x53,0xac,0xe9,0x74, + 0x4a,0x44,0xe7,0xf3,0xd9,0x1a,0x15,0xe,0xa2,0x28,0x2a,0x8a,0x62,0xb9,0x5c,0x3a, + 0xb6,0x44,0xb0,0x2c,0xd7,0xa1,0x28,0x90,0xca,0xb2,0x5c,0xad,0x56,0xd4,0x2a,0x99, + 0xe,0x28,0x90,0x22,0xa2,0x38,0x8e,0x8d,0x31,0x4e,0xfe,0x2d,0x42,0x98,0xd6,0xfa, + 0x7a,0xbd,0x56,0x8,0x63,0xc,0x52,0x70,0x9e,0xdd,0x9e,0xce,0x64,0x32,0xc1,0xc5, + 0x15,0xa2,0x29,0x7a,0x96,0x65,0x49,0x73,0x6a,0xcc,0x5c,0x21,0x7c,0xdf,0xef,0x72, + 0x79,0x5d,0x30,0x2a,0x22,0x1a,0xe,0x87,0xd4,0xb9,0x10,0x10,0x82,0x7,0x83,0x41, + 0x85,0xd0,0x5a,0x53,0x73,0x21,0x66,0x9f,0xf6,0x11,0xc,0xe3,0x2f,0xb5,0x68,0xd7, + 0xab,0x16,0xcc,0xbc,0xd9,0x6c,0xfe,0x81,0x78,0x7d,0x91,0xf1,0x78,0x8c,0x94,0xfe, + 0xea,0x3f,0x1e,0x8f,0x64,0x7f,0x70,0x12,0x8d,0xd8,0x51,0x65,0x59,0x62,0xa1,0xd0, + 0x6d,0xe8,0xbc,0x8e,0x94,0xdb,0xed,0xf6,0x7c,0x3e,0xf7,0xfb,0x3d,0x11,0x5,0x41, + 0xa0,0xe8,0xa7,0x67,0x3b,0x52,0x2e,0x97,0xcb,0xfd,0x7e,0x3f,0x9d,0x4e,0xd6,0xe8, + 0x8e,0x1c,0xf4,0x1f,0xbd,0x37,0x12,0xb4,0xdb,0xed,0x98,0x59,0x6b,0xfd,0x78,0x3c, + 0xa8,0x3e,0x72,0x24,0x45,0x82,0x20,0xcf,0xf3,0x98,0x99,0x99,0xfb,0xfd,0x3e,0x76, + 0xe4,0xe0,0x7b,0x9b,0x9d,0xf5,0xd1,0x5a,0x57,0x3d,0xe6,0x1b,0xf1,0xc5,0xa7,0x36, + 0x5f,0xe6,0x63,0x88,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtwheel.png + 0x0,0x0,0x1,0x2a, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x3,0x0,0x0,0x0,0xf3,0x6a,0x9c,0x9, + 0x0,0x0,0x0,0x2a,0x74,0x45,0x58,0x74,0x43,0x72,0x65,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x54,0x69,0x6d,0x65,0x0,0x4d,0x69,0x20,0x39,0x20,0x4f,0x6b,0x74,0x20,0x32, + 0x30,0x30,0x32,0x20,0x32,0x32,0x3a,0x35,0x33,0x3a,0x30,0x30,0x20,0x2b,0x30,0x31, + 0x30,0x30,0x8a,0x59,0x4f,0x7f,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2, + 0xa,0x9,0x14,0x38,0x1c,0xbc,0x2b,0xab,0xb7,0x0,0x0,0x0,0x9,0x70,0x48,0x59, + 0x73,0x0,0x0,0xe,0xc3,0x0,0x0,0xe,0xc3,0x1,0xc7,0x6f,0xa8,0x64,0x0,0x0, + 0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0, + 0x0,0x27,0x50,0x4c,0x54,0x45,0xfb,0xb3,0x8,0xfb,0xfb,0xfb,0x75,0x75,0x75,0xd7, + 0xd7,0xd7,0xe1,0xe1,0xe1,0xf2,0xf2,0xf2,0xea,0xea,0xea,0xc6,0xc6,0xc6,0xbd,0xbd, + 0xbd,0xb3,0xb3,0xb3,0xa1,0xa1,0xa1,0x86,0x86,0x86,0x7d,0x7d,0x7d,0xab,0xa1,0x7c, + 0x5d,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0, + 0x0,0x43,0x49,0x44,0x41,0x54,0x78,0xda,0xcd,0x8f,0x37,0xe,0x0,0x20,0x10,0xc3, + 0xc8,0xd1,0xcb,0xff,0xdf,0x4b,0x13,0x4c,0x61,0x3,0x9,0xf,0x1e,0x9c,0x29,0x4a, + 0xdd,0x40,0x18,0xa0,0x19,0x3d,0x83,0x30,0xf3,0x98,0xe6,0x2e,0x2b,0x6b,0x6d,0x4, + 0xd6,0x35,0xf9,0x10,0x93,0x20,0x97,0xcf,0xf2,0xf8,0xb5,0xd5,0x8d,0xf3,0x79,0xd0, + 0xf3,0xe0,0xf9,0x21,0x15,0xd5,0x8b,0x3,0xae,0x41,0xc3,0x32,0xc9,0x0,0x0,0x0, + 0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtplot.png + 0x0,0x0,0x2,0x1f, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x6,0x0,0x0,0x0,0xc4,0xb4,0x6c,0x3b, + 0x0,0x0,0x0,0x2a,0x74,0x45,0x58,0x74,0x43,0x72,0x65,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x54,0x69,0x6d,0x65,0x0,0x4d,0x69,0x20,0x39,0x20,0x4f,0x6b,0x74,0x20,0x32, + 0x30,0x30,0x32,0x20,0x32,0x31,0x3a,0x32,0x34,0x3a,0x33,0x30,0x20,0x2b,0x30,0x31, + 0x30,0x30,0x72,0xfb,0x2a,0xa8,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2, + 0xa,0x9,0x13,0x21,0x1,0x41,0x62,0x78,0xf3,0x0,0x0,0x0,0x9,0x70,0x48,0x59, + 0x73,0x0,0x0,0xa,0xf0,0x0,0x0,0xa,0xf0,0x1,0x42,0xac,0x34,0x98,0x0,0x0, + 0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0, + 0x1,0x78,0x49,0x44,0x41,0x54,0x78,0xda,0x63,0x60,0x18,0x5,0x74,0x5,0x1a,0x62, + 0x5c,0xff,0xa9,0x65,0x16,0x23,0x36,0x43,0x6f,0xbc,0xfa,0xc6,0x48,0x9e,0x71,0x8, + 0xc0,0x34,0x28,0x82,0xe2,0x8c,0x28,0x13,0xb,0x10,0xf3,0x82,0x68,0xaa,0xb9,0x18, + 0x68,0x98,0x12,0xab,0x84,0xd4,0x46,0x16,0x11,0xb1,0xb,0x2c,0xc2,0x22,0x1b,0x81, + 0x7c,0x1d,0x8a,0xd,0x6,0x1a,0xc2,0xc5,0x22,0x2e,0x39,0x8b,0x4d,0x5e,0xc9,0x41, + 0xaa,0x7b,0x9a,0x12,0xbb,0xba,0xb6,0x3d,0xd0,0x82,0x79,0x40,0x71,0x41,0x8a,0x82, + 0xe2,0x82,0x96,0xa4,0xf7,0x39,0x25,0x81,0x9f,0x6f,0x76,0x6f,0xfb,0xff,0xfd,0xfb, + 0xf7,0xff,0x1f,0x2e,0x9e,0xfb,0x7f,0x41,0x53,0xe2,0xfb,0x5,0xd,0xf1,0x2c,0x8a, + 0x5c,0xcc,0xc8,0xce,0x9e,0xc0,0xa1,0xaa,0xc9,0xc4,0x69,0x60,0x2,0xe6,0xb3,0xab, + 0x6a,0x30,0xf0,0xfb,0x87,0xb2,0x32,0x30,0x31,0x65,0x2,0x5d,0xcd,0x47,0x96,0xc1, + 0xa0,0xc8,0xfa,0xff,0xeb,0x97,0x9,0xaf,0x87,0x1f,0xb,0x13,0xf,0x2f,0xd4,0x26, + 0x46,0x6,0x81,0xe0,0x28,0xe6,0xff,0x3f,0x7f,0xa8,0x30,0x71,0xf3,0xb8,0x92,0x65, + 0x30,0xb3,0xa0,0x50,0x0,0x23,0xb,0x8b,0x18,0xaf,0x93,0x3b,0x8a,0x38,0xbb,0xba, + 0x16,0x3,0xb7,0x8d,0x23,0x33,0xb3,0xa0,0x70,0x2e,0xd0,0x72,0x36,0xa2,0xd,0x6, + 0x29,0x3e,0x2b,0xcd,0xe1,0xf3,0xff,0xf7,0xef,0xe,0x7e,0xbf,0x50,0x66,0x90,0xf7, + 0x51,0x82,0x87,0x95,0x8d,0x41,0x24,0xbd,0x80,0x95,0x91,0x91,0xd1,0x8c,0x55,0x5a, + 0xb6,0x10,0xdd,0x70,0x26,0x2c,0x6,0x32,0x9e,0x95,0x64,0xb3,0x7,0x25,0x29,0x26, + 0xe,0xce,0xe5,0x40,0x43,0x85,0x45,0xf3,0x2a,0xd8,0x41,0xde,0x47,0x7,0x9c,0x86, + 0xa6,0x3f,0x84,0x92,0xb3,0x19,0xff,0x7d,0xf9,0x5c,0xcf,0xa6,0xa8,0xd2,0xf,0xd4, + 0xcb,0xc,0x93,0xc3,0x96,0xd0,0x99,0x19,0xd9,0xd8,0x4d,0x59,0xa5,0x64,0xdf,0x9, + 0x84,0xc7,0xf5,0xf3,0x79,0xf8,0x3d,0x65,0xe2,0xe1,0xf9,0x85,0xc3,0x63,0xf,0xf9, + 0xdc,0x7d,0x3f,0xfe,0xb8,0x7c,0x5e,0xe7,0xef,0xfb,0x77,0x4f,0xf5,0x4e,0xdd,0xfa, + 0x8b,0x55,0x15,0x25,0x85,0x10,0x48,0x2f,0xb2,0x7e,0x46,0x74,0x49,0x72,0xd,0x46, + 0x6,0xd4,0x28,0xc4,0x70,0xba,0x78,0xe8,0x1,0x0,0x3e,0x3c,0x69,0x30,0x7,0xb3, + 0x24,0xc3,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtscale.png + 0x0,0x0,0x1,0x75, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x6,0x0,0x0,0x0,0xc4,0xb4,0x6c,0x3b, + 0x0,0x0,0x0,0x2b,0x74,0x45,0x58,0x74,0x43,0x72,0x65,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x54,0x69,0x6d,0x65,0x0,0x53,0x6f,0x20,0x32,0x37,0x20,0x4f,0x6b,0x74,0x20, + 0x32,0x30,0x30,0x32,0x20,0x31,0x36,0x3a,0x31,0x33,0x3a,0x32,0x32,0x20,0x2b,0x30, + 0x31,0x30,0x30,0x8c,0x3a,0x78,0x7b,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7, + 0xd2,0xa,0x1b,0x11,0x10,0x23,0xab,0xcb,0x75,0xdf,0x0,0x0,0x0,0x9,0x70,0x48, + 0x59,0x73,0x0,0x0,0xa,0xf0,0x0,0x0,0xa,0xf0,0x1,0x42,0xac,0x34,0x98,0x0, + 0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0, + 0x0,0x0,0xcd,0x49,0x44,0x41,0x54,0x78,0xda,0x63,0x64,0xc0,0x3,0x74,0xf4,0xa6, + 0x54,0x2,0x29,0x6f,0x1c,0xd2,0x6c,0x40,0xfc,0x13,0x88,0x23,0xaf,0x5c,0xca,0x79, + 0x82,0x2e,0xc9,0xc2,0x80,0x1f,0xf4,0x3,0xf1,0x14,0x5c,0xf6,0x2,0xf1,0x5a,0x20, + 0x16,0x2,0x62,0xd2,0xc,0x6,0xba,0xe4,0x7,0x90,0xfa,0x81,0xc3,0x37,0x5f,0x81, + 0xd4,0x7f,0x5c,0x7a,0x99,0x18,0x68,0x4,0x8,0x5,0x5,0xc8,0x65,0x32,0x50,0xef, + 0xa2,0x3,0x35,0x20,0x66,0x26,0xdb,0x60,0x68,0xc4,0x3c,0x29,0x29,0xbb,0x73,0x64, + 0xc7,0x8e,0x1d,0xc8,0x52,0xdc,0x40,0xcc,0x49,0x89,0x8b,0x39,0x80,0x14,0x2b,0xd0, + 0x50,0x4f,0x74,0x29,0x6,0x48,0xe4,0x91,0xed,0x62,0xac,0x11,0x38,0x2,0x23,0xf, + 0x8,0x62,0x19,0xb0,0xe7,0x3e,0xca,0x22,0x8f,0x1,0x77,0xee,0x1b,0x8d,0x3c,0x38, + 0xa0,0x4e,0xce,0xeb,0xe9,0xfb,0x72,0x64,0xc1,0x82,0x5,0xc8,0x52,0x78,0x23,0x8f, + 0x91,0x8,0x17,0x83,0x73,0x1e,0x36,0x29,0x6,0x48,0xe4,0x79,0x0,0x2d,0xbf,0x44, + 0x8e,0x8b,0x87,0x50,0xe4,0xe1,0x89,0x38,0x10,0xa0,0x28,0xf2,0x70,0xe5,0x3a,0x10, + 0xa0,0x28,0xe7,0xe1,0xab,0xf3,0x4,0x80,0xd8,0x1e,0x88,0x1f,0x63,0x93,0x4,0x0, + 0xa7,0x60,0x4a,0x2f,0x7f,0x4f,0xa0,0xf9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44, + 0xae,0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtanalogclock.png + 0x0,0x0,0x1,0xa6, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x2,0x0,0x0,0x0,0x4b,0xd6,0xfb,0x6c, + 0x0,0x0,0x1,0x6d,0x49,0x44,0x41,0x54,0x78,0x9c,0x9d,0x54,0x31,0x8e,0xc2,0x40, + 0xc,0x34,0x4b,0x58,0xb1,0x8f,0xd8,0x32,0x1d,0x95,0x85,0x44,0x8b,0xb6,0xa3,0x47, + 0xe2,0x7,0x54,0x48,0x34,0x3c,0x3,0xf1,0x3,0x5a,0xa4,0x48,0xf4,0x14,0x91,0x22, + 0x5e,0xe0,0x8a,0xce,0x65,0x5e,0xc0,0xf,0xae,0xf0,0x9d,0x65,0x36,0x90,0xcb,0xdd, + 0x54,0x6b,0xed,0xce,0x78,0xec,0x38,0x1e,0x11,0x11,0x18,0x30,0x33,0x0,0x3c,0x1e, + 0xf,0xef,0x7d,0x8,0xc1,0x5e,0xc5,0x18,0x1,0xa0,0x2c,0x4b,0x78,0x45,0x91,0xf1, + 0xef,0xf7,0x7b,0x8,0x61,0xb1,0x58,0xe8,0x53,0x44,0x94,0x34,0x4d,0xd3,0xe8,0x4b, + 0x2b,0xe4,0x2c,0xff,0x76,0xbb,0x2d,0x97,0xcb,0xd3,0xe9,0xd4,0x4d,0x5,0x0,0x29, + 0xa5,0x94,0x52,0xdb,0xb6,0x6a,0xf6,0x45,0x82,0x99,0xaf,0xd7,0xeb,0x6a,0xb5,0x7a, + 0x4b,0x56,0x20,0x62,0x57,0xc5,0x49,0x70,0x3e,0x9f,0xd7,0xeb,0xb5,0xf0,0x89,0x8, + 0x11,0x95,0x96,0x35,0x4b,0xec,0x58,0x95,0x11,0x11,0xed,0xf7,0xfb,0xdd,0x6e,0xf7, + 0x29,0xbf,0xc8,0x89,0xae,0x95,0x6b,0x9a,0x46,0x1a,0xec,0x98,0xd9,0x7b,0xbf,0xd9, + 0x6c,0x6c,0xe6,0xb7,0xc8,0xec,0x1c,0xe,0x87,0xef,0x42,0x2e,0x97,0xcb,0x76,0xbb, + 0x25,0xa2,0xcc,0x7f,0xf,0x10,0x51,0x1c,0x3d,0x9f,0x4f,0x0,0x28,0xbc,0xf7,0x5a, + 0x42,0xb7,0xec,0x7e,0x3b,0xf3,0xf9,0x9c,0x99,0xdd,0x74,0x3a,0x1d,0x42,0xeb,0x81, + 0xcb,0x46,0xf0,0x1f,0x28,0x42,0x8,0xda,0x82,0x9e,0x42,0xb2,0xcf,0xac,0x61,0x55, + 0x55,0x45,0x8,0x61,0x60,0xb,0x2c,0x94,0xc2,0xcc,0xc5,0x64,0x32,0x19,0xf8,0xfa, + 0x13,0xdc,0x6c,0x36,0xab,0xeb,0xfa,0x4f,0x16,0xb4,0xa,0x99,0x4e,0x7,0x0,0xe3, + 0xf1,0x38,0xbb,0xfb,0xd5,0x97,0x8c,0x86,0x84,0x5,0x0,0xc4,0x18,0x75,0x8a,0x7, + 0x1a,0x21,0x22,0xfd,0xcd,0x46,0x1a,0xb4,0x6d,0x9b,0x52,0xea,0xf7,0x6f,0xbb,0x28, + 0x87,0xb2,0x2c,0x1d,0xfc,0xec,0x8f,0x18,0xa3,0x2e,0x15,0x5b,0x91,0xfd,0xe4,0x72, + 0xb6,0x7c,0xd0,0x7d,0xd1,0x55,0xf9,0x84,0x8c,0xf,0x76,0x6b,0xa9,0xa,0x22,0x1e, + 0x8f,0xc7,0xb7,0xe4,0xaa,0xaa,0x32,0x3e,0x48,0x2f,0x7a,0x52,0x75,0xd1,0x5d,0x2b, + 0x5f,0xb,0x0,0xbe,0xfd,0x70,0x63,0x0,0x15,0x0,0x0,0x0,0x0,0x49,0x45,0x4e, + 0x44,0xae,0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtcounter.png + 0x0,0x0,0x4,0x2, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x6,0x0,0x0,0x0,0xc4,0xb4,0x6c,0x3b, + 0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2,0xa,0x9,0x15,0x9,0x2d,0x2a, + 0x6a,0xc6,0x8,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0, + 0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41, + 0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x3,0x91,0x49,0x44,0x41,0x54, + 0x78,0xda,0xad,0x95,0x5b,0x68,0x13,0x59,0x1c,0xc6,0xbf,0x5c,0x6d,0x6a,0xd2,0x34, + 0x69,0x2e,0xbd,0xc5,0x34,0x49,0xa1,0x46,0xbc,0x81,0x14,0x53,0x44,0xc5,0xdb,0x52, + 0x16,0xca,0xb2,0xb,0x22,0xfa,0x24,0xcb,0xae,0x3e,0x6d,0x1f,0x7c,0x13,0x65,0x97, + 0x85,0x45,0x41,0x45,0xc4,0xdb,0x83,0x88,0xa,0x8a,0xa2,0x20,0x8a,0xdd,0x15,0x41, + 0x1f,0x54,0x76,0xdb,0x2e,0x1b,0xb7,0xd5,0xd6,0x5a,0x35,0xb1,0x35,0x6d,0xc5,0x71, + 0x9a,0x9b,0x69,0x26,0xe9,0x34,0x33,0xc7,0x39,0x27,0xda,0x26,0x8a,0x9a,0x8a,0x1f, + 0x4c,0x38,0x27,0x9c,0xfc,0xe6,0x3b,0xdf,0xff,0x9f,0x73,0x54,0x28,0x90,0xb9,0x65, + 0x3d,0x49,0xf2,0x1c,0xbe,0x44,0x66,0xbb,0x13,0xc9,0xae,0x5b,0xaa,0x77,0x73,0x2d, + 0xfd,0x68,0xd8,0xb4,0x8d,0xc,0xdf,0xeb,0x42,0x4b,0xad,0x15,0x96,0x26,0x17,0xaa, + 0x8c,0x73,0x67,0x5,0x8d,0x4e,0xa4,0x21,0xa9,0xb5,0xb8,0xc4,0x2f,0x22,0xd,0xcb, + 0x5a,0x30,0x7c,0xf1,0x84,0x2a,0xff,0x86,0xc6,0x45,0xa4,0x75,0x89,0x1f,0x8d,0x35, + 0xe,0xf8,0xfd,0x7e,0xb8,0x5c,0x2e,0x98,0x4c,0xa6,0x92,0xa0,0x6a,0xb5,0x1a,0x84, + 0x10,0xe8,0xf5,0x7a,0x4,0x7,0x9f,0xa2,0x7d,0xcf,0x1,0x20,0xd4,0xa7,0xd2,0xd2, + 0xed,0x53,0xa7,0x14,0xda,0xd6,0xd6,0x86,0xe6,0xe6,0x66,0x18,0x8d,0x46,0xe8,0x74, + 0xba,0xcf,0x42,0x25,0x99,0x28,0x6e,0x27,0x91,0x11,0x73,0x70,0x56,0xcc,0x41,0x20, + 0x10,0x80,0xd3,0xe9,0xc4,0xb6,0x3f,0xe,0x10,0x35,0xcd,0xd4,0x62,0x9a,0xb,0xaf, + 0xd7,0xcb,0xa0,0x16,0x8b,0xa5,0x24,0x28,0x55,0x42,0x10,0x71,0xae,0x33,0x82,0xed, + 0xa7,0x83,0x18,0x78,0x36,0x8a,0x6c,0x36,0x8b,0xf9,0x3e,0xf,0x28,0x93,0x65,0x4c, + 0x33,0xad,0xaf,0xaf,0x67,0x4e,0x4b,0x15,0x75,0x1b,0x4f,0x4f,0x82,0x4f,0x65,0x71, + 0xff,0xf9,0x38,0xfe,0xed,0x49,0xc1,0x66,0xd4,0x63,0x81,0xcf,0x3b,0x53,0x3c,0xaa, + 0x52,0xb7,0x5f,0xe8,0xf6,0xc6,0x3,0xe,0x2f,0x92,0x79,0xf8,0xd1,0x8e,0x3e,0x78, + 0x6b,0x6d,0xb0,0x56,0x9a,0xf3,0xd9,0x17,0x2f,0x9e,0xc2,0xc9,0x3b,0x43,0x1f,0x1, + 0x4d,0xa1,0xfd,0x7c,0x2f,0xfa,0x46,0x93,0x6f,0xb3,0xcd,0x62,0x2c,0x91,0xc1,0x33, + 0x5e,0x80,0x24,0xc9,0xe0,0x26,0xa6,0xf0,0x30,0x34,0x8c,0x58,0x3c,0x1,0xa5,0x9a, + 0xc5,0xe0,0x5f,0xaf,0x3e,0xc4,0xce,0xcb,0xfd,0x1f,0x40,0xcf,0x77,0x8f,0x60,0xe3, + 0xf1,0x6e,0xdc,0x1e,0xe4,0xb1,0x72,0xef,0x1d,0x56,0xb0,0x53,0x77,0x9f,0xe3,0x7a, + 0x3f,0x87,0xbf,0xfb,0xc2,0x40,0x3c,0x82,0x44,0x22,0x89,0x93,0xd7,0xfe,0xc1,0xa3, + 0x70,0x84,0x81,0xb5,0x85,0x80,0xc3,0x5b,0x96,0xe2,0x82,0x2,0x79,0x5f,0x5b,0x2, + 0x2e,0xac,0x68,0xac,0x82,0xdb,0x56,0x8e,0x85,0xbb,0x6f,0xb2,0x2e,0xe8,0x1c,0x18, + 0x41,0x74,0xe0,0x3f,0x38,0x5e,0xd,0x41,0x16,0x5,0x20,0x37,0x9,0xe8,0xcb,0x11, + 0x8f,0x45,0x15,0xb0,0x5c,0xc,0xfe,0x94,0x28,0x74,0xed,0xbe,0xbb,0x4a,0xa1,0xf5, + 0xac,0xb5,0xe,0x6d,0x5e,0x88,0x70,0xa8,0xc,0xb1,0xe8,0x7c,0x48,0xb9,0x9c,0xb2, + 0x42,0xe9,0x65,0xa5,0x46,0x75,0xe,0x6b,0x71,0xf1,0x3e,0x96,0x6b,0x65,0xf9,0x4c, + 0x41,0x7f,0x5a,0xe5,0xc1,0x8f,0xa7,0x82,0x78,0x99,0x14,0xe1,0x9f,0xe7,0x40,0x5d, + 0x65,0x19,0x32,0x99,0x4c,0xd1,0x6f,0xc,0x6,0x3,0xfd,0xd7,0x7c,0x1a,0x5c,0x8, + 0x7d,0x17,0xc9,0x9e,0x3f,0x7,0x11,0x4b,0x8b,0xe8,0xe8,0x1d,0xc7,0xcb,0xd7,0x59, + 0xf0,0xca,0xf3,0x3a,0x9b,0xc3,0x53,0x6e,0x2,0x9a,0x34,0x8f,0x63,0x5b,0x97,0x7f, + 0xe8,0x98,0x3a,0xcc,0x49,0x64,0x7a,0x6e,0xfb,0xa5,0x3,0xe3,0x47,0xda,0xd8,0xf8, + 0xe7,0x33,0xf7,0xb0,0xcc,0x6d,0x41,0x85,0x41,0xab,0x44,0xa1,0x47,0x88,0x4b,0x61, + 0x24,0x41,0x5b,0x4d,0x44,0xff,0x58,0x12,0xa9,0xa1,0x1e,0xf8,0x75,0x3c,0x5e,0x44, + 0x1c,0x80,0x2c,0x17,0x77,0x45,0x77,0x28,0x8a,0xdf,0xbf,0x5f,0xc0,0x5a,0x8a,0x75, + 0xc9,0x77,0x7e,0x1c,0xbe,0x15,0x62,0xe3,0xe5,0x1e,0x2b,0x22,0x31,0x1,0x9d,0xbb, + 0xd6,0xb0,0x9c,0xbf,0x69,0x32,0xe1,0xf1,0x58,0xc,0xdd,0xe1,0x28,0x12,0xe1,0xff, + 0x61,0xe6,0x82,0xf8,0x76,0xb1,0x13,0x86,0xb7,0x56,0x8b,0x1c,0xb7,0x2e,0xae,0x46, + 0x6b,0xc1,0xbc,0x7d,0x7d,0xe3,0x4c,0xbe,0xab,0x3d,0xd3,0xe3,0x39,0x3a,0x2d,0x7c, + 0x35,0x16,0x58,0xd,0x3a,0x90,0xc9,0x28,0x34,0x89,0x8,0x2c,0xda,0x1c,0x5c,0xb5, + 0xd5,0xa8,0x76,0x2a,0x8e,0x55,0xea,0x62,0xc7,0xa5,0x4a,0xa5,0x1c,0x8a,0x6e,0x7b, + 0x5,0x76,0x6c,0x98,0x7,0x9b,0x36,0x83,0x4a,0x95,0x80,0x1f,0x36,0x4,0xe0,0x6b, + 0x50,0xe6,0x36,0x1b,0x5d,0x90,0x77,0x4c,0xcf,0xd3,0x9c,0xd2,0x32,0x92,0x24,0x41, + 0xa3,0xd1,0x94,0x4,0x2f,0xd3,0xeb,0xd0,0x54,0x57,0x85,0x6,0x23,0x81,0x60,0x35, + 0xc2,0xe3,0x76,0xa3,0xae,0xb6,0x6,0x23,0xaf,0xf8,0x3c,0x98,0x9e,0xfc,0xf1,0x54, + 0x9a,0x9d,0xa9,0xa2,0x28,0xe6,0xdb,0xa5,0x44,0xd7,0x1e,0xa7,0x19,0x47,0xb6,0xaf, + 0xc3,0x68,0xc4,0x7,0x5b,0x45,0x39,0xec,0x76,0x3b,0x6e,0x7,0x7b,0xd8,0x6d,0x92, + 0x97,0x72,0xd0,0xff,0xb6,0xff,0x20,0x99,0xad,0x64,0x59,0x26,0x82,0x20,0x10,0x8e, + 0xe3,0xd8,0x73,0xf6,0xca,0x35,0x42,0x59,0xd3,0x6f,0xa7,0x57,0x13,0xfd,0xe2,0xe2, + 0x5f,0x37,0xc8,0x83,0xc7,0x4f,0x66,0xd,0xef,0x1d,0x78,0x44,0x2e,0x74,0x5c,0x67, + 0xc,0x7a,0x71,0xb0,0x1d,0x15,0x6e,0xef,0x6b,0x5e,0xa6,0x6f,0x0,0x1e,0x59,0xe5, + 0x15,0x7,0x8d,0xbc,0x11,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60, + 0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtcompass.png + 0x0,0x0,0x3,0xe0, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x2,0x0,0x0,0x0,0x4b,0xd6,0xfb,0x6c, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12, + 0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd3,0x4, + 0xe,0xd,0x34,0x33,0x41,0x3,0x14,0x60,0x0,0x0,0x3,0x7f,0x49,0x44,0x41,0x54, + 0x78,0x9c,0x6d,0x54,0xcb,0x6e,0xdb,0x46,0x14,0xbd,0xf3,0x20,0x45,0x72,0xc4,0x21, + 0xf4,0x82,0x64,0x4b,0xb5,0x90,0x8,0x96,0x83,0x78,0x55,0x67,0xdb,0xae,0xbc,0xc9, + 0xa6,0x5d,0x7,0x68,0x7f,0x21,0x9b,0x16,0x8,0xb2,0xce,0xb2,0xfd,0x85,0x7c,0x41, + 0x11,0x20,0x7f,0x11,0x78,0x99,0x38,0x80,0x5b,0x38,0x80,0x1d,0x55,0xb6,0x1e,0x21, + 0x44,0x4a,0x91,0xf8,0x18,0x92,0xc3,0xe9,0x82,0x82,0x22,0x5b,0xbd,0x2b,0xf2,0xc, + 0xef,0xb9,0xe7,0xde,0x73,0x39,0xe8,0xcd,0x5f,0x6f,0xe0,0x6e,0xe4,0x79,0xbe,0x58, + 0x2c,0xa2,0x38,0xd2,0x4b,0xba,0x6d,0xdb,0x94,0x50,0x95,0x2b,0x40,0x40,0x30,0x41, + 0x8,0xc1,0x4e,0xd0,0xed,0x17,0xa5,0xd4,0xcd,0xed,0x4d,0xae,0xf2,0x7e,0xbf,0xdf, + 0x6c,0x35,0x9,0x21,0xdb,0x47,0x61,0x18,0x6,0x41,0x90,0xc6,0x69,0x92,0x24,0xff, + 0x4f,0x91,0x24,0xc9,0xc5,0xe5,0xc5,0x93,0x93,0x27,0x7,0x7,0x7,0x1b,0xf0,0xfa, + 0xfa,0x1a,0x0,0x1e,0x3c,0x78,0x80,0x10,0x62,0x8c,0x31,0xc6,0xd2,0x24,0xd,0x56, + 0xc1,0x62,0xbe,0xc8,0xf3,0xfc,0xe,0x45,0x92,0x24,0x97,0x57,0x97,0xa7,0xa7,0xa7, + 0xdc,0xe6,0x5,0x22,0xa5,0x14,0x42,0x58,0x96,0x65,0x18,0xc6,0x72,0xb9,0xb4,0x6d, + 0xbb,0xc0,0x35,0x5d,0x73,0x2a,0xe,0x63,0x6c,0x3c,0x1a,0x4b,0x29,0x1,0x0,0x17, + 0x22,0x2f,0x2e,0x2f,0xf6,0xf7,0xf6,0xbd,0x99,0xb7,0x5a,0xae,0xf2,0x3c,0xf7,0x3c, + 0x2f,0x8a,0x22,0x8c,0x71,0xb3,0xd9,0x74,0x1c,0x87,0x52,0xea,0xfb,0x7e,0x71,0x34, + 0x99,0x4c,0xae,0xae,0xae,0xe2,0x24,0xee,0x74,0x3a,0xc5,0x68,0x28,0x0,0xc,0x86, + 0x83,0x93,0xef,0x4f,0xb2,0x2c,0x33,0x4d,0x53,0x8,0x21,0x73,0x59,0xad,0x56,0xb7, + 0xbb,0x35,0x4d,0xd3,0x34,0x4d,0x4a,0xe9,0x6a,0xb5,0x32,0xc,0x63,0x36,0x9b,0x61, + 0x8c,0x35,0x43,0xab,0x37,0xea,0xee,0x17,0x17,0x4b,0x29,0x65,0x2e,0xbb,0xdd,0x6e, + 0xaf,0xd7,0x6b,0x34,0x1a,0x54,0xa3,0x9c,0xf3,0xdd,0xb1,0x6b,0x9a,0xf6,0xe8,0xe8, + 0x51,0xa5,0x52,0x1,0x80,0xe3,0xe3,0x63,0xc6,0x98,0x94,0x72,0x7f,0x6f,0x9f,0x10, + 0x82,0x7d,0xdf,0xef,0xf7,0xfb,0xc5,0x77,0xf3,0xf9,0xdc,0x71,0x9c,0x5d,0xe7,0x30, + 0xc6,0xbd,0x87,0xbd,0xe9,0x97,0x69,0x14,0x45,0x8e,0xe3,0xf8,0xbe,0x5f,0xe0,0xa9, + 0x4c,0x6b,0xb5,0x1a,0x8e,0xa2,0xa8,0xdd,0x6e,0x17,0xf3,0xd3,0x75,0x7d,0xb7,0x3e, + 0x0,0x74,0xf,0xba,0x61,0x18,0xba,0xae,0xb,0x0,0x8,0x21,0x4a,0xa9,0x52,0xa, + 0x0,0x62,0x11,0xb7,0x5a,0x2d,0xac,0x95,0xb4,0xc2,0x7f,0x21,0x4,0xa5,0xf4,0x5e, + 0xb2,0x69,0x9a,0xed,0x76,0x9b,0x52,0x3a,0xbc,0x19,0x6e,0x40,0x84,0x50,0x9a,0xa6, + 0x85,0xf,0xe5,0x72,0x19,0x33,0xc6,0xd2,0x34,0x1d,0xc,0x6,0x93,0xc9,0xc4,0x30, + 0x8c,0x3b,0xf9,0x9f,0x3e,0xb5,0xfe,0xfe,0x27,0x11,0xc9,0xe7,0xc1,0xe7,0xa2,0x6c, + 0x11,0xba,0xae,0xbb,0xae,0x3b,0xfc,0x77,0x8,0x0,0x80,0x0,0xeb,0xba,0xae,0x69, + 0x1a,0x21,0xa4,0x56,0xab,0xdd,0x93,0xa0,0x8f,0xc7,0xe1,0x8b,0x17,0xf2,0xf5,0xeb, + 0x2c,0xcb,0xb6,0x71,0x42,0x88,0x65,0x59,0xdc,0xe1,0x6b,0xa,0x99,0x49,0x0,0xe8, + 0x74,0x3a,0x18,0xe3,0x28,0x8a,0xbe,0x59,0xe0,0xba,0xdf,0xfd,0xf1,0x67,0xfc,0xfc, + 0xb9,0xff,0xf3,0x4f,0xdb,0x12,0x0,0x20,0x8,0x2,0xd3,0x34,0x1d,0xc7,0x1,0x0, + 0x82,0x9,0x6,0x80,0x62,0x55,0x6d,0xdb,0x8e,0xe3,0x78,0x6d,0x41,0x14,0x3f,0xfc, + 0xed,0xf7,0xe9,0xaf,0xbf,0x2c,0x7e,0xfc,0x41,0x61,0x7c,0x4f,0x9d,0x94,0xb2,0x68, + 0xb9,0xa8,0x8a,0x4b,0x7a,0x29,0x8,0x82,0x75,0x65,0xaa,0x15,0x74,0xdd,0x57,0xaf, + 0xa2,0xa3,0xbe,0xfb,0xec,0xd9,0xae,0x3b,0x52,0x4a,0x4d,0xd3,0x8a,0x67,0x6e,0xf3, + 0xe9,0x74,0x8a,0x9,0x21,0xcb,0xaf,0xcb,0x2,0xb2,0x98,0xb5,0x5c,0x2e,0xab,0x6f, + 0xdf,0x52,0xcf,0x1b,0xbe,0x7c,0xb9,0x9b,0x9f,0x65,0x59,0x10,0x4,0xe5,0x72,0x79, + 0x4d,0xc1,0xf9,0x78,0x34,0xa6,0x0,0x90,0x88,0x24,0x8e,0xe3,0xd1,0x68,0x4,0xa, + 0xca,0x76,0x79,0xf8,0xf8,0xb1,0xff,0xf4,0xa9,0xda,0x31,0x58,0x4a,0x19,0x86,0x61, + 0x18,0x86,0x83,0xc1,0xa0,0xd7,0xeb,0xed,0xb5,0xf6,0x6e,0x6f,0x6e,0xb3,0x2c,0xa3, + 0x0,0xa0,0x72,0xb5,0xfa,0xba,0xb2,0x2c,0xcb,0x34,0x4d,0x84,0x10,0x3b,0x3a,0xf2, + 0x7c,0x9f,0x66,0x19,0x42,0x48,0xd7,0x75,0x42,0x48,0x10,0x4,0x85,0x7e,0xce,0xb9, + 0xa6,0x69,0x42,0x8,0xc6,0x58,0x99,0x95,0xcf,0xdf,0x9f,0xc3,0xe6,0x67,0x5f,0xad, + 0x56,0x8d,0x7a,0x83,0xd9,0xc,0x10,0x0,0x40,0xa5,0x52,0x51,0x4a,0xa5,0x69,0xea, + 0xfb,0xbe,0x61,0x18,0xa5,0x52,0x69,0xb3,0x32,0xa6,0x69,0x1e,0x1e,0x1e,0xb6,0x9a, + 0xad,0xb3,0x77,0x67,0xc5,0xe0,0xd6,0xd3,0x56,0xb9,0x9a,0xcd,0x66,0x22,0x16,0x18, + 0xad,0x91,0x42,0x2,0xa5,0x54,0x8,0xb1,0xbd,0x72,0xe,0x77,0x1a,0xb5,0xc6,0xd9, + 0xbb,0x33,0x21,0x44,0x81,0x7c,0x6b,0x58,0x4a,0x39,0x1e,0x8d,0x2b,0x95,0x4a,0xa3, + 0xd5,0xc0,0x80,0x45,0x2a,0x94,0x52,0x9b,0x7d,0xc3,0x18,0x73,0x9b,0x73,0xce,0x6f, + 0x6f,0x6e,0xcf,0xdf,0x9f,0x6f,0xae,0x2c,0xd8,0xbd,0x3b,0x3d,0xcf,0x9b,0xcf,0xe7, + 0xd5,0x6a,0xb5,0x5e,0xaf,0x73,0x9b,0x3,0x1,0x4a,0x28,0x21,0x24,0x8a,0xa2,0xe9, + 0x74,0xfa,0xf1,0xc3,0xc7,0x7b,0x9b,0xa,0x0,0xff,0x1,0xeb,0xd6,0xb9,0xfd,0x35, + 0x6a,0x40,0xa3,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtknob.png + 0x0,0x0,0x3,0x27, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x2,0x0,0x0,0x0,0x4b,0xd6,0xfb,0x6c, + 0x0,0x0,0x0,0x2a,0x74,0x45,0x58,0x74,0x43,0x72,0x65,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x54,0x69,0x6d,0x65,0x0,0x4d,0x69,0x20,0x39,0x20,0x4f,0x6b,0x74,0x20,0x32, + 0x30,0x30,0x32,0x20,0x32,0x33,0x3a,0x31,0x32,0x3a,0x30,0x37,0x20,0x2b,0x30,0x31, + 0x30,0x30,0xcd,0x73,0xb0,0xc8,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2, + 0xa,0x9,0x15,0xf,0x9,0x40,0x33,0x85,0x5f,0x0,0x0,0x0,0x9,0x70,0x48,0x59, + 0x73,0x0,0x0,0xe,0xc3,0x0,0x0,0xe,0xc3,0x1,0xc7,0x6f,0xa8,0x64,0x0,0x0, + 0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0, + 0x2,0x80,0x49,0x44,0x41,0x54,0x78,0xda,0xad,0x54,0x6b,0x6b,0xd3,0x50,0x18,0x6e, + 0xd3,0x5b,0xd6,0x26,0xdd,0xb2,0x5e,0xd2,0x76,0x75,0x75,0x17,0x10,0xc6,0xaa,0x93, + 0xb5,0x9b,0x88,0x96,0x21,0x88,0xfe,0x6,0x61,0xf8,0x41,0xf0,0x8f,0x88,0x1f,0xfc, + 0xf,0xc2,0x44,0xf0,0xb3,0x82,0xb8,0x31,0xd1,0x8f,0x7e,0xd0,0x8d,0x2a,0xeb,0x6c, + 0xb3,0xae,0xdd,0x4c,0xb7,0x5e,0xd7,0xa4,0xcd,0x65,0x4d,0xba,0x66,0xa9,0x6f,0x8d, + 0xc,0x7b,0x5b,0x95,0xf9,0xe4,0x25,0x9c,0xf3,0x9c,0xf7,0x3d,0x3c,0xef,0x73,0x4e, + 0xa2,0xdf,0xf8,0xf4,0x5e,0x77,0x31,0x20,0x17,0xac,0x7,0x18,0xbb,0xa9,0x7d,0x9a, + 0x96,0xe5,0xba,0x7f,0xcc,0x87,0x63,0xd8,0x9f,0xfc,0x6e,0x7a,0x4f,0xae,0xc9,0x6e, + 0xb7,0x8b,0x24,0x5d,0x3,0x54,0xac,0xbc,0x78,0xc5,0x32,0x6c,0x3c,0x41,0x75,0xf0, + 0xf1,0xef,0x9,0x2a,0x99,0xfc,0x91,0xa1,0x3b,0x78,0x7d,0xb7,0x17,0x95,0x2a,0x97, + 0xcb,0xe5,0xa6,0x26,0xa7,0x50,0xd4,0xc,0xd3,0x83,0xc3,0xec,0x25,0xff,0x18,0xc, + 0xa8,0x64,0xca,0x68,0x44,0x46,0x9,0x2,0x62,0x40,0x23,0xc4,0xc8,0xb0,0xdd,0x8e, + 0x47,0xa3,0xdf,0x30,0x1c,0xe3,0x79,0x9e,0xa6,0x33,0x62,0x70,0xd6,0x64,0x32,0x3b, + 0x46,0x9,0x97,0xd3,0xf1,0x57,0x5e,0x0,0x58,0xb6,0x22,0x49,0x72,0x78,0xf1,0x86, + 0xd3,0xe9,0x86,0x69,0xb9,0x5c,0x5a,0x5b,0x5d,0xd,0xcd,0x5f,0xef,0x99,0xdc,0xd9, + 0x88,0x20,0x8a,0x5b,0x5b,0xdb,0x5e,0x9f,0xef,0x76,0xe4,0xe,0x5b,0x2e,0x4a,0x35, + 0x1,0xc8,0x21,0x2b,0x3e,0xea,0x24,0x3f,0x7e,0x58,0x67,0x18,0x66,0x7a,0x6a,0x82, + 0x74,0xbb,0x3a,0x55,0x9c,0xaa,0xaa,0xd2,0x50,0x9a,0x4d,0x15,0x45,0x51,0x9b,0xcd, + 0x66,0x36,0x99,0x6f,0xde,0x8a,0x64,0x33,0xa9,0xb3,0x24,0xd8,0xe8,0x80,0xe6,0x8f, + 0xa5,0xba,0xc1,0x80,0xb8,0x5c,0x4e,0x8d,0xac,0xc9,0x32,0xbc,0xad,0x28,0x6a,0x78, + 0xfc,0x68,0x99,0xe3,0xf8,0xe7,0x2b,0x2f,0x25,0xb9,0x95,0x51,0xc8,0x17,0x83,0xd7, + 0xe6,0x4e,0x4f,0xea,0x8a,0xd2,0x68,0x53,0xab,0xd7,0x83,0xbb,0x8a,0xa2,0x82,0x10, + 0x49,0x96,0x4a,0xc5,0xa3,0xd7,0x6f,0xde,0x6e,0xc5,0xe2,0xa1,0xf9,0xb9,0xd6,0xa1, + 0x32,0x2c,0x33,0x17,0x9c,0x1d,0xb1,0x3,0xf0,0x58,0x3c,0xe1,0x26,0xbd,0xb2,0x5c, + 0xeb,0xee,0x19,0x5c,0x56,0x55,0x5d,0x2c,0xb6,0x6d,0x34,0x1a,0x31,0x3b,0x36,0x33, + 0x73,0x25,0x30,0xee,0xff,0xdd,0xc8,0xf4,0xe4,0x24,0x84,0x96,0xa7,0xb1,0x1a,0xa0, + 0xc1,0x6a,0x85,0x73,0x38,0xda,0x8e,0x30,0x10,0x18,0xf7,0x79,0x3c,0x30,0xf0,0x92, + 0x64,0xef,0xab,0x55,0x2e,0x33,0xa5,0x62,0x1e,0x45,0xad,0x50,0xff,0xe4,0xe9,0x33, + 0x5e,0xe0,0xcf,0x96,0xaa,0x1c,0x8f,0x20,0xad,0x84,0x8e,0x92,0xb6,0x2d,0xc0,0xa1, + 0x85,0x70,0x28,0x1a,0xdd,0x1c,0x71,0xba,0x3f,0x7f,0xd9,0x7c,0xb8,0xfc,0x60,0xe2, + 0x72,0x40,0x5b,0x52,0x9b,0xcd,0x7d,0xfa,0x50,0x14,0xf8,0xa5,0xa5,0x8,0xc3,0x54, + 0xfa,0xde,0xb,0xb0,0x17,0xa2,0xa1,0x34,0xbe,0x6e,0x6e,0x20,0x6,0xb,0x86,0xdb, + 0xa1,0xf2,0x97,0x59,0xd5,0xf4,0x5e,0xc6,0xef,0x6b,0x9d,0xa5,0x6d,0x68,0x8,0xa2, + 0xaf,0xa,0xd,0xc,0xc3,0xda,0x71,0x6c,0x21,0x74,0xf5,0xf8,0x58,0x4a,0x50,0x69, + 0x8,0x18,0xc0,0xd4,0xeb,0xf5,0x14,0x4b,0x47,0xd0,0xe0,0x80,0xab,0xf5,0x6e,0x6d, + 0xfd,0xfe,0xbd,0xbb,0x6,0xa4,0xf7,0x4f,0x0,0xea,0xf3,0x85,0x42,0x36,0x9b,0x13, + 0x45,0x11,0xc3,0xb0,0xc5,0x70,0xa8,0x87,0xa,0x6a,0x27,0xd5,0xaf,0x1e,0x0,0x4b, + 0x4,0x41,0x24,0x12,0x3b,0x14,0xb5,0xcb,0x71,0x42,0x6f,0x15,0x9c,0x20,0xc,0xe3, + 0xb8,0xae,0x3f,0xc0,0x9d,0xc6,0x9,0x3c,0xd,0xb5,0xa9,0x6a,0x99,0x9d,0x9f,0xd9, + 0xf9,0xf5,0x2d,0xd9,0x7a,0xbd,0xc5,0x62,0x86,0x38,0xcf,0xce,0x7f,0xc5,0x7f,0xd8, + 0xe2,0x27,0x25,0x35,0x22,0x3,0x9a,0x52,0xcb,0xd9,0x0,0x0,0x0,0x0,0x49,0x45, + 0x4e,0x44,0xae,0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtthermo.png + 0x0,0x0,0x2,0x44, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xd,0x0,0x0,0x0,0x16,0x8,0x2,0x0,0x0,0x0,0x94,0x98,0x81,0x73, + 0x0,0x0,0x0,0x2a,0x74,0x45,0x58,0x74,0x43,0x72,0x65,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x54,0x69,0x6d,0x65,0x0,0x4d,0x69,0x20,0x39,0x20,0x4f,0x6b,0x74,0x20,0x32, + 0x30,0x30,0x32,0x20,0x32,0x33,0x3a,0x30,0x33,0x3a,0x31,0x31,0x20,0x2b,0x30,0x31, + 0x30,0x30,0x4c,0x45,0x31,0x92,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2, + 0xa,0x1b,0xf,0x2,0x6,0x8e,0x83,0x5f,0x31,0x0,0x0,0x0,0x9,0x70,0x48,0x59, + 0x73,0x0,0x0,0xe,0x74,0x0,0x0,0xe,0x74,0x1,0x6b,0x24,0xb3,0xd6,0x0,0x0, + 0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0, + 0x1,0x9d,0x49,0x44,0x41,0x54,0x78,0xda,0x8d,0x53,0xd9,0x6a,0xc2,0x50,0x10,0xcd, + 0xe6,0x52,0x12,0x22,0x62,0x44,0x51,0x7c,0xd0,0x44,0x83,0xa2,0xe2,0x77,0xb4,0x8f, + 0xfd,0x64,0x5f,0x84,0x56,0x2b,0x42,0xab,0xf,0x22,0x28,0xa6,0x5a,0x97,0x98,0xa8, + 0x91,0xba,0xd2,0xa3,0x57,0x34,0xca,0x6d,0xe9,0x81,0x84,0x99,0x9b,0x99,0x33,0xe7, + 0xce,0x4c,0xd8,0x72,0xb9,0xcc,0xfc,0x3,0x2,0x9e,0x6a,0xb5,0x2a,0x49,0xd2,0xf2, + 0x4,0x4d,0xd3,0xe2,0xf1,0xf8,0x62,0xb1,0xc0,0xf9,0x6e,0xb7,0xeb,0xf5,0x7a,0xb9, + 0x5c,0xce,0xe3,0xf1,0x70,0xf0,0x39,0x8e,0x5b,0xad,0x56,0xfb,0xfd,0x5e,0x10,0x84, + 0xd9,0x6c,0x86,0x93,0xd1,0x68,0xd4,0x6c,0x36,0x2b,0x95,0x4a,0x24,0x12,0x51,0x55, + 0xf5,0xcc,0x87,0xc,0xbc,0xd7,0x27,0x84,0xc3,0x61,0xd8,0xa2,0x28,0xb6,0x5a,0x2d, + 0xe4,0x5f,0xea,0x1e,0x2d,0x9f,0xcf,0x77,0x38,0x1c,0xc0,0x87,0x42,0xe4,0x34,0x1a, + 0x8d,0xa2,0xfa,0xbd,0x3e,0x0,0xd9,0x96,0x65,0xf9,0xfd,0xfe,0xc9,0x64,0x52,0x28, + 0x14,0xea,0xf5,0xfa,0xdd,0x3d,0xce,0xcc,0x28,0x14,0x8,0x4,0xb6,0xdb,0x6d,0x28, + 0x14,0x82,0x5b,0x2a,0x95,0xc8,0x79,0xa7,0x63,0x2d,0x97,0x9b,0x2b,0x5f,0x26,0x93, + 0x71,0x67,0xf,0x87,0x43,0xc7,0x61,0xde,0x3f,0xe4,0xd7,0x97,0x37,0x5d,0x2f,0x22, + 0xf7,0xcc,0x67,0x18,0x46,0xbb,0xdd,0xae,0xd5,0x6a,0xb6,0x6d,0x13,0x7d,0xdf,0x6b, + 0xc6,0xf8,0x7c,0x60,0x39,0xfe,0xa6,0x6e,0x7,0x5,0x2c,0x8b,0x65,0x59,0x18,0x70, + 0x7f,0xd5,0x97,0xcd,0x66,0x15,0x45,0xf1,0x7a,0xbd,0x30,0xe0,0xa2,0xdb,0xe6,0x74, + 0x4a,0xb9,0xaf,0x72,0x82,0xfb,0x83,0x2c,0xcb,0x94,0xb8,0xf1,0x78,0xc,0x7d,0x64, + 0x6e,0xc9,0x64,0x72,0x30,0x18,0xd0,0xeb,0x9a,0xa6,0x9,0x7d,0xe8,0xf6,0x66,0x73, + 0xec,0x42,0x2c,0x16,0xa3,0xec,0x1,0xa0,0xeb,0x7a,0x3a,0x9d,0x46,0x1c,0x46,0xc, + 0x17,0x7b,0xc0,0xba,0x86,0x76,0xe5,0x9b,0xcf,0xe7,0xe8,0x19,0x2e,0x8b,0xe9,0x91, + 0xbe,0xf0,0x3c,0x4f,0x89,0x3,0xba,0xdd,0xae,0xe3,0x38,0x8d,0x46,0xe3,0xaf,0xbe, + 0x60,0xcf,0xb0,0x29,0xd8,0x97,0x44,0x22,0xe1,0x9e,0xdb,0xbd,0xbe,0x7c,0x3e,0x4f, + 0xda,0x76,0x99,0x1b,0x9d,0x8f,0x0,0x8b,0x89,0x6,0x11,0x7d,0x74,0x3e,0x2,0x2c, + 0x62,0xbf,0xdf,0x87,0x0,0xe8,0x93,0x44,0xe6,0xe9,0x31,0xa8,0xa9,0xcf,0xa9,0x54, + 0xd0,0xb6,0xbf,0x6e,0xe2,0xf0,0x97,0x90,0x2d,0x77,0xeb,0x43,0x10,0xde,0x3f,0x4, + 0xb,0xc6,0xcd,0x1c,0x98,0xbd,0xf5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae, + 0x42,0x60,0x82, + // /Users/grauser/Documents/DEV/Qt/qwt-6.0.1/designer/pixmaps/qwtwidget.png + 0x0,0x0,0x4,0x36, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x16,0x0,0x0,0x0,0x16,0x8,0x3,0x0,0x0,0x0,0xf3,0x6a,0x9c,0x9, + 0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd2,0xa,0x9,0x12,0x32,0xe,0xb1, + 0xf0,0x4e,0xc7,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0, + 0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41, + 0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45, + 0xf7,0x0,0x0,0xf7,0x8,0x8,0xf7,0x10,0x10,0xff,0x10,0x10,0xff,0x18,0x18,0xff, + 0x21,0x21,0xff,0x29,0x29,0xff,0x31,0x31,0xff,0x39,0x39,0xff,0x42,0x42,0xff,0x52, + 0x52,0xff,0x5a,0x5a,0xff,0x63,0x63,0xff,0x6b,0x6b,0xff,0x73,0x73,0xff,0x7b,0x7b, + 0xff,0x84,0x84,0xff,0x8c,0x8c,0xff,0x94,0x94,0xff,0x9c,0x9c,0xff,0xa5,0xa5,0xff, + 0xad,0xad,0xff,0xb5,0xb5,0xff,0xbd,0xbd,0xff,0xc6,0xc6,0xff,0xce,0xce,0xff,0xd6, + 0xd6,0xff,0xde,0xde,0xff,0xe7,0xe7,0xff,0xef,0xef,0xff,0xf7,0xf7,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x21,0x6a,0xf5,0x10,0x0,0x0,0x0,0x20,0x74,0x52,0x4e,0x53,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0x5c,0x5c,0x1b,0xed, + 0x0,0x0,0x0,0x8d,0x49,0x44,0x41,0x54,0x78,0xda,0xbd,0x90,0xdd,0xa,0xc3,0x20, + 0xc,0x85,0x8d,0xd0,0xfa,0x53,0xb3,0xb6,0xae,0x15,0x5b,0xd4,0xf3,0xfe,0x6f,0xb9, + 0xb8,0xab,0x6d,0xf4,0x72,0x5b,0x8,0xe4,0xf0,0x41,0x38,0x39,0x51,0xb8,0x2c,0xf5, + 0x53,0xdc,0xa2,0xd1,0xa1,0x7d,0xe2,0xe6,0xb8,0xb6,0x99,0xdf,0x20,0x43,0xad,0x93, + 0xcc,0xaa,0x5f,0x60,0x9,0x9,0xca,0xe4,0x2e,0x9,0xd0,0x94,0x61,0xf,0xc,0x22, + 0x8,0x8a,0x3a,0xcd,0xa3,0x6c,0xc,0x28,0x1a,0xad,0xf7,0x9,0xa5,0xab,0x60,0xbf, + 0x0,0x5b,0xc0,0xea,0xb1,0x33,0x92,0x15,0xcb,0x69,0x6e,0x95,0x9d,0x5c,0x12,0xf6, + 0x64,0xe3,0x61,0x2a,0xf8,0x2e,0xb8,0x38,0x1a,0xe3,0xd3,0x5e,0xc7,0x8d,0xec,0x9, + 0xdc,0x68,0xe9,0x71,0xa8,0x94,0x7a,0x91,0x92,0xc9,0x97,0xff,0x7e,0xf0,0xb,0xf8, + 0x1,0x79,0x65,0x34,0x9a,0xd3,0x83,0x54,0x7c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e, + 0x44,0xae,0x42,0x60,0x82, + +}; + +static const unsigned char qt_resource_name[] = { + // pixmaps + 0x0,0x7, + 0x7,0xf,0x38,0x93, + 0x0,0x70, + 0x0,0x69,0x0,0x78,0x0,0x6d,0x0,0x61,0x0,0x70,0x0,0x73, + // qwtslider.png + 0x0,0xd, + 0xb,0x12,0x13,0x47, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x73,0x0,0x6c,0x0,0x69,0x0,0x64,0x0,0x65,0x0,0x72,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtdial.png + 0x0,0xb, + 0xf,0x8e,0x82,0x7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x64,0x0,0x69,0x0,0x61,0x0,0x6c,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtwheel.png + 0x0,0xc, + 0x4,0xa2,0x2c,0x87, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x77,0x0,0x68,0x0,0x65,0x0,0x65,0x0,0x6c,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtplot.png + 0x0,0xb, + 0x3,0x96,0x81,0xa7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x70,0x0,0x6c,0x0,0x6f,0x0,0x74,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtscale.png + 0x0,0xc, + 0xb,0x3d,0x24,0x67, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x73,0x0,0x63,0x0,0x61,0x0,0x6c,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtanalogclock.png + 0x0,0x12, + 0x3,0xcf,0x42,0x7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x61,0x0,0x6e,0x0,0x61,0x0,0x6c,0x0,0x6f,0x0,0x67,0x0,0x63,0x0,0x6c,0x0,0x6f,0x0,0x63,0x0,0x6b,0x0,0x2e,0x0,0x70,0x0,0x6e, + 0x0,0x67, + // qwtcounter.png + 0x0,0xe, + 0x7,0x91,0x99,0xc7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x63,0x0,0x6f,0x0,0x75,0x0,0x6e,0x0,0x74,0x0,0x65,0x0,0x72,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtcompass.png + 0x0,0xe, + 0x5,0xf2,0x81,0xa7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x63,0x0,0x6f,0x0,0x6d,0x0,0x70,0x0,0x61,0x0,0x73,0x0,0x73,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtknob.png + 0x0,0xb, + 0x5,0xa4,0x81,0x7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x6b,0x0,0x6e,0x0,0x6f,0x0,0x62,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtthermo.png + 0x0,0xd, + 0x9,0x19,0xb,0x27, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x74,0x0,0x68,0x0,0x65,0x0,0x72,0x0,0x6d,0x0,0x6f,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // qwtwidget.png + 0x0,0xd, + 0xc,0x10,0xe9,0xe7, + 0x0,0x71, + 0x0,0x77,0x0,0x74,0x0,0x77,0x0,0x69,0x0,0x64,0x0,0x67,0x0,0x65,0x0,0x74,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/pixmaps + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0xb,0x0,0x0,0x0,0x2, + // :/pixmaps/qwtplot.png + 0x0,0x0,0x0,0x6e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x4,0xab, + // :/pixmaps/qwtanalogclock.png + 0x0,0x0,0x0,0xa8,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x8,0x47, + // :/pixmaps/qwtwheel.png + 0x0,0x0,0x0,0x50,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x3,0x7d, + // :/pixmaps/qwtknob.png + 0x0,0x0,0x1,0x16,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x11,0xdb, + // :/pixmaps/qwtcompass.png + 0x0,0x0,0x0,0xf4,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xd,0xf7, + // :/pixmaps/qwtcounter.png + 0x0,0x0,0x0,0xd2,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x9,0xf1, + // :/pixmaps/qwtthermo.png + 0x0,0x0,0x1,0x32,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x15,0x6, + // :/pixmaps/qwtslider.png + 0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/pixmaps/qwtscale.png + 0x0,0x0,0x0,0x8a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x6,0xce, + // :/pixmaps/qwtwidget.png + 0x0,0x0,0x1,0x52,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x17,0x4e, + // :/pixmaps/qwtdial.png + 0x0,0x0,0x0,0x34,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0xc8, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources_qwt_designer_plugin)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_qwt_designer_plugin)) + +int QT_MANGLE_NAMESPACE(qCleanupResources_qwt_designer_plugin)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_qwt_designer_plugin)) diff --git a/qwt/doc/Doxyfile b/qwt/doc/Doxyfile deleted file mode 100644 index 35edacf1b..000000000 --- a/qwt/doc/Doxyfile +++ /dev/null @@ -1,1521 +0,0 @@ -# Doxyfile 1.5.8 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = "Qwt User's Guide" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 5.2 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, -# Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = NO - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = YES - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 2 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = NO - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = NO - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = NO - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = NO - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = NO - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = NO - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = Doxygen.log - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . \ - ../src \ - ../textengines/mathml - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.cpp \ - *.h \ - *.dox - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = qwt.h - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = . - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = images - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = NO - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 4 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = Qwt \ - Q - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 1 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = YES - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = $(QTDIR)/include - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = *.h - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = QwtArray=QwtArray \ - QwtMatrix=QMatrix \ - Q_ENUMS(x)= \ - Q_EXPORT= \ - Q_OBJECT= \ - Q_PROPERTY(x)= \ - QT_VERSION=0x040000 - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = NO - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = NO - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = NO - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Options related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/qwt/doc/images/analogclock.png b/qwt/doc/images/analogclock.png deleted file mode 100644 index a4c5cc21a1a1e2af561a0574509bd5da26b37f05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12649 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 C;X;@I diff --git a/qwt/doc/images/cpuplot.png b/qwt/doc/images/cpuplot.png deleted file mode 100644 index 0f1bfc3628394b85561dd445a7a3319a633c31f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36517 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 diff --git a/qwt/doc/images/dials1.png b/qwt/doc/images/dials1.png deleted file mode 100644 index 690c663d627b0a3ede37c7ef1ea56eb0af86c7ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72717 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 F{{?03=;r_c diff --git a/qwt/doc/images/dials2.png b/qwt/doc/images/dials2.png deleted file mode 100644 index 59d1a611dca7bd174bab5add048f694b33f22707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28153 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 diff --git a/qwt/doc/images/graph.png b/qwt/doc/images/graph.png deleted file mode 100644 index 55f05b876d2e0e1b70b1fef6a480c15ab362a0e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13144 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

jPZcfhXguO4j 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 diff --git a/qwt/doc/images/plot.png b/qwt/doc/images/plot.png deleted file mode 100644 index d0881034dfe485190f5ba7719068eb02704d5b75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31037 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 YpY5E8-s1f81N*D{(n?ZU$R}_9A5*#v`~Uy| diff --git a/qwt/doc/images/scatterplot.png b/qwt/doc/images/scatterplot.png deleted file mode 100644 index fd157f0b243428812118384b7aab18d8174d5e2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23882 zcmafbWmub0wa6!#*9;1qY);#w$DBv^4NZpB)d^qc3- zbAQa-Ie%h%AIqEf?6vmViO~Wn;bOhQLO?*kRZ*7LK|nxyg@AyVfq?{nr$MGi69Iu1 zK}B9h&p-DxBqZK^_}yLg9=7;9KA7qKr$MZqBeBW6=e4x| zHHrN_=7OSs4ZnQ97LutIXd~oqT{GmD?p3zW!L-}Y-jMaq zcg4lULBCJ3q0nJyT{*lR3hxWQKt+A_XO(FF9%+6EyxdlJI5z77YiMY^mhitgfi>N2 z1fA3Touye1Jg$kpCi&O?j*Pj~^(;Pn{rXX{>fUv_muW#N`)z7!YI-^`F;VLFhpzC3 ze=)&!$3dRB|HUT%cZr>M&n7<~Gq^Qgo{nDR1iSw;N$y~qrKR`J*ZBIuHK-t z50N#v}W30)lGi~?Tp-z!T(VD6dH7S_mZl$+*sW9-I=C`+yUM{G5RPRej*_2uo%h;JW~}?pYxu2sjgBNxdUWiOt_7gXfB{AM=Gb9! z(Q*Ue9!mIlvA%`D=?F-zs`hs&9IqoHcp?)Hgii~u7 z7`vikKC=iCb5l96Gk=Y^dUW#H*$A@^pGi$KGY7p4TJ8OS0CAP2kI9w`RmqZoWXI}@ zkH;;7=&2Cf&gG6%0%9^(X+E~QO5Y(K+$*Vei>!&UaSMjbC@KUvbh6H{+5@I12GhUK z*G}Rg8r%?%W^AmczHLc6S#I0|g&8lUmPYKIZN7#v0+fX$I$}VYY3%VDv^EDQ3Ng}O`)3c>YYbz>>>gp$hNB99^?eiU^Qj@V7^kKGx z>*%?MN;>3B9$fjZNpdSmubL@Vd8w6TqZ1qe&}jBHYJnH)`e~NF&b)1BAnV^B<@GgA zA&H(AW$S_{rPxln0b^Y-gU)=)4c5TNSt(Doq-8uzHL^;1=w^Pdf|&7rW5Tmmt8W@Q@}17pvuYPsJkD&utMm# zLnHMllpp$S?3yDKLp`47Gk$#0#_AzNe|l+B5~4;Y`+eQ@sM!|wnv2N^q<}mF6Cj09 zHv7yrwb%sviV{(Z20S1tiYksP#2Yr?rs|DNn{zKOHa{x?VTJ7<2`G?iRWT&}nufRR zMypKxWsGKY7eQ+_=gmx!wXZdBb#@ccP?}aE3`LF&d<&0@<}3-A2%?ETVt147ieT_DyZ9 zC|m+D=Wj3rxriJZ5=1BbnPN{WE=c>u6I$Sa9|rKd(g*XNtu(dTP*aGuAv1_^Vl1>4em1VRBOTJq%T2eWY9zBCfUH- zd92PQ>3%B##uS5E&$`MFlT|azMe*1@cA+Hc1f~?loX#=7qB7alA{BwW*`vBkx_)lliMg9G6ADmAi|u+ug_(&SGK?lIW+B z)gqprqzY?!ky=bQw}cXmCoJ^dG#f_YKvu!b=(rvGamXfUsN7MMsBeYn9@CPnF~qxw zO^|%EiGpAa!s03Z`qK19Fu+!cl7pJ~NFOJ1HI?V+5G;yf75AX2>pM1ldIR}eiiqy| zDixu4<=`R_3+X%^PIQ8%bjv0pl~WXD#Lqd)i4Z-^_#;MqCF8tWjkvFuQ`$~ zu(iZ~l58;%)gTF?K`v*25v8gxfWBRC5)qwSFx!yiU8yuA-aSwZ7LKR$AhIbEx9rW# zb6oW^Pb48eG-3emiQNK7zKb9$h1>=Ug%)oR{GAY*khP@N?v*Od672ksaq}@ zeue7mk7F=IrV*QDVab*uOir$Zg28){UJ)po#4?pSn8$WWyaeV*B|VbjZ^TQ@^6pN4 zct=e4jE9|^TpM!mfd$@{1qzKeU=Rl>3A7Tm=s^S=pg9okt*AuHyxVQh zdP|(cnZoTDhdz}gf9vX{6`I_s;{sfA(c;2rNXxZZ?fZl}M%ung-aF@2zlLifqGgSO zX>|n|F!byI(+fu)nu#Xb77`*krGX_e7tMuu8-dUrNSoIF1*<%yARm{1>N7FjN!wVv!CzJ>QGuL}nvjh;1bl37OkC@Dw1j9f( z1i4LAt0**?$9-TvJejA}h6DSsUE{~0yy8Y@m2Avx21d1m{F&>@HemRtt;wD{{3LGF zwMI#-&-l*yBJKiw6i9ht>AZXk8D3K*!({s-=YNJm_fAmEDq;H%$9l2T_hnTMl1thg zFzxER-u}(+D$5&W_@}Yt?+sjAS*R1b#XMV?0!kxWy=ja0gmOMMRZCgE_AXDDlE_IGdd?EnP0zJiVLT3oBdFShN~( z8Q~EC7eVV`46AoOi{Y!8MGvqOVWx_6DU)p{rjIHz2S6GjVB93ym7P=0IIc#Q0PaYn zdT5$)Cx|KpqUY+Zn@%v4_^zKJ{Clz=-7uDlZeHUpY`>2p>M(fR#L~CC8ON2g5+nnu zR0O6cM@q|=3r}o^Uz^jt5ij>6V*pS8$8#S2pq?-h=+Ibfr`8?vz4HzFno0_9i+M4T zH4Cc#3QQlX72|v%j`Q;O*6zxd&9PswZ$S8uCho>Mydp&)X}iUhBH;BaALO$YmEUGQ z?;OZ@x0#~jDJ2?%>Oy3H?B*3K{aya6uK=9$u`dbyd6S@W2n zMn{s0pJFn`8(KwR#!3Lu|9xdcJ2!?q{ekrd?B?p6>Q7tC{0|UchEJBBi!U)74?Ukv z2yCD~gJpmwLe%d3Bv2##N`K@vYc5%|tne@Y$OF9R)s=wz!&ReHHL8g+_X1Sr^F=fU zn|G-*^58}Vr|iMc1=w#yRsO9ni<@9iEJymKHtl5u%y)(?Kz)t)nZKcm4BB%%nt1yo za}3lv#@QxdYeCfA8cV0;0wfWLHk&M*kmCPleMgS-P@R@;e@uqXNbnr)0>n!{j#5&P zXqCTJtgx0c5!W|%#n{66h?9f_Wu!_WX!WFgA3mg#0Fu@Adpq9eRd7}R!BV75Oyx4# zR^*RB`K$`T)qZpc;U`WTQJJ|MQ~B zHDMzC_zFsHWfNEQ{HQa750sM;Uw&MRVMBBevRv!r`oQk5hV!Y($<~=< zP+cSy8H=RT$E0UHUb&+>cIkvfg#q_4Du9-Pe~8x}oAEsmBpYkADUZ-}8Fl*!|7R!}p(X z=$?2@!1$gmZ(h{JA~Tnq#aVjucpShYQ=}Xz(K&}NU!MI z=(#n3A95(i@Sir7jsM|((8tFolgmuZbF*);#-y%e|MPKem-}P}=hNMJ8&qlLhjc^Q z?lX5GCt)5aZO$X;B(dt1fNQ_#rwOxG49t&1DhR_2ib49#REH8Ee81Bn|9FHnEu6%7 zZVto53TtryYW)4$_=2HDkIiVJ+iGi#S=VpPmmAIefc@;c_qSED(G?XH+1c6pRR)5Y zHRe5!KPq$+uSHl)xVy9P8YG2KFB(mRJbug;V_;|egEY0T|8lKtzV0a~c#UfGVFq8c zNy9>muHOg9)YxF9_Q+V{^}1Li4I%)z>_}6~#olV-)H2UC~PUKy1O~h9u`)1Wh zH&OJ1&`W$H*^{ot=m1kk>6?1!J`t|r>2BuNKYLTcKmQEUJYW2(sw0){{&O{H(&jE1 zcylOz-rZz17zN)hPUB`}46i@;mkkXKgCFrJzyF85h;0A^QjhU9cJCAJ-(~^m`sgMSkZ4!4b&TLiehsWW#xvI8PRdjwirWC#>Mvc3><7rdl zL_korX~&!w^+&IxrLPLopO9t+FU*HqRMMmt*FWAM24O>yMO5Rf`D?pXPs=2=mQz!J zc(x5pVb5Q1^(bCU9brY2dD@juZZT`vwc#Wx1IVSrcA)1?{AbJ4m6oJ8&-btn7%^c_82q|5WyEzu;~RO$u9 zxyCR4-z#Wr%P9eLc9e@wp_%XwOKW6()ct$u^F>6YZ1rT$h8_x*WB?+Qr-3kRVG2yyJw-Viq#`B!R{V7phVnmS(XraWA47hkVMernl+B ze!db%DEc%m9fNfwMy;a=Y!20|^@>k4p&$MUCpyLmzgMM7T6@8!DS_e;w1Aur1bN2J zm+if!f*qVn0)n|XjH+hDuKETs(^w2U9S3o(q`7Zoc+Cy=5&ld}6oIDO1wZZ8;@g^m zIoQhED7_vA3+tGO=bon|MmzHevA2OT|AQRR@he$@Q7n_2!LXS08tpYSSq=H6)1{<9BT;QL3O4dG zmQB`)V4!hVC)v zxcBzqq&;0crdY1a@!Q^b(*(0`l#jZXr}9xI#2qPx5A}|Rf4&bWMw5>%5yWb|Nmjde z>s4k{O&^K8UJo2#H56*vr9AXZ8yxSK@+-pr*gltZA^Teg1*Mvrf#*@x+?BE7y@vTl z`3@LntJ87hDbZIPyyK-u&Ja1^q&h z-gCfvO1NqiV?Z#!6O&NL0BK%2@6z;0X|(QhtK%S<&8=+KoR;~Z zS2=!+Ijt7>bO`Y$jl!K70}_y9DY)!|sJ?45$CsdF)`fH%W!#{+~dUh3*pw{ zD^6FOVxn0=DwM8Z)a9`Z1L9l7HMf=R_~d}^+c!57VzX&kXN_5Wh-XLg>RBn&_ouxx zN24A11a_0wujNSnMt8+Va!Qp6+-qhBMtH;s%?A4$Ce=a{#_>%?FmZ3Xk1Lu4z@;zZ zUGXX^Oe4P1!m_RW(qhOScaek9Y-WC`TfKejgqnTXgNWutyHX(L_q+&AgnVkb25Y0YAN;(%9m2CUh1g@tfF%+I zIg4SbIE?d0Xhb= z9{LtW{G1;x#Ai{lr>*yXU--Ihzf(P*&bU4`ElIbzV(MG;a5bS<_aPhNqav$sF8r3H|)M1R~zlVM&>5ff1%^r7jgK8?m}m0QW<` zGY_t)&{Bjk6sbBYsm2^Y8R|BGK^EdF5%h~vE4d!x%j7ni6`)813;?ZB3a#n;nFLzb zmrkd;kDsp!tCt-y;?G}+=Z!)I zW!n_tm0)y_kFlJwuDnb147&>slNsWo;)qT&oeR4ym(!rZCwf+K%A^FIUxXj>`F?-< z9qeEToIBBK408r=of4qAadz3F3jNN@92Xipy5e~AcM5l6BX)dJb9d-0lTkd~pY`CO z5dlNlS#QKfyO`)E9MmFDZ@;uGSpRyU0C&1GeWRAl_>17J9N?lE3az)}evRs|!`pd$ z(tY(xn{XVTVW8tw>p-VC?O2e7tnZX@+BAqW1y4ocTWy1jrFgSBN$xv|<1}wy*_Paf z7O4BZJ@*4+Mfs*+5u5^Jb6@=t;Q1YjF@LRkIE?o`(`!;m`Sl#QZUfJ%WnLM1rog+2 z<#HKNER!dV!_T%l*q_W8!*;UuCNi2tA-y4qO?&vq;<-Dq`j`{=dPqyYO(`HtHh9! z%!E-R1S{+VHf;>53Bj2aOif1Rt^;eei57(Zk#yIT%&e2iB0@f7FU?(l4MZ)Wn}q;4 z&vklx<%Q%gxw!bogr0++vRo-R&FttWizy0UuUMu}AduI@*5JZc8Qa~1*q}DWusPio zrLi=cmDD$&sGa4%m*K>EYeqbDXOo+E*qH?iBjLzZnny2Q3V*ph|6SV zQXWp%rdu+JQNRX7d(!TO(IcBf`84aw2+5;e$qgO;(&C2x zzm66RH>vK<=IXz7icgnnZ@(Hh8m{$}YgErfa4j}WG_jxf@I^+%q#gB`QTA;y5&wW3 z)^Kcr0=jj=CMmn2??8YsRQWh!(&64vYi`JG#AYnPyOG`Nl(8PwKnmqkn<3mqxk#Js zj;L`BA+zK}hEmhNLBUTjl(2-?P`5Y@KsZL~-Y@naL-v6X#oDuDgJ zOy8Rpr^ymti6qXXzJoya6cRwy7&jCN1}KK&N6m_!ar#gVhG19`B|@%>@=@vbRhyW@ zTQ|;e)Mjd4jsYS#J!B6#7S;cQ;e@_HM&rPLS-E>Qoypl*73L$QlacO;ojslXo;z9^ za!7b!DL?=Zwu*JXW8cn}7ZF|6U^TFM`5l;uH|(`rqfkInqu!3WzKPvfLM4nQklZ$9 z!eV9|3eT(3-y0x0?Q{-dg$lV!+pX-WAQ90I#(k!BwTymuNl z4IyR21V35UWEVAaYkzU#Ot=)UR}$o;76GFtG9Yb=3!twlip!1PBfSub{|1e#h8w2acAmR}!9S2*tRD6e$>#vNE-ksPk?V@Oj$ZcE5 zy`tN7i_hv~=ILxc{J?gL7AeF{rfbwc=O9ju1P`=msZ6f+7%o$X4m#4}XA&R@oQbgU zoCsC4NPfmkUk8Tf?t~O%Pgj2;P-6nBVWd!dTt&6zQPXQI#E1>p9_nxzZFUX08z169 zVGG;om)L89t8fTqjM0P@nj4^W1}$Avnfr)WbQx-99-T4($|uz%h1S=6d1a<-dOEb+ ze%Wq1mYdQ+DAGA36R`Sv0cGoEto$5{9f_f-8*}*;R8Jm7*d#pkoB+v8joI^Q7INl; zqj)ro`B&4jfPk{u%qP0c#W$4*!;f`nP<1>boNXa`B?fmG1}GMR(enrRUhuM+4dG3Y zZ0B$p%N1!7(BtfN$nk}=%JmocfxQr9)8(#|qtQ7$S*mp0Y~uJ(Fp7~993OothP=lZ z=@c_doXq8gO$czCPtJpC&yhxndWkT zoW^=-Z7B+~Z`@p!M9IIEGLop9|R-ZAtKG-tF(O6F7PRwSAoOboa=*W=xT4sQ|G&5MJ1)X6Bxg^__0)yvXfMeW_e6c z?MuJ@7c7R@NsG9C!O>u^IJ6GC-A&Vcz8`(_Jo@3!XjNTr;ArCOuTNcHyKF}B{y%I| zyB|1Gvy55<*`tuYuWEkCcY@tA+zKh?#xAlqk@EVDxxhVr+_(GijCy4`W)G}&+SP#g zuyJMaE;udr^%{B}e57X4`Fq7Blf&rhekbXCxxvQW{cNsO4IPha8NO`6B~zdEcS~-t zM!T2izpd9}yiQMh$m{gELBl}&jR6Dr59WbOwsiq?;&v8@V$c z4q$ioC8KNd{(vMa7oQC_y^XP%>W+RZ9&oqr2j5?O8Yu}evCj8@AJJ)oJ?-rkF?a<9 z1^M}#oEIwh8yBh!^Tpmxcu}KwfC1EwU1YEPsGySgTnuxG#KXl&#^Q+6U-BgVzRBu} z&z>_CcfCD?UrdxvB903Xp*DMg3u&S(k;%;0gf2jSettM*=F$7GfBpTrSz(CilrE@#Z*T^tNfQ!@5L{vFwux;=DLBzlc;P6}_R8 z?YQ4*?BAHEDzNwdx9qQvRbL-xlioM`Us}@*X}-To;||`!R!XD_IDq;Ixh{L2EH@~` zkz&#%(!7xp5(3{}SnWJ8C?z7O!1;>q)Vwf#^t-l*iTp-c%k8cKG(ZO1@JslYm`|pc zbj${)w(u{|(Cpm;e4}Un1RTwkGGD#z^gT*tQUm2lz;fUGZ&}Ri124yu60$h2){<&+ zp_!0qEPtt$Dh=hs&(V(;wiaQEJC zhofSE*foa08czFOm-6SDMfc^ufe%Fp z&tI_$Q+`vmys!5P_I-dGW4SiE6nGFveW%IKwI?jFHthaPO0)2ep`KtYz%e*E-Ud}e zqZ+QKk)Mjn?9xc~NePWLgNA*T3h`|9-%GL9i=gfEniCP2MzWEAl{Z;xMED`bAxlV@ zetWuhNcklQ_^qtFvws3D1S3njYpSxmI#6+^CrA7R_M z8Wip{8g2B+jJDThWG3Acc}y#S07oV)b)>vDR}}+f2OU>G26(^Sj%>2HV+ROX>KC}$ zL|HUaw{lc#?5LivXUp)XNq%#Ksayzr%oRzSU+@A|N$YMBmNq*c^G;O0WYbfv&c8C;8e-gXbf$e`D&mr1*yMla;CP;>Cj~jWvL#r4iA~(vdYZ%QgJukEu*cEf(uDc&idq_`K`7RjqxQp1B_$EG0XNby+wy_iuxY|<#Jp=+7UQz={{U63gR#XUs2%HKJF;}X#E!A9+ zr1^4&6@UW*tjV8s3#cO_2J@~m&{i8a-D}!fh(zO-M%*cmV$kb&VE;mjJIdH!MLxZ- zwjc}*1VeFq>uC19P3RxjTQpr5r=E-TY9Wxo_y8 zBC)_t=)ZG~L2(FJKfjZjtdes6=_eN1mW;yajqZDGK|);a`wHOXsnU6wjha9Z0Y-X$_=hrHsQ zxbazAv?nzO&&c6z9F~l(_~mQuSyV=JTZ58nC{HGfQDM0=5K||(hQxJM*!?HH3{1Ss z_RxbkV+rGRb?aWT9KN?nU1i8$oNnmzr4nLbG3fk3cZl>0iWaf6wKWZ$3Ba~wzNCK= z9#~29!|>kQasO3_Y`iUaU7g8EC_z21hHx`C^X8d_&hXp~lV?beICd>V9&3zB1)B+9 zF+A`5#Jl)|OBnK$rMU1fmX%=%s0OOD}ZjXECwI=m#d=GzRd-Ub-Zu z5o#`wRkhbgPCL63cM?X}Tbd%B2(TFv;nS?w=@2l{wJQR%XGz%rH+z$$CIQlSDD$fT zz!HA@7AMn94FQE4W@ja_2d|rGaecWYNV+hGllKdbqZ&#(d9^=;5#{c8#eMki$ui$l zOc=f4Nz)J$BWbAlwbTh*hC%7{$7RP90B}0x+=rrLf|ALaTb@?oo*AD6y=!TP$ z&3Z_hFZ0Gv7S+U_C{Ll(jQ(|KJ*qO8{b#KGNL1!Z`)uRu#w||Vc+uK;QdC26UMwF= z?S7GS5ktjkboIdA9_Qgb!)(}DY~kdt8(X@rpot4mpx%yCO+6SJ0Tw8$IP)OF8>(FA zpj0@pgYXc&hAYebT1nl5IntCnwi;?$C(}Xebvnd6zm|baYa%wD!C(i|FDc-~T8kkB zIAPxOzVjrYHkORFQiIHQfIm*R*VnPO@?tt5%a9+(dAk7XoV2)G<9^t$LFbS1iC3AaX;xi>S7C(X* zrbv5!?gpj80sI{z`jbn%yJ31I7%=!Wo%0CS(wdiZIu)ef*+O^>2+6(8SkyX<)8TF? z5^+lA)B@B&{Vs-|PLZsPm&$dv)&OK-1(k5pVle0S)*pjY>xt5rX}VF0VS;6*wuFOc zw^OUu`}WTgIh}Co=+zdkm@$U>$`6_){_r;@!3UpJD=F+FkPAK0gjt@E(on;`j*Knk z?$$sds{rp*Hpdk2&z`M?SV_3CoE7o(L+~|@>=2+ZqtoxHzaqY2Yf6`{XEI;VP|@Gg zq0ytL3`arB+IA5oO4VhH=491&0g{WLWCmqg9LU{ch&S6r4@Y~; zXJZHj#bkjmM*2nd%$75^~|hFS%DvOiwH|M z8F4GIGx2);)MuOe_LZ3T@o&X$O#laKvtE>1sHp**tPcjoL=14q>5J8QinNcKN*bu$ zW)~;HH7zIIC+RZMuOpfhU8?()$*Y%`tSz8I`c)kh(@!im*3zMZVj@JfR#HP+r$VxK zB>Qo((PR^hvS8WYf#^psHFH&`k5I&E~C;_42)2c+CS_ZKv?1o6R_6cla zGQLo=5$jR6>Tc4?L%Qw~+wNKaZzu%(M!zW|KUqvo+`Gi9(|*6({p6v&@bay8l?0DP zmm+8z;MzGCB4Et8N#-4d2JN35{T$$a$_CyXCXGIccU?~u-hI*&S@6g zOxCz?OwuT4wbm!9gJ>Ny6#-fT9}C*VNodA<1HT*;`q*XtluLS>;wZg2^|&wVmuXN7@-TYOz+0?Qeu(VzcAY_gyk0*PajG8^N&j<^%Yib8F_l=4xMU zlnrc`&w}tx$r22F<51JzoJ3OAGp1;Fqc%~Jf!PvbXCT^@tpH+Sw-2l&O zaS^wpLhHc*cN{>S86MMVfG>RIj|ZL<=#BK_)3pTl%x^1=Pd~l+v=Wo@{_bt}e|oqd zd>zc_qfBuYzdl}){D50g`wgoi(9XG`Qy=r+$i9E{}Qu4)5yLxiqf zI^P42$Oez<4&}R9(ZHt*uAeKE?)Z$(e1Ld3{Z)Jer<-K`8OsX_Ok#wfR_SysLOoU? zxi>QjAD8X15+;oEh(aY}Mf$7_>Bl8p;2D9&1 zmI17IJX}^+&ZQq2^vs^<^ZFo9&b^!{mHa%p30Tq6sXU~>-!0%dT#K!yJ-Hy8G;5nI z_4%fSo&!053WVA4E?c{zbSwvy$9nsA>q(k@YMu+UA0MDt*DgW+1l^Z)ukE}VK`id zOG;ocqq_hUcx=>OpqU3U5cg~>8!&<`fkAM+1^D2PVrg!~9uIwGAEZp6$M{gsp}jJ- zDRR;1(poLrlHInf911TJfl3DbF8oOCJT+Kr)&(#7z@wIE_dDMpGxxWGBmJ{$46OzD z)!T{!(S8j#6(5*_->0s)f6?SK(^tQ-j{_6#gdKK|X> znQ~^%!p5)CuvN2~+YJY=aHt9E@HyxXcsbvWBjcXVfAe8$AaW`n{#@$AbN5bn_%SEX z?+u)!3*9a8fTxBx|MuSe6`UNPNNNfON%hneT3K8Fg!2U}4x*n>x3ZQRqg%{qzyR2cG8pGz}eV38|WN zxLFy8lU^%-GM?^w?|R@IN6+K0s{gz0WIrW^a0f0u(a?$tm2;-ZSWKwbUs(AQ)$Ywn zbV(MtPiHnsdiC%w3uSnR|5s&1s=y?>anhJo+5(4t6ut>nC_8jDjOV>e`giG8e+iNg z|Gjd`wB6GxIQY*nnT2V+W&dg0PdLf4sAu4MKt~(Qwjo?R%r82lV@;LFI}h-nEd^pG z9NK2?AOQ^SQmfp3zu-1$4HFqH^HE&rN&L*LMp*Ic| z@)T{t>{-#?l3QtS^Hjr4k0_HEuC!ID*zn70pyYML zUX42H-j`4&CX_k<4~Y_*CnfCp3iBy{)%ws;aZTQS@*%d>?tE0VB8mMWW-rUCErKFe zFTd4g&uTa^sJ&b?X&N}CjyB4HqN;`jhAnFC7($Y(RK1r{I(_i$-yv8QAP^_BA#%3IT3X&<!*-F#;FZz8Hg$1zp0{WAr;%mcI>oij#5u3 z3x_E9?LMEsCDg2(Nx!kKi>GEmKgc9;1$>HApkgjp1S62Se{ZG~$=HmmphjnAKVeMX2cJc3E03pZ^AK3n6`GjxkjEgLFiF$bJ1dhcP03+j!q)Iw#2G)G zWQ3NYi_qq|QCpuvFt99oR`cy4~8ygZ~bJ%vQHDIh^I z`-gCq7*dhPK60)}m_FPd!J5>~1)2>5YjTo@t*$28?v8sdEcEGNsbPzt)Bpl)pI(fv zu@dD_xo&F)qE^rHFKo#c<7p{uD7dlUK2|?&yeY$fLB3O3#Bd}7paq_GWXyS5PD!pa z+uey`AgEi0&z-8W0_*dN%9Df9J9{Q;gkN1jUXI4PD2g$V(A_=Rf)AUXDU-EOmNx@q ztzbZ1rjBboixw%54|4=MC)V1jMK>w;vXpXQQYuNpizB)d>Lf8!kbfS#=>Xn+rYjm}WOKlf zrRf%aLZe(3LDs`!b4L(1l~JY->)z5p5s7PN%l^W6LjDfcLPP=m4jp@t`Wf$F2@s-K zgIcNXEc%V>VTR*kY!j6GO*B-x9A6ARjQtxrBac4JV~| zJvh|Is;z7RJ=Gh}By3bdkaUTN2H7G&k>F;~Xxm$WQkf7Pi(fHF4=&}8AB`N)7Dr@D zxm+eo1{b*pX@?SJr7u7^f>6+2LHo3e%80g$nZQ7HwxQ$_CXGMx1DZET^k^jTkE{V} zr^W9Ynf45*q!3iqRL@f}=O9gXDsdQ=YM)I_;rR-aM`vH_VNVI>*W<0*#2-IHlRnaU zwqQI|v=EVOnd^T~-NdDJRp}u4h`Bj8@PV^Hq0!nzW{w`o88}`kPAAPBA{W4x2b=?H ziov#-F7Y1KW^>UzomgEKu$5j(vZ)zEVmJxR&PqSB*+^>+KhgIa=S$h){1X|uk*ywb ztNCogW&H*{XwoV|=A;Z_v*H6PY9l%sr=^tP8WUXDKF+5@k>xSdtwv_W1FOWC!=GcG z^+XWTcWtvnDihm3(cf#)^YNA~f~up%C^UAO6XnX{;Dr#s86M`JM!iB)t1U=l_*Io0 z4aG7!c^e~hxJn#AHPH5CMJa=|>vsd@YkcxKSlj{+#SA);q2EWW3mA_xhj-%F2*q?u zn$zO9MpiI|&6GVh;M0f|xSACL?a8;>MgMl%XvAW~lfUg(IHSVQN=?XAsDvKArZaWw zf!g8-FM?d1CaImYdS7G^2zd(peJt-S zZ%fBk#$8^eV|&{TZar(`EcG^NT$Kep?E1(OXd1Wg&4;8YCWY1t$aie>uBrWi%g#i4 zYT@+_o*9e+Ca%V>Qg4N*9m2>=Hq+U&bJGV)tUX>yhIbjb@5O%Jx&++Ltz+bx-+cwA zzK3mdsPN|P4`*vKzl%gOcfG`t{&Xdckz!t8&D|#H0e3L_=Ay6;uPL<)Kp_Y;b3T>- zxYLoA9`Mb70lO8$%A z>%7zatyjZ9F)LK#R)X3PnBg@%Fu{~qo8F^r;P~aX5;)7y0cv%4pvV%qO(MW40_(7( zcRNh|NMZN|DpWQ}nq$y-UZ2Gd{Cp$SGm>hyqss9JM{zn_z9xV(>ps}rZ$Vbc59sQs z>EYzPZ#vYn_$;h$4(I*b6G@27(C1cfT9{htfK^Zo@+oz_#+Mc%2G=zQK6Xw-cCI%X z8l`g=yI(dkd56^-u^ep0JANve1Zn2h%{U0b48q9`bUlcc)qtzIi?nnC4w|t-p~W zGLslTtb0mIa82Tod`x^~=r5j?Eb38)=mR@1uoA`nCcW(U*#sf`q7$-~{52epdQOdXe6mhs3K z(PAeuhH`%1T-MgV2zBMLX2k3=aIVb+O>fE;!IK>y!+M+8nG8(dpBsEmg!l+1O=Xmu z=eb>%n|JF^v#3SA?}z7^UIkTb7AvKMs#yaqvGZ|6sgOe)3`tpfeM-2l&N7plA2bp# zm|Og;Utyo~;VRlNSn%*RaNC*c6OjMX1_C&SFqczB7J)JeAV48WqQL5JH!^v6Es{>< zl*HlAX-U6-|De)OF8ZLn4I5lya_;a7MKTY%3{+;L-mnh!33!@`TKY({)q?5i{X=;Y z#@O$-MjWoUfc3fMXet^rYS!8!g}|gwyCH~3iac9~^qfOSRS|#ebQITNB#=%ZBL#5; z;(@4b;>60?aK0?6IZ9eQSEcorW+v7kMwxY3q!K)hIHcF!UJdfT#GLjSqtZ}6Nvp%B z6BGgjRc|5fDDaFQ7VRSgE-W%GP$;}*;df$e=u!1{(X6ar38Z9})@P_@&R(u@$O)Uu z!FXji3!o!TM`6}o!p`~P_F2c8u(v z@rFlX3Lrb2Z#V2%g6;m(pFdcA=Mftl8>?qv%~$6(*X;W3SR?lh4165q%%AQS z^F54VWj@fXc1^BO-oC+!UO1iQyV-+f{tA1tKns2fGfraj>U6qSD+2kfn_n98PBe{W z5{0Y#oJT1Z=Bt-M3(yJP8zX>g@Ye8M(C!OXnai^)ih}QQl3G@U&(;*!`+mAR|EcNu zQS)va5eRcU%TsIprTS=OdE zYu;N+iECQjUAUzQ7m5^8d+54mDqs9vYGf-K#|bXjK_e4x@W@IY%DJ_9`dLkGA0&0& zS8>CmGA#W!3R%zJK&%}d9RX?WFDQHO9eqz^4c%9IGSrL8E+G+Eecd3d5;W*;gV02fZK+WI-ho3`A z#vHvOzk%jMh9`d4(iTgKi!T;fFBT^4^Un7(S_HyS|3WMR8va5oq^}?r*f!(+yIEIh z68`Ozk3n%4&RVwqf>3}h5jCU-C;zL zYI7v;d2O1XGhSz#+4FsXn475RfTt3A$?~X#7EkJgUNBFD1bL`D!dXF|DmfZN$nG#s zY1cfng;%g7+&MWp3A+BGx8SDzzAwC{vR(BVFZ$Ns-d7^RwI5V{8J^v$GlDugO z((6^vf^U+>YYaKS)rk<~ADMU$9$843xvRHd%g%@6`u^S2{&?WaUO3N*W2r813utHk z-C|5h?e|x*R85tOy69R?`rWqYS}s8oeFGeh{gqy@eIEt^=@W};+wSfZXttA1jzpE` zie{G|)1r3Wrd3xIe<4Q>jO#SllrkBI%To9INOxSHx&Gfv69YGG;@QdJadB~dKwuax)&@DB+}vEbz|%tv1_K}) zE&!;Jglna`PVFn#YYkPOC>Wnci0fF+22kkWz!o)PNh~w{lba7M*_?)aYwI&#FJnnk z;K%8kd5$l{s6!=Nfbh!2VTt_tr4Tc{3Cew;SLmt?K)UMq_&8Rm z83hal({3$+&d$!WjedV}TK2U3Yf{3gpNW%pLg&=e4Cn<+i+P`@vcm{TJJUZ0cd7S= zmh;xdy$)*fsD|$!#9a5>schwLIBv!k0k>tDX`u#!Tx;)$_@~m>yINT|f2O_jNv6Zs zq3NOb+lqaa*gb)rDG>E#&vD4t$ZK9~#KQ?nPd=TFzs5g0$q@!qHCxOs-t9rBU=*-# z32~SIgU=>Gus|#oOF_0pxA5X8LwH5&yfLnUFvwuvmSs;IofK1pRrr=VLH)=-_!O`f zDt*S_+s0P8Qa!y+P-W(RKegE>`8vK1T%vsl>DYzO`hJ`z;QEbE9HYC`!%eCQyR_b7xyH$4JQ_-V?7WFA45@`?2PCBW9!>?_`?LQcdmJMI@HC_R_&RY z^03ras31PqynxjSpZe!0P~R^$L~B)Xyu6`wuaFWOQmWGg#o&)reV9UYq93(%LZ{Um<{d>uXkm~&6M3vcGYp7=~MOYZ|340 z+nbtk0xg|%jO>#*%ElHvafkJSZ?{4Tt=0+rkE(tX%TQ>o84*=t!}zNXwhOWX5jJoj7~`u32lh?~N8V8WV6ZKiOLR2N86h2r(C z>xI8aNZ9)}8aux|@mdFHX?t10&?UuL92m2UJ_O8p}SxouCq> z2OqT-;`F;hQG;!{Kljt5JYh=h7SaUcy!c+&%%5I*e=G}EkX_9FGgSKQgM%ar_pl?LHP%Kf-b^%X|O+mCgWMoQ0EE2BQyo2hMiG)_g2D`4Z5&j}{# zl>_UC%X+{z7YP+qY2pK$HVkUF#pRLNqZ+YitT+ggX}1Pj6;5Hjk6ytocTfe2W43Pg zOWTVp?nN9;f>@H~?%s9YkHke(+sRr2E zPIY{>-)ZktPA6|-r^xAtxufK$$*|k7(Pl4VL-i2Drdu5}Gb1#HL!4y{0dM>1DK%Bs z2XDm)mJqUw?LPUS5kxG#hJ}Y<7g}UUTuDJPmAg?5;N{}E0KZ#xAQ#HL~ ztU>gyD1Hx3x#0a4VvUpYAbYt)=$1Q#&eXzvkl|%JPK=K6Yx0l+h^40C{13VLbg_LE zE1E+(n(!AjlWosJAT1+-2pp7^%^?LNO1M&^xk7av_jffgugruvK}aHLb2*L~*A_&wQs<&{>BkWnK9g zDjR35fJ)e1h>ObCUf(pKscS9O&YXZ61cL;biP(&6SCkBvyT5z)gC)0)UTyaDSGYf4 zO<2t5mb2kmQ{RfY_J|`_!?08_?mff6;i@&!%c<1pK=`+1CmsEdWJs^g4-|^Ucw2#2 zLp=$SA*N`|{DEj@lzRD|rZQ60i3-Pbkg810;YT*AC{nZu9V!M_LqN)0zfKWcV{@w7 z@kerRL|azdKpoShygHelh5Bu1ui(hOv}IZc9{OED+(*@=V9$#y1Pp_8%&wxdGl9pG z`!^jqukCrO$W&Hyv-^j!sEd&1r@+yUU}t`yp+NOZ*!Mh`lwMF|)wMyS1<5?AkqOIv zP0UxkXSCg`uT`OT9{Kp;+N#D$!+$iG`HN!U@wL1m<47O>MHP8NubxE#%X@AlRotZ@ zl+o9hi2Va)&S;P5grP+DvKk*k{eeg6hm#^a1Aekwyj^eyXk*$&OieOu~Xk|DCTWNhdX|S+Q1CwY# z_&Apk8(AX?oYM54MD-ZS=)nqHFzK%1XOUX?lu*S4HIuLb{@Pt%qUh@pU+Xz@)WTDu zSWBt64NPX%bC9Oe-NdUW)~1-=rO`U`drhx&*~YKu9(;~xVRPIn!s7BV-Uqr$M@Aw+ z;O?vI?_IqKlJqed;1DWgOCbmDc4^Y2A=(B6qy=Vmj@{YUpc14qhh z4w2O>ToFAlb9&%?EeZ!xRnx%rbkPB8E;6ek<7VXHKnV_@pD6%ywc${B%yAl`)^ISHJ(+{YcVO0 zCU3`D~H3!)eQNO zDIMt(2^vwu%+gJJ@HJ-jU&|05pN^=Dtm3TTmybs$D8%Xen)s5Rz)RXvzEr`v*gdlF zFQn5X%;3_v;$F@NvH5eIG}+Yb(VZfzUl1vGfLy*uhZkPc+QF~S(XmcADfl?|fIIW1 z4X3N&-M(~)hI-D;sp^%1UlU0?`^-8;#4HJt_@`!w;gz0rAJQWrdNgt3;pe;uGmQg# z$*~ztgA+7KWZtEwr-Zz(Fa_f6UrcIvw>#ZkLp_tn$r0Mt9JUZaDFivRBTWc8;dUbo zc1~c97N>vu-9-vJ?|rosw8u@PIDpSmn0*&xy}>*727g)Co}!UeM%T)pH_FZAyS|ti z+)`TO*2mUPqH<)|B?BiZNmq8TOB^;@*rOPZ7Y3uhUyC?HOi(OE5fV-vr7# zNo`h}EUX5`V%|l;dq^w0_{RjHFFbfVKbELB!7aqH6<}dk>nP_PJf;{NN zV48m!3keVfbC4IL37gj`o*}_y!M`Om(vx+}~A&l$m#mH`*m? zNeC!?Z2dg*%YuKnpu5aoGX_6 z8GFox=tFti{yQv@t$W+jCY|c1)rf@x=P^zTXZ^>VjYAH3K}=D=g%hn6u)U2PE&TW$ z!{;v2I%QKO>G4x{Mj9P-9}Q;ldQQW{J`JZfo_D(kmI&8M0WnuMU9CrrA8D=YOwphh zDU#0HJ6S?&dt2}&-TW3WL9-HC7)VZW_C1&k&ehz1|xlvL6YagirStaPd3SMdMlSIB@ap?R~uW zm}G&(yDo>ec@*5(mt!qFghn>j@M8wy%YrlC6r()63DMu0^t!%^FsNo|TSfy|8BNGN zm4*j(@%1fHLv*TM>Jvy2d+~)Q-z#l9`~ndS(dk`DLBaal@A^13_NqJb z3sc;KF-{1tXL!)g3EpV8w2`AoC6lObSWJWB9125Th_x0~lYLifN|_a+<0XKfH9BF^IDQ{xkx$Jrd? z%#G^*4rJ?oA%;qIAEfj%*WbUketa!sWM=+WV?VgLDe$p0wT{ct=obDL}5WieclE(B=tl(Ko^v2TC$x;XJEp`B^hmbj{^27@~UmMID7is{KOm_e7 z>G@FeUPH)*WNHQ*Ae!Ze7zfiZ`VDi+lLM6 zMzWBch(c1k%K@+i09%-(eVm62RNzrdU5SbD@ywE*n0n;p`QhaWfRpO!8D3#s7sAiF z%m0tZA@8rpfx7_dsKo~!G3^0ub^r1|FGuCiM=#F?FYn&HJL5Gd8|C93QFR4_<=~7G zC!BjW7YMK{4I9PT+o+|4ct-JA&t6#V)*qniE^cATBK1VfUzlqW#G0HZ#bOy>{OMMW z0MpdMC_caS@$I&lf224rFuPB}UjFlP`lMM8b#?FpHUlsHtFu)Man!jwD?a=oFRwPo zLPhRQe7RJ79n9`4Wdm!0d8O!i#k+(38Y)*01_Li_Y`oqomSPq#nf4`~MyL-v7Smtz_vHu9gi;+RJl$2E8?1UjYax-rnAWxw17iHE3SV zNHiM#Uv*XRIvOpBgw-9O@yN+R8mFRhzX#-t_;gLre$}@GE=EJ;PP%nLG5dfaGCDfi z@5e|P(V7E3r4&gT_^T$*qULcw&}rq5(1YiTv@LX~zQ*6%4SA~i1s)l|l^liBT28bC2fN0MJOUag&~<>=D1ZEkEI0V#iXtPk|CzJjNUV-H#sZWq zne5>`{;o7AJnE|aflRc~a`B^uMatU&n0|C+_LRMXKKEtj=FZl+OkXLdR+m4mE>H3< zPoTm3P^+^=+U$xOpVLL{2hO(UF1A2{fF|M3JF>eTrqbBg4GM~sNuu)UkFQSU=vCn9 znXb0e%3J+FX+MzTchE0>MSQ)=eSwh9RWvCv=#Y~gv$^Tqo<4VZK6eQ)I7{iE=>j_j zkkayd(Ym+)oGB0tcLLU=txiWW%A0;oaciZ^TpTY+`)vM`oh|x3X)9n`amWUoKI`dF zB%s!UN0um{*F<*Qvs;~VsyGMeqBRhEo8F?gB0y-73VDhAo4y+SE6VZ-Y4GkPB?c_p z%m1D%P>E%@;|sVvav-NfC~X$eUJkkk2aojZyHN|csD>=js|Ex`|IFY2ba$b>u(0sQ zct!B;Cp`Pdk1_L^H9%-(mi7tQi?zB6+2x&2=E)xPiCUe1H|m(5>JR-oAvfzk?D z=Ew(MfKX4iJa`@es6UNdue)YuX2!|H){riPI|3qGA2i|GOrruyggIY9{9Ct z0Atzj;35z6AQzt<$jhs%tFr+I{cCx_7p(}Kou;E%n?%{0oBp>U=UGVPHz4(2^<&H7 zh}PWY#gS2kB@kd;_3TtbE5fk2BQqpT0A~m!rgpRE&WcYC09mT#K)NL*qbL=$a5fTo zepR`>uzGWlqyoJ@SKe}Qnv|3j0lQK;XJ&F~fdL>bMPHkX6#?2|$sjGFh(L zf>~NCT|m-r-}YcFniBe;+&nX*2y?tD-hvLkys*y;^a%(EIN4w6*I>NrA|p$`6$Bm& zY9WGA%x(7U;`h!RaCBXD6krU4M3^DCKE;DIP@)W%9`k+Z?{D9wipGCqmN2tDuEze% z0lpCkqS<0DQ=oAU4-Yp+OQ1Jzfq}2qq5p^_>CN-%*OL9NJ?^RqyAzNB}pkpya0IH9t_|dwYAdRskNL zLa*1)1^u3wFwPd-k=4nQJI@>pD2_%k3YgZe0|6Z#1>Adl&QJCmPfu8CoPa|yUVIj{ zRW}W$p&Z%gKEP2INy=;r{9nb|+1sEKJ1Ofoh9QSn?*ya%s$hl-)xe(3F*xojXiB%m zx=%fQ;Aal-x9c*jg3z){{OpkKNA`cGWliM@0rx+Xui$^o*#9xBD%^qo;dvb z@IbzQ_TUQ$)cfZjtQmoY37#r?Zv-Jec&uem5ll4TSqOEsW)l;2TAxK&vw4GoAo`o* zQ#GX&k^XX`fmauI_kV6}c6WJ|ry10Q^V1EX)#!fPj6vNuFz~obA%@MZMSKYi%ue`3 z9{-5uK@~0KMPpA-k3u3Zm8g4Nb@kMx63P89;?w+W6P1*ZxH~QKa61{68Sp6kZ`zPw z(Y21iJIx*2%^wCmL~o3LJ%Xx;a|UVX#8p;SWP5vOJj%LP6_z{7gUNifwJCd^H1R%q zlReRGBVn)uDElpQ)JmS4`rnn}FX@ZN*rI7dvx|pOxVp>SQvug3h;=9gEWK)TX z>Y8(Y2FL#q{y8|fOg_olxm}_fy>NuGjlNf=F%~FC>nR2mcE0 zm&wPEgh!2Wn-BzieNc=M0cs} z)r13u-O^;iCBB3=_`!wcup)MKz3(At5ycZqsa(&u5SD8zmTM##>Ez%a>~KjsP@5gG zLWqdfexP1e{G73UVM)hVgpskb@#wokZe5LK5o)geTo~kPOfj=^W{AJKNNno|q za<+K>X6?$#-BycrO=Bt12mU=n#;3yEgfAsj5f@fesFBq-fa|=B)5zXfcQ!NsU{uCS zk%NZ`*>kb=)B0eM$N6lE=uL55wR)Ms>&cNUhh)L^^g~I+?o7b#BA%LB;mu`|1FI>I zosBuv=>&L&IGRc@TVcbv2SnX>V0oh~=5&L_XHt%zR;?`th;geq2VnfZHMx1eeO*9A$UC z%GEvF(cS)w=6ZlsGKD&`h+RJ%aB^~TKIc-jy$`==!DiR2vQAsyGwMN<|?gpl$A$2LMW`rN+8eT;$r>I(AlHAHdCsjvl)77=U*>`Zf?|c)YCI+ z6)6$h19TBK9l_Ws?!RAtHJGgV)^ZZTev*#|pPZb$`1{F9_^6A1R=e1s`$vBw-}wzD z@2!p?0am>5%)zu-Yz!NP_WPyQ@|V8&-tZs4f7d>C=@YOsZcnt*@bPgW>qCX;h$lpj z`=a|3B|Q)>^JU!4!DyDREeaf`{s@LqMc!V|i{_0J2l}3*T5WD_zJC2WBqRiW(TuV0 zc0POC8}otfll_-{3k-OZFAEY+HiiHJ_dl$9P46Wfn`5GV%+%YlbnK}BWE zABRFiL&K7PUPdbA&!2aALJLl(TVW|~_Pd9julI>BXL7>&GhWSBo5!DbM|$tR{9adA zmzl{>I~xjz$0Z~1_^qD^6V7hAT{^X05Ry>q>7d&6CC}h5zva##M z0GYP-`1`%~gl5=^8uuHnpUB4*f7|~1{rmUbnaakKkvAnJ3U1{|x~=}v(a}y$PDl_$ zDeQbwSi84X_FDn7M5Ex#z)ya=jiE0oZmJp@R|A6kC$68QPV#?0(5k=c=?M9-JyGfB zd(v$`of9_haW#4{p67-~O{|$J3IG0`lRV_hU^1ic&Bb!qhYue#3M!Nw#M-W|u1>cn ztR{=aize8$>l~LmLXrwiEG+7sPfhLZ&-BBD&$jaT{)|%!Ia+UxE5 zRaFJ#B#>f$<)3`4p$KcRzJ*_r*7nx#B7 z;y7iY@m3*D1ea1tNhwJ&Ha`9}CRn?-5)$5(l@2;Nrz*m~^YRK*x4qG@?RO@JPrb9= z#5%jUY}*M0wM$^8&D(>e$RM#Bn^{=+e6>95Fh6^&7W3&sbfg)r@FUFm<|W4SaDhhf zR@%OGz(sa8-kJ)!>)WMyy)8=OzK z^3_W>evNh8Ke0>OR@kw>mZ5gzcG%NQ>_1zL)d{5*ZP-3fk!5&*i<>;evi;IYl4}=Hc zQpqVQ?m3GO3ZOuDcXw9xr>d`Bz54p~ND@!j?r5c3(cu6Dywg)gU%2}e%R6Od{mPl! zo0|xH-+j6U6d_r!KA3C$6QuHj;7D3CC5ZJ=O(TfQzmT@P`0dmq3mEM~UG z^ESh%EY@$&dtEB1q+E~t`AYx%sj!+CF&+C=Nb)vf$KK`Jx6|Fqc}2`>*UO`DT1n@s z9K_i!>fzSbID8|#Rn+c^^k7(~^>1OpO|OndM=;riu=~G9$1b z!*=zl>pOqo#w8!kd1qqSKH(o8EVfecS&nVmQ59`gkAmde9<=LRYdZdW?&jH&$h=3C zJ(qT^eVq1w<}Qa_zt!Y)xv1NL7fKQ}8WgNi(BCOjZk1A;Oe=;d-WDeEpvt=0YYDK#(?AKUJ8IW-Fw)olTw3d(7Xd?N%ILEb9vQt-^*)%iV7dJFOaT?JEbuZjNqc zFfT#!vg9TQx39{uHzsuSOz~plv>^cZ17Z=+o}C>d*)?ml)9g*`+?fXggE%O|a@!K} zRAC7T3YsZ1QU3b%PgU*PYc_p!kT!Ow%R9rUE2qrM%gg_0%dh%)dqb%W4as-Mq0TOA zePqrG78biy4*!N*75;5phm8!QHQd^_&pP1kAwzWEar|{XE?V0?ZhHmv+CB>*L%$~q zC{7oA{?_hs%1C3$EYFfju`)+c39MXSZIjg3Ukg!Bm*`{AiQF8tLI)?KN<})2cacgW zhbJeQ9&i30RZm6Qfw=yxzMG0m7)L`6k`tEXN4 zH7k)Kq2J-=axnI89$|KTY+GeHx|t!w$G5RtnKzLSGtZf4U|_gED9p^vvv(GQ^Bz#D z3d;nzOh)|)Ad(Gd$XHF6ZN?}?$ucZ1E`n$o7!tCpY9%Zr1Olh+e*O8`iLv{*unGH^ z#P0H!7FC z68`XK{J|8_uiJlvmOD;$^(JzzWWd&*H|lK7pTJ-qSDQI#*u-{r-}!1eSK3LiXrs3$ z@RC)1ri8YdF^ckatU?2AlxE08-GyikXilwcZEbbjFIR7`&wWb&6woc@q_|&=Dv1h% zlgsC_1VV3x{qFQ@zQOBd?ZZL)4f(UFFL|POFH=v6WxOza=hstQR6l5GmFN}wM8-^h zRF?1CEo#_GMrRenMDoO;@E5tYQ%L!#Bbv-<_}#G8|5+pAwz%}mb)rO{+3$^Oj;;)oZQS*=zQ-3&X18dJ-sL*7Yj$d>=`-hpYzb@REs|4bPb*} zGn0*BU{$fEc_dkY>HR~KpxTqgMA|fJ6!lz>cNrJWY3%BR<`-`LDOAU8n_{h+p z$fwf|ib}GFdYyP=s@qf^SIYfdgJn18i}T{h&<>~i>hT~(!!a(|n34ukY-XM2AHz38 z$AfB4&H_dO27^PJ897XQ)2s7pGbT#k{wj}fdd}#$jdQqEFbX&~wak$VxSjNO9oWdd z$BltJK@{8lSFN1&o*!|Kbd*Fc4JzN)gCtHb6S`85*uKmhhRFCw1Z<63D=frAsW|Zu zD+)d(?p5c|@=uv?$w3_LorDpx-xfUaJ8Yiis~+Wu&X#;N?ALNAf2lm5>{hWg>wtox zfAv(*d2GEcaGEK_F7(Oh=5llhg(R;f5fAsv#X#gj2=8V-7x(4O8obKYsXtA!LG*5; z*whRDl>NEt%8I5|c~AEu5%kOXY^up&{t-opH?|!izRmXE8E>C^7;pQh0cYgoor;dA z-R)J+>GrPMAj60i)ReE9ST;SQ?V(jn#pi`_XZ02diteefGui!Qg~l(n34={fd-GZR zcHZN!eb0YDarS7tDuWK>0`Gw27XD^$K=S2$>PQD$1ZhlR~N^Fp+7}%XN%L^ z?`}E*36n(K>T2}-&NoNhb=(-M#2lJtZ>ecfA>!xxf*#t=OTL3m(T|}Uhh0+~tP;Ce zjAkqvz5b)s-$jivHy89w$e1s2q|D8H6cW949MeVy2lrf&0OCn;pI-maWGOC%U~f3c z|NYzT=(Xh&Yl3c&Q5$v!Lns%u(#`H=eKQ)R}UJT2SDPRuZxRt_UiuTti>lkAY9^MYuW>9lFJg zQJi3p&R_If^w|t+Aut{7) zsf%t?5Q}r>Lc)1>7oFfde=sP2@I3rAzRgTUYCIQ(gk)0X`ms@4hek__Mui3TP9+0m zJ@dC9L^+#ut=~4^{1$>0nNKd9x08(ElD$Qnlsxd@OI?r0q@9}Tx#NEbVS;5cMKmJ9 zA}!dpO4>RqeEo9Ic9&hPiL7739T&YPz@Y>zv`PX&w?uvSw%nz1{_^;?8&eYVkeTI2 zbd;vs8kt&L;jpyt)|ZqIyHm>#jxZk*cq6VKMPSCT7tL0%6?^1)9{tlaw%}>+tc5qz z=#5j~EmXQxu4lc`?4?`y3@uP2FtuySV(w>v1hj;TN6$>PU0-BU!-%BnEP7+Mc+7T0 zL<$!MuoOa)qB37Pk8QW0k(3xC1<+qK>ZIj)`i9@!h!i2y=`GAyO^6(#es3?-Z?Zr_ zI?c@mEK@bR9K!?xocT_ zJ@kavI$Vc5o&`5ttLO6Fs}R%b{RV$L5z-NtDL|MFrKQ137iOnGpU)3pWM-qg9tGxg zKUu)nw5(gBjKEBG$~Ho{NB5)Gt2oEz|WqTkSP#yj69&Dl3bfzyL$h@{E5|y%Ru&fEw_AcZ%NB+)iPem=x0+vF&d%+7}(2 zjDh>hSw9@ipIv(=0bL&8tLfF=dZpy3m}ndDrk;@J`8=MyLIEDmw_yTmXkpb*r(|g> zfEu?tt5rE@S69u(bgC286yz>&v zxk!0uJGnZ=O@{p_(2lmYnp!^TAN>H1fK{IH@y97{Yv)6f&&zhRowy*rX;9##Wcjwqt z0@mrFgRQ(uHXUvH*xDQUAbbcD$AXOKH$PYDwYeNz7C+!-UG&@YI_n`^I`S`l;Uq+k z+6{f>tjM9h7xS~g7ZL-SAJ5B=5z*~FMIXEnPx#an zG2{7)lG)ubpyTz4_0?}Fa>!8B)D&;lNWN;Vdk_Q(3*+SGN(gXw;NQ$EAVKkc4ImBv zEtrk!$O4DwMQ7VVI|G#Je&>o96j}CbB{s%@iC(rLN;(UJ+6%ue)MMb=T-hy0&>ww& zFlc%A*AnkvMZsQ#jHN-6wG;T>oDgDAl;k^IiSGi!85vsZ&qEx_n3$NXk5r9$n#HoO z2O$xXcf^ZmIp5V~rhA*IqdH^LX*cfK>?V9M$n;}Rc!h}sDJjV-@E90=!}X%0OA;h6 z*LYmsCE)6K{Oes$pZw$Q9aS1VXXh)I{rZVr)Kxzc?JDai+ymDeYEYbxV>=&T+{Y zoH1Q0gSmWwCiSmU=@Fs+n!X1PwdDsE3z@LHng^2&)}O~rFURSi)J4LgAd*YQ%hVsS zv9VE629+}~7))7N8Sk;sWZ3!W(9i+kG$NdwoX?-{h49U#^5y5{eFBm~6tl9PzCPlt zva!6ZY$(U|_H?4VyPJ?n@u#qhy}P?eed}Dk3s7b<-*58GyGBMujZIF%;Q+VK0a{^F zIU^HHs#~t1^z-HLVVV#{LlPb&n`NIg;J6XazN=!|WN&3PN56e4p8@hUXuK~WrqGhi;K&D+uv}%|tH=A&ncRSy!-6xQEh~5hH6h8CG)QN2p z!02q2UpWW(VBjex2|R)b2nm_~Z^@^uacOC3WMo7@MCHJv5*=FWGnuTvekD*w@yz2* z?9qrPmUvrD0QK2?b!6DU%q-;TcI~SC{-G;2_df{AR^p3^b{f^>uv=`(R!LY|b}|(N zS2Xu*pGla~+>T2~SooWOmXXmD+LfU+Nh~a^xw$#FElnxz#Qu3eqiViwySljnDte|> zYtQzvxXGM%eQoXTFw8?GS4A=a*KI2|2lug%Y!Q>MikjM|g1>;=>`a!Rz&>ec0A(L& zk}~_3H^+lHSy=_z_0Fq3(X_O*D#^7#+L|oUr=spx%KQ2pPD*C-f>g-;W;lqvcy?xn zlCV|g{<3?TT-m+;5DhROz@#=i_CI2>6S#7`8imJ`vHkHSNN@{9ub%D`<34SCOxM%9 zY!!Cmk44zwaII5GG8p%Qo{NhRhDRk3_4DVy*;#?nP4DfAB9tZ|7R()X*3<|@$P!Uf z%F9d(?p0+}RK(yft*@U0`P0zA0B}yxlOai<8#DNhjg3w2+KY;cURmAV-U4;Z?R0A# zkje6S4i1ikBaf7YlZ|Z`8%f9$U;g!rotgDoQ$ziQ3JbM~{KZ_Pc`=5XvyBXQ9rvl7 zwkQE)kPA+otL4Ud^`y9zm_Dtr#6|J#<`K6_|Lh}&NEI=D1_My0PZHuo$mWwpS(zf{hcnVA75k4ekkc=Jat zO9L>WS<9lr!iL?78BAKWLQPQ8q4E95N}SkVVc1J7CFFW>05%6~eGUbX^lbhw%|+`& z=%7y(VH)jF8F#dhVC8CIt)q=`B?kWRK@-ZK9|U1}YSl5)3)w>p>p%I?lWQKxxjc`v zYW(m^(w#sj1ZKoLQXCQAXD>siomz6XGL`*Lql)X)i2i)t+F#S@g;x^21sWZ zwWww3l&P7SAtxCv!_%jj(AM@gY}lx@{-6cBH--&p9-~12JOk8kbg`zQ;w)5fZ{xza z8F3mDLH|kRcZKpkVl4b;pBc)NMipOUS-A)JED}{53JT%TS@N$JZ4M%lAv}?fmDkFC z`T2eM!w0kW_zTk+Vd&=b1Ly8GG~kwe`}S>2^xLWmNsadLMB`m~R+eA?+ z$uEhS_RJek^v2rS`T(%}diUF_iV9wdu6V958x}LLrIh-1%gRB8-~2a4@93W>EtMlF z1B`gM^v-ro(`6};_d^j2)q|IWQhj|YzsF-dJ$W0>ap?x)be#=-JkF1A zhj>ExWfqAmOVVb>Pv>1aX}eaBfTE0(DdpAJh}bS_oZIXK7}?|QI7N$HyUchvT{=kM zHtxrdABl++U=KlQ0OW`vYU=yi9JN~%CaqQMMZ>(5|CJu_-elGrO>)j7 z#cPg?2JQ%?sw6>&fdrm63Fn}AmdvODn$I02*KOn&2CIY~P$SWBw@irKm z%d3Z0eZ7&TX(!<8hn=^g2+D*+a8y&dCJF<4d+YV|ot$>+3E>-B+IN{7w_(ToB~w!7 zWxp&B_2z>g+PDc%{IOR0-(tdxN63bg!`th3Qx&3Y9JI|{p4h06nX&P5Tj1}ahTq^8qieK1gvZ6K3EF1AV=3nv zVuu!Lt*EO#{{0&5zq~vGpjPt@_gg4cAuD|`GT}?IZfe*S4rC{w()kDqkBYJ@ZFB=? zsphWBXJ1qef{4`BLn0z-qW;>hXEG_;DF*Z_LkrW(VR%y|DEL#xFbb%t!R_~jBXPF6 zFTP%7-pI&9peU#4RGP(#QY5^x=tLY3O0%(4}T6$ z4%i40Y&iS<<;H1W85{{j<=)Q+aQKEhqmK?vx_pt*qj;i@I#mnpVzrpG z1+4*mia&pK^$?f`?D+U?AT{kdA}RL(a&!#Gpw6Eu?@jTtkI+#aLJ_%*;wZ`O1k;=^NNZNo*Q1lm z`VY<*r|#XJ2NW-I7z=P4I@kQFjt?O|B$tvxO*jt5VM0<+7_nXN8y@CHtb3z<19X9v z_(=l#&`T2n6SL#tZM2z1P};8L;l7v(|1qMC&^=tL34W;K)9izjRoS~5(>1xI5d+(NIB!9~HeqS|+jaPNUs_7ZRIo@#ECJ^h^P7 zPF#i|O2KsNyfZsE7!y8paCq{>|L_0y0(9>9+5`s%Hr)Q6W?cAad|*33i9+Fq1OX|R z$3MU!A5m$oJ6ouQ)HfLla-X45c30oELV+cy&08WtPdT|v4oYujq+D+f&45le|F6#* z2gUPs4xvQqPak-HKi&Q7pVM$AGDb%Oa&9-4_v_ay30a#GJcqAh^9DOc)01Nhtq*SgCYtLTSiQT}3V5fR_>S)1)I{O+MTEAc!E#uhQ_ zhH3%KrrF#1uS9B#u68Kosa1=7UyQIUY!@{?7$qQ^V!oKVtHdVJo-gezDhMImr0fg9 zH+HW1EO;XUlnyl5ZNuF(CDkl3>12Thil?fXkn3b+K}Zt*FHYekuZja$5LzhpdGd?a zu8!-R`(wP+Z~mnXP8{E-t;wpNTF;HjGP>=D|FrRc2ns^0c8mD=j;>D=Qi@)2o z@ry^ew5UC_@Qc$4_lSs?Cb2oS>x>ipn@p(b_MBp5)DQm`^aT(zn-7StoT|yagu&_X-`!Rwg!9%9BPI z@+0#A9WYMPmgnf>@9?|(r9XK)7UOlkGdkZRV5{Z3 z5eRM|d~H*^;v4??q#X<&%}M-I`pEogeK_`5H;tY}fsDA<&D}MQd7Ul!4Yy*-oFuq0 za^xbq8Lr?gGcfhay_wpOaS%K3m>vGRhFFb#Qc%J7JY+zZi%UJOm4KGy*C>+bpy+uD zPoDS_{S`kHPt*B^>_9>*6Bxu{9vAJeL^{ML#XS&5`|SBye*TIEv6nVr^aC{MM>AGz zFxcOPg}Ewjsh=Ea-Nr;ZbzKtDVqnZj6Ek`p_imMg(b7NfHG#$-yt8@|0mh0GL5AcQ zLeBru4|eNj^G&@v@JLD{+omw;-^v1dG}O_V*l-={7b!2*g|;Pye+W)83>E{U*O+vi zf&ZE=?TiceBzVo96Q)tHxuecZQGo)T;t8b+SVQ-jU&5Vo>S3|=< zTH5@C84R}H2r2@)y2q0xygKu9dF*ti+-pGRY;J0~Cc7PIH8Wt(?Fo=O* z%$OAojrFGioy7CEIiB#&FqbgOsXqAu5)IZq4lC`Hd2kb-ut(!iUxCvyW)+Rf zgmk#>{dAD@iNkR#y}nAwQT&jVRWe-q@Luv0m)cj(F_+8wHd)-j@|;dF(WtNcU0DV0 z4?9I^OfLZ>DS$G}xP$9-p|@FC@i~g+*H>q!^Uh8YwfmM=dxFGA8w3*gB_cc@%3b&< zgnKz~&phsni}y9`uCA`Csw%!Y$5zWqhxgt;fBtmYs}5K@t^?R&tuKE0BN<5lPydus zto3aMz$%z*N4Ddq(YBP|w{(QBm=5XhM@Rp_A|#)3Yz0T4zSi>Y#(hJSZq7lcb+I)# ziU0))(qQ8yuV-PIG=}B9yu02%ozN-D&AoR8gi;9tB6+qqJG1ExJO$VLjVWu#LQY33 zpngvIToNHBC2f?=EYje?@vog@?TA zUFp6}6anzEZ!q@5hZldaqu^5h)wUn5&q`j97k~G;O_{X>cplLc{R~j206gjj02~YN z_D8bbq@|^Wy6rWIOLb?x(aR_?Y=htBvbuEt3>HYD;~LE<42_`ejuvbCr|INc7a!t) z4S^znVVod|)Gg)vx;ojfUt5!fS$HYY>B!$J--=uZ7r&eHen+{3Ff}#pGXk2G{swht z2!)!q_S|Lyc+Z`kosA9SkXOfzi0ek93E5a&s3$+)pWjy211GM;K+zZfdg3GN89fL27f@xxViWDcV zt@*A9c-LB6TYGzhG|J_ln3?Zrj$~C=^Ruw907;-1_@h8^8vOU~RD{sdTR&?Tla2-K zuTdW<{Li1LzCZw=ahRFs3=O@J1c{-S?*9ZC+Q^9vmNkem#FWv=_iKw{nNe!dppH-r zRTc|r>EQfS6tUKP^*JWR;uqu`fnce@uY$+KB#qp>OD?H>*;$DCm@M^5k(JT#T ze6Mx?>b8KSft78F%Y=8cBYm){ehIaTxQZ^)%Zvv^?8ub?K~*HN6D>Dm44Zz z_PAIKh@h9LK(NuNe)!-Q5TH|QA96=W9K=WvsBgG|0j2hJgY|A})%QG4t1f2O(laER zZ*8Td$m{Df(3kxRgJ{^59#ixx9*kaJ?_Wo87JtHj!PpMmU3F<*ezxk+=i}4z%c~v` z8zY82`6=_iKpdcw%l4^)^r3$c3A;P^eNa{R=)|_H-K_vKxx3x>;7jZuA0M}BxHOWJ z`+h$Q_|w7u-SdIL&>;gwb@iPcWF7`4?A36}HwqzDf8KMNyeCAliq3v$PA*)d^xyJF z$<2)Au9a~=Lb386vMtjnpc70C8TJ&W6dlwkH~sMT?OQ#)CBT)8KqVPCH6&!6oGw?o zBay@y2@{(h(CqH5xF-4-EIxjQ|t+$=Ob8f#f+hcGV(bkJ|!R{3_o(KCk^L zN2h0tn-&seWwj5yTUJ2CTi(~z)$I(W%0PImCpk0#-x|1gVi2^y+*v?NTaii=@J}J* zMdM+I1rCm$jt&Kik$mjo2Mj#kfB;)IY;35>3#9=l6iG<4G%K%qno^P-k%y7?C}HEK zz5Y0~z$q9))_QHo1r_5`7%8*VD#N`+F`G&IO|>^vlvgp9YZ z=RGHrq}=!YW}nQ05Ht0UseeXF8?-6Ox?9#_y)qx}5Njyd?rBQe^9m+*$&cn>)4rVm z{!~e@V!SjEe{<(4i8rqZRD*__VXTrhPZXTCyk>tYuY-D zn+W#y5cu!jz5T43_m1IfYRTnAs;XH}*XJ)J#**)U&+LyzMu4iJ=)NyMc-E1yxv^4hW+p?3eA$`%X; z3Y#=PN~g0`iPHZNxrbcus{ZwmjviwXsVOe*S64S|t@suN7V_#4h}%&_C=~nQ*$?fy za;FMW(WWFM@EZmk+p@yctz zZ34^p&~g{ZKsG18UguFUpeQQxQod|bd_7pvBxWWHKe^tYGLDE8Z=0?CkehpIURO`S zjFO{3udVH4hX8&C?Z?=kK4T_{C?;*uXZ~<_@oySIn=Zs|wcvye!X+rA2jYJ{VxV6Q zhngr!a$bJ*4WaFhr&+=il?{1SqG6%Cyi1!-N8d_7#xGkF0*`#c^FdY4)U?gV#)C;x zGWGjE%^IvYGaFRPCKLpp>}l9NmQ@8u2S}APIIkfNGu75+pND>8`udO5)xD9kVwwPwz42TKc@0(j-vn4L|(qE zch%=A>cY|1^0^@G+c$P)=kZ+T8xX~PeTD%3OJ0dObJmOq)LhEvYy!&jgYVB+P`_z; z-7h#;1b&*O%6S%jy}ssVRo*#@a;oK%O`qT6a8fD@7M35SCCd+>KGX92OkW(T&nSGS z9`KEKYU|1xrZ#Wqt`dA3{Nd{RPx zUs`iPG#tfj3~fCf4+Q8m($jsvRz3Giyb^^DK=mneJUwhMRRj|j`GdUSPGfwst7Q@c z%HA+`dIy`_1-x#c*|M`mV(Q|MRppw#5mgk>Hy`pFa}QO`pZrWR%}rxSkof~?+mCU@ z*kj+UmBGnuFfjpn)TaOrE$q(|!-hY;r_-0*v=A5n8;%bm9vSJ6pAcQLAQRP#bjFue z(II^H^cV4Q8>nut+9p4a`eAFEPvSzL_PXllXKsv)Qk8*_l}A=1as+1N=E<;^!x=51u|UljwF^hab;hWBpo1(PDjpJ0z=A}Ix& zi9b~WaN}|blic8}ebF2=(U}xd3bW@=!?`{S`rI--%lqzeWnrGM<`ht@Iha7sVx<*L+mo>KZARW-*>mBuVR8eN` zXjjEh(cOY&+`v4_V;r17oDp0D#BZN<+LNU^d; z$;gx{AIL^T8^#MwnKUcO$;u{5=n6V0_INf7OBr)6q86Af*x!Yfm0vyX)`8@j(yYG zNNul@y(VB1i zYu@>5l=)9-`$Ul~TTpE);Mc#dWZ=L0dN>tQERR>8P<(kC4(^-tO%)#s3LTCYZwS>h zUok6mx{-EK^f^2_@7X=KwP3>|1I02DXoG-;qC)@t%<`v@y7tE|Ps;=H#}}e9{a~=a7?63ut;EHE<^2{?cyhQg-2bqS8afbhuLEoT=`B7J zGEMp`{pU|VGX&Dyr_!f*)J9@_jyQNXDH&q5TB;u>x!r}-o}fY{CE0{bu9I)CC}@XH z>}XM^A0?d0=kWwe1)r2JZ4Ad0bKqJq3DuRQB*T87?`dfzijgNKOk~A^ngEo#=@C5 z{*N3FGA_@~XJw?2Q<6;Otk=f$vPXpmk|J@brpXCLI?7pbA=o1{G^28IX*$cCFmfFF z9Ech8LHOdEsFO{2SFu|zBJg4Ps_G`Wj4a$Q>&KXo?aIj3UAFgQXBhfq`Xp?6)k&xX! zSo|xvhtJYt>j#X{Q1~OFI6Xa0@$Qc}UOmUhWTbl-xO5{4GMw?Vk4`Lrbz^Dc-TL~? z4snNhz|j4#(=o{uQz?Fy3UPjAz%AF?o7mE-CEh(PnF&s{XD4 zC8}cdKXvvJsYW3kIb}q< z_JxLvk2^+^oyPtm>m6SlK2OgJp2DSVBgP*RGK~tyO(dK=_W*>1h0~0?FhiR=IAfxB z5_1_6GqdIpKl%OZ^XDOIOt>*;ph-Xd#BilM3iRC@Sy_`3Rx8(me*YSFlUzm@Q86{u zyVl6`0%IuPd^|NK7ySEeEU23!luHw4^~K;|T|v4en_2H^0|2 zFU+_bHaGc>o?yO&b=-oGt@oi>}8sC^@5o7)#_@b(Xub5JlKMwSl@V^ z-Si!+-k31!SAZ@jY%FnTv)UGD`Rp8f2ykX1Rk7(NOqum{DWPI1>2A3P~cT^`MGyZ93L!vs`pzG6vuctplDr{Ma55N;nbYeuEZ9;~m% zlGxhfs+eq`zp+mp9sRg$4Tj?O9nM)l2Rx;D<$l65NKmN;+r;+ll>JL!6fBy*AHlq& z>%_U#?B~rkD$erCdg)TPne;uP%1O9PG~bNsk>mJ$H%YV zV1p1qB6Q$!i+*1R0aAUf=0G{?tXS(yM#f-Yn+?u}{8Ug~$fbtFRAcCPVOBSNp z+k#_My0N3aA4mF1@$U6=Z3f?ul9F0ONnA#PnQj>6;h6o^9NUO#pOoi6YH~k8pQpK% z-9@k&wIGO*;Ej}TepMWpixQ2VYK-2IL6E$Weg@xWXG(8{U%gNbx9gIBMJsLJl_&|G z`+NKsoFhMCI|n!$qzht59+kXcIK{db=sMash;D@J`#7Ec^qM}=uNFh{^jB(o64~2e zd-hrUTTOerPs)ENk3fRu8Dk;q7j~Ooq3a)K%JXh-GrG!@;$pQ$3^Z$;?k0)CKK#k z#*6ipr#tqsF{QCXRAX~FN~LMib)E_c2Y|Z57nacF-7oJ(x79E1=o=X%BCDq;|C$qT zo^ob;r*ww$C?@YL31C6Z%>@tqcK`7+qgXwLCCY@I)qQQx`18X|{T~|oEj5n2bBgeG zLg!p9r>o;L+RXHpNHcLtD5;g@>(_rw@$5M6uU`EjyvdyR2q9#uamPazvn$Ig4!;LE z_z<~>%`M*``opV63PDjOCHvb2Cci!8@oh3JuL?ikNumdU_ke^~?}aW(2ykCnZ1PPh zbM#-`R?S9f_%GGOpzow5RKTO#))hwizec)W9)+YHl1Rw2JCdz4w1g13TuKHscv0!h zAt10go6bDcmgta_w7T3IL)B*-2Y0YxZi@sEJOxhaT* zj33RBKE7zYr<~OX*QHs>y&#ED0zcw85+?wH{$k$*sxyu^=+fKuobE2y>48eMv^3|q zj8i+i*K~bM1UzIScokA32?{$~ZcfRu4{ZvBqGy6q%QMs)ICS=UL=8a5j z9sod2$L8px>gqNl+XV}xh5sMDaT|;pm3Y-C>~baq`pbZ!gm>M47I@=tH0q55l97dM zI}(p8ckwM5j{67K)!0uSk>3P|@s$$YsAT6PUJ~9g_|oV(I_f)BN5xAS7c@8XR@c>2 zT54-+zkmP!dR@cRbgS71U zkb;7O0U~4113D{dwU0f>lK-B-$f1>0=4=J77o%pb-3enbC|s6_Q9!4u72wAF{?xugBg?<>%(UNbCo_c%T`Jl+RKVs6MIXo_u!8 z2>io7P`V#X)~Ya%Z~olX-~X-Q<85p7vzXZ*phuF87{-+Y&C z_gsKdU-|Tpl%j=*nLQ*a?kzju0sE~+5Ga*1YG`CcAb|@!E#cub(Q@F&A!AF+vx9?! zqoefm*lq*ROy|QO8n$tFZM8pF&lzvN3HmNUL)nCm$F4#A6;A&rU7O3gN3#+RUNO-x zI0Fnt;@R&BQT^>1s9dP>PIm=G9nMM+rX`8=4;+afZw&k5gWLg!!?}$5y88O0+JNVW zk%`G+yb?=m=>>8E$qU$}1`!zqI}gx@`yo85kKE`S>ae z3qwi1w{P!@##A)n^U1DZLwYHNAAJ;d~b4 z|4d(BpIxgaDk4IcHxab_P4FgfN#xYxka0@os*KRE(A^!h;sGXdewTeZSmmcL=VMTVk8ivkw>dYmGCO8{`kKYHyM@Z=l>o<45Pn#LY!EpA?+>#Fxh`j5QR97G>-z5|D_{t zpI+VE+<+_fU5b^Ggp4Lh$4i#M`Jfpi2Q){5(+%!4)Rg%;lK8o%EFW$)Ctm|1TOOF7 z2%kh=0-pT!>%|N`$h6qltHZ;=sG?Z3b%JMekD`0r&u10P<*8r0U~&smz>2hLD{R*X zfVJwKPFK0{j`b*WQwjoDL_xdQ0Fj~Rzn7PMc26g~PpHu&FSqP~+dEUt-QNl1!;zWfXl3$Eg#R>zBp*6 z)JhJz^MML1!1CX8X=z=le@sVSl83PRW}9G^ne2R&Rwd>_4~E+vhItXw(uo7KLq~UE z34{Y^XfrrIUJiX);{Sz{U0K#=cd=*O`6pqaa;MsgQ`iKWDkE znY4=l1LTd%;StTT;%xWJ-G2KsGN*#NLIrm`%Rd3l;h+PHg!H0?1|*b?o@fC6T6d;g ztzdM8S`-OUW1xe->Ad2tM2fSV(+cLBY?b#*rQghkFsN_(%4q;!1KpHyZEalq{B5gv zy2rR*_B~9LTICQ=Gj(?#D6DR08Q|BpA$Q=!vUl))chlL=f-jLR!3?qcwwrMUV!h=fN*uNPYoY0kDBQ zbu})fIVaIb@f?9va1ht(O0j;^360RagBRUBD4phh_5BLjv#xlEfT|z7A3Bi3m4W=e zYHh;&h_`GYYoQ5&W%AJqi)Z1VW_3HAk>n;BrWalMEbi3Qcfc4uJ`Ka9q5!AkAumL; z;kcI%MeO@JKY!LWNAm1Aur_h3o^0!C>;3jwTr^JVd8N#MtP{YRZGga{Vy=As%6)yy zfNLKmmEu|E>S{>vt^p$|FvRVU;|MxM!DC|?=_FJ&`#Ovl1nka$+x7Wu>6fr>gC!|) zFMIqKFNWhH(hOQX$-2M9tONRs!Fcnl)+Whybag%Q6K|$~5j~`3ByGhB(pkddvK=nGd@g}Rdc*v;K zhAu@AD9C`MvMzt3qkja<##GiOa_JA=rzc*J09X~pw(~_m~{R8{D6Nnt&}Na81(5=3xU={ z#n>UYG}^cI+8ysP#|X$awNyINU7xYOH1#p4D;lT z&*dnVOzZp{nnK(zQzPO)N=3mFIvDi0E6vYm<>o&5f4VyBu&jb^Z*M>vBt#mK2P71c zk}i>!5J6ESrBf+EX#{)(2?>#Ik!}zWK}1SP>6Gr4j^`|V-|xH5b@UG}(LH>T6B_g98m06~3US4wdd`uFy_RL%wE73=yyJF4Kuvg!fMa!msfSq$?s1zDL zSNDrt>)t(6emZ>qYQB|#Gf~j3k&4aS>*x=$*}c|kC<@kZ8t;a0$kR8>gU&0O4GToWii_TeiU( zINTULOmZ1ig!Izd`meweWKF5PD7YEg$UoUkWE_2??0(%(Ul60}0cm)SDZQj4Nv-1&HIHAzZplBB$gAHnUq}~mY>dW#@?URz`L+Pdx9Ew3%eP|4!0*W4 z^&GLhBssj@b`eZ|A;HMo=P=D=h)ilxw`m{=rz8pv!7uE29&+pbbcFCzipgdKMvR;|VeAw-*KE$IMR=B<@!i z1a2wlNqvKUnHQKX;vt~h$nAT(ax8b|Z?=4cHj;5V#4`Db?@wN%Hx4o~)U{yJlNlly zIKmq@C@GA&c+6Se{=S5L-_)$?4@`gO%}!ji68 zbX;5{S>SjLF}A7~C+VS=({$TAxMb+DAlyW1`m;cnv~>hZJY@XI z7krG3NnEZWGXM2Q2k57~!bYG^Jg82Df-a z_@it|x(cYV?W|bNJdQX-sJ5VB5a59ZAoV(qfAK613jTlK+5gXFxeI=bc^-TU@X*Ho z>Ztd@M$V$*dW<-B4g}!qJ%ETbQN?#fT21WAG|6*u(V0fK7qRN2!c$sWCp|uVtxUf46dZk^Z|?Ma7@oQW|FBjemP@plnKacTfW3lS(HZ!aG)-61h1@ z@fGg3q>}%=3C$-7>Eu{yQBs(Fl=MyA%VxIz4oJ#%-Y$Ad)XAy)c_uPcoaz(ZZM1Ky z|3^t+Q{kbgqZ&1N&BbS8E;=Xo+{0tHQxBvdeJ1>YWctJO)aQHxGNf$oT?~y5N`z7_ ziss_Y5a!OnKoKG#JH>R(nYrzP(HDyCNHxK@q zd-;|egr2_?h5Kg53m9h{jgjv*h{$mZ<@SLSykJzrEE7NfMPvODRZr3m;trZU^KxA{ zLDl!R$HGTMxP!6BBb`nV`KB)A?&R@BLO3Rp<;_RQc+pZUAKncqEbxdwNxA+C%e}(n zO;AMi`-u0T#GbqW4q(}ny7*h)MJ7DwzbimbRlB?4l@^U8u47|ChHi9mG549JnUNU) zEleLZP5v+Muj<0)_;=Zfn(KmZ1)M)c$Lghk4hF;qdz;f8uCfD#!QRK3VrE3F@rIV| ztnq${a)zP*yx7&}IRCn>QyeqbVfpx~4t=pr7Np}fB2MaJuw#gDuA$Qpz zL{(zaoFK%;@LFB^6bhy&?y%Y3Ng+4eI9RhWohJIq(@uKq*6HZC< z3G)>AZPL_AnR?D;oBIyb)ec?;#8XG>HL1$7jR}l9Gp#!$g5DA|`TcWi1lwZ~c_tuWZ zq>lUg$N)cVXE9$jE3uHicdQ{~5;EE%qDPh6e+*c#|dkOS|3GSZqHB3yjk(uy9 z?t#s%&oS?x@92`FKP0Y3e`ryk&no-abdp=BN$eeGHGC3`Bo}%_VvruExFco(Ko(scnAlcG|3$-Ps zR?MF{+N2eb`cImHKVxQXSN@I_ftHYp>eJLT>DRBSqsJW%$e-v${p1fVO;TNUy06K| z>FA_*LupxRp0}5O(Ob}EOeEL}>zB4BlVcRho6JhqyLK&8cHjyASwpC~dH1H~Wjf0( zw}RQ(5}N_b;ZpTKui->vGFeTB+`XEgEU28AsOH`<_U1Ci@+5s1LEfA@`dgeJm2Ya2 zwcb;HnY`Ql6{M&6`+tB|L_%-NxjcV|gn0=$Q*bF9thkp*_Ot-~qe;R|c( z=MEHy2|;jq^O9s+1FzJ;51U&^{ZMJpc1gkY%KwWfmWd|CPPm?yjyN5^_=v*`;iaP7y9NKq#7CRt(iWnJ>M`Oc9Oq#!TKy1XQuTmVN6 z2j$nd6djo!|F0n`a8;{&?-$VsOc-zbV7>q9c`-Bdmj|jQ{n&&^I`;SE_p5kuE}`q# zAz?bR^CNqRLgRF^WO{lC!ib~x-TQ%iSdjJFgyDj&90^5p$ZuxxkGw`>!Tm#pfc3y_Hp;9QD~s5Og{u^bHJ1czjlLDDDan;cS!c=M{~O%u8!92oXmm zN#+s|6zw0B^ODmdDOWi^#Y>GXEnjoK&P{OM{$6$-hsIU9L1CC9jY|`!{rr~U|81hE zlG@*)k>I|4K`pxzwhz41?)0I>W9`}5o1{!_^%c+0p}}j-Bk(&uWc>p2>)kuG+pmfA z(XUFJPFd1gOCcBwVX+^!ZNeA;(b#2VtWp9 zZNW3YI#|pqF76J=oWdusz+V8)zm4r!$e~;N^X=91!f&m771aJr98R*0Iag`&9|+k# z#KH0XHgPbt|L2uZx$c7Q;N+|sgFq9wJk5>BSX?dUk4uMaA3b^mn%dpXO*&qqdI2D+ z*_@sLAns&QVYQ$Ux}0!wHXtxNIMnlE`1yX~qh3-|(LOO566tn;g(pF;`IlbG49`k} zH!$lI()lVbC4(o)8|cif|p5*f5TpMUitNIsHYoGvY;Gkc=j-q9^6^1`?CLvgJ9>IzEhHu_8j6E- z9(&xjm<6k6)c|tt3^50JsTG(MaO=Z- z0(@(2wCYu4B^w*y zw^L#}Bc1`y4dnZvpr)gx{cPEdsu_^^j8UH}vxy-yi4^6+oUE%0!f`2fk%`IfNxJB5 zIS7w<-lN2Z4V94;b$U2(`2BTlT%12ofHR%=TTD4FLKN@>rU0m~?T(HhMwl$+8Hd>h zT{Gr%uWn?|v(>I#eNNCZLwP}W1%b6#9lmI~rnifh>4t_k4z})u#TfRN@af_qN%U&7 z4FMz`)XnD*1A~5iW?T3wO;#Q%^uJ*fPCe*+*fegc9{5=VR)}8Hr7jNH#uZz57KP}x zHig^l-HW3U|9_s-H^;C+;@R~Vz9 z=(>{AZH(n}SdVq$PiSka^%@sBIeesjb@^bMNNAVQ@j{z)(`KaT>PT~kehSkn*o=_s zlq7Z^zrLY`x!IxQPRxu>!H2Z8!NHHABnWKY;404L#LzZt%w-JRxuIud%FpqYxVJPV zMN*9trOO>2IUSvlXOd2MTW(^k#>V28OmNYtwToT!fad!EH0` zv8N;}8O6H?QQqpl(y!aw@5icgm&Kpm5t3K>HYQgjcK^WL+E<3Cyv9^{<_~vD8Ku{5 zO-Pu?g?pEsPMqK%nLYG$R#&-AXVfd)r3gA*z1~N0nwZeVeo@hV#8u}gFKkA{@c6DA zIiHk);oX$9r%8OMmbz^_IP0OYWMuuMIGTe)c!AP6ajf9^r#>-`?d!Gxf6vTXhirTR zTFQO5SL1_`ldFXZaS#F0_=7GeNJ5o;3EM0P4qSt{6S%tf(m=g2xPYWE3#-4_%{$(j z9T8IYn75GiOY+4drub&PbFdB(D%>$#b`uo zb|T;H=onX<$ll=tI+|wLc@E@LC?g-BL99yS1Q*rOAHq{Q+cSCYe!P1sO7WFADziq$ z#-e?ztsVDwd#-r-b1#0U`7E6W?|Hc1&>N<1=%-w{q5{1noK3!9Tu5B@qqESeE9J2w z7Txl3RGeyC1f`SQIR*|Ml)Qe*ig79v+iIf$4JXpuk+fRl?mEK$rnW<)6J%JX8SUS1 zFX$%FyZDy8-s-G^hB15IE2Fn9LxZM7I!=1C`zJOMlL-l5nu|%_uc|uqKWF_spl=v= zc#t#I?i*g4^n8P>Z<6SAhXM^}a~L+XzrC2153}Fg!d>k{z4m+-3r}dQ7WL*-jZEEf zM70dvHzii3;Wz8ptG}DUiQVE6h};!63u-Pl;kkbw0_itz!k+~c6zq8PTuaB!oE|g_ z*;*<>p-i#|^UjFTlJ?kFPbrc{9J1)P!`4X8-8EdmiFfRR4l3ntQJ1XdeAeyB8kx=n zhpZZzAsM&^CdT;P2ke+r_o}Y)L3~vIucXyd*Bb*perSBM9K{fR{w@i)3TJDhXmgCC zOrG}aBFJD)ewp*~=(!=DtlzWkn+5WTVV$vZd&G+WBrez?m z=mJQnVOwrSarMxxPCBgmGOOw|RA;V^*)KVxvA1+ma7K8v)F_uIhdSJt))kj-4zn;} zD8@p(PHa5w^0m`b@mb`;wmOxoswVRul{0${zVcmW3pJ$Rl^S0)Ret{dD%YEUzVXN6 z(jk0&wzjP1N^Ic~_o9>5UbpZSWr+$<%rNJB_g*C5Y~`@o-ueRj_L*^j7)AedlBGUW zS;ix?H@eKb-=X0ti|yhiMlbg^q|b>ltDBcUI^{RztQj+ow!S0f~tlZA&$xfJ5TT{O=A%Z+RzH&JPJBXh6I_@GP;$=6mr- zEWP%P1#p6=P)~08>S#x4?#3&*Ja|7C&xUM_S8Bv0{Ax9o9gwvTW5zw+H({p7rMl53 zofU`%PGPN6R-xK20W%Z|wb!lqRluTuF*2feXs8~e@`an)#oT=C@8Z-cmFl!27Ac;U zF^k%3_OoS(6bU31_-R^^t|-|!(u?h*kbaNTmQ|6S;WdesW^VMAD^qq6)eN(zx5Yide2IDHd2ig0?z`uEX-Rd(8!gf(qS z<~HdDEEz|~vDV18AR-+H`ODH<%?^6DE1kI~ENMKVLl%4X4xZGZ)8rI!@qMwe)mFbb zkL9osJ$*jWN0m>LD;IW!We*fZLZ_otRMq=ehp&{_CseR{=SSoCcr~1RBp)#HBY4U> z0+Dfz19%q0_LnnKzZ4I-JU`FbeNXFRURC?huAm_+uK%R zg6~p~Ss9xhkggh6C+9LQ0WHQck$hHfF0T8P1(3|@(%PCcss|_e@GUW4<^!9x?(Y(| zv^UeI{LnC6R>!V|n!GMcJ7&dvlO}i*746aG zx-pR)(UBYzCW)>H@9Ti_Pkonu{5U_t#*#MGfO|0e^M0q)a?6Bh6$b(%aQM`F+r;D+ zpM?yJ5f(*c&T?S1#gO)!!St-+vj=h zKFV+z|M7H2NvqJHeR0vt`6??>l=ln`Qa?74RE?qA^RegWw1U1374a@&+qAkEY~d3kY{lKL))Ga{9=vbZD~L0gR5{;$p*8 zEZ_p(iz1QyAWjUBs3pNsgfU-zMwcl3as z2w`LE?psVUhB_E%t16&;^mn?0&|W6&B*+{}SzqiwAju1^_|1 zJ)x+^iD_BIs-OBHZ8zNe`&NfBmQj10)b_lNU&fm$WRDTFa|0YR}U%Xf#VBYH@ z_Lidf>J@p1wFGzNH=Z`ja#yZ~G|jCQoONgY{U8(4GFuUS?OK1~`q(J9^Uay_&?hFA zsfGY){VLQ*Y4hVjm9{q1#})g9k6qjQE{ZeJB1VxvuRSPODR*Gy(2M`O-7;}}Ah^}c zi_pT^;K5_p^^Xk3j8sfsGokzC`9LwOFbnp66s!7)pPSl#w(V;$jm~-cUgu<;JBSfn zk@LWvNs3z=W@3(?AGM*Oi7Ls>U|SrY7=xVsKRD8f9V~bhEoTEYhSaCrQiH4QhkJ7~ zYc)oPE}-m3`UOx85>Dp%`qe~ODN~s-9s>LsVu_d4A~FgJ_J+%&gQ>e)k_BkRdifom zocQASNvb$+WgG<%|K&Yh)jWOY{wLWYLTMvC?4`4l(dDVu$V&kMNuAOYvF=jqjr`7^ zUhF@^{QbN3G=jXiGw$Y2B!}=he64*^9643x?BizXmr*gqU9avLtW{gzp9sXWo_`wl zmB#TYQe@t~1GDt&VO#A8ikw1?y>+S2^PX0r`-`D%Q8~FhRpm`FXQk(h5ln^^lIzQ* zu7x)8KQxGG?(K^bB6oB1J0*2?zTta~c^q2uDpB9Kw9#`%7`9W_`J*88nS&DJbZ&gS zqO1%UNte3pBGa(yn?h>6wi)!@++K|t4&^-1k=)Z;CuOJ>=$Ms0{!?f66MPRMu|}`5 zGmfz8SB8KS6{M9_{nQFvS&xg;CNh+F!1wjLwLcMk=DC!{=d+Ho8sy!6e|@Y>LEoWx zYml$=#dc10S}Wo+JXES*t~;BpHP*$(0yQP}^sBa-f-b)Q_NwM^6`k(jGW(z)?_p&@ zOlvPwRv7xTm*)))jb*3K`0nm970y&S(9}M&%IiDX6^{tx;%IfMS_x3Im{ivl8 zU1HPGv9q@BtUH!}zGJN;tc-LyjR!*J=;W@RkMr;1+t0&%D8(pk1yHk~w#o9i;9L|YR z!bfDlSY&VNa>>O(J#i?WpZ#f1Omo^xsxRykCTY$nTC%rX_^Q2MKDk9cclD_4+OUpc zc}`z1-E5hz2J=AvvK_xmtGy2zzRYVnyY8#y%Q$#lc>;S12Z~~Nh=Ipu(|D~^X69}k zO_a0`m2QbmqeDU>GVdJK9p>y#zFzhCNegDP((4y)e}D@A_1JL&_R;y2ENjkpZiI0xv`Tfzw%g>EN4u*t_zvl~l zM`k|{Jx|ITcwXx%1cn*h@H{=>dGTj*4XN*`!<1K!FV#6`$4g!+y(QN<^`vlg)aGez z0Ff@%>*IzZV^ZpJ$O`h1GPr$Z&`g%q6mIrRHS6W277zaF=8sF6t+ zO%M^@86ADLI&8zLK&y2R56al|cVj}~jTc$pPbQ|JO7?JkvCySJR2NFgeMX=Fd}Y8( z*C&ea-p%DdE`(KcyHDo`Vi?1=gB>=vf&<(!o^{Qa7!DWGcj)NMUg1xyZz=4p&lBi< z)qAl*TXB?1AUDHJegFAxcr)`r7_;~6$zHyfm%jdW3ULIe&~wo`Wp`qBC%%p~Th9*H z)!o-_N%DHx70#lTovkY^UA?tTg0-cQ+xHb>Et1h3PYxe{m^!>X&748y> zE4l{bHrsP4{^#Hf-ZtS`Ik(v?8t3+^j0}-ehy(Cli9)(=ZMB9=`AJ>8 zNRuRMo}V6D3s-jBAX=S~`J{aFXImS<_+6@BRgMJs`)}aZ!TD4q^ytK?ZaHE~DeE!{ zmDT;J=l2OVcAUkpPYgHPkd0uY(xGq+{?%xgZ+>lxm-xizQhyfq6!ciaBo__Mjps{e z5&6u;NiZvYBXdsIU`_L0nwWFTYER~H^QGTvNuv@*KF_YW8Y~;j1B+RRAtUQ(b~Zc7 ztJ=IJyeTDxJ$8l0WYR9|Ms!=X$AL!O;r(>|@srfom!?G4V5zV8nfs>2Go*&Hhq^Aw z#^Vc%(1XJ6PrysYtO%@kbtN?R>87(<~?JTYLQO_7Hg5KsO3N-VYlK_r##eyZ249U2+7C@7emaYb- zyX)HDT1R=IXDL_Mn?Bupbl~mudy@5C*Xi>*MnQ~aHmhc&(q$fXW`^7w+shE@54 zXsC^~-}=``@FB|Py4amOKHYGbxuEE<7OaHZsvHTg&&P*^s#D2i^3Pz2^u0 zsMkD5irzRabw4dNyYqE_Pe;+ffSZ8=5%O=yQgvOUAij#^2EHhpr3)^ISGyY-L zl(GcHti=Xr>aih?d)TUuIzA1k5V0P@q)qLigS1SQX2 zKoJl~9U&wmGX!Sm?=>=9TwK8QK|L$Qw6wIj&SXrx@C1RrrfY6?HdLyxJ7TaFc>G2R zBlL7!@6jVzcTyp-#ni%LeWK2AA?Tb@xh_<_qNSqB=(Yqd>mXouhiwW8^`pW;{+@F` zH{qb(3s|`w@KHkIf*&MOt5#V3W>39FDFbCcwq}3Mx5v8zz!gNL;Hv^;C856d9uy=2 zlx+i$c}ehYk4$LA52=hESd{BREf#8Ea4#>5gKpCz=|z)hW#)t2GioL9AptDwzPnOo z^vw?({RGefNG}Qj3QuY-`P+8$5qL(-apzgdxlh_TqzpnCnVHZ_#FRf)Hy;l{{&@e+ z)wyAOXGt9j;;et!?tpSkkG)@^d(A7ZtR3g(1#}RkQ`L12dt*!>mcQTlx-+&zn2^JSGUJSV;DR%X$HSlN^(lr;- z&i$F3eE0r+1z>t0nTCQ@!2<{~%l-KmsyTf%gV-YzUI?*8#Zo;`9?`f9XF=@7TA zazjpDo?fZBnu0oyso{yW|W`MTxKi}$jY=Bh7FTqts!Re?MlZ*L5Mc&VtUph*Nk zH4k#nG`9=0vlq$9i$I^6mWE0Vrlc*8wW}h~ulHQ+PJgYEc?g8IhK2@_(3)qH4FCfU z;8CFkPOm+TGu#+{@K{kip$ih40B=+JvT@Pm1X2=>Z-YC_0aIbaXT|iy^Al*eD0j;gg(f=;pQ$ z)xcnW%FF+N%0cYv37pQFvXI6vFhc2i>c9xlQc4&Ve}8|F0;?v7I6$Q;SsgYXDDeZ# zASitn{_j^8d@vi&QiD;lFaPmdNBjvdeAGyW3S@vmMZss%1b1;3(}zMQZ|MZEad2X| zAEBJ(8`6bJFXm%p&K8L`r-!ht5GghE~Vo9>3DQqWG^k5xVzl0?RNKu-cRP2#fFr4rSttLNb zqyWVBr#|cZSMNW0^2E`RA2X5YG36**%?#@tQw6}J&N6Wro6o>PkX0spvI<cRk0iy`r;=l+Q0q-knJ8bOjJKEblp@z@$@^Ye6HoNROIF>5mUw-oF(GV!& z&!E9e&edml+V8K))-Bh~04oknsH>|R8>jYJGeJQ#@%1mit*5J-^B~uIuV$ikb_=Sp8CE&Y7J8p7mzez=#-IRztE{3D2YjbOubpev+X3XM zT|3MyV?XqK+Vh*ARq2n2ZoU86M?! zL=a{KbwyUwBXMEKUzy5%uldKRD_VBF*7wq!bh~7ps98FZeW7t040n1!^hr1UOzh`G z3;MGKKOcpr#wL>M)0d>)5c$4FY8g3q>5PKxM6cniGqzsUR+%kV7pN)tjGwqXnLo>n zS=}{t+8!$4o&UHOH#9KAwpZ^LH_&N8GC;dJw@Slr@Rl7xQmJoSQNUfzs0AfjAPl9}+3Os_Oaud-bG8$w;NWg1K8w9z|^8df%m=%T0_OQrSOc6CjAH(J+C~pTT03=Bb$WvG^t1X7}UMVq#`yyUACeic(=T~{Q7!=n7FttpLua*R@V29 z_={pmcI`2I;_i!w53Tmjo<^ZRCW)6j$N2UGKW#bSMXl0v1+yOMRW*^8<=21E%d z%lE=$&YwSjLgpie+SXS=$(($dmiDaG0iR&=?)|28+r!^QO` zCx_~4mwUDH*o1&7>aQ6L z1av}zf_E;&qtWQe*lexb?+XiScf);seUp-s!lkypv4u+%S#&Z+woZ005?w0mO5QK; zi+Jl@*J*xGs4r5wXO9&TG_|qem5`8NWtH>G?3-H}telu*?C$QC-ujk)f>Xt3W5_+f zY9&||bE2oeiMx8+(>sIVelVOOO5fC3d9SId>C{((Hyom(I%sxT%5w&9Cv8qu8%m3c ziV6t4=$<8#J)iI)A|hg#q3QW0Ya&_7t3SpYL(;g)%F5anq_?`l6%`fR+S;nHNo>+K z=@+wX^4X|20`|EN3R$!+jT;fI`2V>3VHrazb8m5RQ787vlP5YA4r9?g+Un}+M6wk= zI43!|K=((t_p>EML^kJ)_O~X&rNhF)XozlqOcX7nI5P6%y^vUX+q#&#BgJM4+FR1L zmA|%xqqcaR`<&r(TTNGjb2E4w=Zqx3iqnF(#~(&x|G8p6L9h5;ljegfq?;R znQeP(D>oO{vVl<=SIzoY>vFrHwvG;;l~&FZCr&6SD*E*OS)Oy(awSLo?NWlNuBuU8 z6~$RwS=o)$41NAwWZHbxVxi`wAflS1U%9e_TV3aa)r8`O&F`B5RpaL7rtpYQH-+!O z>Wt7=4Qub-UG8k9G1HlkXla){RvCu~c9h>~jhaX~J4c^+bu@c^Nj9cX=CSka;}2_- z6iKyYqXr}T)o1-3D;95DHZ67^8C-jEQpl!%G}=(jO8MVr^+z;D1_! zk|?|PthC!HYU)y0eXMEhuoY=4P2drhwt*{$fBk(%R=!|m`Q9~Lp%U))O%(dIMA)pS z_o!a6d8lsqz?=Tkx7Cl#`}PzHSRQ+>guuB(rKHYD^NCM6DtBTD-UMkxkf|+7g|$v3 zXmmIUp259iLe6)#`RU#(9H*StIsa<8&AE`}Y&shV8nI;Z97iEEAIT&SJ8MUYik zsHVeDL?2K$u9byzVPAfG@7}$wtu6Oq&zZ#`j7ANIb^tp24q4zRikK_#NI=TZz4DPc zCD!FuZSpH>RUSV~JUu;ibOxYP^9?XUW&)LjJq-;H^oKr0lHbT8rl-9+Dw=G1fG}lu zX*%c-?K%C50_(nWI5Q`wq6JJD`3-Jv?m!FbRLw&|&EYI*M;BQ;0!CT)KPsYK7QU8# zND%hNO~pE4xPoEVOP4N{+mG1Yy*p57`l!gTg6BAr`h0kJxTi-GXMMk(lAb;xDXH2P zTb7u3x{*4yqKO1q=GnfWzP|SI_gVrcIW&;eG3nP{N=eupW5K^D4C{Sj9b$jhe#!>2 zVs0N{(&Lm@;7CiNOp+E6lLLb9Xp0LD)IVnXi_p|?n(W<{1W1+AlyPxwcIdPFn2I5$ z05&^DSxUAJL}Z-qzY*Zo+XYFI-floc(z~;&fSdjsn33J>k^LC#2Xp7ESFh^o>dMQ@ z`}$V*TCEM=AVA`h(8k+ikC+TS#)1~G<^Jmf7EJy-Kfab)r}*!A;`CfyT`yn0oS~W` z<+rn$sgd#Z>(?qVT?8?I!QRix%DRYIk^+cOi_)XvH{?a38%<`vedFTe3kA#z59jCQ zWe0Bddp$|8fLone8mZl{oJo#kM^O@08}66a?p~*S@ZtqaWNTDZ6gz*JRc}^PlRSSI zbzES)0wSV*+=eFPRZ)@CL{lh#&1Ra9+CobN8vu=|sVVT?v17+pOuVZ1fMmn6A5Hh@ zG=Kwl^7)>ZoYP z=s9|iR9!=Zf>A<5OiWBfr2o^WXOWR?{{_kW6b>VGhpD8R-Ihn|0XioD2#*Xr=9*jwmaQIok}s+j+KpAG$ItD+|tA zSSYaVriZKhTY~f#)aR~)K*%aaA&DBI{qvkxzPPmrlokeqwxFY<%QL`~d9Ir4rT1Db zeEVi;XBQTX-_Y%(cKAcx0*{c%oF&!!CZg}&(#Y{dX5T?e>eG-La_^z>Dv$Zb#yJZG zTwc%J$ad1UAa0N-(G)J_3^J)K&@vL-f@fnXPBSsZDouQCBYlfK%KXVen_Vs{*C%!7 z^IxaAOsQwuJmdNkWyW#Mo*IMQ%7%y^Ya#l?f6uRow}CWk6&_kyt9pvQ7OX>~7K z{WRyx=lqoBGNaC~CN+$VMnGT!3^Sn6ez+0=v$!rJ*+k`DrC zShr^!hF&~uGT;9>rP!JQlH%vjpVIrdPBu0+YHDhbWQt~Huf`b<0)|mks;^|0miCr8 zpin3sop?^kl>ni@IL_kj1Iyv@N>V7apomBu8tpXqg|E^KWRVlm*{0vzLPa(_%f54e zcfz#{t@=+`yh|8D!>4%d+MCQw-0qUU{e^hCU+PD47M4IRWF#+VGi>f+I9KYu-4g+? z`EWg0EXH$ndUd8VByIDnbv^^U_lp-b^803HW@4kFJU%mkomghE;7FV2K{Ylv*W#uV zhQFBcsBL+UViineBda2ly|P7J<6X*wP8Y-;N%X-6n!AfaHtR=(jvo5}hHe`Qhd zi}^+iw;e590i`in@uw?Vx6KLYY-;NG4+w_q^%Ahu-48W65iob{k_^qKdXhRq2b|)2o;*3|dGBufOY)DZOpftH z$fziXaCk#g)5ip1dnYG#zq^IECeuse+g}nQqoj&~eBcX&h0EW*{c0(A^ytwqeSI_2 z)4^#cX=u*GqAt;eLJRQm@j(|DG6^8a#Ty=&eI@?tJEgjKM&nHOVCCj+)mrE=J`a~L zx3I9smho|NDx8ZXM*>E;64kBi1Bs#L!WQ7xZ$3;oNq~?OeT&k4Nr%Y9BS}O9jahf? zPx~tEjXMmnmSe;enfw6a5vCFG ze@1IG`+#o8zY=#e``xc@uA~%od>xAv3qW&kz<+-K4h>OkpP!vgPe&)_yY&-bSWT_# z^D8A`oBs2*+hFf*(upJGAP5(Jt7j3n`8eO-fQ@JD;9%VvAJ5yjZ|mt{4=*5r#Pts; zFa4{XOM1Z|Q*dKJll_Ecz4OOC+Di2RmtTfWKco9#ATtVWm|yEW^AUf1kX8NkX4mDO zdV^%mPhaNNA|oR~M*?dHGRJ+GZfR)&qegT{`KN3}saWZRqq5gQho zJSagZ1FCvcZ^?hVmyz&%Xm7SQwl-=%MhwWSW-6Ycc5S0zR0@<`$C^e&0HKEZ^~Q)g zKDg79w@LC7oaFDFI9&f2!%FZwy`Tb2$J*Bp)%bc_Sy_2`Z2?z4l~4C|)O+g5`bE8?n7seCN)oC@OxRpSQ8Mul3$o ztnu9@l6}U0*Vs6c$1i$%dK%b!1K?qPpcq!Vw6xR-ldIqJW1?9#No?xY zP17&LHkvg}=Ki4%I?q&uSla}=1#`c(y?un_@|7zM;O9bugUjqk&XEOj1v^!~vF^*W z9j+QEt71nj)$aRgXmq1Fl&+{rcr2$5+7;dct@At~Asu3hw6sYlH7DOIo_v+bnqW#@ z@LNe$K(XADMCc2y5}Sdd5L*84E@Em_#Il<|yH&MwZV9|!0Zk&G{$sGxIX*sqc6Juy zz9fW)l@Ge-+H$?rA?K-MbGiV!G{3aewKG}rA}@FIEq{N1Z*Ok}g=Pxro#pS@`Q&a> zX_EmiytEwr%zcA#ZUo-=e24|dK2~VjOioVDOVj@31m~9=9kxf^C6kJe;373kHQS6H zqxayxi!C~Toq%5cbowXhHLEE0AjfG(G2E;)4bf`@a z(wbyR@3PX;O9BFpUxGlB&VZE=73Hoixy8F88<(rE3I5}}K_wTK5DZB7IpgqOPOI$; zvOL(((12O0!43}2n+&`Yb)KG_p4QUV230p$pwJKkwY9g~Y9#b0A7)};;5&O(_pM82G3htTqN+IcL5Z}0a=TNXlDW;SUpEdP zB2Q*ixv8a(VAV@0Vv z`7kL`M;nzAJioM*pP%nPljOcQT+LHnv3WqE}>1f7m}9yKHrGE;qcAepUW z)Ih_$Nli%YsAh8sGr~;P5clxBHakKV$ShGjQ4UgIxc=Bbo4GMM`kmmp)qD3V{p4;u z9=w+0RPZC4+Uhuym*v-W`#i(wS`g81UK9?5vytCT_UXvgDVERey*aNt)GN89`{Ql> zRWObFEI}VtNRiE>efVtj-6asOuX_kb9~)o(Z6Gz-e^vy{j8R#F zCz5Z>NxB@}{FjI|?W?nmaw;*hOxzpRe@^s2`6z)!FQdN~i{>I)y`3Pi5l0dYQlD>U;2J-1@cJAw1i)B1> zyOF9=C>52MaxsYO`1w0A)k^4}AB0CFc7JwfW@Z8y@$vG`fB){}KH{}`f^4rhZ?&feNY1i+XdU^>(Zf4aRYirb0R4(rB?f&n|%F9F2zBLZ>(I`1O zIznz|VPWCzy$#}IV*xu;ekA3^Momr4&W?{~HU@*iVzJd&3_Hrq%nabh0rs`9nAuvJ zGxEck)!KS6v-KkjkAH=aJfVTy){Wh)#fnxKqCUUh|3Qyf10b7O=4@I&H5 zG`zYcZ{EE5w%REj`zvy>r-pcziHW~98naMrw^mXuj&)dC_gkI*P+wm^K5kNNXkT~> zytj#|DfPTwqx6q}s|76V6&`^qL$X^f;5=LJK#GYr%F`{)DlgZT#hCnu1eP6zru8-g zd(jv|>nfJCv(l|9ZBS?uG$J&pvs8A(sMfFA_I)+hTVH<=A{CH{KbGH9SlqcIcu7HmcbWu+)Ur0$r>CpCvbqY7S!~&r_Ta&T=g;Yi2X=NhMudfgfbYG^ zHz31zAMq`(tb~YLZSOAmzIa%~NSmeL`r2Bn{gmBy4!wx&(mK7}g?PK+DsKAn@fQ+g{R@*;22)mo&Jyj$PGb58D|qjBD-Z{-RtK_ zqw|IJsT#rPK#*gyyS0XoJFZn}Nu?&tp$*e{Zk8JP~Z9h#Iq z18Jk4HMR6c4l@}6My;*N@h6|f_Ecz+!EspNwF{fnzz30%RD2ub+wRrxC2xpN0XGFR79ibrI1 zOTV&RHo2pVxNqJWo1mgEZXAN)0X?RJ6h z_Ch%XTm}XP&eI*ZflfayH8scm-Hk(m#zG0%Sy@nJ>D{x?wM8JZ3(g-UALGHFM^U}m zq>zf1mXm|S)y)k6Zlv1VeWb>BrCjc%6C1*8%zdy7!kxW6zx(wC#`S?$LukOX`|jap z(Cj+AG?h-Kpw@hRsvhzP6C#8$Xk&ct@GrnXsTfU9fDp8&Cn!vQc4PAW*_E>QlXJ{J znttkRVc=?8sB#jq{n+#|B#eqAq1Or=sRzi#e80797~6p1BHzy*6cG?$Vd@ag9{e_c z;Bno34B18e-g>5{69dH-dU|@$SCd7dX!gd2242t}ZP7gV=$2W(#z&Ner9R<4F=8yF zm{%AY9$ve>i23m015}+;7Wj@>xmX@yy3i&7ZkT-mcISuDAOSjDq9*td0GyDPR?Ln% zRpaBwWR;(z>y1SmMrGXG)t9+R&VaFP0vE={)_(y7sG!=_YIf+%5?u^*Z(rj^pK&Keflf) z{l4w{Kxu z*28!RNx=tt8FFVPN7;Z8j~qDyv<&%Y@mEuVQHVeAH5w#;tRazMN+aV4nHd-z>RDoA z-QVB*J(V>CWAUG=wCF^!I5?+_CH~-Xc%=|9Ep;0rM1=gLdIknVpFVw>?aok8Pypu< z1M@n^3Hc>Ag6q)NT9B>^zDszd0Vyy*3d}UXZ%9ei6ciMIWeQoMK_eI^p> z1m#x=0rK#$A%BfDf)uYzXSP601#?<>>9|+Fd}-K(2~;Vv%wSKFV3?nhn3xzB2deH5 zLwc>b(Ibxr85JLvpg#3i?AyZ6Z&Z``?Ad7J1}S2!HGH@Xu3uGE#ikH;@*fKBkBhD> z?2+6btGjmqCT`H8APTJ^zjYt+CpVJbAwtN+43Cxpu7g|u{@rS+Cif!bL3^`g2qkYE z4H48=RPGN_m3YE{k;j8ROV-)i`C3(ZO&?3Wig@nOVObELd%q^(zeL^tc``npVGNeX z5XjKn+#D?E-Mg7xmL>a(%gYYX78AN?_V~X8ryZ&%vZwV{*E>&v({f+P4aJF5~rUd({SC zh7h>wYmy#nn<9s1k8IU6G_)(#1^LOInUgcGUAuJ?h8tYLp#Sh=9dL-3u`6j@DwqwV z?vy_fAd@fPDL5j?t%+nsz{oD>LD7Te@UpjG0`kf*D1>4IGChmmvVIjC-y7+{{neEH zM6hc7{KjrY14HuCk3Cky}W8 zGgAiZqeqWIlR zh5PSJ9OAE{Ja$ZAPO9s38CKkLWinTG-Ea|08c{gH9Jk5VuY3lkF1x$C3kwS%E@4&PXXn>^ZwvlCN)by^p}Hzd3E~RG zn~%gTrY*32FqzxvHw`~{ZvI55EheY7wieK}sOSRk{QmyLle7w_sWx!*ew$;DK$z#| z)2Y{2m8s?=dLN1HdwQ%sVPv~aBhfIVG^#d4?k(ZOR@}uKEEY`y2CriY@o4WwG$E( zql|QUW1zvcwVwVpil2;)IBR`30B~D=2*j+8@>ZWrd#E9Nj_F;RE;_tPh!f3USlxZkio^CGuRrvPvIgq z1hg8nW>n=~#2sQj4l$XZ({qsY^ t2M~(}xVubA5(KGw$X)us{^VwlqR{a5iH^HnFmyr?)K!%$d2+^q{{yH`ABX?| diff --git a/qwt/doc/images/spectrogram1.png b/qwt/doc/images/spectrogram1.png deleted file mode 100644 index e2774e93bbc1bf6392f19b79d2b7a4a2dd8ba4bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47416 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 b?_VlF-4^kTX@zt|z?Y_~wn~|jW$6C`GKOLq diff --git a/qwt/doc/images/spectrogram2.png b/qwt/doc/images/spectrogram2.png deleted file mode 100644 index dcc33857d74f3cadd6d41c23053558c7a94a228a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16812 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

xz%C^#`-s4# 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 z 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

&Vs$g~B|@mjoPiErmW3#5u#X1$ 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

-
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.
+ /*! + \brief Determine what to do when the user presses a mouse button. - \param p point where the mouse was pressed - \retval scrollMode The scrolling mode - \retval direction direction: 1, 0, or -1. - */ - virtual void getScrollMode( const QPoint &p, - int &scrollMode, int &direction) = 0; + 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. - void setMouseOffset(double); + \param pos point where the mouse was pressed + \retval scrollMode The scrolling mode + \retval direction direction: 1, 0, or -1. + */ + virtual void getScrollMode( const QPoint &pos, + ScrollMode &scrollMode, int &direction ) const = 0; + + void setMouseOffset( double ); double mouseOffset() const; int scrollMode() const; diff --git a/qwt/src/qwt_analog_clock.cpp b/qwt/src/qwt_analog_clock.cpp index 35f6fd058..1aa0f3ec8 100644 --- a/qwt/src/qwt_analog_clock.cpp +++ b/qwt/src/qwt_analog_clock.cpp @@ -8,50 +8,34 @@ *****************************************************************************/ #include "qwt_analog_clock.h" +#include /*! Constructor \param parent Parent widget */ -QwtAnalogClock::QwtAnalogClock(QWidget *parent): - QwtDial(parent) +QwtAnalogClock::QwtAnalogClock( QWidget *parent ): + QwtDial( parent ) { initClock(); } -#if QT_VERSION < 0x040000 -/*! - Constructor - \param parent Parent widget - \param name Object name -*/ -QwtAnalogClock::QwtAnalogClock(QWidget* parent, const char *name): - QwtDial(parent, name) -{ - initClock(); -} -#endif - void QwtAnalogClock::initClock() { - setWrapping(true); - setReadOnly(true); + setWrapping( true ); + setReadOnly( true ); - setOrigin(270.0); - setRange(0.0, 60.0 * 60.0 * 12.0); // seconds - setScale(-1, 5, 60.0 * 60.0); + setOrigin( 270.0 ); + setRange( 0.0, 60.0 * 60.0 * 12.0 ); // seconds + setScale( -1, 5, 60.0 * 60.0 ); - setScaleOptions(ScaleTicks | ScaleLabel); - setScaleTicks(1, 0, 8); - scaleDraw()->setSpacing(8); + setScaleComponents( + QwtAbstractScaleDraw::Ticks | QwtAbstractScaleDraw::Labels ); + setScaleTicks( 1, 0, 8 ); + scaleDraw()->setSpacing( 8 ); - QColor knobColor = -#if QT_VERSION < 0x040000 - palette().color(QPalette::Active, QColorGroup::Text); -#else - palette().color(QPalette::Active, QPalette::Text); -#endif - knobColor = knobColor.dark(120); + QColor knobColor = palette().color( QPalette::Active, QPalette::Text ); + knobColor = knobColor.dark( 120 ); QColor handColor; int width; @@ -61,7 +45,7 @@ void QwtAnalogClock::initClock() if ( i == SecondHand ) { width = 2; - handColor = knobColor.dark(120); + handColor = knobColor.dark( 120 ); } else { @@ -70,11 +54,11 @@ void QwtAnalogClock::initClock() } 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( ( Hand )i, hand ); } } @@ -85,11 +69,11 @@ QwtAnalogClock::~QwtAnalogClock() delete d_hand[i]; } -/*! +/*! Nop method, use setHand instead \sa setHand() */ -void QwtAnalogClock::setNeedle(QwtDialNeedle *) +void QwtAnalogClock::setNeedle( QwtDialNeedle * ) { // no op return; @@ -101,7 +85,7 @@ void QwtAnalogClock::setNeedle(QwtDialNeedle *) \param needle Hand \sa hand() */ -void QwtAnalogClock::setHand(Hand hand, QwtDialNeedle *needle) +void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle ) { if ( hand >= 0 || hand < NHands ) { @@ -115,7 +99,7 @@ void QwtAnalogClock::setHand(Hand hand, QwtDialNeedle *needle) \param hd Specifies the type of hand \sa setHand() */ -QwtDialNeedle *QwtAnalogClock::hand(Hand hd) +QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) { if ( hd < 0 || hd >= NHands ) return NULL; @@ -128,9 +112,9 @@ QwtDialNeedle *QwtAnalogClock::hand(Hand hd) \param hd Specifies the type of hand \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 ); } /*! @@ -140,37 +124,37 @@ const QwtDialNeedle *QwtAnalogClock::hand(Hand hd) const can't handle default parameters for slots. */ void QwtAnalogClock::setCurrentTime() -{ - setTime(QTime::currentTime()); +{ + setTime( QTime::currentTime() ); } /*! - Set a time + Set a time \param time Time to display */ -void QwtAnalogClock::setTime(const QTime &time) +void QwtAnalogClock::setTime( const QTime &time ) { if ( time.isValid() ) { - setValue((time.hour() % 12) * 60.0 * 60.0 - + time.minute() * 60.0 + time.second()); + setValue( ( time.hour() % 12 ) * 60.0 * 60.0 + + time.minute() * 60.0 + time.second() ); } else - setValid(false); + setValid( false ); } -/*! +/*! Find the scale label for a given value \param value Value \return Label */ -QwtText QwtAnalogClock::scaleLabel(double value) const +QwtText QwtAnalogClock::scaleLabel( double value ) const { if ( value == 0.0 ) value = 60.0 * 60.0 * 12.0; - return QString::number(int(value / (60.0 * 60.0))); + return QString::number( int( value / ( 60.0 * 60.0 ) ) ); } /*! @@ -183,20 +167,23 @@ QwtText QwtAnalogClock::scaleLabel(double value) const \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 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 { + Q_UNUSED( dir ); + 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; + 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; @@ -211,7 +198,7 @@ void QwtAnalogClock::drawNeedle(QPainter *painter, const QPoint ¢er, d -= origin(); - drawHand(painter, (Hand)hand, center, radius, d, cg); + drawHand( painter, ( Hand )hand, center, radius, d, colorGroup ); } } } @@ -226,16 +213,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); + 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/qwt/src/qwt_analog_clock.h b/qwt/src/qwt_analog_clock.h index 519bc7d74..f20c3f1f2 100644 --- a/qwt/src/qwt_analog_clock.h +++ b/qwt/src/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 @@ -47,45 +47,47 @@ class QWT_EXPORT QwtAnalogClock: public QwtDial Q_OBJECT public: - /*! + /*! Hand type \sa setHand(), hand() */ - enum Hand { + //! Needle displaying the seconds SecondHand, + + //! Needle displaying the minutes MinuteHand, + + //! Needle displaying the hours HourHand, + //! Number of needles NHands }; - explicit QwtAnalogClock(QWidget* parent = NULL); -#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); + virtual void setHand( Hand, QwtDialNeedle * ); + const QwtDialNeedle *hand( Hand ) const; + QwtDialNeedle *hand( Hand ); -public slots: +public Q_SLOTS: void setCurrentTime(); - void setTime(const QTime & = QTime::currentTime()); + void setTime( const QTime & = QTime::currentTime() ); protected: - virtual QwtText scaleLabel(double) const; + 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 *); + virtual void setNeedle( QwtDialNeedle * ); void initClock(); QwtDialNeedle *d_hand[NHands]; diff --git a/qwt/src/qwt_arrow_button.cpp b/qwt/src/qwt_arrow_button.cpp index b4914ceb7..f451b44cd 100644 --- a/qwt/src/qwt_arrow_button.cpp +++ b/qwt/src/qwt_arrow_button.cpp @@ -2,17 +2,18 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ +#include "qwt_arrow_button.h" +#include "qwt_math.h" #include #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,57 +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 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); + setAutoRepeat( true ); + setAutoDefault( false ); - switch(d_data->arrowType) + switch ( d_data->arrowType ) { case Qt::LeftArrow: case Qt::RightArrow: - setSizePolicy(QSizePolicy::Expanding, - QSizePolicy::Fixed); + setSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Fixed ); break; default: - setSizePolicy(QSizePolicy::Fixed, - QSizePolicy::Expanding); + setSizePolicy( QSizePolicy::Fixed, + QSizePolicy::Expanding ); } } @@ -89,17 +86,17 @@ QwtArrowButton::~QwtArrowButton() /*! \brief The direction of the arrows */ -Qt::ArrowType QwtArrowButton::arrowType() const -{ - return d_data->arrowType; +Qt::ArrowType QwtArrowButton::arrowType() const +{ + return d_data->arrowType; } /*! \brief The number of arrows */ -int QwtArrowButton::num() const -{ - return d_data->num; +int QwtArrowButton::num() const +{ + return d_data->num; } /*! @@ -110,43 +107,33 @@ 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); + 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 + 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 @@ -154,7 +141,7 @@ void QwtArrowButton::paintEvent(QPaintEvent *event) \param painter Painter \sa The Qt Manual on QPushButton */ -void QwtArrowButton::drawButtonLabel(QPainter *painter) +void QwtArrowButton::drawButtonLabel( QPainter *painter ) { const bool isVertical = d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow; @@ -163,12 +150,12 @@ void QwtArrowButton::drawButtonLabel(QPainter *painter) QSize boundingSize = labelRect().size(); if ( isVertical ) boundingSize.transpose(); - - const int w = - (boundingSize.width() - (MaxNum - 1) * Spacing) / MaxNum; - QSize arrow = arrowSize(Qt::RightArrow, - QSize(w, boundingSize.height())); + const int w = + ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum; + + QSize arrow = arrowSize( Qt::RightArrow, + QSize( w, boundingSize.height() ) ); if ( isVertical ) arrow.transpose(); @@ -176,25 +163,25 @@ void QwtArrowButton::drawButtonLabel(QPainter *painter) 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()); + 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); + 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++) + for ( int i = 0; i < d_data->num; i++ ) { - drawArrow(painter, arrowRect, d_data->arrowType); + drawArrow( painter, arrowRect, d_data->arrowType ); int dx = 0; int dy = 0; @@ -204,29 +191,18 @@ 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 QStyleOptionFocusRect option; - option.init(this); - option.backgroundColor = palette().color(QPalette::Background); + option.init( this ); + option.backgroundColor = palette().color( QPalette::Window ); - 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 + style()->drawPrimitive( QStyle::PE_FrameFocusRect, + &option, painter, this ); } } @@ -237,46 +213,43 @@ void QwtArrowButton::drawButtonLabel(QPainter *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); + QPolygon pa( 3 ); - switch(arrowType) + switch ( arrowType ) { case Qt::UpArrow: - pa.setPoint(0, r.bottomLeft()); - pa.setPoint(1, r.bottomRight()); - pa.setPoint(2, r.center().x(), r.top()); + 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()); + 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()); + 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()); + 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->setPen( palette().color( QPalette::ButtonText ) ); + painter->setBrush( palette().brush( QPalette::ButtonText ) ); + painter->drawPolygon( pa ); + painter->restore(); } @@ -285,7 +258,8 @@ void QwtArrowButton::drawArrow(QPainter *painter, */ QSize QwtArrowButton::sizeHint() const { - return minimumSizeHint(); + const QSize hint = minimumSizeHint(); + return hint.expandedTo( QApplication::globalStrut() ); } /*! @@ -293,30 +267,21 @@ 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); + 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; - -#else - sz = style().sizeFromContents(QStyle::CT_PushButton, this, sz); -#endif + sz = style()->sizeFromContents( QStyle::CT_PushButton, + &styleOption, sz, this ); return sz; } @@ -328,16 +293,16 @@ QSize QwtArrowButton::minimumSizeHint() const \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 ) bs.transpose(); - + 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; @@ -345,10 +310,10 @@ QSize QwtArrowButton::arrowSize(Qt::ArrowType arrowType, 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(); @@ -358,10 +323,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/qwt/src/qwt_arrow_button.h b/qwt/src/qwt_arrow_button.h index 9d1a7829b..ae436fec0 100644 --- a/qwt/src/qwt_arrow_button.h +++ b/qwt/src/qwt_arrow_button.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -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/qwt/src/qwt_clipper.cpp b/qwt/src/qwt_clipper.cpp index ccbf0eb06..6eabb7ddf 100644 --- a/qwt/src/qwt_clipper.cpp +++ b/qwt/src/qwt_clipper.cpp @@ -2,404 +2,368 @@ * 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 -#include "qwt_math.h" #include "qwt_clipper.h" +#include "qwt_point_polar.h" +#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(); -#endif -} - -enum Edge -{ - Left, - Top, - Right, - Bottom, - NEdges -}; - -class QwtPolygonClipper: public QRect -{ -public: - QwtPolygonClipper(const QRect &r); - - QwtPolygon clipPolygon(const QwtPolygon &) const; - -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; -}; - -class QwtPolygonClipperF: public QwtDoubleRect -{ -public: - QwtPolygonClipperF(const QwtDoubleRect &r); - QwtPolygonF clipPolygon(const QwtPolygonF &) const; - -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; - - void addPoint(QwtPolygonF &, uint pos, const QwtDoublePoint &point) const; -}; - -#if QT_VERSION >= 0x040000 -class QwtCircleClipper: public QwtDoubleRect -{ -public: - QwtCircleClipper(const QwtDoubleRect &r); - QwtArray clipCircle( - const QwtDoublePoint &, double radius) const; - -private: - QList cuttingPoints( - Edge, const QwtDoublePoint &pos, double radius) const; - double toAngle(const QwtDoublePoint &, const QwtDoublePoint &) const; -}; +#if QT_VERSION < 0x040601 +#define qAtan(x) ::atan(x) #endif -QwtPolygonClipper::QwtPolygonClipper(const QRect &r): - QRect(r) +namespace QwtClip { + // some templates used for inlining + template class LeftEdge; + template class RightEdge; + template class TopEdge; + template class BottomEdge; + + template class PointBuffer; } -inline void QwtPolygonClipper::addPoint( - QwtPolygon &pa, uint pos, const QPoint &point) const +template +class QwtClip::LeftEdge { - if ( uint(pa.size()) <= pos ) - pa.resize(pos + 5); - - pa.setPoint(pos, point); -} - -//! Sutherland-Hodgman polygon clipping -QwtPolygon QwtPolygonClipper::clipPolygon(const QwtPolygon &pa) const -{ - if ( contains( pa.boundingRect() ) ) - return pa; - - QwtPolygon cpa(pa.size()); - - clipEdge((Edge)0, pa, cpa); - - for ( uint edge = 1; edge < NEdges; edge++ ) +public: + inline LeftEdge( Value x1, Value, Value, Value ): + d_x1( x1 ) { - const QwtPolygon rpa = cpa; -#if QT_VERSION < 0x040000 - cpa.detach(); + } + + 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, ( Value ) ( p2.y() + ( d_x1 - p2.x() ) * dy ) ); + } +private: + const Value d_x1; +}; + +template +class QwtClip::RightEdge +{ +public: + inline RightEdge( Value, Value x2, Value, Value ): + d_x2( x2 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.x() <= d_x2; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() ); + return Point( d_x2, ( Value ) ( p2.y() + ( d_x2 - p2.x() ) * dy ) ); + } + +private: + const Value d_x2; +}; + +template +class QwtClip::TopEdge +{ +public: + inline TopEdge( Value, Value, Value y1, Value ): + d_y1( y1 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.y() >= d_y1; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() ); + return Point( ( Value )( p2.x() + ( d_y1 - p2.y() ) * dx ), d_y1 ); + } + +private: + const Value d_y1; +}; + +template +class QwtClip::BottomEdge +{ +public: + inline BottomEdge( Value, Value, Value, Value y2 ): + d_y2( y2 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.y() <= d_y2; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() ); + return Point( ( Value )( p2.x() + ( d_y2 - p2.y() ) * dx ), d_y2 ); + } + +private: + const Value d_y2; +}; + +template +class QwtClip::PointBuffer +{ +public: + PointBuffer( int capacity = 0 ): + m_capacity( 0 ), + m_size( 0 ), + m_buffer( NULL ) + { + if ( capacity > 0 ) + reserve( capacity ); + } + + ~PointBuffer() + { + if ( m_buffer ) + qFree( m_buffer ); + } + + inline void setPoints( int numPoints, const Point *points ) + { + reserve( numPoints ); + + m_size = numPoints; + qMemCopy( m_buffer, points, m_size * sizeof( Point ) ); + } + + inline void reset() + { + m_size = 0; + } + + inline int size() const + { + return m_size; + } + + inline Point *data() const + { + return m_buffer; + } + + inline Point &operator[]( int i ) + { + return m_buffer[i]; + } + + inline const Point &operator[]( int i ) const + { + return m_buffer[i]; + } + + inline void add( const Point &point ) + { + if ( m_capacity <= m_size ) + reserve( m_size + 1 ); + + m_buffer[m_size++] = point; + } + +private: + inline void reserve( int size ) + { + if ( m_capacity == 0 ) + m_capacity = 1; + + while ( m_capacity < size ) + m_capacity *= 2; + + m_buffer = ( Point * ) qRealloc( + m_buffer, m_capacity * sizeof( Point ) ); + } + + int m_capacity; + int m_size; + Point *m_buffer; +}; + +using namespace QwtClip; + +template +class QwtPolygonClipper +{ +public: + QwtPolygonClipper( const Rect &clipRect ): + d_clipRect( clipRect ) + { + } + + Polygon clipPolygon( const Polygon &polygon, bool closePolygon ) const + { +#if 0 + if ( d_clipRect.contains( polygon.boundingRect() ) ) + return polygon; #endif - clipEdge((Edge)edge, rpa, cpa); + + PointBuffer points1; + PointBuffer points2( qMin( 256, polygon.size() ) ); + + points1.setPoints( polygon.size(), polygon.data() ); + + clipEdge< LeftEdge >( closePolygon, points1, points2 ); + clipEdge< RightEdge >( closePolygon, points2, points1 ); + clipEdge< TopEdge >( closePolygon, points1, points2 ); + clipEdge< BottomEdge >( closePolygon, points2, points1 ); + + Polygon p; + p.resize( points1.size() ); + qMemCopy( p.data(), points1.data(), points1.size() * sizeof( Point ) ); + + return p; } - return cpa; -} - -bool QwtPolygonClipper::insideEdge(const QPoint &p, Edge edge) const -{ - switch(edge) +private: + template + inline void clipEdge( bool closePolygon, + PointBuffer &points, PointBuffer &clippedPoints ) const { - 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; - } + clippedPoints.reset(); - return false; -} - -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; - } - - return QPoint(x,y); -} - -void QwtPolygonClipper::clipEdge(Edge edge, - const QwtPolygon &pa, QwtPolygon &cpa) const -{ - if ( pa.count() == 0 ) - { - cpa.resize(0); - return; - } - - 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 ( points.size() < 2 ) { - if ( insideEdge(p1, edge) ) - addPoint(cpa, count++, p2); - else - { - addPoint(cpa, count++, intersectEdge(p1, p2, edge)); - addPoint(cpa, count++, p2); - } + if ( points.size() == 1 ) + clippedPoints.add( points[0] ); + return; + } + + const Edge edge( d_clipRect.x(), d_clipRect.x() + d_clipRect.width(), + d_clipRect.y(), d_clipRect.y() + d_clipRect.height() ); + + int lastPos, start; + if ( closePolygon ) + { + start = 0; + lastPos = points.size() - 1; } else { - if ( insideEdge(p1, edge) ) - addPoint(cpa, count++, intersectEdge(p1, p2, edge)); + start = 1; + lastPos = 0; + + if ( edge.isInside( points[0] ) ) + clippedPoints.add( points[0] ); } - p1 = p2; - } - cpa.resize(count); -} -QwtPolygonClipperF::QwtPolygonClipperF(const QwtDoubleRect &r): - QwtDoubleRect(r) -{ -} - -inline void QwtPolygonClipperF::addPoint(QwtPolygonF &pa, uint pos, const QwtDoublePoint &point) const -{ - if ( uint(pa.size()) <= pos ) - pa.resize(pos + 5); - - pa[(int)pos] = point; -} - -//! Sutherland-Hodgman polygon clipping -QwtPolygonF QwtPolygonClipperF::clipPolygon(const QwtPolygonF &pa) const -{ - if ( contains( ::boundingRect(pa) ) ) - return pa; - - QwtPolygonF cpa(pa.size()); - - clipEdge((Edge)0, pa, cpa); - - for ( uint edge = 1; edge < NEdges; edge++ ) - { - const QwtPolygonF rpa = cpa; -#if QT_VERSION < 0x040000 - cpa.detach(); -#endif - clipEdge((Edge)edge, rpa, cpa); - } - - return cpa; -} - -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; - } - - return false; -} - -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; - } - - return QwtDoublePoint(x,y); -} - -void QwtPolygonClipperF::clipEdge(Edge edge, - const QwtPolygonF &pa, QwtPolygonF &cpa) const -{ - if ( pa.count() == 0 ) - { - cpa.resize(0); - return; - } - - 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) ) + const uint nPoints = points.size(); + for ( uint i = start; i < nPoints; i++ ) { - if ( insideEdge(p1, edge) ) - addPoint(cpa, count++, p2); + 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 { - addPoint(cpa, count++, intersectEdge(p1, p2, edge)); - addPoint(cpa, count++, p2); + if ( edge.isInside( p2 ) ) + { + clippedPoints.add( edge.intersection( p1, p2 ) ); + } } + lastPos = i; } - else - { - if ( insideEdge(p1, edge) ) - addPoint(cpa, count++, intersectEdge(p1, p2, edge)); - } - p1 = p2; } - cpa.resize(count); -} -#if QT_VERSION >= 0x040000 + const Rect d_clipRect; +}; -QwtCircleClipper::QwtCircleClipper(const QwtDoubleRect &r): - QwtDoubleRect(r) +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 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); + points += cuttingPoints( ( Edge )edge, pos, radius ); - QwtArray intv; + QVector 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); + 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); + angles += toAngle( pos, points[i] ); + qSort( angles ); + + const int in = d_rect.contains( qwtPolar2Pos( pos, radius, + angles[0] + ( angles[1] - angles[0] ) / 2 ) ); - 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]); + 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 += QwtDoubleInterval(angles[i], angles[i+1]); - intv += QwtDoubleInterval(angles.last(), angles.first()); + for ( int i = 1; i < angles.size() - 1; i += 2 ) + intv += QwtInterval( angles[i], angles[i+1] ); + intv += QwtInterval( angles.last(), angles.first() ); } } @@ -407,16 +371,16 @@ 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); + double angle = qAtan( m ); if ( to.x() > from.x() ) - { + { if ( to.y() > from.y() ) angle = 2 * M_PI - angle; } @@ -431,79 +395,81 @@ 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; + QList points; if ( edge == Left || edge == Right ) { - const double x = (edge == Left) ? left() : right(); - if ( qwtAbs(pos.x() - x) < radius ) + const double x = ( edge == Left ) ? d_rect.left() : d_rect.right(); + if ( qAbs( 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); + 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 y = ( edge == Top ) ? d_rect.top() : d_rect.bottom(); + if ( qAbs( pos.y() - y ) < radius ) { - const double off = ::sqrt(qwtSqr(radius) - qwtSqr(pos.y() - y)); + 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 - -/*! + +/*! Sutherland-Hodgman polygon clipping \param clipRect Clip rectangle \param polygon Polygon + \param closePolygon True, when the polygon is closed \return Clipped polygon */ -QwtPolygon QwtClipper::clipPolygon( - const QRect &clipRect, const QwtPolygon &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 ); } -/*! +/*! Sutherland-Hodgman polygon clipping \param clipRect Clip rectangle \param polygon Polygon + \param closePolygon True, when the polygon is closed \return Clipped polygon */ -QwtPolygonF QwtClipper::clipPolygonF( - const QwtDoubleRect &clipRect, const QwtPolygonF &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 -/*! +/*! Circle clipping clipCircle() devides a circle into intervals of angles representing arcs - of the circle. When the circle is completely inside the clip rectangle + 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 @@ -512,11 +478,9 @@ QwtPolygonF QwtClipper::clipPolygonF( \return Arcs of the circle */ -QwtArray QwtClipper::clipCircle( - const QwtDoubleRect &clipRect, - const QwtDoublePoint ¢er, double radius) +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/qwt/src/qwt_clipper.h b/qwt/src/qwt_clipper.h index 5f17834f7..5e67b841b 100644 --- a/qwt/src/qwt_clipper.h +++ b/qwt/src/qwt_clipper.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -11,12 +11,12 @@ #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 @@ -25,13 +25,13 @@ class QRect; 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 QPolygonF clipPolygonF( const QRectF &, + const QPolygonF &, bool closePolygon = false ); -#if QT_VERSION >= 0x040000 - static QwtArray clipCircle( - const QwtDoubleRect &, const QwtDoublePoint &, double radius); -#endif + static QVector clipCircle( + const QRectF &, const QPointF &, double radius ); }; #endif diff --git a/qwt/src/qwt_color_map.cpp b/qwt/src/qwt_color_map.cpp index bf04d6cd9..4318e5a0a 100644 --- a/qwt/src/qwt_color_map.cpp +++ b/qwt/src/qwt_color_map.cpp @@ -7,32 +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 + _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: @@ -40,18 +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()) + ColorStop( double p, const QColor &c ): + pos( p ), + rgb( c.rgb() ) { - r = qRed(rgb); - g = qGreen(rgb); - b = qBlue(rgb); + r = qRed( rgb ); + g = qGreen( rgb ); + b = qBlue( rgb ); } double pos; @@ -59,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 ... @@ -75,57 +66,49 @@ void QwtLinearColorMap::ColorStops::insert(double pos, const QColor &color) if ( _stops.size() == 0 ) { index = 0; -#if QT_VERSION < 0x040000 - _stops.resize(1, QGArray::SpeedOptim); -#else - _stops.resize(1); -#endif + _stops.resize( 1 ); } else { - index = findUpper(pos); - if ( index == (int)_stops.size() || - qwtAbs(_stops[index].pos - pos) >= 0.001 ) + index = findUpper( pos ); + if ( index == _stops.size() || + qAbs( _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( _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; } @@ -133,14 +116,14 @@ 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); + const int index = findUpper( pos ); if ( mode == FixedColors ) { return _stops[index-1].rgb; @@ -150,19 +133,19 @@ inline QRgb QwtLinearColorMap::ColorStops::rgb( 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)); - - return qRgb(r, g, 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 ); } } //! Constructor -QwtColorMap::QwtColorMap(Format format): - d_format(format) +QwtColorMap::QwtColorMap( Format format ): + d_format( format ) { } @@ -175,21 +158,20 @@ QwtColorMap::~QwtColorMap() Build and return a color map of 256 colors The color table is needed for rendering indexed images in combination - with using colorIndex(). + with using colorIndex(). \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); + 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; @@ -202,43 +184,35 @@ public: QwtLinearColorMap::Mode mode; }; -/*! +/*! Build a color map with two stops at 0.0 and 1.0. The color at 0.0 is Qt::blue, at 1.0 it is Qt::yellow. \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 ); } /*! - Build a color map with two stops at 0.0 and 1.0. + Build a color map with two stops at 0.0 and 1.0. \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 */ -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 @@ -247,34 +221,16 @@ 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 FixedColors means the color is calculated from the next lower color stop. ScaledColors means the color is calculated - by interpolating the colors of the adjacent stops. + by interpolating the colors of the adjacent stops. \sa mode() */ -void QwtLinearColorMap::setMode(Mode mode) +void QwtLinearColorMap::setMode( Mode mode ) { d_data->mode = mode; } @@ -289,9 +245,9 @@ QwtLinearColorMap::Mode QwtLinearColorMap::mode() const } /*! - Set the color range + Set the color range - Add stops at 0.0 and 1.0. + Add stops at 0.0 and 1.0. \param color1 Color used for the minimum value of the value interval \param color2 Color used for the maximum value of the value interval @@ -299,53 +255,53 @@ 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 ); } /*! Add a color stop - The value has to be in the range [0.0, 1.0]. + The value has to be in the range [0.0, 1.0]. F.e. a stop at position 17.0 for a range [10.0,20.0] must be passed as: (17.0 - 10.0) / (20.0 - 10.0) \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 */ -QwtArray QwtLinearColorMap::colorStops() const +QVector QwtLinearColorMap::colorStops() const { return d_data->colorStops.stops(); } -/*! +/*! \return the first color of the color range \sa setColorInterval() */ 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 ) ); } -/*! +/*! \return the second color of the color range \sa setColorInterval() */ 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 ) ); } /*! @@ -355,15 +311,18 @@ QColor QwtLinearColorMap::color2() const \param value Value to map into a rgb 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 ); } /*! @@ -373,23 +332,23 @@ QRgb QwtLinearColorMap::rgb( \param value Value to map into a color index */ 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 ( unsigned char )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 = ( unsigned char )( ratio * 255 ); // always floor else - index = (unsigned char)qRound(ratio * 255); + index = ( unsigned char )qRound( ratio * 255 ); return index; } @@ -402,27 +361,16 @@ 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 @@ -431,42 +379,20 @@ 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 + 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(); } -/*! - \return the color +/*! + \return the color \sa setColor() */ QColor QwtAlphaColorMap::color() const @@ -483,33 +409,32 @@ QColor QwtAlphaColorMap::color() const \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 ) + if ( !qIsNaN(value) && width >= 0.0 ) { - const double ratio = (value - interval.minValue()) / width; - int alpha = qRound(255 * ratio); + 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; } /*! Dummy function, needed to be implemented as it is pure virtual - in QwtColorMap. Color indices make no sense in combination with + in QwtColorMap. Color indices make no sense in combination with an alpha channel. \return Always 0 */ unsigned char QwtAlphaColorMap::colorIndex( - const QwtDoubleInterval &, double) const + const QwtInterval &, double ) const { return 0; } diff --git a/qwt/src/qwt_color_map.h b/qwt/src/qwt_color_map.h index 3d54aa395..e75483026 100644 --- a/qwt/src/qwt_color_map.h +++ b/qwt/src/qwt_color_map.h @@ -10,27 +10,16 @@ #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. + \brief QwtColorMap is used to map values into colors. For displaying 3D data on a 2D plane the 3rd dimension is often - displayed using colors, like f.e in a spectrogram. + displayed using colors, like f.e in a spectrogram. Each color map is optimized to return colors for only one of the following image formats: @@ -44,69 +33,59 @@ template class QWT_EXPORT QwtArray; 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 { + //! The map is intended to map into QRgb 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(); Format format() const; - //! Clone the color map - virtual QwtColorMap *copy() const = 0; - - /*! + /*! 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 */ - 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 { @@ -117,39 +96,40 @@ public: */ 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; }; @@ -160,23 +140,20 @@ private: 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; @@ -196,16 +173,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) ); + return QColor( rgb( interval, value ) ); } else { - const unsigned int index = colorIndex(interval, value); - return colorTable(interval)[index]; // slow + const unsigned int index = colorIndex( interval, value ); + return colorTable( interval )[index]; // slow } } diff --git a/qwt/src/qwt_column_symbol.cpp b/qwt/src/qwt_column_symbol.cpp new file mode 100644 index 000000000..314e9d2f1 --- /dev/null +++ b/qwt/src/qwt_column_symbol.cpp @@ -0,0 +1,296 @@ +/* -*- 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_text.h" +#include "qwt_painter.h" +#include +#include + +static void drawBox( 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 drawPanel( 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; + QwtText label; + + 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: + { + ::drawPanel( painter, r, d_data->palette, d_data->lineWidth ); + break; + } + case QwtColumnSymbol::Plain: + { + ::drawBox( painter, r, d_data->palette, d_data->lineWidth ); + break; + } + default: + { + painter->fillRect( r, d_data->palette.window() ); + } + } +} diff --git a/qwt/src/qwt_column_symbol.h b/qwt/src/qwt_column_symbol.h new file mode 100644 index 000000000..3c278f19a --- /dev/null +++ b/qwt/src/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 und 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/qwt/src/qwt_compass.cpp b/qwt/src/qwt_compass.cpp index 9b484e996..17ab03340 100644 --- a/qwt/src/qwt_compass.cpp +++ b/qwt/src/qwt_compass.cpp @@ -7,25 +7,21 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - -#include +#include "qwt_compass.h" +#include "qwt_compass_rose.h" +#include "qwt_math.h" +#include "qwt_scale_draw.h" +#include "qwt_painter.h" +#include "qwt_dial_needle.h" #include #include #include -#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" class QwtCompass::PrivateData { public: PrivateData(): - rose(NULL) + rose( NULL ) { } @@ -42,39 +38,19 @@ public: \brief Constructor \param parent Parent widget - Create a compass widget with a scale, no needle and no rose. + 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): - QwtDial(parent) +*/ +QwtCompass::QwtCompass( QWidget* parent ): + QwtDial( parent ) { initCompass(); } -#if QT_VERSION < 0x040000 - -/*! - \brief Constructor - \param parent Parent widget - \param name Object name - - 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(); -} - -#endif - //! Destructor -QwtCompass::~QwtCompass() +QwtCompass::~QwtCompass() { delete d_data; } @@ -83,42 +59,43 @@ void QwtCompass::initCompass() { d_data = new PrivateData; - setScaleOptions(ScaleLabel); // Only labels, no backbone, no ticks + // Only labels, no backbone, no ticks + setScaleComponents( QwtAbstractScaleDraw::Labels ); - setOrigin(270.0); - setWrapping(true); + 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")); + 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")); + 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 \param painter Painter \param center Center of the content circle \param radius Radius of the content circle */ -void QwtCompass::drawScaleContents(QPainter *painter, - const QPoint ¢er, int radius) const +void QwtCompass::drawScaleContents( QPainter *painter, + const QPointF ¢er, double radius ) const { QPalette::ColorGroup cg; if ( isEnabled() ) @@ -130,27 +107,27 @@ void QwtCompass::drawScaleContents(QPainter *painter, if ( isValid() ) { if ( mode() == RotateScale ) - north -= value(); + north -= value(); } const int margin = 4; - drawRose(painter, center, radius - margin, 360.0 - north, cg); + drawRose( painter, center, radius - margin, 360.0 - north, cg ); } /*! Draw the compass rose - + \param painter Painter \param center Center of the compass \param radius of the circle, where to paint the rose \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 ); } /*! @@ -160,7 +137,7 @@ 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 ) { @@ -172,25 +149,25 @@ void QwtCompass::setRose(QwtCompassRose *rose) } } -/*! +/*! \return rose \sa setRose() */ -const QwtCompassRose *QwtCompass::rose() const -{ - return d_data->rose; +const QwtCompassRose *QwtCompass::rose() const +{ + return d_data->rose; } -/*! +/*! \return rose \sa setRose() */ -QwtCompassRose *QwtCompass::rose() -{ - return d_data->rose; +QwtCompassRose *QwtCompass::rose() +{ + return d_data->rose; } -/*! +/*! Handles key events Beside the keys described in QwtDial::keyPressEvent numbers @@ -199,9 +176,9 @@ QwtCompassRose *QwtCompass::rose() \sa isReadOnly() */ -void QwtCompass::keyPressEvent(QKeyEvent *kev) +void QwtCompass::keyPressEvent( QKeyEvent *kev ) { - if (isReadOnly()) + if ( isReadOnly() ) return; #if 0 @@ -219,39 +196,39 @@ void QwtCompass::keyPressEvent(QKeyEvent *kev) if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 ) return; - switch (kev->key()) + switch ( kev->key() ) { - case Qt::Key_6: + case Qt::Key_6: newValue = 180.0 * 0.0; break; - case Qt::Key_3: + case Qt::Key_3: newValue = 180.0 * 0.25; break; - case Qt::Key_2: + case Qt::Key_2: newValue = 180.0 * 0.5; break; - case Qt::Key_1: + case Qt::Key_1: newValue = 180.0 * 0.75; break; - case Qt::Key_4: + case Qt::Key_4: newValue = 180.0 * 1.0; break; - case Qt::Key_7: + case Qt::Key_7: newValue = 180.0 * 1.25; break; - case Qt::Key_8: + case Qt::Key_8: newValue = 180.0 * 1.5; break; - case Qt::Key_9: + case Qt::Key_9: newValue = 180.0 * 1.75; break; } newValue -= origin(); - setValue(newValue); + setValue( newValue ); } else { - QwtDial::keyPressEvent(kev); + QwtDial::keyPressEvent( kev ); } } @@ -259,18 +236,18 @@ void QwtCompass::keyPressEvent(QKeyEvent *kev) \return map, mapping values to labels \sa setLabelMap() */ -const QMap &QwtCompass::labelMap() const -{ - return d_data->labelMap; +const QMap &QwtCompass::labelMap() const +{ + return d_data->labelMap; } /*! \return map, mapping values to labels \sa setLabelMap() */ -QMap &QwtCompass::labelMap() -{ - return d_data->labelMap; +QMap &QwtCompass::labelMap() +{ + return d_data->labelMap; } /*! @@ -285,9 +262,9 @@ QMap &QwtCompass::labelMap() \sa labelMap(), scaleDraw(), setScale() */ -void QwtCompass::setLabelMap(const QMap &map) -{ - d_data->labelMap = map; +void QwtCompass::setLabelMap( const QMap &map ) +{ + d_data->labelMap = map; } /*! @@ -300,18 +277,15 @@ void QwtCompass::setLabelMap(const QMap &map) \sa labelMap(), setLabelMap() */ -QwtText QwtCompass::scaleLabel(double value) const +QwtText QwtCompass::scaleLabel( double value ) const { -#if 0 - // better solution ??? - if ( value == -0 ) + if ( qFuzzyCompare( value, 0.0 ) ) value = 0.0; -#endif if ( value < 0.0 ) value += 360.0; - if ( d_data->labelMap.contains(value) ) + if ( d_data->labelMap.contains( value ) ) return d_data->labelMap[value]; return QwtText(); diff --git a/qwt/src/qwt_compass.h b/qwt/src/qwt_compass.h index 68b942964..a1044b7f5 100644 --- a/qwt/src/qwt_compass.h +++ b/qwt/src/qwt_compass.h @@ -10,27 +10,10 @@ #ifndef QWT_COMPASS_H #define QWT_COMPASS_H 1 +#include "qwt_global.h" +#include "qwt_dial.h" #include #include -#include "qwt_dial.h" - -#if defined(QWT_TEMPLATEDLL) - -#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 -*/ -// MOC_SKIP_BEGIN -template class QWT_EXPORT QMap; -// MOC_SKIP_END -#endif - -#endif - class QwtCompassRose; @@ -38,42 +21,39 @@ class QwtCompassRose; \brief A Compass Widget QwtCompass is a widget to display and enter directions. It consists - of a scale, an optional needle and rose. + of a scale, an optional needle and rose. - \image html dials1.png + \image html dials1.png \note The examples/dials example shows how to use QwtCompass. */ -class QWT_EXPORT QwtCompass: public QwtDial +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); + void setLabelMap( const QMap &map ); protected: - virtual QwtText scaleLabel(double value) const; + virtual QwtText scaleLabel( double value ) const; - virtual void drawRose(QPainter *, const QPoint ¢er, - int radius, double north, QPalette::ColorGroup) const; + virtual void drawRose( QPainter *, const QPointF ¢er, + double radius, double north, QPalette::ColorGroup ) const; - virtual void drawScaleContents(QPainter *, - const QPoint ¢er, int radius) const; + virtual void drawScaleContents( QPainter *, + const QPointF ¢er, double radius ) const; - virtual void keyPressEvent(QKeyEvent *); + virtual void keyPressEvent( QKeyEvent * ); private: void initCompass(); diff --git a/qwt/src/qwt_compass_rose.cpp b/qwt/src/qwt_compass_rose.cpp index e85644021..064e5b14f 100644 --- a/qwt/src/qwt_compass_rose.cpp +++ b/qwt/src/qwt_compass_rose.cpp @@ -7,83 +7,93 @@ * 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(); + const QLineF line1( p11, p12 ); + const QLineF line2( p21, p22 ); - if ( dx1 == 0.0 && dx2 == 0.0 ) - return QPoint(); + QPointF pos; + if ( line1.intersect( line2, &pos ) == QLineF::NoIntersection ) + return QPointF(); - 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)); - } - - 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(); - - const double m2 = dy2 / dx2; - const double t2 = p21.y() - m2 * p21.x(); - - if ( m1 == m2 ) - return QPoint(); - - const double x = ( t2 - t1 ) / ( m1 - m2 ); - const double y = t1 + m1 * x; - - return QPoint(qRound(x), qRound(y)); + return pos; } +class QwtSimpleCompassRose::PrivateData +{ +public: + PrivateData(): + width( 0.2 ), + numThorns( 8 ), + numThornLevels( -1 ), + shrinkFactor( 0.9 ) + { + } + + double width; + int numThorns; + int numThornLevels; + double shrinkFactor; +}; + /*! Constructor \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::ColorGroup )i, + QPalette::Dark, dark ); + palette.setColor( ( QPalette::ColorGroup )i, + 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. + + \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; } /*! @@ -95,29 +105,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 ); } /*! @@ -134,14 +129,10 @@ void QwtSimpleCompassRose::draw(QPainter *painter, const QPoint ¢er, \param shrinkFactor Factor to shrink the thorns with each level */ void QwtSimpleCompassRose::drawRose( - QPainter *painter, -#if QT_VERSION < 0x040000 - const QColorGroup &cg, -#else + QPainter *painter, 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; @@ -160,11 +151,11 @@ 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; + double step = qPow( 2.0, j ) * M_PI / numThorns; if ( step > M_PI_2 ) break; @@ -180,37 +171,30 @@ void QwtSimpleCompassRose::drawRose( leafWidth = 16; const double origin = north / 180.0 * M_PI; - for ( double angle = origin; - angle < 2.0 * M_PI + origin; angle += step) + 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); + 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 ); - QwtPolygon pa(3); - pa.setPoint(0, center); - pa.setPoint(1, p); + QPainterPath darkPath; + darkPath.moveTo( center ); + darkPath.lineTo( p ); + darkPath.lineTo( qwtIntersection( center, p3, p1, 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); + painter->setBrush( palette.brush( QPalette::Dark ) ); + painter->drawPath( darkPath ); - QPoint p4 = qwtPolar2Pos(center, r, angle - step / 2.0); - p2 = cutPoint(center, p4, p2, p); + QPainterPath lightPath; + lightPath.moveTo( center ); + lightPath.lineTo( p ); + lightPath.lineTo( qwtIntersection( 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); + painter->setBrush( palette.brush( QPalette::Light ) ); + painter->drawPath( lightPath ); } } painter->restore(); @@ -222,25 +206,30 @@ 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_width > 0.4) - d_width = 0.4; + if ( d_data->width > 0.4 ) + d_data->width = 0.4; +} + +//! \sa setWidth() +double QwtSimpleCompassRose::width() const +{ + return d_data->width; } /*! Set the number of thorns on one level - The number is aligned to a multiple of 4, with a minimum of 4 + The number is aligned to a multiple of 4, with a minimum of 4 \param numThorns Number of thorns \sa numThorns(), setNumThornLevels() */ -void QwtSimpleCompassRose::setNumThorns(int numThorns) +void QwtSimpleCompassRose::setNumThorns( int numThorns ) { if ( numThorns < 4 ) numThorns = 4; @@ -248,7 +237,7 @@ void QwtSimpleCompassRose::setNumThorns(int numThorns) if ( numThorns % 4 ) numThorns += 4 - numThorns % 4; - d_numThorns = numThorns; + d_data->numThorns = numThorns; } /*! @@ -257,7 +246,7 @@ void QwtSimpleCompassRose::setNumThorns(int numThorns) */ int QwtSimpleCompassRose::numThorns() const { - return d_numThorns; + return d_data->numThorns; } /*! @@ -266,9 +255,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; } /*! @@ -277,5 +266,5 @@ void QwtSimpleCompassRose::setNumThornLevels(int numThornLevels) */ int QwtSimpleCompassRose::numThornLevels() const { - return d_numThornLevels; + return d_data->numThornLevels; } diff --git a/qwt/src/qwt_compass_rose.h b/qwt/src/qwt_compass_rose.h index d5649ee9f..4272a6e82 100644 --- a/qwt/src/qwt_compass_rose.h +++ b/qwt/src/qwt_compass_rose.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,8 +10,8 @@ #ifndef QWT_COMPASS_ROSE_H #define QWT_COMPASS_ROSE_H 1 -#include #include "qwt_global.h" +#include class QPainter; @@ -21,13 +21,20 @@ class QPainter; class QWT_EXPORT QwtCompassRose { public: + //! Destructor virtual ~QwtCompassRose() {}; //! Assign a palette - virtual void setPalette(const QPalette &p) { d_palette = p; } + virtual void setPalette( const QPalette &p ) + { + d_palette = p; + } //! \return Current palette - const QPalette &palette() const { return d_palette; } + const QPalette &palette() const + { + return d_palette; + } /*! Draw the rose @@ -38,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; @@ -52,39 +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); + void setWidth( double w ); + double width() const; - //! \sa setWidth() - double width() const { return d_width; } - - 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/qwt/src/qwt_compat.h b/qwt/src/qwt_compat.h new file mode 100644 index 000000000..dc74a5d28 --- /dev/null +++ b/qwt/src/qwt_compat.h @@ -0,0 +1,40 @@ +/* -*- 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 +#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/qwt/src/qwt_counter.cpp b/qwt/src/qwt_counter.cpp index 31e87d935..8ecc89c39 100644 --- a/qwt/src/qwt_counter.cpp +++ b/qwt/src/qwt_counter.cpp @@ -7,22 +7,20 @@ * 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) + editable( true ) { increment[Button1] = 1; increment[Button2] = 10; @@ -34,7 +32,7 @@ public: QLineEdit *valueEdit; int increment[ButtonCnt]; - int nButtons; + int numButtons; bool editable; }; @@ -47,96 +45,67 @@ public: \param parent */ -QwtCounter::QwtCounter(QWidget *parent): - QWidget(parent) +QwtCounter::QwtCounter( QWidget *parent ): + QWidget( parent ) { initCounter(); } -#if QT_VERSION < 0x040000 -/*! - 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 - - \param parent - */ -QwtCounter::QwtCounter(QWidget *parent, const char *name): - QWidget(parent, name) -{ - 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); + 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 + connect( d_data->valueEdit, SIGNAL( editingFinished() ), + SLOT( textChanged() ) ); - layout->setStretchFactor(d_data->valueEdit, 10); + layout->setStretchFactor( d_data->valueEdit, 10 ); - for(i = 0; i < ButtonCnt; i++) + for ( int i = 0; i < ButtonCnt; i++ ) { -#if QT_VERSION >= 0x040000 - using namespace Qt; -#endif 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, 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 @@ -145,35 +114,17 @@ QwtCounter::~QwtCounter() delete d_data; } -/*! - Sets the minimum width for the buttons -*/ -void QwtCounter::polish() -{ - 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); - } - -#if QT_VERSION < 0x040000 - QWidget::polish(); -#endif -} - //! Set from lineedit -void QwtCounter::textChanged() +void QwtCounter::textChanged() { - if ( !d_data->editable ) + if ( !d_data->editable ) return; bool converted = false; - const double value = d_data->valueEdit->text().toDouble(&converted); - if ( converted ) - setValue( value ); + const double value = d_data->valueEdit->text().toDouble( &converted ); + if ( converted ) + setValue( value ); } /** @@ -182,156 +133,152 @@ void QwtCounter::textChanged() \param editable true enables editing \sa editable() */ -void QwtCounter::setEditable(bool editable) +void QwtCounter::setEditable( bool editable ) { -#if QT_VERSION >= 0x040000 - using namespace Qt; -#endif - if ( editable == d_data->editable ) + if ( editable == d_data->editable ) return; d_data->editable = editable; - d_data->valueEdit->setReadOnly(!editable); + d_data->valueEdit->setReadOnly( !editable ); } //! returns whether the line edit is edatble. (default is yes) -bool QwtCounter::editable() const -{ +bool QwtCounter::editable() const +{ return d_data->editable; } /*! - Handle PolishRequest events + Handle PolishRequest events + \param event Event */ -bool QwtCounter::event ( QEvent * e ) +bool QwtCounter::event( QEvent *event ) { -#if QT_VERSION >= 0x040000 - if ( e->type() == QEvent::PolishRequest ) - polish(); -#endif - return QWidget::event(e); + 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 ); } /*! Handle key events - - Ctrl + Qt::Key_Home + - Ctrl + Qt::Key_Home\n Step to minValue() - - Ctrl + Qt::Key_End + - Ctrl + Qt::Key_End\n Step to maxValue() - - Qt::Key_Up + - Qt::Key_Up\n Increment by incSteps(QwtCounter::Button1) - - Qt::Key_Down + - Qt::Key_Down\n Decrement by incSteps(QwtCounter::Button1) - - Qt::Key_PageUp + - Qt::Key_PageUp\n Increment by incSteps(QwtCounter::Button2) - - Qt::Key_PageDown + - Qt::Key_PageDown\n Decrement by incSteps(QwtCounter::Button2) - - Shift + Qt::Key_PageUp + - Shift + Qt::Key_PageUp\n Increment by incSteps(QwtCounter::Button3) - - Shift + Qt::Key_PageDown + - Shift + Qt::Key_PageDown\n Decrement by incSteps(QwtCounter::Button3) + + \param event Key event */ -void QwtCounter::keyPressEvent (QKeyEvent *e) +void QwtCounter::keyPressEvent ( QKeyEvent *event ) { bool accepted = true; - switch ( e->key() ) + switch ( event->key() ) { case Qt::Key_Home: -#if QT_VERSION >= 0x040000 - if ( e->modifiers() & Qt::ControlModifier ) -#else - if ( e->state() & Qt::ControlButton ) -#endif - setValue(minValue()); + { + if ( event->modifiers() & Qt::ControlModifier ) + 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()); + { + if ( event->modifiers() & Qt::ControlModifier ) + setValue( maxValue() ); else accepted = false; break; + } case Qt::Key_Up: - incValue(d_data->increment[0]); + { + incValue( d_data->increment[0] ); break; + } case Qt::Key_Down: - incValue(-d_data->increment[0]); + { + 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 ) + if ( d_data->numButtons >= 2 ) increment = d_data->increment[1]; - if ( d_data->nButtons >= 3 ) + if ( d_data->numButtons >= 3 ) { -#if QT_VERSION >= 0x040000 - if ( e->modifiers() & Qt::ShiftModifier ) -#else - if ( e->state() & Qt::ShiftButton ) -#endif + if ( event->modifiers() & Qt::ShiftModifier ) increment = d_data->increment[2]; } - if ( e->key() == Qt::Key_PageDown ) + if ( event->key() == Qt::Key_PageDown ) increment = -increment; - incValue(increment); + incValue( increment ); break; } default: + { accepted = false; + } } if ( accepted ) { - e->accept(); + event->accept(); return; } - QWidget::keyPressEvent (e); + QWidget::keyPressEvent ( event ); } /*! Handle wheel events - \param e Wheel event + \param event Wheel event */ -void QwtCounter::wheelEvent(QWheelEvent *e) +void QwtCounter::wheelEvent( QWheelEvent *event ) { - e->accept(); + event->accept(); - if ( d_data->nButtons <= 0 ) + if ( d_data->numButtons <= 0 ) return; int increment = d_data->increment[0]; - if ( d_data->nButtons >= 2 ) + if ( d_data->numButtons >= 2 ) { -#if QT_VERSION >= 0x040000 - if ( e->modifiers() & Qt::ControlModifier ) -#else - if ( e->state() & Qt::ControlButton ) -#endif + if ( event->modifiers() & Qt::ControlModifier ) increment = d_data->increment[1]; } - if ( d_data->nButtons >= 3 ) + if ( d_data->numButtons >= 3 ) { -#if QT_VERSION >= 0x040000 - if ( e->modifiers() & Qt::ShiftModifier ) -#else - if ( e->state() & Qt::ShiftButton ) -#endif + if ( event->modifiers() & Qt::ShiftModifier ) increment = d_data->increment[2]; } - - for ( int i = 0; i < d_data->nButtons; i++ ) + + for ( int i = 0; i < d_data->numButtons; i++ ) { - if ( d_data->buttonDown[i]->geometry().contains(e->pos()) || - d_data->buttonUp[i]->geometry().contains(e->pos()) ) + if ( d_data->buttonDown[i]->geometry().contains( event->pos() ) || + d_data->buttonUp[i]->geometry().contains( event->pos() ) ) { increment = d_data->increment[i]; } @@ -339,11 +286,11 @@ void QwtCounter::wheelEvent(QWheelEvent *e) const int wheel_delta = 120; - int delta = e->delta(); + int delta = event->delta(); if ( delta >= 2 * wheel_delta ) delta /= 2; // Never saw an abs(delta) < 240 - incValue(delta / wheel_delta * increment); + incValue( delta / wheel_delta * increment ); } /*! @@ -351,42 +298,46 @@ 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 button Button index \param nSteps Number of steps + + \sa incSteps() */ -void QwtCounter::setIncSteps(QwtCounter::Button btn, int nSteps) +void QwtCounter::setIncSteps( QwtCounter::Button button, int nSteps ) { - if (( btn >= 0) && (btn < ButtonCnt)) - d_data->increment[btn] = nSteps; + if ( button >= 0 && button < ButtonCnt ) + d_data->increment[button] = nSteps; } /*! \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 + \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 < 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. + + \param value New value \sa QwtDoubleRange::setValue() */ -void QwtCounter::setValue(double v) +void QwtCounter::setValue( double value ) { - QwtDoubleRange::setValue(v); + QwtDoubleRange::setValue( value ); - showNum(value()); + showNum( this->value() ); updateButtons(); } @@ -396,14 +347,14 @@ void QwtCounter::setValue(double v) void QwtCounter::valueChange() { if ( isValid() ) - showNum(value()); + showNum( value() ); else - d_data->valueEdit->setText(QString::null); + d_data->valueEdit->setText( QString::null ); updateButtons(); if ( isValid() ) - emit valueChanged(value()); + Q_EMIT valueChanged( value() ); } /*! @@ -421,34 +372,34 @@ void QwtCounter::updateButtons() // 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 < ButtonCnt; i++ ) + for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) { - d_data->buttonDown[i]->setEnabled(value() > minValue()); - d_data->buttonUp[i]->setEnabled(value() < maxValue()); + d_data->buttonDown[i]->setEnabled( value() > minValue() ); + d_data->buttonUp[i]->setEnabled( value() < maxValue() ); } } else { - for ( int i = 0; i < ButtonCnt; i++ ) + for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) { - d_data->buttonDown[i]->setEnabled(false); - d_data->buttonUp[i]->setEnabled(false); + d_data->buttonDown[i]->setEnabled( false ); + d_data->buttonUp[i]->setEnabled( false ); } } } /*! \brief Specify the number of buttons on each side of the label - \param n Number of buttons + \param numButtons Number of buttons */ -void QwtCounter::setNumButtons(int n) +void QwtCounter::setNumButtons( int numButtons ) { - if ( n<0 || n>ButtonCnt ) + if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt ) return; - for ( int i = 0; i < ButtonCnt; i++ ) + for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) { - if ( i < n ) + if ( i < numButtons ) { d_data->buttonDown[i]->show(); d_data->buttonUp[i]->show(); @@ -460,30 +411,30 @@ void QwtCounter::setNumButtons(int n) } } - d_data->nButtons = n; + d_data->numButtons = numButtons; } /*! \return The number of buttons on each side of the widget. */ -int QwtCounter::numButtons() const -{ - return d_data->nButtons; +int QwtCounter::numButtons() const +{ + return d_data->numButtons; } -/*! +/*! Display number string \param number Number */ -void QwtCounter::showNum(double number) +void QwtCounter::showNum( double number ) { - QString v; - v.setNum(number); + 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 @@ -492,17 +443,17 @@ void QwtCounter::btnClicked() for ( int i = 0; i < ButtonCnt; i++ ) { if ( d_data->buttonUp[i] == sender() ) - incValue(d_data->increment[i]); + incValue( d_data->increment[i] ); if ( d_data->buttonDown[i] == sender() ) - incValue(-d_data->increment[i]); + incValue( -d_data->increment[i] ); } } //! Button released void QwtCounter::btnReleased() { - emit buttonReleased(value()); + Q_EMIT buttonReleased( value() ); } /*! @@ -521,36 +472,32 @@ QSize QwtCounter::sizeHint() const { QString tmp; - int w = tmp.setNum(minValue()).length(); - int w1 = tmp.setNum(maxValue()).length(); + int w = tmp.setNum( minValue() ).length(); + int w1 = tmp.setNum( maxValue() ).length(); if ( w1 > w ) w = w1; - w1 = tmp.setNum(minValue() + step()).length(); + w1 = tmp.setNum( minValue() + step() ).length(); if ( w1 > w ) w = w1; - w1 = tmp.setNum(maxValue() - step()).length(); + w1 = tmp.setNum( maxValue() - step() ).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); + const int h = qMin( QWidget::sizeHint().height(), + d_data->valueEdit->minimumSizeHint().height() ); + return QSize( w, h ); } //! returns the step size @@ -558,94 +505,94 @@ double QwtCounter::step() const { return QwtDoubleRange::step(); } - -/*! + +/*! Set the step size \param stepSize Step size \sa QwtDoubleRange::setStep() */ -void QwtCounter::setStep(double stepSize) +void QwtCounter::setStep( double stepSize ) { - QwtDoubleRange::setStep(stepSize); + QwtDoubleRange::setStep( stepSize ); } //! returns the minimum value of the range -double QwtCounter::minVal() const +double QwtCounter::minValue() const { - return minValue(); + return QwtDoubleRange::minValue(); } -/*! +/*! Set the minimum value of the range \param value Minimum value - \sa setMaxValue(), minVal() + \sa setMaxValue(), minValue() */ -void QwtCounter::setMinValue(double value) +void QwtCounter::setMinValue( double value ) { - setRange(value, maxValue(), step()); + setRange( value, maxValue(), step() ); } //! returns the maximum value of the range -double QwtCounter::maxVal() const +double QwtCounter::maxValue() const { return QwtDoubleRange::maxValue(); } -/*! +/*! Set the maximum value of the range \param value Maximum value \sa setMinValue(), maxVal() */ -void QwtCounter::setMaxValue(double value) +void QwtCounter::setMaxValue( double value ) { - setRange(minValue(), value, step()); + setRange( minValue(), value, step() ); } -/*! +/*! Set the number of increment steps for button 1 \param nSteps Number of steps */ -void QwtCounter::setStepButton1(int nSteps) +void QwtCounter::setStepButton1( int nSteps ) { - setIncSteps(Button1, nSteps); + setIncSteps( Button1, nSteps ); } //! returns the number of increment steps for button 1 int QwtCounter::stepButton1() const { - return incSteps(Button1); + return incSteps( Button1 ); } -/*! +/*! Set the number of increment steps for button 2 \param nSteps Number of steps */ -void QwtCounter::setStepButton2(int nSteps) +void QwtCounter::setStepButton2( int nSteps ) { - setIncSteps(Button2, nSteps); + setIncSteps( Button2, nSteps ); } //! returns the number of increment steps for button 2 int QwtCounter::stepButton2() const { - return incSteps(Button2); + return incSteps( Button2 ); } -/*! +/*! Set the number of increment steps for button 3 \param nSteps Number of steps */ -void QwtCounter::setStepButton3(int nSteps) +void QwtCounter::setStepButton3( int nSteps ) { - setIncSteps(Button3, nSteps); + setIncSteps( Button3, nSteps ); } //! returns the number of increment steps for button 3 int QwtCounter::stepButton3() const { - return incSteps(Button3); + return incSteps( Button3 ); } //! \return Current value @@ -653,4 +600,3 @@ double QwtCounter::value() const { return QwtDoubleRange::value(); } - diff --git a/qwt/src/qwt_counter.h b/qwt/src/qwt_counter.h index e92e2fc91..b3f4ad549 100644 --- a/qwt/src/qwt_counter.h +++ b/qwt/src/qwt_counter.h @@ -2,19 +2,17 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_COUNTER_H #define QWT_COUNTER_H -#include #include "qwt_global.h" #include "qwt_double_range.h" +#include /*! \brief The Counter Widget @@ -63,8 +61,8 @@ class QWT_EXPORT QwtCounter : public QWidget, public QwtDoubleRange 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( double minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( double maxValue READ maxValue 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 ) @@ -72,74 +70,79 @@ class QWT_EXPORT QwtCounter : public QWidget, public QwtDoubleRange Q_PROPERTY( bool editable READ editable WRITE setEditable ) public: - /*! - Button index - */ + //! Button index + enum Button + { + //! Button intended for minor steps + Button1, - enum Button - { - Button1, - Button2, - Button3, - ButtonCnt + //! 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 setNumButtons(int n); + void setEditable( bool ); + + void setNumButtons( int n ); int numButtons() const; - - void setIncSteps(QwtCounter::Button btn, int nSteps); - int incSteps(QwtCounter::Button btn) const; - virtual void setValue(double); + void setIncSteps( QwtCounter::Button btn, int nSteps ); + int incSteps( QwtCounter::Button btn ) const; + + virtual void setValue( double ); virtual QSize sizeHint() const; - virtual void polish(); - // a set of dummies to help the designer 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 setStep( double s ); + + double minValue() const; + void setMinValue( double m ); + + double maxValue() const; + void setMaxValue( double m ); + + 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: +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 bool event( QEvent * ); + virtual void wheelEvent( QWheelEvent * ); + virtual void keyPressEvent( QKeyEvent * ); virtual void rangeChange(); -private slots: +private Q_SLOTS: void btnReleased(); void btnClicked(); void textChanged(); @@ -147,9 +150,9 @@ private slots: private: void initCounter(); void updateButtons(); - void showNum(double); + void showNum( double ); virtual void valueChange(); - + class PrivateData; PrivateData *d_data; }; diff --git a/qwt/src/qwt_curve_fitter.cpp b/qwt/src/qwt_curve_fitter.cpp index 0e352cb74..639a80dab 100644 --- a/qwt/src/qwt_curve_fitter.cpp +++ b/qwt/src/qwt_curve_fitter.cpp @@ -2,14 +2,20 @@ * 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_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,8 @@ class QwtSplineCurveFitter::PrivateData { public: PrivateData(): - fitMode(QwtSplineCurveFitter::Auto), - splineSize(250) + fitMode( QwtSplineCurveFitter::Auto ), + splineSize( 250 ) { } @@ -53,7 +59,7 @@ QwtSplineCurveFitter::~QwtSplineCurveFitter() \param mode Mode representing a spline algorithm \sa fitMode() */ -void QwtSplineCurveFitter::setFitMode(FitMode mode) +void QwtSplineCurveFitter::setFitMode( FitMode mode ) { d_data->fitMode = mode; } @@ -67,27 +73,51 @@ 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; } -QwtSpline &QwtSplineCurveFitter::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; @@ -99,14 +129,9 @@ int QwtSplineCurveFitter::splineSize() const \param points Series of data points \return Curve points */ -#if QT_VERSION < 0x040000 -QwtArray QwtSplineCurveFitter::fitCurve( - const QwtArray & points) const -#else -QPolygonF QwtSplineCurveFitter::fitCurve(const QPolygonF &points) const -#endif +QPolygonF QwtSplineCurveFitter::fitCurve( const QPolygonF &points ) const { - const int size = (int)points.size(); + const int size = points.size(); if ( size <= 2 ) return points; @@ -115,7 +140,7 @@ QPolygonF QwtSplineCurveFitter::fitCurve(const QPolygonF &points) const { fitMode = Spline; - const QwtDoublePoint *p = points.data(); + const QPointF *p = points.data(); for ( int i = 1; i < size; i++ ) { if ( p[i].x() <= p[i-1].x() ) @@ -127,114 +152,254 @@ QPolygonF QwtSplineCurveFitter::fitCurve(const QPolygonF &points) const } 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++) + for ( int i = 0; i < d_data->splineSize; i++ ) { - QwtDoublePoint &p = fittedPoints[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()) + const double delta = qSqrt( qwtSqr( x - spX[i-1].y() ) + qwtSqr( y - spY[i-1].y() ) ); - param += qwtMax(delta, 1.0); + 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 ) + { + } + + double tolerance; +}; + +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 accaptable + 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; +} + +/*! + \param points Series of data points + \return Curve points +*/ +QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const +{ + QStack stack; + stack.reserve( 500 ); + + const QPointF *p = points.data(); + const int nPoints = points.size(); + + QVector usePoint( nPoints, false ); + + double distToSegment; + + 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 maxDist = 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(); + const double fromVecLength = + qSqrt( fromVecX * fromVecX + fromVecY * fromVecY ); + + if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) + { + distToSegment = fromVecLength; + } + if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) + { + distToSegment = fromVecLength; + } + else + { + const double toVecX = p[i].x() - p[r.to].x(); + const double toVecY = p[i].y() - p[r.to].y(); + const double toVecLength = qSqrt( toVecX * toVecX + toVecY * toVecY ); + const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY ); + if ( s < 0.0 ) + distToSegment = toVecLength; + else + { + distToSegment = qSqrt( qFabs( toVecLength * toVecLength - s * s ) ); + } + } + + if ( maxDist < distToSegment ) + { + maxDist = distToSegment; + nVertexIndexMaxDistance = i; + } + } + if ( maxDist <= d_data->tolerance ) + { + usePoint[r.from] = true; + usePoint[r.to] = true; + } + else + { + stack.push( Line( r.from, nVertexIndexMaxDistance ) ); + stack.push( Line( nVertexIndexMaxDistance, r.to ) ); + } + } + + int cnt = 0; + + QPolygonF stripped( nPoints ); + for ( int i = 0; i < nPoints; i++ ) + { + if ( usePoint[i] ) + stripped[cnt++] = p[i]; + } + stripped.resize( cnt ); + return stripped; +} diff --git a/qwt/src/qwt_curve_fitter.h b/qwt/src/qwt_curve_fitter.h index e17e3f8c3..c9ae60373 100644 --- a/qwt/src/qwt_curve_fitter.h +++ b/qwt/src/qwt_curve_fitter.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -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,18 +24,13 @@ class QWT_EXPORT QwtCurveFitter public: virtual ~QwtCurveFitter(); -#if QT_VERSION < 0x040000 - virtual QwtArray fitCurve( - const QwtArray&) const = 0; -#else /*! 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; -#endif + virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0; protected: QwtCurveFitter(); @@ -71,44 +46,81 @@ private: class QWT_EXPORT QwtSplineCurveFitter: public QwtCurveFitter { public: + /*! + 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 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; + + virtual QPolygonF fitCurve( const QPolygonF & ) const; + +private: + class Line; + class PrivateData; PrivateData *d_data; }; diff --git a/qwt/src/qwt_data.cpp b/qwt/src/qwt_data.cpp deleted file mode 100644 index caf73d4cc..000000000 --- a/qwt/src/qwt_data.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#include "qwt_math.h" -#include "qwt_data.h" - -//! Constructor -QwtData::QwtData() -{ -} - -//! Destructor -QwtData::~QwtData() -{ -} - -/*! - Returns the bounding rectangle of the data. If there is - no bounding rect, like for empty data the rectangle is invalid: - QwtDoubleRect::isValid() == false - - \warning This is an slow implementation iterating over all points. - It is intended to be overloaded by derived classes. In case of - auto scaling boundingRect() is called for every replot, so it - might be worth to implement a cache, or use x(0), x(size() - 1) - for ordered data ... -*/ -QwtDoubleRect QwtData::boundingRect() const -{ - const size_t sz = size(); - - if ( sz <= 0 ) - return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid - - double minX, maxX, minY, maxY; - minX = maxX = x(0); - minY = maxY = y(0); - - for ( size_t i = 1; i < sz; i++ ) - { - const double xv = x(i); - if ( xv < minX ) - minX = xv; - if ( xv > maxX ) - maxX = xv; - - const double yv = y(i); - if ( yv < minY ) - minY = yv; - if ( yv > maxY ) - maxY = yv; - } - return QwtDoubleRect(minX, minY, maxX - minX, maxY - minY); -} - -/*! - Constructor - - \param polygon Polygon data - \sa QwtPlotCurve::setData() -*/ -#if QT_VERSION >= 0x040000 -QwtPolygonFData::QwtPolygonFData(const QPolygonF &polygon): -#else -QwtPolygonFData::QwtPolygonFData(const QwtArray &polygon): -#endif - d_data(polygon) -{ -} - -//! Assignment -QwtPolygonFData& QwtPolygonFData::operator=( - const QwtPolygonFData &data) -{ - if (this != &data) - { - d_data = data.d_data; - } - return *this; -} - -//! \return Size of the data set -size_t QwtPolygonFData::size() const -{ - return d_data.size(); -} - -/*! - Return the x value of data point i - - \param i Index - \return x X value of data point i -*/ -double QwtPolygonFData::x(size_t i) const -{ - return d_data[int(i)].x(); -} - -/*! - Return the y value of data point i - - \param i Index - \return y Y value of data point i -*/ -double QwtPolygonFData::y(size_t i) const -{ - return d_data[int(i)].y(); -} - -//! \return Point array -#if QT_VERSION >= 0x040000 -const QPolygonF &QwtPolygonFData::data() const -#else -const QwtArray &QwtPolygonFData::data() const -#endif -{ - return d_data; -} - -/*! - \return Pointer to a copy (virtual copy constructor) -*/ -QwtData *QwtPolygonFData::copy() const -{ - return new QwtPolygonFData(d_data); -} - -/*! - Constructor - - \param x Array of x values - \param y Array of y values - - \sa QwtPlotCurve::setData() -*/ -QwtArrayData::QwtArrayData( - const QwtArray &x, const QwtArray &y): - d_x(x), - d_y(y) -{ -} - -/*! - Constructor - - \param x Array of x values - \param y Array of y values - \param size Size of the x and y arrays - \sa QwtPlotCurve::setData() -*/ -QwtArrayData::QwtArrayData(const double *x, const double *y, size_t size) -{ -#if QT_VERSION >= 0x040000 - d_x.resize(size); - qMemCopy(d_x.data(), x, size * sizeof(double)); - - d_y.resize(size); - qMemCopy(d_y.data(), y, size * sizeof(double)); -#else - d_x.detach(); - d_x.duplicate(x, size); - - d_y.detach(); - d_y.duplicate(y, size); -#endif -} - -//! Assignment -QwtArrayData& QwtArrayData::operator=(const QwtArrayData &data) -{ - if (this != &data) - { - d_x = data.d_x; - d_y = data.d_y; - } - return *this; -} - -//! \return Size of the data set -size_t QwtArrayData::size() const -{ - return qwtMin(d_x.size(), d_y.size()); -} - -/*! - Return the x value of data point i - - \param i Index - \return x X value of data point i -*/ -double QwtArrayData::x(size_t i) const -{ - return d_x[int(i)]; -} - -/*! - Return the y value of data point i - - \param i Index - \return y Y value of data point i -*/ -double QwtArrayData::y(size_t i) const -{ - return d_y[int(i)]; -} - -//! \return Array of the x-values -const QwtArray &QwtArrayData::xData() const -{ - return d_x; -} - -//! \return Array of the y-values -const QwtArray &QwtArrayData::yData() const -{ - return d_y; -} - -/*! - \return Pointer to a copy (virtual copy constructor) -*/ -QwtData *QwtArrayData::copy() const -{ - return new QwtArrayData(d_x, d_y); -} - -/*! - Returns the bounding rectangle of the data. If there is - no bounding rect, like for empty data the rectangle is invalid: - QwtDoubleRect::isValid() == false -*/ -QwtDoubleRect QwtArrayData::boundingRect() const -{ - const size_t sz = size(); - - if ( sz <= 0 ) - return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid - - double minX, maxX, minY, maxY; - QwtArray::ConstIterator xIt = d_x.begin(); - QwtArray::ConstIterator yIt = d_y.begin(); - QwtArray::ConstIterator end = d_x.begin() + sz; - minX = maxX = *xIt++; - minY = maxY = *yIt++; - - while ( xIt < end ) - { - const double xv = *xIt++; - if ( xv < minX ) - minX = xv; - if ( xv > maxX ) - maxX = xv; - - const double yv = *yIt++; - if ( yv < minY ) - minY = yv; - if ( yv > maxY ) - maxY = yv; - } - return QwtDoubleRect(minX, minY, maxX - minX, maxY - minY); -} - -/*! - Constructor - - \param x Array of x values - \param y Array of y values - \param size Size of the x and y arrays - - \warning The programmer must assure that the memory blocks referenced - by the pointers remain valid during the lifetime of the - QwtPlotCPointer object. - - \sa QwtPlotCurve::setData(), QwtPlotCurve::setRawData() -*/ -QwtCPointerData::QwtCPointerData( - const double *x, const double *y, size_t size): - d_x(x), - d_y(y), - d_size(size) -{ -} - -//! Assignment -QwtCPointerData& QwtCPointerData::operator=(const QwtCPointerData &data) -{ - if (this != &data) - { - d_x = data.d_x; - d_y = data.d_y; - d_size = data.d_size; - } - return *this; -} - -//! \return Size of the data set -size_t QwtCPointerData::size() const -{ - return d_size; -} - -/*! - Return the x value of data point i - - \param i Index - \return x X value of data point i -*/ -double QwtCPointerData::x(size_t i) const -{ - return d_x[int(i)]; -} - -/*! - Return the y value of data point i - - \param i Index - \return y Y value of data point i -*/ -double QwtCPointerData::y(size_t i) const -{ - return d_y[int(i)]; -} - -//! \return Array of the x-values -const double *QwtCPointerData::xData() const -{ - return d_x; -} - -//! \return Array of the y-values -const double *QwtCPointerData::yData() const -{ - return d_y; -} - -/*! - \return Pointer to a copy (virtual copy constructor) -*/ -QwtData *QwtCPointerData::copy() const -{ - return new QwtCPointerData(d_x, d_y, d_size); -} - -/*! - Returns the bounding rectangle of the data. If there is - no bounding rect, like for empty data the rectangle is invalid: - QwtDoubleRect::isValid() == false -*/ -QwtDoubleRect QwtCPointerData::boundingRect() const -{ - const size_t sz = size(); - - if ( sz <= 0 ) - return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid - - double minX, maxX, minY, maxY; - const double *xIt = d_x; - const double *yIt = d_y; - const double *end = d_x + sz; - minX = maxX = *xIt++; - minY = maxY = *yIt++; - - while ( xIt < end ) - { - const double xv = *xIt++; - if ( xv < minX ) - minX = xv; - if ( xv > maxX ) - maxX = xv; - - const double yv = *yIt++; - if ( yv < minY ) - minY = yv; - if ( yv > maxY ) - maxY = yv; - } - return QwtDoubleRect(minX, minY, maxX - minX, maxY - minY); -} diff --git a/qwt/src/qwt_data.h b/qwt/src/qwt_data.h deleted file mode 100644 index 03b90bf70..000000000 --- a/qwt/src/qwt_data.h +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -// vim: expandtab - -#ifndef QWT_DATA_H -#define QWT_DATA_H 1 - -#include "qwt_global.h" -#include "qwt_array.h" -#include "qwt_double_rect.h" -#if QT_VERSION >= 0x040000 -#include -#endif - -// MOC_SKIP_BEGIN - -#if defined(QWT_TEMPLATEDLL) - -template class QWT_EXPORT QwtArray; - -#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 QwtData defines an interface to any type of curve data. - - Classes, derived from QwtData may: - - store the data in almost any type of container - - calculate the data on the fly instead of storing it - */ - -class QWT_EXPORT QwtData -{ -public: - QwtData(); - virtual ~QwtData(); - - //! \return Pointer to a copy (virtual copy constructor) - virtual QwtData *copy() const = 0; - - //! \return Size of the data set - virtual size_t size() const = 0; - - /*! - Return the x value of data point i - \param i Index - \return x X value of data point i - */ - virtual double x(size_t i) const = 0; - /*! - Return the y value of data point i - \param i Index - \return y Y value of data point i - */ - virtual double y(size_t i) const = 0; - - virtual QwtDoubleRect boundingRect() const; - -protected: - /*! - Assignment operator (virtualized) - */ - QwtData &operator=(const QwtData &); -}; - - -/*! - \brief Data class containing a single QwtArray object. - */ -class QWT_EXPORT QwtPolygonFData: public QwtData -{ -public: -#if QT_VERSION < 0x040000 - QwtPolygonFData(const QwtArray &); -#else - QwtPolygonFData(const QPolygonF &); -#endif - - QwtPolygonFData &operator=(const QwtPolygonFData &); - virtual QwtData *copy() const; - - virtual size_t size() const; - virtual double x(size_t i) const; - virtual double y(size_t i) const; - -#if QT_VERSION < 0x040000 - const QwtArray &data() const; -#else - const QPolygonF &data() const; -#endif - -private: -#if QT_VERSION < 0x040000 - QwtArray d_data; -#else - QPolygonF d_data; -#endif -}; - -/*! - \brief Data class containing two QwtArray objects. - */ - -class QWT_EXPORT QwtArrayData: public QwtData -{ -public: - QwtArrayData(const QwtArray &x, const QwtArray &y); - QwtArrayData(const double *x, const double *y, size_t size); - QwtArrayData &operator=(const QwtArrayData &); - virtual QwtData *copy() const; - - virtual size_t size() const; - virtual double x(size_t i) const; - virtual double y(size_t i) const; - - const QwtArray &xData() const; - const QwtArray &yData() const; - - virtual QwtDoubleRect boundingRect() const; - -private: - QwtArray d_x; - QwtArray d_y; -}; - -/*! - \brief Data class containing two pointers to memory blocks of doubles. - */ -class QWT_EXPORT QwtCPointerData: public QwtData -{ -public: - QwtCPointerData(const double *x, const double *y, size_t size); - QwtCPointerData &operator=(const QwtCPointerData &); - virtual QwtData *copy() const; - - virtual size_t size() const; - virtual double x(size_t i) const; - virtual double y(size_t i) const; - - const double *xData() const; - const double *yData() const; - - virtual QwtDoubleRect boundingRect() const; - -private: - const double *d_x; - const double *d_y; - size_t d_size; -}; - -#endif // !QWT_DATA diff --git a/qwt/src/qwt_dial.cpp b/qwt/src/qwt_dial.cpp index c79e82712..3b13f7c83 100644 --- a/qwt/src/qwt_dial.cpp +++ b/qwt/src/qwt_dial.cpp @@ -7,39 +7,43 @@ * 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_painter.h" -#include "qwt_dial_needle.h" -#include "qwt_dial.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if QT_VERSION < 0x040601 +#define qAtan(x) ::atan(x) +#endif class QwtDial::PrivateData { public: PrivateData(): - visibleBackground(true), - frameShadow(Sunken), - lineWidth(0), - mode(RotateNeedle), - direction(Clockwise), - 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 ), + direction( Clockwise ), + origin( 90.0 ), + minScaleArc( 0.0 ), + maxScaleArc( 0.0 ), + scaleDraw( 0 ), + maxMajIntv( 36 ), + maxMinIntv( 10 ), + scaleStep( 0.0 ), + needle( 0 ) { } @@ -48,7 +52,6 @@ public: delete scaleDraw; delete needle; } - bool visibleBackground; Shadow frameShadow; int lineWidth; @@ -76,9 +79,9 @@ double QwtDial::PrivateData::previousDir = -1.0; \param parent Parent dial widget */ -QwtDialScaleDraw::QwtDialScaleDraw(QwtDial *parent): - d_parent(parent), - d_penWidth(1) +QwtDialScaleDraw::QwtDialScaleDraw( QwtDial *parent ): + d_parent( parent ), + d_penWidth( 1.0 ) { } @@ -88,148 +91,89 @@ QwtDialScaleDraw::QwtDialScaleDraw(QwtDial *parent): \param penWidth Pen width \sa penWidth(), QwtDial::drawScale() */ - -void QwtDialScaleDraw::setPenWidth(uint penWidth) + +void QwtDialScaleDraw::setPenWidth( double penWidth ) { - d_penWidth = penWidth; + d_penWidth = qMax( penWidth, 0.0 ); } /*! \return Pen width used for painting the scale \sa setPenWidth, QwtDial::drawScale() */ -uint QwtDialScaleDraw::penWidth() const +double 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 +*/ +QwtText QwtDialScaleDraw::label( double value ) const { if ( d_parent == NULL ) - return QwtRoundScaleDraw::label(value); + return QwtRoundScaleDraw::label( value ); - return d_parent->scaleLabel(value); + return d_parent->scaleLabel( value ); } /*! \brief Constructor \param parent Parent widget - Create a dial widget with no scale and no needle. + 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. -*/ - -QwtDial::QwtDial(QWidget* parent): - QwtAbstractSlider(Qt::Horizontal, parent) +*/ +QwtDial::QwtDial( QWidget* parent ): + QwtAbstractSlider( Qt::Horizontal, parent ) { initDial(); } -#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. -*/ -QwtDial::QwtDial(QWidget* parent, const char *name): - QwtAbstractSlider(Qt::Horizontal, parent) -{ - setName(name); - initDial(); -} -#endif - void QwtDial::initDial() { 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; + const QPalette::ColorGroup cg = ( QPalette::ColorGroup )i; // Base: background color of the circle inside the frame. - // Foreground: background color of the circle inside the scale + // WindowText: 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 + p.setColor( cg, QPalette::WindowText, + p.color( cg, QPalette::Base ) ); } - setPalette(p); + setPalette( p ); - d_data->scaleDraw = new QwtDialScaleDraw(this); - d_data->scaleDraw->setRadius(0); + d_data->scaleDraw = new QwtDialScaleDraw( this ); + d_data->scaleDraw->setRadius( 0 ); - setScaleArc(0.0, 360.0); // scale as a full circle - setRange(0.0, 360.0, 1.0, 10); // degrees as deafult + setScaleArc( 0.0, 360.0 ); // scale as a full circle + setRange( 0.0, 360.0, 1.0, 10 ); // degrees as deafult } //! Destructor -QwtDial::~QwtDial() +QwtDial::~QwtDial() { delete d_data; } -/*! - Show/Hide the area outside of the frame - \param show Show if true, hide if false - - \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(); - } -} - -/*! - true when the area outside of the frame is visible - - \sa showBackground(), setMask() -*/ -bool QwtDial::hasVisibleBackground() const -{ - return d_data->visibleBackground; -} - /*! 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 ) { @@ -243,9 +187,9 @@ void QwtDial::setFrameShadow(Shadow shadow) \return Frame shadow /sa setFrameShadow(), lineWidth(), QFrame::frameShadow */ -QwtDial::Shadow QwtDial::frameShadow() const -{ - return d_data->frameShadow; +QwtDial::Shadow QwtDial::frameShadow() const +{ + return d_data->frameShadow; } /*! @@ -254,7 +198,7 @@ QwtDial::Shadow QwtDial::frameShadow() const \param lineWidth Line width \sa setFrameShadow() */ -void QwtDial::setLineWidth(int lineWidth) +void QwtDial::setLineWidth( int lineWidth ) { if ( lineWidth < 0 ) lineWidth = 0; @@ -270,99 +214,90 @@ void QwtDial::setLineWidth(int lineWidth) \return Line width of the frame \sa setLineWidth(), frameShadow(), lineWidth() */ -int QwtDial::lineWidth() const -{ - return d_data->lineWidth; +int QwtDial::lineWidth() const +{ + return d_data->lineWidth; } /*! \return bounding rect of the circle inside the frame - \sa setLineWidth(), scaleContentsRect(), boundingRect() + \sa setLineWidth(), scaleInnerRect(), boundingRect() */ -QRect QwtDial::contentsRect() const +QRectF 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; + const double lw = lineWidth(); + return boundingRect().adjusted( lw, lw, -lw, -lw ); } /*! \return bounding rect of the dial including the frame - \sa setLineWidth(), scaleContentsRect(), contentsRect() + \sa setLineWidth(), scaleInnerRect(), innerRect() */ -QRect QwtDial::boundingRect() const +QRectF QwtDial::boundingRect() const { - const int radius = qwtMin(width(), height()) / 2; + const QRectF cr = contentsRect(); - QRect r(0, 0, 2 * radius, 2 * radius); - r.moveCenter(rect().center()); - return r; + const double dim = qMin( cr.width(), cr.height() ); + + QRectF inner( 0, 0, dim, dim ); + inner.moveCenter( cr.center() ); + + return inner; } /*! \return rect inside the scale - \sa setLineWidth(), boundingRect(), contentsRect() + \sa setLineWidth(), boundingRect(), innerRect() */ -QRect QwtDial::scaleContentsRect() const +QRectF 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 + QRectF rect = innerRect(); - int scaleDist = 0; if ( d_data->scaleDraw ) { - scaleDist = d_data->scaleDraw->extent(scalePen, font()); + double scaleDist = qCeil( d_data->scaleDraw->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. - \param mode New mode - + \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 QwtDial::RotateScale, the needle points to origin() and the scale is rotating. - + The default mode is QwtDial::RotateNeedle. \sa mode(), setValue(), setOrigin() -*/ -void QwtDial::setMode(Mode mode) -{ +*/ +void QwtDial::setMode( Mode mode ) +{ if ( mode != d_data->mode ) { d_data->mode = mode; - update(); + update(); } -} +} -/*! +/*! \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. \sa setMode(), origin(), setScaleArc(), value() @@ -372,29 +307,29 @@ QwtDial::Mode QwtDial::mode() const return d_data->mode; } -/*! - Sets whether it is possible to step the value from the highest value to +/*! + 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. + but not like it is used in QDial. */ -void QwtDial::setWrapping(bool wrapping) +void QwtDial::setWrapping( bool wrapping ) { - setPeriodic(wrapping); -} + setPeriodic( wrapping ); +} -/*! - wrapping() holds whether it is possible to step the value from the - highest value to the lowest value and vice versa. +/*! + 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. -*/ + but not like it is used in QDial. +*/ bool QwtDial::wrapping() const { return periodic(); @@ -403,10 +338,10 @@ bool QwtDial::wrapping() const /*! Set the direction of the dial (clockwise/counterclockwise) - Direction direction + \param direction Direction \sa direction() */ -void QwtDial::setDirection(Direction direction) +void QwtDial::setDirection( Direction direction ) { if ( direction != d_data->direction ) { @@ -427,46 +362,31 @@ QwtDial::Direction QwtDial::direction() const return d_data->direction; } -/*! - Resize the dial widget - \param e Resize event +/*! + Paint the dial + \param event Paint event */ -void QwtDial::resizeEvent(QResizeEvent *e) +void QwtDial::paintEvent( QPaintEvent *event ) { - QWidget::resizeEvent(e); + QPainter painter( this ); + painter.setClipRegion( event->region() ); - if ( !hasVisibleBackground() ) - updateMask(); -} + QStyleOption opt; + opt.init(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); -/*! - 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 + painter.setRenderHint( QPainter::Antialiasing, true ); - painter.save(); - drawContents(&painter); - painter.restore(); + painter.save(); + drawContents( &painter ); + painter.restore(); - painter.save(); - drawFrame(&painter); - painter.restore(); + painter.save(); + drawFrame( &painter ); + painter.restore(); - if ( hasFocus() ) - drawFocusIndicator(&painter); - } + if ( hasFocus() ) + drawFocusIndicator( &painter ); } /*! @@ -474,43 +394,31 @@ void QwtDial::paintEvent(QPaintEvent *e) \param painter Painter */ -void QwtDial::drawFocusIndicator(QPainter *painter) const +void QwtDial::drawFocusIndicator( QPainter *painter ) const { if ( !isReadOnly() ) { - QRect focusRect = contentsRect(); + QRectF focusRect = innerRect(); const int margin = 2; - focusRect.setRect( - focusRect.x() + margin, - focusRect.y() + margin, - focusRect.width() - 2 * margin, - focusRect.height() - 2 * margin); + focusRect.adjust( margin, margin, -margin, -margin ); -#if QT_VERSION < 0x040000 - QColor color = colorGroup().color(QColorGroup::Base); -#else - QColor color = palette().color(QPalette::Base); -#endif - if (color.isValid()) + QColor color = palette().color( QPalette::Base ); + if ( color.isValid() ) { - const QColor gray(Qt::gray); + 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); + color.getHsv( &h, &s, &v ); + 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->setBrush( Qt::NoBrush ); + painter->setPen( QPen( color, 0, Qt::DotLine ) ); + painter->drawEllipse( focusRect ); painter->restore(); } } @@ -521,140 +429,111 @@ 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; + if ( lineWidth() <= 0 ) + return; - 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 - r.setX(r.x() + 1); - r.setY(r.y() + 1); - r.setWidth(r.width() - 2); - r.setHeight(r.height() - 2); -#endif + const double lw2 = 0.5 * lineWidth(); - if ( lw > 0 ) + QRectF r = boundingRect(); + r.adjust( lw2, lw2, -lw2, -lw2 ); + + QPen pen; + + switch ( d_data->frameShadow ) { - switch(d_data->frameShadow) + case QwtDial::Raised: + case QwtDial::Sunken: { - case QwtDial::Raised: -#if QT_VERSION < 0x040000 - QwtPainter::drawRoundFrame(painter, r, - lw, colorGroup(), false); -#else - QwtPainter::drawRoundFrame(painter, r, - lw, palette(), false); + QColor c1 = palette().color( QPalette::Light ); + QColor c2 = palette().color( QPalette::Dark ); + + if ( d_data->frameShadow == QwtDial::Sunken ) + qSwap( c1, c2 ); + + QLinearGradient gradient( r.topLeft(), r.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); +#if 0 + gradient.setColorAt( 0.3, c1 ); + gradient.setColorAt( 0.7, c2 ); #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(); - } + gradient.setColorAt( 1.0, c2 ); + + pen = QPen( gradient, lineWidth() ); + break; + } + default: // Plain + { + pen = QPen( palette().brush( QPalette::Dark ), lineWidth() ); } } + + painter->save(); + + painter->setPen( pen ); + painter->setBrush( Qt::NoBrush ); + painter->drawEllipse( r ); + + painter->restore(); } /*! \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; - - painter->save(); - drawScaleContents(painter, center, radius); - painter->restore(); + const QPointF center = insideScaleRect.center(); + const double radius = 0.5 * insideScaleRect.width(); double direction = d_data->origin; - if (isValid()) + if ( isValid() ) { direction = d_data->minScaleArc; - if ( maxValue() > minValue() && d_data->maxScaleArc > 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); + const double ratio = + ( value() - minValue() ) / ( maxValue() - minValue() ); + direction += ratio * ( d_data->maxScaleArc - d_data->minScaleArc ); } if ( d_data->direction == QwtDial::CounterClockwise ) - direction = d_data->maxScaleArc - (direction - d_data->minScaleArc); + direction = d_data->maxScaleArc - ( direction - d_data->minScaleArc ); direction += d_data->origin; if ( direction >= 360.0 ) @@ -671,8 +550,12 @@ void QwtDial::drawContents(QPainter *painter) const } painter->save(); - drawScale(painter, center, radius, origin, - d_data->minScaleArc, d_data->maxScaleArc); + drawScale( painter, center, radius, origin, + d_data->minScaleArc, d_data->maxScaleArc ); + painter->restore(); + + painter->save(); + drawScaleContents( painter, center, radius ); painter->restore(); if ( isValid() ) @@ -684,7 +567,7 @@ void QwtDial::drawContents(QPainter *painter) const cg = QPalette::Disabled; painter->save(); - drawNeedle(painter, center, radius, direction, cg); + drawNeedle( painter, center, radius, direction, cg ); painter->restore(); } } @@ -698,13 +581,13 @@ void QwtDial::drawContents(QPainter *painter) const \param direction Direction of the needle in degrees, counter clockwise \param cg 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 cg ) const { 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, cg ); } } @@ -715,13 +598,13 @@ void QwtDial::drawNeedle(QPainter *painter, const QPoint ¢er, \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() + \param minArc Minimum of the arc + \param maxArc Minimum of the arc + + \sa QwtRoundScaleDraw::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, double origin, double minArc, double maxArc ) const { if ( d_data->scaleDraw == NULL ) return; @@ -730,67 +613,70 @@ void QwtDial::drawScale(QPainter *painter, const QPoint ¢er, double angle = maxArc - minArc; if ( angle > 360.0 ) - angle = ::fmod(angle, 360.0); + angle = ::fmod( angle, 360.0 ); minArc += origin; if ( minArc < -360.0 ) - minArc = ::fmod(minArc, 360.0); - + minArc = ::fmod( minArc, 360.0 ); + maxArc = minArc + angle; if ( maxArc > 360.0 ) { - // QwtAbstractScaleDraw::setAngleRange accepts only values + // QwtRoundScaleDraw::setAngleRange accepts only values // in the range [-360.0..360.0] minArc -= 360.0; maxArc -= 360.0; } if ( d_data->direction == QwtDial::CounterClockwise ) - qSwap(minArc, maxArc); - - painter->setFont(font()); + qSwap( minArc, maxArc ); - d_data->scaleDraw->setAngleRange(minArc, maxArc); - d_data->scaleDraw->setRadius(radius); - d_data->scaleDraw->moveCenter(center); + painter->setFont( font() ); -#if QT_VERSION < 0x040000 - QColorGroup cg = colorGroup(); + d_data->scaleDraw->setAngleRange( minArc, maxArc ); + d_data->scaleDraw->setRadius( radius ); + d_data->scaleDraw->moveCenter( center ); - const QColor textColor = cg.color(QColorGroup::Text); - cg.setColor(QColorGroup::Foreground, textColor); - painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth())); - - d_data->scaleDraw->draw(painter, cg); -#else QPalette pal = palette(); - const QColor textColor = pal.color(QPalette::Text); - pal.setColor(QPalette::Foreground, textColor); //ticks, backbone - - painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth())); + const QColor textColor = pal.color( QPalette::Text ); + pal.setColor( QPalette::WindowText, textColor ); //ticks, backbone - d_data->scaleDraw->draw(painter, pal); -#endif + painter->setPen( QPen( textColor, d_data->scaleDraw->penWidth() ) ); + + painter->setBrush( Qt::red ); + d_data->scaleDraw->draw( painter, pal ); } -void QwtDial::drawScaleContents(QPainter *, - const QPoint &, int) const +/*! + Draw the contents inside the scale + + Paints nothing. + + \param painter Painter + \param center Center of the contents circle + \param radius Radius of the contents circle +*/ + +void QwtDial::drawScaleContents( QPainter *painter, + const QPointF ¢er, double radius ) const { - // empty default implementation + Q_UNUSED(painter); + Q_UNUSED(center); + Q_UNUSED(radius); } /*! Set a needle for the dial - Qwt is missing a set of good looking needles. + Qwt is missing a set of good looking needles. Contributions are very welcome. \param needle Needle \warning The needle will be deleted, when a different needle is set or in ~QwtDial() */ -void QwtDial::setNeedle(QwtDialNeedle *needle) +void QwtDial::setNeedle( QwtDialNeedle *needle ) { if ( needle != d_data->needle ) { @@ -802,22 +688,22 @@ void QwtDial::setNeedle(QwtDialNeedle *needle) } } -/*! +/*! \return needle \sa setNeedle() */ -const QwtDialNeedle *QwtDial::needle() const -{ - return d_data->needle; +const QwtDialNeedle *QwtDial::needle() const +{ + return d_data->needle; } -/*! +/*! \return needle \sa setNeedle() */ -QwtDialNeedle *QwtDial::needle() -{ - return d_data->needle; +QwtDialNeedle *QwtDial::needle() +{ + return d_data->needle; } //! QwtDoubleRange update hook @@ -826,7 +712,7 @@ void QwtDial::rangeChange() updateScale(); } -/*! +/*! Update the scale with the current attributes \sa setScale() */ @@ -837,24 +723,24 @@ void QwtDial::updateScale() QwtLinearScaleEngine scaleEngine; const QwtScaleDiv scaleDiv = scaleEngine.divideScale( - minValue(), maxValue(), - d_data->maxMajIntv, d_data->maxMinIntv, d_data->scaleStep); + minValue(), maxValue(), + d_data->maxMajIntv, d_data->maxMinIntv, d_data->scaleStep ); - d_data->scaleDraw->setTransformation(scaleEngine.transformation()); - d_data->scaleDraw->setScaleDiv(scaleDiv); + d_data->scaleDraw->setTransformation( scaleEngine.transformation() ); + d_data->scaleDraw->setScaleDiv( scaleDiv ); } } //! Return the scale draw -QwtDialScaleDraw *QwtDial::scaleDraw() -{ - return d_data->scaleDraw; +QwtDialScaleDraw *QwtDial::scaleDraw() +{ + return d_data->scaleDraw; } //! Return the scale draw -const QwtDialScaleDraw *QwtDial::scaleDraw() const -{ - return d_data->scaleDraw; +const QwtDialScaleDraw *QwtDial::scaleDraw() const +{ + return d_data->scaleDraw; } /*! @@ -863,13 +749,13 @@ const QwtDialScaleDraw *QwtDial::scaleDraw() const \param scaleDraw Scale draw \warning The previous scale draw is deleted */ -void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw) +void QwtDial::setScaleDraw( QwtDialScaleDraw *scaleDraw ) { if ( scaleDraw != d_data->scaleDraw ) { if ( d_data->scaleDraw ) delete d_data->scaleDraw; - + d_data->scaleDraw = scaleDraw; updateScale(); update(); @@ -878,9 +764,14 @@ void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw) /*! Change the intervals of the scale - \sa QwtAbstractScaleDraw::setScale() + + \param maxMajIntv Maximum for the number of major steps + \param maxMinIntv Maximum number of minor steps + \param step Step size + + \sa QwtScaleEngine::divideScale() */ -void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step) +void QwtDial::setScale( int maxMajIntv, int maxMinIntv, double step ) { d_data->maxMajIntv = maxMajIntv; d_data->maxMinIntv = maxMinIntv; @@ -890,39 +781,32 @@ void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step) } /*! - A wrapper method for accessing the scale draw. + A wrapper method for accessing the scale draw. - - options == 0\n - No visible scale: setScaleDraw(NULL) - - options & ScaleBackbone\n - En/disable the backbone of the scale. - - options & ScaleTicks\n - En/disable the ticks of the scale. - - options & ScaleLabel\n - En/disable scale labels - + \param components Scale components \sa QwtAbstractScaleDraw::enableComponent() */ -void QwtDial::setScaleOptions(int options) +void QwtDial::setScaleComponents( + QwtAbstractScaleDraw::ScaleComponents components ) { - if ( options == 0 ) - setScaleDraw(NULL); + if ( components == 0 ) + setScaleDraw( NULL ); QwtDialScaleDraw *sd = d_data->scaleDraw; if ( sd == NULL ) return; - sd->enableComponent(QwtAbstractScaleDraw::Backbone, - options & ScaleBackbone); + sd->enableComponent( QwtAbstractScaleDraw::Backbone, + components & QwtAbstractScaleDraw::Backbone ); - sd->enableComponent(QwtAbstractScaleDraw::Ticks, - options & ScaleTicks); - - sd->enableComponent(QwtAbstractScaleDraw::Labels, - options & ScaleLabel); + sd->enableComponent( QwtAbstractScaleDraw::Ticks, + components & QwtAbstractScaleDraw::Ticks ); + + sd->enableComponent( QwtAbstractScaleDraw::Labels, + components & QwtAbstractScaleDraw::Labels ); } -/*! +/*! Assign length and width of the ticks \param minLen Length of the minor ticks @@ -932,16 +816,16 @@ void QwtDial::setScaleOptions(int options) \sa QwtAbstractScaleDraw::setTickLength(), QwtDialScaleDraw::setPenWidth() */ -void QwtDial::setScaleTicks(int minLen, int medLen, - int majLen, int penWidth) +void QwtDial::setScaleTicks( int minLen, int medLen, + int majLen, int penWidth ) { QwtDialScaleDraw *sd = d_data->scaleDraw; if ( sd ) { - sd->setTickLength(QwtScaleDiv::MinorTick, minLen); - sd->setTickLength(QwtScaleDiv::MediumTick, medLen); - sd->setTickLength(QwtScaleDiv::MajorTick, majLen); - sd->setPenWidth(penWidth); + sd->setTickLength( QwtScaleDiv::MinorTick, minLen ); + sd->setTickLength( QwtScaleDiv::MediumTick, medLen ); + sd->setTickLength( QwtScaleDiv::MajorTick, majLen ); + sd->setPenWidth( penWidth ); } } @@ -949,39 +833,39 @@ void QwtDial::setScaleTicks(int minLen, int medLen, Find the label for a value \param value Value - \return label + \return label */ -QwtText QwtDial::scaleLabel(double value) const +QwtText QwtDial::scaleLabel( double value ) const { #if 1 if ( value == -0 ) value = 0; #endif - return QString::number(value); + return QString::number( value ); } //! \return Lower limit of the scale arc -double QwtDial::minScaleArc() const -{ - return d_data->minScaleArc; +double QwtDial::minScaleArc() const +{ + return d_data->minScaleArc; } //! \return Upper limit of the scale arc -double QwtDial::maxScaleArc() const -{ - return d_data->maxScaleArc; +double QwtDial::maxScaleArc() const +{ + return d_data->maxScaleArc; } /*! - \brief Change the origin - + \brief Change the origin + The origin is the angle where scale and needle is relative to. \param origin New origin \sa origin() */ -void QwtDial::setOrigin(double origin) +void QwtDial::setOrigin( double origin ) { d_data->origin = origin; update(); @@ -1004,18 +888,18 @@ double QwtDial::origin() const \param minArc Lower limit \param maxArc Upper limit */ -void QwtDial::setScaleArc(double minArc, double maxArc) +void QwtDial::setScaleArc( double minArc, double maxArc ) { if ( minArc != 360.0 && minArc != -360.0 ) - minArc = fmod(minArc, 360.0); + minArc = ::fmod( minArc, 360.0 ); if ( maxArc != 360.0 && maxArc != -360.0 ) - maxArc = fmod(maxArc, 360.0); + maxArc = ::fmod( maxArc, 360.0 ); - d_data->minScaleArc = qwtMin(minArc, maxArc); - d_data->maxScaleArc = qwtMax(minArc, maxArc); + d_data->minScaleArc = qMin( minArc, maxArc ); + d_data->maxScaleArc = qMax( minArc, maxArc ); if ( d_data->maxScaleArc - d_data->minScaleArc > 360.0 ) d_data->maxScaleArc = d_data->minScaleArc + 360.0; - + update(); } @@ -1033,40 +917,44 @@ QSize QwtDial::sizeHint() const { int sh = 0; if ( d_data->scaleDraw ) - sh = d_data->scaleDraw->extent( QPen(), font() ); + sh = qCeil( d_data->scaleDraw->extent( font() ) ); const int d = 6 * sh + 2 * lineWidth(); - - return QSize( d, d ); + + QSize hint( d, d ); + if ( !isReadOnly() ) + hint = hint.expandedTo( QApplication::globalStrut() ); + + return hint; } -/*! +/*! \brief Return a minimum size hint \warning The return value of QwtDial::minimumSizeHint() depends on the font and the scale. -*/ +*/ QSize QwtDial::minimumSizeHint() const -{ +{ int sh = 0; if ( d_data->scaleDraw ) - sh = d_data->scaleDraw->extent(QPen(), font() ); + sh = qCeil( d_data->scaleDraw->extent( font() ) ); const int d = 3 * sh + 2 * lineWidth(); - + return QSize( d, d ); } -static double line2Radians(const QPoint &p1, const QPoint &p2) +static double line2Radians( const QPointF &p1, const QPointF &p2 ) { - const QPoint p = p2 - p1; + const QPointF p = p2 - p1; double angle; if ( p.x() == 0 ) - angle = ( p.y() <= 0 ) ? M_PI_2 : 3 * M_PI_2; + angle = ( p.y() <= 0.0 ) ? M_PI_2 : 3 * M_PI_2; else { - angle = atan(double(-p.y()) / double(p.x())); - if ( p.x() < 0 ) + angle = qAtan( double( -p.y() ) / double( p.x() ) ); + if ( p.x() < 0.0 ) angle += M_PI; if ( angle < 0.0 ) angle += 2 * M_PI; @@ -1080,12 +968,12 @@ static double line2Radians(const QPoint &p1, const QPoint &p2) \param pos Position \return Value */ -double QwtDial::getValue(const QPoint &pos) +double QwtDial::getValue( const QPoint &pos ) { if ( d_data->maxScaleArc == d_data->minScaleArc || maxValue() == minValue() ) return minValue(); - double dir = line2Radians(rect().center(), pos) - d_data->origin; + double dir = line2Radians( innerRect().center(), pos ) - d_data->origin; if ( dir < 0.0 ) dir += 360.0; @@ -1095,8 +983,8 @@ double QwtDial::getValue(const QPoint &pos) // The position might be in the area that is outside the scale arc. // We need the range of the scale if it was a complete circle. - const double completeCircle = 360.0 / (d_data->maxScaleArc - d_data->minScaleArc) - * (maxValue() - minValue()); + const double completeCircle = 360.0 / ( d_data->maxScaleArc - d_data->minScaleArc ) + * ( maxValue() - minValue() ); double posValue = minValue() + completeCircle * dir / 360.0; @@ -1110,7 +998,7 @@ double QwtDial::getValue(const QPoint &pos) bool clockWise = false; const double angle = dir - d_data->previousDir; - if ( (angle >= 0.0 && angle <= 180.0) || angle < -180.0 ) + if ( ( angle >= 0.0 && angle <= 180.0 ) || angle < -180.0 ) clockWise = true; if ( clockWise ) @@ -1118,7 +1006,7 @@ double QwtDial::getValue(const QPoint &pos) if ( dir < d_data->previousDir && mouseOffset() > 0.0 ) { // We passed 360 -> 0 - setMouseOffset(mouseOffset() - completeCircle); + setMouseOffset( mouseOffset() - completeCircle ); } if ( wrapping() ) @@ -1128,18 +1016,18 @@ double QwtDial::getValue(const QPoint &pos) // We passed maxValue and the value will be set // to minValue. We have to adjust the mouseOffset. - setMouseOffset(posValue - minValue()); + setMouseOffset( posValue - minValue() ); } } else { if ( posValue - mouseOffset() > maxValue() || - value() == maxValue() ) + value() == maxValue() ) { // We fix the value at maxValue by adjusting // the mouse offset. - setMouseOffset(posValue - maxValue()); + setMouseOffset( posValue - maxValue() ); } } } @@ -1147,8 +1035,8 @@ double QwtDial::getValue(const QPoint &pos) { if ( dir > d_data->previousDir && mouseOffset() < 0.0 ) { - // We passed 0 -> 360 - setMouseOffset(mouseOffset() + completeCircle); + // We passed 0 -> 360 + setMouseOffset( mouseOffset() + completeCircle ); } if ( wrapping() ) @@ -1158,7 +1046,7 @@ double QwtDial::getValue(const QPoint &pos) // We passed minValue and the value will be set // to maxValue. We have to adjust the mouseOffset. - setMouseOffset(posValue - maxValue()); + setMouseOffset( posValue - maxValue() ); } } else @@ -1169,7 +1057,7 @@ double QwtDial::getValue(const QPoint &pos) // We fix the value at minValue by adjusting // the mouse offset. - setMouseOffset(posValue - minValue()); + setMouseOffset( posValue - minValue() ); } } } @@ -1189,20 +1077,21 @@ double QwtDial::getValue(const QPoint &pos) \sa QwtAbstractSlider::getScrollMode() */ -void QwtDial::getScrollMode(const QPoint &pos, int &scrollMode, int &direction) +void QwtDial::getScrollMode( const QPoint &pos, + QwtAbstractSlider::ScrollMode &scrollMode, int &direction ) const { direction = 0; - scrollMode = ScrNone; + scrollMode = QwtAbstractSlider::ScrNone; - const QRegion region(contentsRect(), QRegion::Ellipse); - if ( region.contains(pos) && pos != rect().center() ) + const QRegion region( innerRect().toRect(), QRegion::Ellipse ); + if ( region.contains( pos ) && pos != innerRect().center() ) { - scrollMode = ScrMouse; + scrollMode = QwtAbstractSlider::ScrMouse; d_data->previousDir = -1.0; } } -/*! +/*! Handles key events - Key_Down, KeyLeft\n @@ -1222,7 +1111,7 @@ void QwtDial::getScrollMode(const QPoint &pos, int &scrollMode, int &direction) \param event Key event \sa isReadOnly() */ -void QwtDial::keyPressEvent(QKeyEvent *event) +void QwtDial::keyPressEvent( QKeyEvent *event ) { if ( isReadOnly() ) { @@ -1238,53 +1127,29 @@ void QwtDial::keyPressEvent(QKeyEvent *event) { case Qt::Key_Down: case Qt::Key_Left: - QwtDoubleRange::incValue(-1); + QwtDoubleRange::incValue( -1 ); break; -#if QT_VERSION < 0x040000 - case Qt::Key_Prior: -#else case Qt::Key_PageUp: -#endif - QwtDoubleRange::incValue(-pageSize()); + QwtDoubleRange::incValue( -pageSize() ); break; case Qt::Key_Home: - setValue(minValue()); + setValue( minValue() ); break; case Qt::Key_Up: case Qt::Key_Right: - QwtDoubleRange::incValue(1); + QwtDoubleRange::incValue( 1 ); break; -#if QT_VERSION < 0x040000 - case Qt::Key_Next: -#else case Qt::Key_PageDown: -#endif - QwtDoubleRange::incValue(pageSize()); + QwtDoubleRange::incValue( pageSize() ); break; case Qt::Key_End: - setValue(maxValue()); + setValue( maxValue() ); break; default:; event->ignore(); } - if (value() != previous) - emit sliderMoved(value()); -} - -/*! - \brief Update the mask of the dial - - In case of "hasVisibleBackground() == false", the backgound is - transparent by a mask. - - \sa showBackground(), hasVisibleBackground() -*/ -void QwtDial::updateMask() -{ - if ( d_data->visibleBackground ) - clearMask(); - else - setMask(QRegion(boundingRect(), QRegion::Ellipse)); + if ( value() != previous ) + Q_EMIT sliderMoved( value() ); } diff --git a/qwt/src/qwt_dial.h b/qwt/src/qwt_dial.h index 00d410474..0d34c799a 100644 --- a/qwt/src/qwt_dial.h +++ b/qwt/src/qwt_dial.h @@ -7,59 +7,58 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_DIAL_H #define QWT_DIAL_H 1 -#include -#include #include "qwt_global.h" #include "qwt_abstract_slider.h" #include "qwt_round_scale_draw.h" +#include +#include class QwtDialNeedle; class QwtDial; /*! \brief A special scale draw made for QwtDial - + \sa QwtDial, QwtCompass */ class QWT_EXPORT QwtDialScaleDraw: public QwtRoundScaleDraw { public: - explicit QwtDialScaleDraw(QwtDial *); - virtual QwtText label(double value) const; + explicit QwtDialScaleDraw( QwtDial * ); - void setPenWidth(uint); - uint penWidth() const; + virtual QwtText label( double value ) const; + + void setPenWidth( double ); + double penWidth() const; private: QwtDial *d_parent; - int d_penWidth; + double d_penWidth; }; /*! - \brief QwtDial class provides a rounded range control. + \brief QwtDial class provides a rounded range control. QwtDial is intended as base class for dial widgets like - speedometers, compass widgets, clocks ... + speedometers, compass widgets, clocks ... \image html dials2.png A dial contains a scale and a needle indicating the current value - of the dial. Depending on Mode one of them is fixed and the + of the dial. Depending on Mode one of them is fixed and the other is rotating. If not isReadOnly() the - dial can be rotated by dragging the mouse or using keyboard inputs + dial can be rotated by dragging the mouse or using keyboard inputs (see keyPressEvent()). A dial might be wrapping, what means a rotation below/above one limit continues on the other limit (f.e compass). The scale might cover any arc of the dial, its values are related to the origin() of the dial. - + Qwt is missing a set of good looking needles (QwtDialNeedle). Contributions are very welcome. - + \sa QwtCompass, QwtAnalogClock, QwtDialNeedle \note The examples/dials example shows different types of dials. */ @@ -68,17 +67,16 @@ class QWT_EXPORT QwtDial: public QwtAbstractSlider { Q_OBJECT - Q_ENUMS(Shadow) - Q_ENUMS(Mode) - Q_ENUMS(Direction) + Q_ENUMS( Shadow ) + Q_ENUMS( Mode ) + Q_ENUMS( Direction ) - Q_PROPERTY(bool visibleBackground READ hasVisibleBackground WRITE showBackground) - Q_PROPERTY(int lineWidth READ lineWidth WRITE setLineWidth) - Q_PROPERTY(Shadow frameShadow READ frameShadow WRITE setFrameShadow) - Q_PROPERTY(Mode mode READ mode WRITE setMode) - Q_PROPERTY(double origin READ origin WRITE setOrigin) - Q_PROPERTY(bool wrapping READ wrapping WRITE setWrapping) - Q_PROPERTY(Direction direction READ direction WRITE setDirection) + Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth ) + Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow ) + Q_PROPERTY( Mode mode READ mode WRITE setMode ) + Q_PROPERTY( double origin READ origin WRITE setOrigin ) + Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) + Q_PROPERTY( Direction direction READ direction WRITE setDirection ) friend class QwtDialScaleDraw; public: @@ -93,105 +91,94 @@ public: */ enum Shadow { + //! QFrame::Plain Plain = QFrame::Plain, + + //! QFrame::Raised Raised = QFrame::Raised, + + //! QFrame::Sunken Sunken = QFrame::Sunken }; - //! see QwtDial::setScaleOptions - enum ScaleOptions - { - ScaleBackbone = 1, - ScaleTicks = 2, - ScaleLabel = 4 - }; - - /*! - In case of RotateNeedle the needle is rotating, in case of - RotateScale, the needle points to origin() - and the scale is rotating. - */ + //! Mode controlling wether the needle or the scale is rotating enum Mode { + //! The needle is rotating RotateNeedle, + + //! The needle is fixed, the scales are rotating RotateScale }; - /*! - Direction of the dial - */ + //! Direction of the dial enum Direction { + //! Clockwise Clockwise, + + //! Counter clockwise CounterClockwise }; - explicit QwtDial( QWidget *parent = NULL); -#if QT_VERSION < 0x040000 - explicit QwtDial( QWidget *parent, const char *name); -#endif - + explicit QwtDial( QWidget *parent = NULL ); virtual ~QwtDial(); - void setFrameShadow(Shadow); + void setFrameShadow( Shadow ); Shadow frameShadow() const; - bool hasVisibleBackground() const; - void showBackground(bool); - - void setLineWidth(int); + void setLineWidth( int ); int lineWidth() const; - void setMode(Mode); + void setMode( Mode ); Mode mode() const; - virtual void setWrapping(bool); + virtual void setWrapping( bool ); bool wrapping() const; - virtual void setScale(int maxMajIntv, int maxMinIntv, double step = 0.0); + virtual void setScale( int maxMajIntv, int maxMinIntv, double step = 0.0 ); - void setScaleArc(double min, double max); - void setScaleOptions(int); - void setScaleTicks(int minLen, int medLen, int majLen, int penWidth = 1); + void setScaleArc( double min, double max ); + void setScaleComponents( QwtAbstractScaleDraw::ScaleComponents ); + void setScaleTicks( int minLen, int medLen, int majLen, int penWidth = 1 ); double minScaleArc() const; double maxScaleArc() const; - virtual void setOrigin(double); + virtual void setOrigin( double ); double origin() const; - void setDirection(Direction); + void setDirection( Direction ); Direction direction() const; - virtual void setNeedle(QwtDialNeedle *); + virtual void setNeedle( QwtDialNeedle * ); const QwtDialNeedle *needle() const; QwtDialNeedle *needle(); - QRect boundingRect() const; - QRect contentsRect() const; - virtual QRect scaleContentsRect() const; + QRectF boundingRect() const; + QRectF innerRect() const; + virtual QRectF scaleInnerRect() const; virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; - virtual void setScaleDraw(QwtDialScaleDraw *); + virtual void setScaleDraw( QwtDialScaleDraw * ); QwtDialScaleDraw *scaleDraw(); const QwtDialScaleDraw *scaleDraw() const; protected: - virtual void paintEvent(QPaintEvent *); - virtual void resizeEvent(QResizeEvent *); - virtual void keyPressEvent(QKeyEvent *); + virtual void paintEvent( QPaintEvent * ); + virtual void keyPressEvent( QKeyEvent * ); - virtual void updateMask(); + virtual void drawFrame( QPainter *p ); + virtual void drawContents( QPainter * ) const; + virtual void drawFocusIndicator( QPainter * ) const; - virtual void drawFrame(QPainter *p); - virtual void drawContents(QPainter *) const; - virtual void drawFocusIndicator(QPainter *) const; - - virtual void drawScale(QPainter *, const QPoint ¢er, - int radius, double origin, double arcMin, double arcMax) const; + virtual void drawScale( + QPainter *, const QPointF ¢er, + double radius, double origin, + double arcMin, double arcMax ) const; /*! Draw the contents inside the scale @@ -202,21 +189,21 @@ protected: \param center Center of the contents circle \param radius Radius of the contents circle */ - virtual void drawScaleContents(QPainter *painter, const QPoint ¢er, - int radius) const; + virtual void drawScaleContents( QPainter *painter, + const QPointF ¢er, double radius ) 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 QwtText scaleLabel(double) const; + virtual QwtText scaleLabel( double ) const; void updateScale(); virtual void rangeChange(); virtual void valueChange(); - virtual double getValue(const QPoint &); - virtual void getScrollMode(const QPoint &, - int &scrollMode, int &direction); + virtual double getValue( const QPoint & ); + virtual void getScrollMode( const QPoint &, + QwtAbstractSlider::ScrollMode &, int &direction ) const; private: void initDial(); diff --git a/qwt/src/qwt_dial_needle.cpp b/qwt/src/qwt_dial_needle.cpp index 7f4772474..6c4a46a1e 100644 --- a/qwt/src/qwt_dial_needle.cpp +++ b/qwt/src/qwt_dial_needle.cpp @@ -7,28 +7,186 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -#include -#include -#include +#include "qwt_dial_needle.h" +#include "qwt_global.h" #include "qwt_math.h" #include "qwt_painter.h" -#include "qwt_polygon.h" -#include "qwt_dial_needle.h" +#include +#include -#if QT_VERSION < 0x040000 -typedef QColorGroup QwtPalette; -#else -typedef QPalette QwtPalette; -#endif +static void qwtDrawStyle1Needle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, + double length ) +{ + const double r[] = { 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4 }; + const double a[] = { -45, -20, -15, 0, 15, 20, 45 }; + + QPainterPath path; + for ( int i = 0; i < 7; i++ ) + { + const double angle = a[i] / 180.0 * M_PI; + const double radius = r[i] * length; + + const double x = radius * qCos( angle ); + const double y = radius * qSin( angle ); + + path.lineTo( x, -y ); + } + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette.brush( colorGroup, QPalette::Light ) ); + painter->drawPath( path ); +} + +static void qwtDrawStyle2Needle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, double length ) +{ + const double ratioX = 0.7; + const double ratioY = 0.3; + + QPainterPath path1; + path1.lineTo( ratioX * length, 0.0 ); + path1.lineTo( length, ratioY * length ); + + QPainterPath path2; + path2.lineTo( ratioX * length, 0.0 ); + path2.lineTo( length, -ratioY * length ); + + painter->setPen( Qt::NoPen ); + + painter->setBrush( palette.brush( colorGroup, QPalette::Light ) ); + painter->drawPath( path1 ); + + painter->setBrush( palette.brush( colorGroup, QPalette::Dark ) ); + painter->drawPath( path2 ); +} + +static void qwtDrawShadedPointer( QPainter *painter, + const QColor &lightColor, const QColor &darkColor, + double length, double width ) +{ + const double peak = qMax( length / 10.0, 5.0 ); + + const double knobWidth = width + 8; + QRectF knobRect( 0, 0, knobWidth, knobWidth ); + knobRect.moveCenter( QPointF(0, 0) ); + + QPainterPath path1; + path1.lineTo( 0.0, 0.5 * width ); + path1.lineTo( length - peak, 0.5 * width ); + path1.lineTo( length, 0.0 ); + path1.lineTo( 0.0, 0.0 ); + + QPainterPath arcPath1; + arcPath1.arcTo( knobRect, 0.0, -90.0 ); + + path1 = path1.united( arcPath1 ); + + QPainterPath path2; + path2.lineTo( 0.0, -0.5 * width ); + path2.lineTo( length - peak, -0.5 * width ); + path2.lineTo( length, 0.0 ); + path2.lineTo( 0.0, 0.0 ); + + QPainterPath arcPath2; + arcPath2.arcTo( knobRect, 0.0, 90.0 ); + + path2 = path2.united( arcPath2 ); + + painter->setPen( Qt::NoPen ); + + painter->setBrush( lightColor ); + painter->drawPath( path1 ); + + painter->setBrush( darkColor ); + painter->drawPath( path2 ); +} + +static void qwtDrawArrowNeedle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, + double length, double width ) +{ + if ( width <= 0 ) + width = qMax( length * 0.06, 9.0 ); + + const double peak = qMax( 2.0, 0.4 * width ); + + QPainterPath path; + path.moveTo( 0.0, 0.5 * width ); + path.lineTo( length - peak, 0.3 * width ); + path.lineTo( length, 0.0 ); + path.lineTo( length - peak, -0.3 * width ); + path.lineTo( 0.0, -0.5 * width ); + + QRectF br = path.boundingRect(); + + QPalette pal( palette.color( QPalette::Mid ) ); + QColor c1 = pal.color( QPalette::Light ); + QColor c2 = pal.color( QPalette::Dark ); + + QLinearGradient gradient( br.topLeft(), br.bottomLeft() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.5, c1 ); + gradient.setColorAt( 0.5001, c2 ); + gradient.setColorAt( 1.0, c2 ); + + QPen pen( gradient, 1 ); + pen.setJoinStyle( Qt::MiterJoin ); + + painter->setPen( pen ); + painter->setBrush( palette.brush( colorGroup, QPalette::Mid ) ); + + painter->drawPath( path ); +} + +static void qwtDrawTriangleNeedle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, + double length ) +{ + const double width = qRound( length / 3.0 ); + + QPainterPath path[4]; + + path[0].lineTo( length, 0.0 ); + path[0].lineTo( 0.0, width / 2 ); + + path[1].lineTo( length, 0.0 ); + path[1].lineTo( 0.0, -width / 2 ); + + path[2].lineTo( -length, 0.0 ); + path[2].lineTo( 0.0, width / 2 ); + + path[3].lineTo( -length, 0.0 ); + path[3].lineTo( 0.0, -width / 2 ); + + + const int colorOffset = 10; + const QColor darkColor = palette.color( colorGroup, QPalette::Dark ); + const QColor lightColor = palette.color( colorGroup, QPalette::Light ); + + QColor color[4]; + color[0] = darkColor.light( 100 + colorOffset ); + color[1] = darkColor.dark( 100 + colorOffset ); + color[2] = lightColor.light( 100 + colorOffset ); + color[3] = lightColor.dark( 100 + colorOffset ); + + painter->setPen( Qt::NoPen ); + + for ( int i = 0; i < 4; i++ ) + { + painter->setBrush( color[i] ); + painter->drawPath( path[i] ); + } +} //! Constructor QwtDialNeedle::QwtDialNeedle(): - d_palette(QApplication::palette()) + d_palette( QApplication::palette() ) { } //! Destructor -QwtDialNeedle::~QwtDialNeedle() +QwtDialNeedle::~QwtDialNeedle() { } @@ -37,50 +195,70 @@ QwtDialNeedle::~QwtDialNeedle() \param palette New Palette */ -void QwtDialNeedle::setPalette(const QPalette &palette) -{ - d_palette = palette; +void QwtDialNeedle::setPalette( const QPalette &palette ) +{ + d_palette = palette; } /*! \return the palette of the needle. */ -const QPalette &QwtDialNeedle::palette() const -{ - return d_palette; +const QPalette &QwtDialNeedle::palette() const +{ + return d_palette; } -//! Draw the knob -void QwtDialNeedle::drawKnob(QPainter *painter, - const QPoint &pos, int width, const QBrush &brush, bool sunken) +/*! + Draw the needle + + \param painter Painter + \param center Center of the dial, start position for the needle + \param length Length of the needle + \param direction Direction of the needle, in degrees counter clockwise + \param colorGroup Color group, used for painting +*/ +void QwtDialNeedle::draw( QPainter *painter, + const QPointF ¢er, double length, double direction, + QPalette::ColorGroup colorGroup ) const { painter->save(); - QRect rect(0, 0, width, width); - rect.moveCenter(pos); + painter->translate( center ); + painter->rotate( -direction ); - painter->setPen(Qt::NoPen); - painter->setBrush(brush); - painter->drawEllipse(rect); + drawNeedle( painter, length, colorGroup ); - painter->setBrush(Qt::NoBrush); + painter->restore(); +} - const int colorOffset = 20; +//! Draw the knob +void QwtDialNeedle::drawKnob( QPainter *painter, + double width, const QBrush &brush, bool sunken ) const +{ + QPalette palette( brush.color() ); + + QColor c1 = palette.color( QPalette::Light ); + QColor c2 = palette.color( QPalette::Dark ); - int startAngle = 45; if ( sunken ) - startAngle += 180; + qSwap( c1, c2 ); - QPen pen; - pen.setWidth(1); + QRectF rect( 0.0, 0.0, width, width ); + rect.moveCenter( painter->combinedTransform().map( QPointF() ) ); - pen.setColor(brush.color().dark(100 - colorOffset)); - painter->setPen(pen); - painter->drawArc(rect, startAngle * 16, 180 * 16); + QLinearGradient gradient( rect.topLeft(), rect.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.3, c1 ); + gradient.setColorAt( 0.7, c2 ); + gradient.setColorAt( 1.0, c2 ); - pen.setColor(brush.color().dark(100 + colorOffset)); - painter->setPen(pen); - painter->drawArc(rect, (startAngle + 180) * 16, 180 * 16); + painter->save(); + + painter->resetTransform(); + + painter->setPen( QPen( gradient, 1 ) ); + painter->setBrush( brush ); + painter->drawEllipse( rect ); painter->restore(); } @@ -93,30 +271,30 @@ void QwtDialNeedle::drawKnob(QPainter *painter, \param mid Middle color \param base Base color */ -QwtDialSimpleNeedle::QwtDialSimpleNeedle(Style style, bool hasKnob, - const QColor &mid, const QColor &base): - d_style(style), - d_hasKnob(hasKnob), - d_width(-1) +QwtDialSimpleNeedle::QwtDialSimpleNeedle( Style style, bool hasKnob, + const QColor &mid, const QColor &base ): + d_style( style ), + d_hasKnob( hasKnob ), + d_width( -1 ) { QPalette palette; for ( int i = 0; i < QPalette::NColorGroups; i++ ) { - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Mid, mid); - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Base, base); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Mid, mid ); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Base, base ); } - setPalette(palette); + setPalette( palette ); } -/*! +/*! Set the width of the needle \param width Width \sa width() */ -void QwtDialSimpleNeedle::setWidth(int width) +void QwtDialSimpleNeedle::setWidth( double width ) { d_width = width; } @@ -125,7 +303,7 @@ void QwtDialSimpleNeedle::setWidth(int width) \return the width of the needle \sa setWidth() */ -int QwtDialSimpleNeedle::width() const +double QwtDialSimpleNeedle::width() const { return d_width; } @@ -134,479 +312,141 @@ int QwtDialSimpleNeedle::width() const Draw the needle \param painter Painter - \param center Center of the dial, start position for the needle \param length Length of the needle - \param direction Direction of the needle, in degrees counter clockwise \param colorGroup Color group, used for painting */ -void QwtDialSimpleNeedle::draw(QPainter *painter, const QPoint ¢er, - int length, double direction, QPalette::ColorGroup colorGroup) const +void QwtDialSimpleNeedle::drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const { + double knobWidth = 0.0; + double width = d_width; + if ( d_style == Arrow ) { - drawArrowNeedle(painter, palette(), colorGroup, - center, length, d_width, direction, d_hasKnob); + if ( width <= 0.0 ) + width = qMax(length * 0.06, 6.0); + + qwtDrawArrowNeedle( painter, + palette(), colorGroup, length, width ); + + knobWidth = qMin( width * 2.0, 0.2 * length ); } else { - drawRayNeedle(painter, palette(), colorGroup, - center, length, d_width, direction, d_hasKnob); + if ( width <= 0.0 ) + width = 5.0; + + QPen pen ( palette().brush( colorGroup, QPalette::Mid ), width ); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + painter->drawLine( 0, 0, length, 0 ); + + knobWidth = qMax( width * 3.0, 5.0 ); } -} -/*! - Draw a needle looking like a ray - - \param painter Painter - \param palette Palette - \param colorGroup Color group - \param center center of the needle - \param length Length of the needle - \param width Width of the needle - \param direction Current Direction - \param hasKnob With/Without knob -*/ -void QwtDialSimpleNeedle::drawRayNeedle(QPainter *painter, - const QPalette &palette, QPalette::ColorGroup colorGroup, - const QPoint ¢er, int length, int width, double direction, - bool hasKnob) -{ - if ( width <= 0 ) - width = 5; - - direction *= M_PI / 180.0; - - painter->save(); - - const QPoint p1(center.x() + 1, center.y() + 2); - const QPoint p2 = qwtPolar2Pos(p1, length, direction); - - if ( width == 1 ) + if ( d_hasKnob && knobWidth > 0.0 ) { - const QColor midColor = - palette.color(colorGroup, QwtPalette::Mid); - - painter->setPen(QPen(midColor, 1)); - painter->drawLine(p1, p2); + drawKnob( painter, knobWidth, + palette().brush( colorGroup, QPalette::Base ), false ); } - else - { - QwtPolygon pa(4); - pa.setPoint(0, qwtPolar2Pos(p1, width / 2, direction + M_PI_2)); - pa.setPoint(1, qwtPolar2Pos(p2, width / 2, direction + M_PI_2)); - pa.setPoint(2, qwtPolar2Pos(p2, width / 2, direction - M_PI_2)); - pa.setPoint(3, qwtPolar2Pos(p1, width / 2, direction - M_PI_2)); - - painter->setPen(Qt::NoPen); - painter->setBrush(palette.brush(colorGroup, QwtPalette::Mid)); - painter->drawPolygon(pa); - } - if ( hasKnob ) - { - int knobWidth = qwtMax(qRound(width * 0.7), 5); - if ( knobWidth % 2 == 0 ) - knobWidth++; - - drawKnob(painter, center, knobWidth, - palette.brush(colorGroup, QwtPalette::Base), - false); - } - - painter->restore(); -} - -/*! - Draw a needle looking like an arrow - - \param painter Painter - \param palette Palette - \param colorGroup Color group - \param center center of the needle - \param length Length of the needle - \param width Width of the needle - \param direction Current Direction - \param hasKnob With/Without knob -*/ -void QwtDialSimpleNeedle::drawArrowNeedle(QPainter *painter, - const QPalette &palette, QPalette::ColorGroup colorGroup, - const QPoint ¢er, int length, int width, - double direction, bool hasKnob) -{ - direction *= M_PI / 180.0; - - painter->save(); - - if ( width <= 0 ) - { - width = (int)qwtMax(length * 0.06, 9.0); - if ( width % 2 == 0 ) - width++; - } - - const int peak = 3; - const QPoint p1(center.x() + 1, center.y() + 1); - const QPoint p2 = qwtPolar2Pos(p1, length - peak, direction); - const QPoint p3 = qwtPolar2Pos(p1, length, direction); - - QwtPolygon pa(5); - pa.setPoint(0, qwtPolar2Pos(p1, width / 2, direction - M_PI_2)); - pa.setPoint(1, qwtPolar2Pos(p2, 1, direction - M_PI_2)); - pa.setPoint(2, p3); - pa.setPoint(3, qwtPolar2Pos(p2, 1, direction + M_PI_2)); - pa.setPoint(4, qwtPolar2Pos(p1, width / 2, direction + M_PI_2)); - - painter->setPen(Qt::NoPen); - painter->setBrush(palette.brush(colorGroup, QwtPalette::Mid)); - painter->drawPolygon(pa); - - QwtPolygon shadowPa(3); - - const int colorOffset = 10; - - int i; - for ( i = 0; i < 3; i++ ) - shadowPa.setPoint(i, pa[i]); - - const QColor midColor = palette.color(colorGroup, QwtPalette::Mid); - - painter->setPen(midColor.dark(100 + colorOffset)); - painter->drawPolyline(shadowPa); - - for ( i = 0; i < 3; i++ ) - shadowPa.setPoint(i, pa[i + 2]); - - painter->setPen(midColor.dark(100 - colorOffset)); - painter->drawPolyline(shadowPa); - - if ( hasKnob ) - { - drawKnob(painter, center, qRound(width * 1.3), - palette.brush(colorGroup, QwtPalette::Base), - false); - } - - painter->restore(); } //! Constructor -QwtCompassMagnetNeedle::QwtCompassMagnetNeedle(Style style, - const QColor &light, const QColor &dark): - d_style(style) -{ +QwtCompassMagnetNeedle::QwtCompassMagnetNeedle( Style style, + const QColor &light, const QColor &dark ): + d_style( style ) +{ QPalette palette; for ( int i = 0; i < QPalette::NColorGroups; i++ ) { - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Light, light); - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Dark, dark); - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Base, Qt::darkGray); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Light, light ); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Dark, dark ); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Base, Qt::gray ); } - setPalette(palette); + setPalette( palette ); } /*! Draw the needle \param painter Painter - \param center Center of the dial, start position for the needle \param length Length of the needle - \param direction Direction of the needle, in degrees counter clockwise \param colorGroup Color group, used for painting */ -void QwtCompassMagnetNeedle::draw(QPainter *painter, const QPoint ¢er, - int length, double direction, QPalette::ColorGroup colorGroup) const +void QwtCompassMagnetNeedle::drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const { if ( d_style == ThinStyle ) { - drawThinNeedle(painter, palette(), colorGroup, - center, length, direction); + const double width = qMax( length / 6.0, 3.0 ); + + const int colorOffset = 10; + + const QColor light = palette().color( colorGroup, QPalette::Light ); + const QColor dark = palette().color( colorGroup, QPalette::Dark ); + + qwtDrawShadedPointer( painter, + dark.light( 100 + colorOffset ), + dark.dark( 100 + colorOffset ), + length, width ); + + painter->rotate( 180.0 ); + + qwtDrawShadedPointer( painter, + light.light( 100 + colorOffset ), + light.dark( 100 + colorOffset ), + length, width ); + + const QBrush baseBrush = palette().brush( colorGroup, QPalette::Base ); + drawKnob( painter, width, baseBrush, true ); } else { - drawTriangleNeedle(painter, palette(), colorGroup, - center, length, direction); + qwtDrawTriangleNeedle( painter, palette(), colorGroup, length ); } } /*! - Draw a compass needle - - \param painter Painter - \param palette Palette - \param colorGroup Color group - \param center Center, where the needle starts - \param length Length of the needle - \param direction Direction -*/ -void QwtCompassMagnetNeedle::drawTriangleNeedle(QPainter *painter, - const QPalette &palette, QPalette::ColorGroup colorGroup, - const QPoint ¢er, int length, double direction) -{ - const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark); - const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light); - - QBrush brush; - - const int width = qRound(length / 3.0); - const int colorOffset = 10; - - painter->save(); - painter->setPen(Qt::NoPen); - - const QPoint arrowCenter(center.x() + 1, center.y() + 1); - - QwtPolygon pa(3); - pa.setPoint(0, arrowCenter); - pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction)); - - pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction + 90.0)); - - brush = darkBrush; - brush.setColor(brush.color().dark(100 + colorOffset)); - painter->setBrush(brush); - painter->drawPolygon(pa); - - pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction - 90.0)); - - brush = darkBrush; - brush.setColor(brush.color().dark(100 - colorOffset)); - painter->setBrush(brush); - painter->drawPolygon(pa); - - // -- - - pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction + 180.0)); - - pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction + 90.0)); - - brush = lightBrush; - brush.setColor(brush.color().dark(100 + colorOffset)); - painter->setBrush(brush); - painter->drawPolygon(pa); - - pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction - 90.0)); - - brush = lightBrush; - brush.setColor(brush.color().dark(100 - colorOffset)); - painter->setBrush(brush); - painter->drawPolygon(pa); - - painter->restore(); -} - -/*! - Draw a compass needle - - \param painter Painter - \param palette Palette - \param colorGroup Color group - \param center Center, where the needle starts - \param length Length of the needle - \param direction Direction -*/ -void QwtCompassMagnetNeedle::drawThinNeedle(QPainter *painter, - const QPalette &palette, QPalette::ColorGroup colorGroup, - const QPoint ¢er, int length, double direction) -{ - const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark); - const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light); - const QBrush baseBrush = palette.brush(colorGroup, QwtPalette::Base); - - const int colorOffset = 10; - const int width = qwtMax(qRound(length / 6.0), 3); - - painter->save(); - - const QPoint arrowCenter(center.x() + 1, center.y() + 1); - - drawPointer(painter, darkBrush, colorOffset, - arrowCenter, length, width, direction); - drawPointer(painter, lightBrush, -colorOffset, - arrowCenter, length, width, direction + 180.0); - - drawKnob(painter, arrowCenter, width, baseBrush, true); - - painter->restore(); -} - -/*! - Draw a compass needle - - \param painter Painter - \param brush Brush - \param colorOffset Color offset - \param center Center, where the needle starts - \param length Length of the needle - \param width Width of the needle - \param direction Direction -*/ -void QwtCompassMagnetNeedle::drawPointer( - QPainter *painter, const QBrush &brush, - int colorOffset, const QPoint ¢er, int length, - int width, double direction) -{ - painter->save(); - - const int peak = qwtMax(qRound(length / 10.0), 5); - - const int knobWidth = width + 8; - QRect knobRect(0, 0, knobWidth, knobWidth); - knobRect.moveCenter(center); - - QwtPolygon pa(5); - - pa.setPoint(0, qwtDegree2Pos(center, width / 2, direction + 90.0)); - pa.setPoint(1, center); - pa.setPoint(2, qwtDegree2Pos(pa.point(1), length - peak, direction)); - pa.setPoint(3, qwtDegree2Pos(center, length, direction)); - pa.setPoint(4, qwtDegree2Pos(pa.point(0), length - peak, direction)); - - painter->setPen(Qt::NoPen); - - QBrush darkBrush = brush; - darkBrush.setColor(darkBrush.color().dark(100 + colorOffset)); - painter->setBrush(darkBrush); - painter->drawPolygon(pa); - painter->drawPie(knobRect, qRound(direction * 16), 90 * 16); - - pa.setPoint(0, qwtDegree2Pos(center, width / 2, direction - 90.0)); - pa.setPoint(4, qwtDegree2Pos(pa.point(0), length - peak, direction)); - - QBrush lightBrush = brush; - lightBrush.setColor(lightBrush.color().dark(100 - colorOffset)); - painter->setBrush(lightBrush); - painter->drawPolygon(pa); - painter->drawPie(knobRect, qRound(direction * 16), -90 * 16); - - painter->restore(); -} - -/*! Constructor \param style Arrow style \param light Light color \param dark Dark color */ -QwtCompassWindArrow::QwtCompassWindArrow(Style style, - const QColor &light, const QColor &dark): - d_style(style) +QwtCompassWindArrow::QwtCompassWindArrow( Style style, + const QColor &light, const QColor &dark ): + d_style( style ) { QPalette palette; for ( int i = 0; i < QPalette::NColorGroups; i++ ) { - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Light, light); - palette.setColor((QPalette::ColorGroup)i, - QwtPalette::Dark, dark); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Light, light ); + palette.setColor( ( QPalette::ColorGroup )i, + QPalette::Dark, dark ); } - setPalette(palette); + setPalette( palette ); } /*! Draw the needle \param painter Painter - \param center Center of the dial, start position for the needle \param length Length of the needle - \param direction Direction of the needle, in degrees counter clockwise \param colorGroup Color group, used for painting */ -void QwtCompassWindArrow::draw(QPainter *painter, const QPoint ¢er, - int length, double direction, QPalette::ColorGroup colorGroup) const +void QwtCompassWindArrow::drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const { if ( d_style == Style1 ) - { - drawStyle1Needle(painter, palette(), colorGroup, - center, length, direction); - } + qwtDrawStyle1Needle( painter, palette(), colorGroup, length ); else - { - drawStyle2Needle(painter, palette(), colorGroup, - center, length, direction); - } + qwtDrawStyle2Needle( painter, palette(), colorGroup, length ); } - -/*! - Draw a compass needle - - \param painter Painter - \param palette Palette - \param colorGroup colorGroup - \param center Center of the dial, start position for the needle - \param length Length of the needle - \param direction Direction of the needle, in degrees counter clockwise -*/ -void QwtCompassWindArrow::drawStyle1Needle(QPainter *painter, - const QPalette &palette, QPalette::ColorGroup colorGroup, - const QPoint ¢er, int length, double direction) -{ - const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light); - - const double AR1[] = {0, 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4}; - const double AW1[] = {0, -45, -20, -15, 0, 15, 20, 45}; - - const QPoint arrowCenter(center.x() + 1, center.y() + 1); - - QwtPolygon pa(8); - pa.setPoint(0, arrowCenter); - for (int i=1; i<8; i++) - { - const QPoint p = qwtDegree2Pos(center, - AR1[i] * length, direction + AW1[i]); - pa.setPoint(i, p); - } - - painter->save(); - painter->setPen(Qt::NoPen); - painter->setBrush(lightBrush); - painter->drawPolygon(pa); - painter->restore(); -} - -/*! - Draw a compass needle - - \param painter Painter - \param palette Palette - \param colorGroup colorGroup - \param center Center of the dial, start position for the needle - \param length Length of the needle - \param direction Direction of the needle, in degrees counter clockwise -*/ -void QwtCompassWindArrow::drawStyle2Needle(QPainter *painter, - const QPalette &palette, QPalette::ColorGroup colorGroup, - const QPoint ¢er, int length, double direction) -{ - const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light); - const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark); - - painter->save(); - painter->setPen(Qt::NoPen); - - const double angle = 12.0; - const double ratio = 0.7; - - const QPoint arrowCenter(center.x() + 1, center.y() + 1); - - QwtPolygon pa(3); - - pa.setPoint(0, center); - pa.setPoint(2, qwtDegree2Pos(arrowCenter, ratio * length, direction)); - - pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction + angle)); - painter->setBrush(darkBrush); - painter->drawPolygon(pa); - - pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction - angle)); - painter->setBrush(lightBrush); - painter->drawPolygon(pa); - - painter->restore(); -} - diff --git a/qwt/src/qwt_dial_needle.h b/qwt/src/qwt_dial_needle.h index b8dba4e41..e76b9d129 100644 --- a/qwt/src/qwt_dial_needle.h +++ b/qwt/src/qwt_dial_needle.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,8 +10,8 @@ #ifndef QWT_DIAL_NEEDLE_H #define QWT_DIAL_NEEDLE_H 1 -#include #include "qwt_global.h" +#include class QPainter; class QPoint; @@ -19,10 +19,10 @@ class QPoint; /*! \brief Base class for needles that can be used in a QwtDial. - QwtDialNeedle is a pointer that indicates a value by pointing - to a specific direction. - - Qwt is missing a set of good looking needles. + QwtDialNeedle is a pointer that indicates a value by pointing + to a specific direction. + + Qwt is missing a set of good looking needles. Contributions are very welcome. \sa QwtDial, QwtCompass @@ -34,25 +34,34 @@ public: QwtDialNeedle(); virtual ~QwtDialNeedle(); - /*! - Draw the needle + virtual void setPalette( const QPalette & ); + const QPalette &palette() const; - \param painter Painter - \param center Center of the dial, start position for the needle - \param length Length of the needle - \param direction Direction of the needle, in degrees counter clockwise - \param cg Color group, used for painting - */ - virtual void draw(QPainter *painter, const QPoint ¢er, - int length, double direction, - QPalette::ColorGroup cg = QPalette::Active) const = 0; - - virtual void setPalette(const QPalette &); - const QPalette &palette() const; + virtual void draw( QPainter *painter, const QPointF ¢er, + double length, double direction, + QPalette::ColorGroup = QPalette::Active ) const; protected: - static void drawKnob(QPainter *, const QPoint &pos, - int width, const QBrush &, bool sunken); + /*! + \brief Draw the needle + + The origin of the needle is at position (0.0, 0.0 ) + pointing in direction 0.0 ( = east ). + + The painter is already initilaized with translation and + rotation. + + \param painter Painter + \param length Length of the needle + \param colorGroup Color group, used for painting + + \sa setPalette(), palette() + */ + virtual void drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const = 0; + + virtual void drawKnob( QPainter *, double width, + const QBrush &, bool sunken ) const; private: QPalette d_palette; @@ -62,9 +71,10 @@ private: \brief A needle for dial widgets The following colors are used: - - QColorGroup::Mid\n + + - QPalette::Mid\n Pointer - - QColorGroup::base\n + - QPalette::Base\n Knob \sa QwtDial, QwtCompass @@ -76,33 +86,27 @@ public: //! Style of the needle enum Style { + //! Arrow Arrow, + + //! A straight line from the center Ray }; - QwtDialSimpleNeedle(Style, bool hasKnob = true, - const QColor &mid = Qt::gray, const QColor &base = Qt::darkGray); + QwtDialSimpleNeedle( Style, bool hasKnob = true, + const QColor &mid = Qt::gray, const QColor &base = Qt::darkGray ); - virtual void draw(QPainter *, const QPoint &, int length, - double direction, QPalette::ColorGroup = QPalette::Active) const; + void setWidth( double width ); + double width() const; - static void drawArrowNeedle(QPainter *, - const QPalette&, QPalette::ColorGroup, - const QPoint &, int length, int width, double direction, - bool hasKnob); - - static void drawRayNeedle(QPainter *, - const QPalette&, QPalette::ColorGroup, - const QPoint &, int length, int width, double direction, - bool hasKnob); - - void setWidth(int width); - int width() const; +protected: + virtual void drawNeedle( QPainter *, double length, + QPalette::ColorGroup ) const; private: Style d_style; bool d_hasKnob; - int d_width; + double d_width; }; /*! @@ -112,11 +116,11 @@ private: north and south. The following colors are used: - - QColorGroup::Light\n + - QPalette::Light\n Used for pointing south - - QColorGroup::Dark\n + - QPalette::Dark\n Used for pointing north - - QColorGroup::Base\n + - QPalette::Base\n Knob (ThinStyle only) \sa QwtDial, QwtCompass @@ -128,27 +132,19 @@ public: //! Style of the needle enum Style { + //! A needle with a triangular shape TriangleStyle, + + //! A thin needle ThinStyle }; - QwtCompassMagnetNeedle(Style = TriangleStyle, - const QColor &light = Qt::white, const QColor &dark = Qt::red); - virtual void draw(QPainter *, const QPoint &, int length, - double direction, QPalette::ColorGroup = QPalette::Active) const; - - static void drawTriangleNeedle(QPainter *, - const QPalette &, QPalette::ColorGroup, - const QPoint &, int length, double direction); - - static void drawThinNeedle(QPainter *, - const QPalette &, QPalette::ColorGroup, - const QPoint &, int length, double direction); + QwtCompassMagnetNeedle( Style = TriangleStyle, + const QColor &light = Qt::white, const QColor &dark = Qt::red ); protected: - static void drawPointer(QPainter *painter, const QBrush &brush, - int colorOffset, const QPoint ¢er, - int length, int width, double direction); + virtual void drawNeedle( QPainter *, + double length, QPalette::ColorGroup ) const; private: Style d_style; @@ -159,9 +155,9 @@ private: QwtCompassWindArrow shows the direction where the wind comes from. - - QColorGroup::Light\n + - QPalette::Light\n Used for Style1, or the light half of Style2 - - QColorGroup::Dark\n + - QPalette::Dark\n Used for the dark half of Style2 \sa QwtDial, QwtCompass @@ -173,26 +169,22 @@ public: //! Style of the arrow enum Style { + //! A needle pointing to the center Style1, + + //! A needle pointing to the center Style2 }; - QwtCompassWindArrow(Style, const QColor &light = Qt::white, - const QColor &dark = Qt::gray); + QwtCompassWindArrow( Style, const QColor &light = Qt::white, + const QColor &dark = Qt::gray ); - virtual void draw(QPainter *, const QPoint &, int length, - double direction, QPalette::ColorGroup = QPalette::Active) const; - - static void drawStyle1Needle(QPainter *, - const QPalette &, QPalette::ColorGroup, - const QPoint &, int length, double direction); - - static void drawStyle2Needle(QPainter *, - const QPalette &, QPalette::ColorGroup, - const QPoint &, int length, double direction); +protected: + virtual void drawNeedle( QPainter *, + double length, QPalette::ColorGroup ) const; private: Style d_style; }; -#endif // QWT_DIAL_NEEDLE_H +#endif diff --git a/qwt/src/qwt_double_interval.h b/qwt/src/qwt_double_interval.h deleted file mode 100644 index 8d0b06f45..000000000 --- a/qwt/src/qwt_double_interval.h +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#ifndef QWT_DOUBLE_INTERVAL_H -#define QWT_DOUBLE_INTERVAL_H - -#include "qwt_global.h" - -/*! - \brief A class representing an interval - - The interval is represented by 2 doubles, the lower and the upper limit. -*/ - -class QWT_EXPORT QwtDoubleInterval -{ -public: - /*! - Flag indicating if a border is included/excluded from an interval - - - IncludeBorders\n - min/max values are inside the interval - - ExcludeMinimum\n - min value is not included in the interval - - ExcludeMaximum\n - max value is not included in the interval - - ExcludeBorders\n - min/max values are not included in the interval - - \sa setBorderMode(), testBorderMode() - */ - enum BorderMode - { - IncludeBorders = 0, - - ExcludeMinimum = 1, - ExcludeMaximum = 2, - - ExcludeBorders = ExcludeMinimum | ExcludeMaximum - }; - - QwtDoubleInterval(); - QwtDoubleInterval(double minValue, double maxValue, - int borderFlags = IncludeBorders); - - void setInterval(double minValue, double maxValue, - int borderFlags = IncludeBorders); - - QwtDoubleInterval normalized() const; - QwtDoubleInterval inverted() const; - QwtDoubleInterval limited(double minValue, double maxValue) const; - - int operator==(const QwtDoubleInterval &) const; - int operator!=(const QwtDoubleInterval &) const; - - void setBorderFlags(int); - int borderFlags() const; - - double minValue() const; - double maxValue() const; - - double width() const; - - void setMinValue(double); - void setMaxValue(double); - - bool contains(double value) const; - - bool intersects(const QwtDoubleInterval &) const; - QwtDoubleInterval intersect(const QwtDoubleInterval &) const; - QwtDoubleInterval unite(const QwtDoubleInterval &) const; - - QwtDoubleInterval operator|(const QwtDoubleInterval &) const; - QwtDoubleInterval operator&(const QwtDoubleInterval &) const; - - QwtDoubleInterval &operator|=(const QwtDoubleInterval &); - QwtDoubleInterval &operator&=(const QwtDoubleInterval &); - - QwtDoubleInterval extend(double value) const; - QwtDoubleInterval operator|(double) const; - QwtDoubleInterval &operator|=(double); - - bool isValid() const; - bool isNull() const; - void invalidate(); - - QwtDoubleInterval symmetrize(double value) const; - -private: - double d_minValue; - double d_maxValue; - int d_borderFlags; -}; - -/*! - \brief Default Constructor - - Creates an invalid interval [0.0, -1.0] - \sa setInterval(), isValid() -*/ -inline QwtDoubleInterval::QwtDoubleInterval(): - d_minValue(0.0), - d_maxValue(-1.0), - d_borderFlags(IncludeBorders) -{ -} - -/*! - Constructor - - Build an interval with from min/max values - - \param minValue Minimum value - \param maxValue Maximum value - \param borderFlags Include/Exclude borders -*/ -inline QwtDoubleInterval::QwtDoubleInterval( - double minValue, double maxValue, int borderFlags): - d_minValue(minValue), - d_maxValue(maxValue), - d_borderFlags(borderFlags) -{ -} - -/*! - Assign the limits of the interval - - \param minValue Minimum value - \param maxValue Maximum value - \param borderFlags Include/Exclude borders -*/ -inline void QwtDoubleInterval::setInterval( - double minValue, double maxValue, int borderFlags) -{ - d_minValue = minValue; - d_maxValue = maxValue; - d_borderFlags = borderFlags; -} - -/*! - Change the border flags - - \param borderFlags Or'd BorderMode flags - \sa borderFlags() -*/ -inline void QwtDoubleInterval::setBorderFlags(int borderFlags) -{ - d_borderFlags = borderFlags; -} - -/*! - \return Border flags - \sa setBorderFlags() -*/ -inline int QwtDoubleInterval::borderFlags() const -{ - return d_borderFlags; -} - -/*! - Assign the lower limit of the interval - - \param minValue Minimum value -*/ -inline void QwtDoubleInterval::setMinValue(double minValue) -{ - d_minValue = minValue; -} - -/*! - Assign the upper limit of the interval - - \param maxValue Maximum value -*/ -inline void QwtDoubleInterval::setMaxValue(double maxValue) -{ - d_maxValue = maxValue; -} - -//! \return Lower limit of the interval -inline double QwtDoubleInterval::minValue() const -{ - return d_minValue; -} - -//! \return Upper limit of the interval -inline double QwtDoubleInterval::maxValue() const -{ - return d_maxValue; -} - -/*! - Return the width of an interval - The width of invalid intervals is 0.0, otherwise the result is - maxValue() - minValue(). - - \sa isValid() -*/ -inline double QwtDoubleInterval::width() const -{ - return isValid() ? (d_maxValue - d_minValue) : 0.0; -} - -/*! - Intersection of two intervals - \sa intersect() -*/ -inline QwtDoubleInterval QwtDoubleInterval::operator&( - const QwtDoubleInterval &interval ) const -{ - return intersect(interval); -} - -/*! - Union of two intervals - \sa unite() -*/ -inline QwtDoubleInterval QwtDoubleInterval::operator|( - const QwtDoubleInterval &interval) const -{ - return unite(interval); -} - -//! Compare two intervals -inline int QwtDoubleInterval::operator==(const QwtDoubleInterval &other) const -{ - return (d_minValue == other.d_minValue) && - (d_maxValue == other.d_maxValue) && - (d_borderFlags == other.d_borderFlags); -} - -//! Compare two intervals -inline int QwtDoubleInterval::operator!=(const QwtDoubleInterval &other) const -{ - return (!(*this == other)); -} - -/*! - Extend an interval - \sa extend() -*/ -inline QwtDoubleInterval QwtDoubleInterval::operator|(double value) const -{ - return extend(value); -} - -//! \return true, if isValid() && (minValue() >= maxValue()) -inline bool QwtDoubleInterval::isNull() const -{ - return isValid() && d_minValue >= d_maxValue; -} - -/*! - A interval is valid when minValue() <= maxValue(). - In case of QwtDoubleInterval::ExcludeBorders it is true - when minValue() < maxValue() -*/ -inline bool QwtDoubleInterval::isValid() const -{ - if ( (d_borderFlags & ExcludeBorders) == 0 ) - return d_minValue <= d_maxValue; - else - return d_minValue < d_maxValue; -} - -/*! - Invalidate the interval - - The limits are set to interval [0.0, -1.0] - \sa isValid() -*/ -inline void QwtDoubleInterval::invalidate() -{ - d_minValue = 0.0; - d_maxValue = -1.0; -} - -#endif diff --git a/qwt/src/qwt_double_range.cpp b/qwt/src/qwt_double_range.cpp index c19428b88..3748f2a11 100644 --- a/qwt/src/qwt_double_range.cpp +++ b/qwt/src/qwt_double_range.cpp @@ -2,48 +2,70 @@ * 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 #include "qwt_double_range.h" #include "qwt_math.h" -static double MinRelStep = 1.0e-10; -static double DefaultRelStep = 1.0e-2; -static double MinEps = 1.0e-10; +#if QT_VERSION < 0x040601 +#define qFabs(x) ::fabs(x) +#endif + +class QwtDoubleRange::PrivateData +{ +public: + PrivateData(): + minValue( 0.0 ), + maxValue( 0.0 ), + step( 1.0 ), + pageSize( 1 ), + isValid( false ), + value( 0.0 ), + exactValue( 0.0 ), + exactPrevValue( 0.0 ), + prevValue( 0.0 ), + periodic( false ) + { + } + + double minValue; + double maxValue; + double step; + int pageSize; + + bool isValid; + double value; + double exactValue; + double exactPrevValue; + double prevValue; + + bool periodic; +}; /*! The range is initialized to [0.0, 100.0], the step size to 1.0, and the value to 0.0. */ -QwtDoubleRange::QwtDoubleRange(): - d_minValue(0.0), - d_maxValue(0.0), - d_step(1.0), - d_pageSize(1), - d_isValid(false), - d_value(0.0), - d_exactValue(0.0), - d_exactPrevValue(0.0), - d_prevValue(0.0), - d_periodic(false) +QwtDoubleRange::QwtDoubleRange() { + d_data = new PrivateData(); } //! Destroys the QwtDoubleRange QwtDoubleRange::~QwtDoubleRange() { + delete d_data; } //! Set the value to be valid/invalid -void QwtDoubleRange::setValid(bool isValid) +void QwtDoubleRange::setValid( bool isValid ) { - if ( isValid != d_isValid ) + if ( isValid != d_data->isValid ) { - d_isValid = isValid; + d_data->isValid = isValid; valueChange(); } } @@ -51,74 +73,67 @@ void QwtDoubleRange::setValid(bool isValid) //! Indicates if the value is valid bool QwtDoubleRange::isValid() const { - return d_isValid; + return d_data->isValid; } -/*! - \brief No docs - - Description - \param x ??? - \param align - \todo Documentation -*/ -void QwtDoubleRange::setNewValue(double x, bool align) +void QwtDoubleRange::setNewValue( double value, bool align ) { - double vmin,vmax; - - d_prevValue = d_value; + d_data->prevValue = d_data->value; - vmin = qwtMin(d_minValue, d_maxValue); - vmax = qwtMax(d_minValue, d_maxValue); + const double vmin = qMin( d_data->minValue, d_data->maxValue ); + const double vmax = qMax( d_data->minValue, d_data->maxValue ); - // - // Range check - // - if (x < vmin) + if ( value < vmin ) { - if ((d_periodic) && (vmin != vmax)) - d_value = x + ::ceil( (vmin - x) / (vmax - vmin ) ) - * (vmax - vmin); - else - d_value = vmin; - } - else if (x > vmax) - { - if ((d_periodic) && (vmin != vmax)) - d_value = x - ::ceil( ( x - vmax) / (vmax - vmin )) - * (vmax - vmin); - else - d_value = vmax; - } - else - d_value = x; - - d_exactPrevValue = d_exactValue; - d_exactValue = d_value; - - // align to grid - if (align) - { - if (d_step != 0.0) + if ( d_data->periodic && vmin != vmax ) { - d_value = d_minValue + - qwtRound((d_value - d_minValue) / d_step) * d_step; + d_data->value = value + + qwtCeilF( ( vmin - value ) / ( vmax - vmin ) ) * ( vmax - vmin ); } else - d_value = d_minValue; - - // correct rounding error at the border - if (fabs(d_value - d_maxValue) < MinEps * qwtAbs(d_step)) - d_value = d_maxValue; - - // correct rounding error if value = 0 - if (::fabs(d_value) < MinEps * qwtAbs(d_step)) - d_value = 0.0; + d_data->value = vmin; + } + else if ( value > vmax ) + { + if ( ( d_data->periodic ) && ( vmin != vmax ) ) + { + d_data->value = value - + qwtCeilF( ( value - vmax ) / ( vmax - vmin ) ) * ( vmax - vmin ); + } + else + d_data->value = vmax; + } + else + { + d_data->value = value; } - if (!d_isValid || d_prevValue != d_value) + d_data->exactPrevValue = d_data->exactValue; + d_data->exactValue = d_data->value; + + if ( align ) { - d_isValid = true; + if ( d_data->step != 0.0 ) + { + d_data->value = d_data->minValue + + qRound( ( d_data->value - d_data->minValue ) / d_data->step ) * d_data->step; + } + else + d_data->value = d_data->minValue; + + const double minEps = 1.0e-10; + // correct rounding error at the border + if ( qFabs( d_data->value - d_data->maxValue ) < minEps * qAbs( d_data->step ) ) + d_data->value = d_data->maxValue; + + // correct rounding error if value = 0 + if ( qFabs( d_data->value ) < minEps * qAbs( d_data->step ) ) + d_data->value = 0.0; + } + + if ( !d_data->isValid || d_data->prevValue != d_data->value ) + { + d_data->isValid = true; valueChange(); } } @@ -132,9 +147,9 @@ void QwtDoubleRange::setNewValue(double x, bool align) \verbatim new value := x + n * (max. value - min. value)\endverbatim with an integer number n. */ -void QwtDoubleRange::fitValue(double x) +void QwtDoubleRange::fitValue( double x ) { - setNewValue(x, true); + setNewValue( x, true ); } @@ -147,9 +162,9 @@ void QwtDoubleRange::fitValue(double x) \verbatim new value := x + n * (max. value - min. value)\endverbatim with an integer number n. */ -void QwtDoubleRange::setValue(double x) +void QwtDoubleRange::setValue( double x ) { - setNewValue(x, false); + setNewValue( x, false ); } /*! @@ -169,66 +184,67 @@ void QwtDoubleRange::setValue(double x) \li If the step size has an absurd value, it will be corrected to a better one. */ -void QwtDoubleRange::setRange(double vmin, double vmax, double vstep, int pageSize) +void QwtDoubleRange::setRange( + double vmin, double vmax, double vstep, int pageSize ) { - bool rchg = ((d_maxValue != vmax) || (d_minValue != vmin)); - - if (rchg) - { - d_minValue = vmin; - d_maxValue = vmax; - } - - // - // look if the step width has an acceptable - // value or otherwise change it. - // - setStep(vstep); + const bool rchg = ( d_data->maxValue != vmax || d_data->minValue != vmin ); + + if ( rchg ) + { + d_data->minValue = vmin; + d_data->maxValue = vmax; + } + + // look if the step width has an acceptable + // value or otherwise change it. + setStep( vstep ); - // // limit page size - // - d_pageSize = qwtLim(pageSize,0, - int(qwtAbs((d_maxValue - d_minValue) / d_step))); - - // - // If the value lies out of the range, it - // will be changed. Note that it will not be adjusted to + const int max = + int( qAbs( ( d_data->maxValue - d_data->minValue ) / d_data->step ) ); + d_data->pageSize = qBound( 0, pageSize, max ); + + // If the value lies out of the range, it + // will be changed. Note that it will not be adjusted to // the new step width. - setNewValue(d_value, false); - - // call notifier after the step width has been + setNewValue( d_data->value, false ); + + // call notifier after the step width has been // adjusted. - if (rchg) - rangeChange(); + if ( rchg ) + rangeChange(); } /*! - \brief Change the step raster + \brief Change the step raster \param vstep new step width \warning The value will \e not be adjusted to the new step raster. */ -void QwtDoubleRange::setStep(double vstep) +void QwtDoubleRange::setStep( double vstep ) { - double intv = d_maxValue - d_minValue; - + const double intv = d_data->maxValue - d_data->minValue; + double newStep; - if (vstep == 0.0) - newStep = intv * DefaultRelStep; + if ( vstep == 0.0 ) + { + const double defaultRelStep = 1.0e-2; + newStep = intv * defaultRelStep; + } else { - if ( (intv > 0 && vstep < 0) || (intv < 0 && vstep > 0) ) - newStep = -vstep; + if ( ( intv > 0.0 && vstep < 0.0 ) || ( intv < 0.0 && vstep > 0.0 ) ) + newStep = -vstep; else - newStep = vstep; - - if ( fabs(newStep) < fabs(MinRelStep * intv) ) - newStep = MinRelStep * intv; + newStep = vstep; + + const double minRelStep = 1.0e-10; + if ( qFabs( newStep ) < qFabs( minRelStep * intv ) ) + newStep = minRelStep * intv; } - - if (newStep != d_step) + + if ( newStep != d_data->step ) { - d_step = newStep; + d_data->step = newStep; stepChange(); } } @@ -248,9 +264,9 @@ void QwtDoubleRange::setStep(double vstep) \param tf true for a periodic range */ -void QwtDoubleRange::setPeriodic(bool tf) +void QwtDoubleRange::setPeriodic( bool tf ) { - d_periodic = tf; + d_data->periodic = tf; } /*! @@ -259,10 +275,10 @@ void QwtDoubleRange::setPeriodic(bool tf) \warning As a result of this operation, the new value will always be adjusted to the step raster. */ -void QwtDoubleRange::incValue(int nSteps) +void QwtDoubleRange::incValue( int nSteps ) { if ( isValid() ) - setNewValue(d_value + double(nSteps) * d_step, true); + setNewValue( d_data->value + double( nSteps ) * d_data->step, true ); } /*! @@ -271,10 +287,13 @@ void QwtDoubleRange::incValue(int nSteps) A negative number decrements the value. \warning The Page size is specified in the constructor. */ -void QwtDoubleRange::incPages(int nPages) +void QwtDoubleRange::incPages( int nPages ) { if ( isValid() ) - setNewValue(d_value + double(nPages) * double(d_pageSize) * d_step, true); + { + const double off = d_data->step * d_data->pageSize * nPages; + setNewValue( d_data->value + off, true ); + } } /*! @@ -315,7 +334,7 @@ void QwtDoubleRange::stepChange() */ double QwtDoubleRange::step() const { - return qwtAbs(d_step); + return qAbs( d_data->step ); } /*! @@ -323,46 +342,46 @@ double QwtDoubleRange::step() const maxValue returns the value which has been specified as the second parameter in QwtDoubleRange::setRange. - - \sa setRange() -*/ -double QwtDoubleRange::maxValue() const -{ - return d_maxValue; -} - -/*! - \brief Returns the value at the first border of the range - - minValue returns the value which has been specified - as the first parameter in setRange(). - + \sa setRange() */ -double QwtDoubleRange::minValue() const +double QwtDoubleRange::maxValue() const { - return d_minValue; -} + return d_data->maxValue; +} + +/*! + \brief Returns the value at the first border of the range + + minValue returns the value which has been specified + as the first parameter in setRange(). + + \sa setRange() +*/ +double QwtDoubleRange::minValue() const +{ + return d_data->minValue; +} /*! \brief Returns true if the range is periodic \sa setPeriodic() */ -bool QwtDoubleRange::periodic() const -{ - return d_periodic; +bool QwtDoubleRange::periodic() const +{ + return d_data->periodic; } //! Returns the page size in steps. -int QwtDoubleRange::pageSize() const -{ - return d_pageSize; +int QwtDoubleRange::pageSize() const +{ + return d_data->pageSize; } //! Returns the current value. -double QwtDoubleRange::value() const -{ - return d_value; +double QwtDoubleRange::value() const +{ + return d_data->value; } /*! @@ -370,23 +389,22 @@ double QwtDoubleRange::value() const The exact value is the value which QwtDoubleRange::value would return if the value were not adjusted to the step raster. It differs from - the current value only if QwtDoubleRange::fitValue or - QwtDoubleRange::incValue have been used before. This function - is intended for internal use in derived classes. + the current value only if fitValue() or incValue() have been used before. + This function is intended for internal use in derived classes. */ -double QwtDoubleRange::exactValue() const -{ - return d_exactValue; +double QwtDoubleRange::exactValue() const +{ + return d_data->exactValue; } //! Returns the exact previous value -double QwtDoubleRange::exactPrevValue() const -{ - return d_exactPrevValue; +double QwtDoubleRange::exactPrevValue() const +{ + return d_data->exactPrevValue; } //! Returns the previous value -double QwtDoubleRange::prevValue() const -{ - return d_prevValue; +double QwtDoubleRange::prevValue() const +{ + return d_data->prevValue; } diff --git a/qwt/src/qwt_double_range.h b/qwt/src/qwt_double_range.h index 2f9d7da2a..209857f8a 100644 --- a/qwt/src/qwt_double_range.h +++ b/qwt/src/qwt_double_range.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -17,14 +17,14 @@ This class is useful as a base class or a member for sliders. It represents an interval of type double within which a value can - be moved. The value can be either an arbitrary point inside + be moved. The value can be either an arbitrary point inside the interval (see QwtDoubleRange::setValue), or it can be fitted into a step raster (see QwtDoubleRange::fitValue and QwtDoubleRange::incValue). As a special case, a QwtDoubleRange can be periodic, which means that a value outside the interval will be mapped to a value inside the - interval when QwtDoubleRange::setValue(), QwtDoubleRange::fitValue(), + interval when QwtDoubleRange::setValue(), QwtDoubleRange::fitValue(), QwtDoubleRange::incValue() or QwtDoubleRange::incPages() are called. */ @@ -34,29 +34,29 @@ public: QwtDoubleRange(); virtual ~QwtDoubleRange(); - void setRange(double vmin, double vmax, double vstep = 0.0, - int pagesize = 1); + void setRange( double vmin, double vmax, + double vstep = 0.0, int pagesize = 1 ); - void setValid(bool); + void setValid( bool ); bool isValid() const; - virtual void setValue(double); + virtual void setValue( double ); double value() const; - void setPeriodic(bool tf); + void setPeriodic( bool tf ); bool periodic() const; - void setStep(double); + void setStep( double ); double step() const; double maxValue() const; - double minValue() const; + double minValue() const; int pageSize() const; - virtual void incValue(int); - virtual void incPages(int); - virtual void fitValue(double); + virtual void incValue( int ); + virtual void incPages( int ); + virtual void fitValue( double ); protected: @@ -69,20 +69,10 @@ protected: virtual void rangeChange(); private: - void setNewValue(double x, bool align = false); + void setNewValue( double value, bool align = false ); - double d_minValue; - double d_maxValue; - double d_step; - int d_pageSize; - - bool d_isValid; - double d_value; - double d_exactValue; - double d_exactPrevValue; - double d_prevValue; - - bool d_periodic; + class PrivateData; + PrivateData *d_data; }; #endif diff --git a/qwt/src/qwt_double_rect.cpp b/qwt/src/qwt_double_rect.cpp deleted file mode 100644 index 2b2a18ab4..000000000 --- a/qwt/src/qwt_double_rect.cpp +++ /dev/null @@ -1,605 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#include - -#if QT_VERSION < 0x040000 - -#include "qwt_math.h" -#include "qwt_double_rect.h" - -/*! - Constructs a null point. - - \sa QwtDoublePoint::isNull() -*/ -QwtDoublePoint::QwtDoublePoint(): - d_x(0.0), - d_y(0.0) -{ -} - -//! Constructs a point with coordinates specified by x and y. -QwtDoublePoint::QwtDoublePoint(double x, double y ): - d_x(x), - d_y(y) -{ -} - -/*! - Copy constructor. - - Constructs a point using the values of the point specified. -*/ -QwtDoublePoint::QwtDoublePoint(const QPoint &p): - d_x(double(p.x())), - d_y(double(p.y())) -{ -} - -/*! - Returns true if point1 is equal to point2; otherwise returns false. - - Two points are equal to each other if both x-coordinates and - both y-coordinates are the same. -*/ -bool QwtDoublePoint::operator==(const QwtDoublePoint &other) const -{ - return (d_x == other.d_x) && (d_y == other.d_y); -} - -//! Returns true if point1 is not equal to point2; otherwise returns false. -bool QwtDoublePoint::operator!=(const QwtDoublePoint &other) const -{ - return !operator==(other); -} - -/*! - Negates the coordinates of the point, and returns a point with the - new coordinates. (Inversion). -*/ -const QwtDoublePoint QwtDoublePoint::operator-() const -{ - return QwtDoublePoint(-d_x, -d_y); -} - -/*! - Adds the coordinates of the point to the corresponding coordinates of - the other point, and returns a point with the new coordinates. - (Vector addition.) -*/ -const QwtDoublePoint QwtDoublePoint::operator+( - const QwtDoublePoint &other) const -{ - return QwtDoublePoint(d_x + other.d_x, d_y + other.d_y); -} - -/*! - Subtracts the coordinates of the other point from the corresponding - coordinates of the given point, and returns a point with the new - coordinates. (Vector subtraction.) -*/ -const QwtDoublePoint QwtDoublePoint::operator-( - const QwtDoublePoint &other) const -{ - return QwtDoublePoint(d_x - other.d_x, d_y - other.d_y); -} - -/*! - Multiplies the coordinates of the point by the given scale factor, - and returns a point with the new coordinates. - (Scalar multiplication of a vector.) -*/ -const QwtDoublePoint QwtDoublePoint::operator*(double factor) const -{ - return QwtDoublePoint(d_x * factor, d_y * factor); -} - -/*! - Divides the coordinates of the point by the given scale factor, - and returns a point with the new coordinates. - (Scalar division of a vector.) -*/ -const QwtDoublePoint QwtDoublePoint::operator/(double factor) const -{ - return QwtDoublePoint(d_x / factor, d_y / factor); -} - -/*! - Adds the coordinates of this point to the corresponding coordinates - of the other point, and returns a reference to this point with the - new coordinates. This is equivalent to vector addition. -*/ -QwtDoublePoint &QwtDoublePoint::operator+=(const QwtDoublePoint &other) -{ - d_x += other.d_x; - d_y += other.d_y; - return *this; -} - -/*! - Subtracts the coordinates of the other point from the corresponding - coordinates of this point, and returns a reference to this point with - the new coordinates. This is equivalent to vector subtraction. -*/ -QwtDoublePoint &QwtDoublePoint::operator-=(const QwtDoublePoint &other) -{ - d_x -= other.d_x; - d_y -= other.d_y; - return *this; -} - -/*! - Multiplies the coordinates of this point by the given scale factor, - and returns a reference to this point with the new coordinates. - This is equivalent to scalar multiplication of a vector. -*/ -QwtDoublePoint &QwtDoublePoint::operator*=(double factor) -{ - d_x *= factor; - d_y *= factor; - return *this; -} - -/*! - Divides the coordinates of this point by the given scale factor, - and returns a references to this point with the new coordinates. - This is equivalent to scalar division of a vector. -*/ -QwtDoublePoint &QwtDoublePoint::operator/=(double factor) -{ - d_x /= factor; - d_y /= factor; - return *this; -} - -//! Constructs an invalid size. -QwtDoubleSize::QwtDoubleSize(): - d_width(-1.0), - d_height(-1.0) -{ -} - -//! Constructs a size with width width and height height. -QwtDoubleSize::QwtDoubleSize( double width, double height ): - d_width(width), - d_height(height) -{ -} - -//! Constructs a size with floating point accuracy from the given size. -QwtDoubleSize::QwtDoubleSize(const QSize &sz): - d_width(double(sz.width())), - d_height(double(sz.height())) -{ -} - -//! Swaps the width and height values. -void QwtDoubleSize::transpose() -{ - double tmp = d_width; - d_width = d_height; - d_height = tmp; -} - -/*! - Returns a size with the maximum width and height of this - size and other. -*/ -QwtDoubleSize QwtDoubleSize::expandedTo( - const QwtDoubleSize &other) const -{ - return QwtDoubleSize( - qwtMax(d_width, other.d_width), - qwtMax(d_height, other.d_height) - ); -} - -/*! - Returns a size with the minimum width and height of this size and other. -*/ -QwtDoubleSize QwtDoubleSize::boundedTo( - const QwtDoubleSize &other) const -{ - return QwtDoubleSize( - qwtMin(d_width, other.d_width), - qwtMin(d_height, other.d_height) - ); -} - -//! Returns true if s1 and s2 are equal; otherwise returns false. -bool QwtDoubleSize::operator==(const QwtDoubleSize &other) const -{ - return d_width == other.d_width && d_height == other.d_height; -} - -//! Returns true if s1 and s2 are different; otherwise returns false. -bool QwtDoubleSize::operator!=(const QwtDoubleSize &other) const -{ - return !operator==(other); -} - -/*! - Returns the size formed by adding both components by - the components of other. Each component is added separately. -*/ -const QwtDoubleSize QwtDoubleSize::operator+( - const QwtDoubleSize &other) const -{ - return QwtDoubleSize(d_width + other.d_width, - d_height + other.d_height); -} - -/*! - Returns the size formed by subtracting both components by - the components of other. Each component is subtracted separately. -*/ -const QwtDoubleSize QwtDoubleSize::operator-( - const QwtDoubleSize &other) const -{ - return QwtDoubleSize(d_width - other.d_width, - d_height - other.d_height); -} - -//! Returns the size formed by multiplying both components by c. -const QwtDoubleSize QwtDoubleSize::operator*(double c) const -{ - return QwtDoubleSize(d_width * c, d_height * c); -} - -//! Returns the size formed by dividing both components by c. -const QwtDoubleSize QwtDoubleSize::operator/(double c) const -{ - return QwtDoubleSize(d_width / c, d_height / c); -} - -//! Adds size other to this size and returns a reference to this size. -QwtDoubleSize &QwtDoubleSize::operator+=(const QwtDoubleSize &other) -{ - d_width += other.d_width; - d_height += other.d_height; - return *this; -} - -//! Subtracts size other from this size and returns a reference to this size. -QwtDoubleSize &QwtDoubleSize::operator-=(const QwtDoubleSize &other) -{ - d_width -= other.d_width; - d_height -= other.d_height; - return *this; -} - -/* - Multiplies this size's width and height by c, - and returns a reference to this size. -*/ -QwtDoubleSize &QwtDoubleSize::operator*=(double c) -{ - d_width *= c; - d_height *= c; - return *this; -} - -/* - Devides this size's width and height by c, - and returns a reference to this size. -*/ -QwtDoubleSize &QwtDoubleSize::operator/=(double c) -{ - d_width /= c; - d_height /= c; - return *this; -} - -//! Constructs an rectangle with all components set to 0.0 -QwtDoubleRect::QwtDoubleRect(): - d_left(0.0), - d_right(0.0), - d_top(0.0), - d_bottom(0.0) -{ -} - -/*! - Constructs an rectangle with x1 to x2 as x-range and, - y1 to y2 as y-range. -*/ -QwtDoubleRect::QwtDoubleRect(double left, double top, - double width, double height): - d_left(left), - d_right(left + width), - d_top(top), - d_bottom(top + height) -{ -} - -/*! - Constructs a rectangle with topLeft as the top-left corner and - size as the rectangle size. -*/ -QwtDoubleRect::QwtDoubleRect( - const QwtDoublePoint &p, const QwtDoubleSize &size): - d_left(p.x()), - d_right(p.x() + size.width()), - d_top(p.y()), - d_bottom(p.y() + size.height()) -{ -} - -QwtDoubleRect::QwtDoubleRect(const QRect &rect): - d_left(rect.left()), - d_right(rect.right()), - d_top(rect.top()), - d_bottom(rect.bottom()) -{ -} - -QRect QwtDoubleRect::toRect() const -{ - return QRect(qRound(x()), qRound(y()), qRound(width()), qRound(height())); -} - -/*! - Set the x-range from x1 to x2 and the y-range from y1 to y2. -*/ -void QwtDoubleRect::setRect(double left, double top, - double width, double height) -{ - d_left = left; - d_right = left + width; - d_top = top; - d_bottom = top + height; -} - -/*! - Sets the size of the rectangle to size. - Changes x2 and y2 only. -*/ -void QwtDoubleRect::setSize(const QwtDoubleSize &size) -{ - setWidth(size.width()); - setHeight(size.height()); -} - -/*! - Returns a normalized rectangle, i.e. a rectangle that has a non-negative - width and height. - - It swaps x1 and x2 if x1() > x2(), and swaps y1 and y2 if y1() > y2(). -*/ -QwtDoubleRect QwtDoubleRect::normalized() const -{ - QwtDoubleRect r; - if ( d_right < d_left ) - { - r.d_left = d_right; - r.d_right = d_left; - } - else - { - r.d_left = d_left; - r.d_right = d_right; - } - if ( d_bottom < d_top ) - { - r.d_top = d_bottom; - r.d_bottom = d_top; - } - else - { - r.d_top = d_top; - r.d_bottom = d_bottom; - } - return r; -} - -/*! - Returns the bounding rectangle of this rectangle and rectangle other. - r.unite(s) is equivalent to r|s. -*/ -QwtDoubleRect QwtDoubleRect::unite(const QwtDoubleRect &other) const -{ - return *this | other; -} - -/*! - Returns the intersection of this rectangle and rectangle other. - r.intersect(s) is equivalent to r&s. -*/ -QwtDoubleRect QwtDoubleRect::intersect(const QwtDoubleRect &other) const -{ - return *this & other; -} - -/*! - Returns true if this rectangle intersects with rectangle other; - otherwise returns false. -*/ -bool QwtDoubleRect::intersects(const QwtDoubleRect &other) const -{ - return ( qwtMax(d_left, other.d_left) <= qwtMin(d_right, other.d_right) ) && - ( qwtMax(d_top, other.d_top ) <= qwtMin(d_bottom, other.d_bottom) ); -} - -//! Returns true if this rect and other are equal; otherwise returns false. -bool QwtDoubleRect::operator==(const QwtDoubleRect &other) const -{ - return d_left == other.d_left && d_right == other.d_right && - d_top == other.d_top && d_bottom == other.d_bottom; -} - -//! Returns true if this rect and other are different; otherwise returns false. -bool QwtDoubleRect::operator!=(const QwtDoubleRect &other) const -{ - return !operator==(other); -} - -/*! - Returns the bounding rectangle of this rectangle and rectangle other. - The bounding rectangle of a nonempty rectangle and an empty or - invalid rectangle is defined to be the nonempty rectangle. -*/ -QwtDoubleRect QwtDoubleRect::operator|(const QwtDoubleRect &other) const -{ - if ( isEmpty() ) - return other; - - if ( other.isEmpty() ) - return *this; - - const double minX = qwtMin(d_left, other.d_left); - const double maxX = qwtMax(d_right, other.d_right); - const double minY = qwtMin(d_top, other.d_top); - const double maxY = qwtMax(d_bottom, other.d_bottom); - - return QwtDoubleRect(minX, minY, maxX - minX, maxY - minY); -} - -/*! - Returns the intersection of this rectangle and rectangle other. - Returns an empty rectangle if there is no intersection. -*/ -QwtDoubleRect QwtDoubleRect::operator&(const QwtDoubleRect &other) const -{ - if (isNull() || other.isNull()) - return QwtDoubleRect(); - - const QwtDoubleRect r1 = normalized(); - const QwtDoubleRect r2 = other.normalized(); - - const double minX = qwtMax(r1.left(), r2.left()); - const double maxX = qwtMin(r1.right(), r2.right()); - const double minY = qwtMax(r1.top(), r2.top()); - const double maxY = qwtMin(r1.bottom(), r2.bottom()); - - return QwtDoubleRect(minX, minY, maxX - minX, maxY - minY); -} - -//! Unites this rectangle with rectangle other. -QwtDoubleRect &QwtDoubleRect::operator|=(const QwtDoubleRect &other) -{ - *this = *this | other; - return *this; -} - -//! Intersects this rectangle with rectangle other. -QwtDoubleRect &QwtDoubleRect::operator&=(const QwtDoubleRect &other) -{ - *this = *this & other; - return *this; -} - -//! Returns the center point of the rectangle. -QwtDoublePoint QwtDoubleRect::center() const -{ - return QwtDoublePoint(d_left + (d_right - d_left) / 2.0, - d_top + (d_bottom - d_top) / 2.0); -} - -/*! - Returns true if the point (x, y) is inside or on the edge of the rectangle; - otherwise returns false. - - If proper is true, this function returns true only if p is inside - (not on the edge). -*/ -bool QwtDoubleRect::contains(double x, double y, bool proper) const -{ - if ( proper ) - return x > d_left && x < d_right && y > d_top && y < d_bottom; - else - return x >= d_left && x <= d_right && y >= d_top && y <= d_bottom; -} - -/*! - Returns true if the point p is inside or on the edge of the rectangle; - otherwise returns false. - - If proper is true, this function returns true only if p is inside - (not on the edge). -*/ -bool QwtDoubleRect::contains(const QwtDoublePoint &p, bool proper) const -{ - return contains(p.x(), p.y(), proper); -} - -/*! - Returns true if the rectangle other is inside this rectangle; - otherwise returns false. - - If proper is true, this function returns true only if other is entirely - inside (not on the edge). -*/ -bool QwtDoubleRect::contains(const QwtDoubleRect &other, bool proper) const -{ - return contains(other.d_left, other.d_top, proper) && - contains(other.d_right, other.d_bottom, proper); -} - -//! moves x1() to x, leaving the size unchanged -void QwtDoubleRect::moveLeft(double x) -{ - const double w = width(); - d_left = x; - d_right = d_left + w; -} - -//! moves x1() to x, leaving the size unchanged -void QwtDoubleRect::moveRight(double x) -{ - const double w = width(); - d_right = x; - d_left = d_right - w; -} - -//! moves y1() to y, leaving the size unchanged -void QwtDoubleRect::moveTop(double y) -{ - const double h = height(); - d_top = y; - d_bottom = d_top + h; -} - -//! moves y1() to y, leaving the size unchanged -void QwtDoubleRect::moveBottom(double y) -{ - const double h = height(); - d_bottom = y; - d_top = d_bottom - h; -} - -//! moves left() to x and top() to y, leaving the size unchanged -void QwtDoubleRect::moveTo(double x, double y) -{ - moveLeft(x); - moveTop(y); -} - -//! moves x1() by dx and y1() by dy. leaving the size unchanged -void QwtDoubleRect::moveBy(double dx, double dy) -{ - d_left += dx; - d_right += dx; - d_top += dy; - d_bottom += dy; -} - -//! moves the center to pos, leaving the size unchanged -void QwtDoubleRect::moveCenter(const QwtDoublePoint &pos) -{ - moveCenter(pos.x(), pos.y()); -} - -//! moves the center to (x, y), leaving the size unchanged -void QwtDoubleRect::moveCenter(double x, double y) -{ - moveTo(x - width() / 2.0, y - height() / 2.0); -} - -#endif // QT_VERSION < 0x040000 diff --git a/qwt/src/qwt_double_rect.h b/qwt/src/qwt_double_rect.h deleted file mode 100644 index 341e17c08..000000000 --- a/qwt/src/qwt_double_rect.h +++ /dev/null @@ -1,501 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -/*! \file */ -#ifndef QWT_DOUBLE_RECT_H -#define QWT_DOUBLE_RECT_H 1 - -#include "qwt_global.h" -#include "qwt_array.h" - -#if QT_VERSION >= 0x040000 - -#include -#include -#include - -/*! - \typedef QPointF QwtDoublePoint - \brief This is a typedef, see Trolltech Documentation for QPointF - in QT assistant 4.x. As soon as Qt3 compatibility is dropped - this typedef will disappear. -*/ -typedef QPointF QwtDoublePoint; - -/*! - \typedef QSizeF QwtDoubleSize - \brief This is a typedef, see Trolltech Documentation for QSizeF - in QT assistant 4.x. As soon as Qt3 compatibility is dropped - this typedef will disappear. -*/ -typedef QSizeF QwtDoubleSize; - -/*! - \typedef QRectF QwtDoubleRect - \brief This is a typedef, see Trolltech Documentation for QRectF - in QT assistant 4.x. As soon as Qt3 compatibility is dropped - this typedef will disappear. -*/ -typedef QRectF QwtDoubleRect; - -#else - -#include -#include -#include - -/*! - \brief The QwtDoublePoint class defines a point in double coordinates -*/ - -class QWT_EXPORT QwtDoublePoint -{ -public: - QwtDoublePoint(); - QwtDoublePoint(double x, double y); - QwtDoublePoint(const QPoint &); - - QPoint toPoint() const; - - bool isNull() const; - - double x() const; - double y() const; - - double &rx(); - double &ry(); - - void setX(double x); - void setY(double y); - - bool operator==(const QwtDoublePoint &) const; - bool operator!=(const QwtDoublePoint &) const; - - const QwtDoublePoint operator-() const; - const QwtDoublePoint operator+(const QwtDoublePoint &) const; - const QwtDoublePoint operator-(const QwtDoublePoint &) const; - const QwtDoublePoint operator*(double) const; - const QwtDoublePoint operator/(double) const; - - QwtDoublePoint &operator+=(const QwtDoublePoint &); - QwtDoublePoint &operator-=(const QwtDoublePoint &); - QwtDoublePoint &operator*=(double); - QwtDoublePoint &operator/=(double); - -private: - double d_x; - double d_y; -}; - -/*! - The QwtDoubleSize class defines a size in double coordinates -*/ - -class QWT_EXPORT QwtDoubleSize -{ -public: - QwtDoubleSize(); - QwtDoubleSize(double width, double height); - QwtDoubleSize(const QSize &); - - bool isNull() const; - bool isEmpty() const; - bool isValid() const; - - double width() const; - double height() const; - void setWidth( double w ); - void setHeight( double h ); - void transpose(); - - QwtDoubleSize expandedTo(const QwtDoubleSize &) const; - QwtDoubleSize boundedTo(const QwtDoubleSize &) const; - - bool operator==(const QwtDoubleSize &) const; - bool operator!=(const QwtDoubleSize &) const; - - const QwtDoubleSize operator+(const QwtDoubleSize &) const; - const QwtDoubleSize operator-(const QwtDoubleSize &) const; - const QwtDoubleSize operator*(double) const; - const QwtDoubleSize operator/(double) const; - - QwtDoubleSize &operator+=(const QwtDoubleSize &); - QwtDoubleSize &operator-=(const QwtDoubleSize &); - QwtDoubleSize &operator*=(double c); - QwtDoubleSize &operator/=(double c); - -private: - double d_width; - double d_height; -}; - -/*! - The QwtDoubleRect class defines a size in double coordinates. -*/ - -class QWT_EXPORT QwtDoubleRect -{ -public: - QwtDoubleRect(); - QwtDoubleRect(double left, double top, double width, double height); - QwtDoubleRect(const QwtDoublePoint&, const QwtDoubleSize &); - - QwtDoubleRect(const QRect &); - QRect toRect() const; - - bool isNull() const; - bool isEmpty() const; - bool isValid() const; - - QwtDoubleRect normalized() const; - - double x() const; - double y() const; - - double left() const; - double right() const; - double top() const; - double bottom() const; - - void setX(double); - void setY(double); - - void setLeft(double); - void setRight(double); - void setTop(double); - void setBottom(double); - - QwtDoublePoint center() const; - - void moveLeft(double x); - void moveRight(double x); - void moveTop(double y ); - void moveBottom(double y ); - void moveTo(double x, double y); - void moveTo(const QwtDoublePoint &); - void moveBy(double dx, double dy); - void moveCenter(const QwtDoublePoint &); - void moveCenter(double dx, double dy); - - void setRect(double x1, double x2, double width, double height); - - double width() const; - double height() const; - QwtDoubleSize size() const; - - void setWidth(double w ); - void setHeight(double h ); - void setSize(const QwtDoubleSize &); - - QwtDoubleRect operator|(const QwtDoubleRect &r) const; - QwtDoubleRect operator&(const QwtDoubleRect &r) const; - QwtDoubleRect &operator|=(const QwtDoubleRect &r); - QwtDoubleRect &operator&=(const QwtDoubleRect &r); - bool operator==( const QwtDoubleRect &) const; - bool operator!=( const QwtDoubleRect &) const; - - bool contains(const QwtDoublePoint &p, bool proper = false) const; - bool contains(double x, double y, bool proper = false) const; - bool contains(const QwtDoubleRect &r, bool proper=false) const; - - QwtDoubleRect unite(const QwtDoubleRect &) const; - QwtDoubleRect intersect(const QwtDoubleRect &) const; - bool intersects(const QwtDoubleRect &) const; - - QwtDoublePoint bottomRight() const; - QwtDoublePoint topRight() const; - QwtDoublePoint topLeft() const; - QwtDoublePoint bottomLeft() const; - -private: - double d_left; - double d_right; - double d_top; - double d_bottom; -}; - -/*! - Returns true if the point is null; otherwise returns false. - - A point is considered to be null if both the x- and y-coordinates - are equal to zero. -*/ -inline bool QwtDoublePoint::isNull() const -{ - return d_x == 0.0 && d_y == 0.0; -} - -//! Returns the x-coordinate of the point. -inline double QwtDoublePoint::x() const -{ - return d_x; -} - -//! Returns the y-coordinate of the point. -inline double QwtDoublePoint::y() const -{ - return d_y; -} - -//! Returns a reference to the x-coordinate of the point. -inline double &QwtDoublePoint::rx() -{ - return d_x; -} - -//! Returns a reference to the y-coordinate of the point. -inline double &QwtDoublePoint::ry() -{ - return d_y; -} - -//! Sets the x-coordinate of the point to the value specified by x. -inline void QwtDoublePoint::setX(double x) -{ - d_x = x; -} - -//! Sets the y-coordinate of the point to the value specified by y. -inline void QwtDoublePoint::setY(double y) -{ - d_y = y; -} - -/*! - Rounds the coordinates of this point to the nearest integer and - returns a QPoint with these rounded coordinates. -*/ -inline QPoint QwtDoublePoint::toPoint() const -{ - return QPoint(qRound(d_x), qRound(d_y)); -} - -/*! - Returns true if the width is 0 and the height is 0; - otherwise returns false. -*/ -inline bool QwtDoubleSize::isNull() const -{ - return d_width == 0.0 && d_height == 0.0; -} - -/*! - Returns true if the width is <= 0.0 or the height is <= 0.0, - otherwise false. -*/ -inline bool QwtDoubleSize::isEmpty() const -{ - return d_width <= 0.0 || d_height <= 0.0; -} - -/*! - Returns true if the width is equal to or greater than 0.0 and the height - is equal to or greater than 0.0; otherwise returns false. -*/ -inline bool QwtDoubleSize::isValid() const -{ - return d_width >= 0.0 && d_height >= 0.0; -} - -//! Returns the width. -inline double QwtDoubleSize::width() const -{ - return d_width; -} - -//! Returns the height. -inline double QwtDoubleSize::height() const -{ - return d_height; -} - -//! Sets the width to width. -inline void QwtDoubleSize::setWidth(double width) -{ - d_width = width; -} - -//! Sets the height to height. -inline void QwtDoubleSize::setHeight(double height) -{ - d_height = height; -} - -/*! - Returns true if the rectangle is a null rectangle; otherwise returns false. - A null rectangle has both the width and the height set to 0. - A null rectangle is also empty and invalid. - - \sa isEmpty(), isValid() -*/ -inline bool QwtDoubleRect::isNull() const -{ - return d_right == d_left && d_bottom == d_top; -} - -/*! - Returns true if the rectangle is empty; otherwise returns false. - An empty rectangle has a width() <= 0 or height() <= 0. - An empty rectangle is not valid. isEmpty() == !isValid() - - \sa isNull(), isValid() -*/ -inline bool QwtDoubleRect::isEmpty() const -{ - return d_left >= d_right || d_top >= d_bottom; -} - -/*! - Returns true if the rectangle is valid; otherwise returns false. - A valid rectangle has a width() > 0 and height() > 0. - Note that non-trivial operations like intersections are not defined - for invalid rectangles. isValid() == !isEmpty() - - \sa isNull(), isEmpty(), and normalized(). -*/ -inline bool QwtDoubleRect::isValid() const -{ - return d_left < d_right && d_top < d_bottom; -} - -//! Returns x -inline double QwtDoubleRect::x() const -{ - return d_left; -} - -//! Returns y -inline double QwtDoubleRect::y() const -{ - return d_top; -} - -//! Returns left -inline double QwtDoubleRect::left() const -{ - return d_left; -} - -//! Returns right -inline double QwtDoubleRect::right() const -{ - return d_right; -} - -//! Returns top -inline double QwtDoubleRect::top() const -{ - return d_top; -} - -//! Returns bottom -inline double QwtDoubleRect::bottom() const -{ - return d_bottom; -} - -//! Set left -inline void QwtDoubleRect::setX(double x) -{ - d_left = x; -} - -//! Set left -inline void QwtDoubleRect::setY(double y) -{ - d_top = y; -} - -//! Set left -inline void QwtDoubleRect::setLeft(double x) -{ - d_left = x; -} - -//! Set right -inline void QwtDoubleRect::setRight(double x) -{ - d_right = x; -} - -//! Set top -inline void QwtDoubleRect::setTop(double y) -{ - d_top = y; -} - -//! Set bottom -inline void QwtDoubleRect::setBottom(double y) -{ - d_bottom = y; -} - -//! Returns the width -inline double QwtDoubleRect::width() const -{ - return d_right - d_left; -} - -//! Returns the height -inline double QwtDoubleRect::height() const -{ - return d_bottom - d_top; -} - -//! Returns the size -inline QwtDoubleSize QwtDoubleRect::size() const -{ - return QwtDoubleSize(width(), height()); -} - -//! Set the width, by right = left + w; -inline void QwtDoubleRect::setWidth(double w) -{ - d_right = d_left + w; -} - -//! Set the height, by bottom = top + h; -inline void QwtDoubleRect::setHeight(double h) -{ - d_bottom = d_top + h; -} - -/*! - Moves the top left corner of the rectangle to p, - without changing the rectangles size. -*/ -inline void QwtDoubleRect::moveTo(const QwtDoublePoint &p) -{ - moveTo(p.x(), p.y()); -} - -inline QwtDoublePoint QwtDoubleRect::bottomRight() const -{ - return QwtDoublePoint(bottom(), right()); -} - -inline QwtDoublePoint QwtDoubleRect::topRight() const -{ - return QwtDoublePoint(top(), right()); -} - -inline QwtDoublePoint QwtDoubleRect::topLeft() const -{ - return QwtDoublePoint(top(), left()); -} - -inline QwtDoublePoint QwtDoubleRect::bottomLeft() const -{ - return QwtDoublePoint(bottom(), left()); -} - - -#endif // QT_VERSION < 0x040000 - -#endif // QWT_DOUBLE_RECT_H diff --git a/qwt/src/qwt_dyngrid_layout.cpp b/qwt/src/qwt_dyngrid_layout.cpp index 78fba6fc9..cd621dcfc 100644 --- a/qwt/src/qwt_dyngrid_layout.cpp +++ b/qwt/src/qwt_dyngrid_layout.cpp @@ -7,96 +7,47 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -#include #include "qwt_dyngrid_layout.h" #include "qwt_math.h" - -#if QT_VERSION < 0x040000 -#include -#else +#include #include -#endif class QwtDynGridLayout::PrivateData { public: - -#if QT_VERSION < 0x040000 - class LayoutIterator: public QGLayoutIterator - { - public: - LayoutIterator(PrivateData *data): - d_data(data) - { - d_iterator = d_data->itemList.begin(); - } - - virtual QLayoutItem *current() - { - if (d_iterator == d_data->itemList.end()) - return NULL; - - return *d_iterator; - } - - virtual QLayoutItem *next() - { - if (d_iterator == d_data->itemList.end()) - return NULL; - - d_iterator++; - if (d_iterator == d_data->itemList.end()) - return NULL; - - return *d_iterator; - } - - virtual QLayoutItem *takeCurrent() - { - if ( d_iterator == d_data->itemList.end() ) - return NULL; - - QLayoutItem *item = *d_iterator; - - d_data->isDirty = true; - d_iterator = d_data->itemList.remove(d_iterator); - return item; - } - - private: - - QValueListIterator d_iterator; - QwtDynGridLayout::PrivateData *d_data; - }; -#endif - PrivateData(): - isDirty(true) + isDirty( true ) { } -#if QT_VERSION < 0x040000 - typedef QValueList LayoutItemList; -#else - typedef QList LayoutItemList; -#endif + void updateLayoutCache(); - mutable LayoutItemList itemList; + mutable QList itemList; uint maxCols; uint numRows; uint numCols; -#if QT_VERSION < 0x040000 - QSizePolicy::ExpandData expanding; -#else Qt::Orientations expanding; -#endif bool isDirty; - QwtArray itemSizeHints; + QVector itemSizeHints; }; +void QwtDynGridLayout::PrivateData::updateLayoutCache() +{ + itemSizeHints.resize( itemList.count() ); + + int index = 0; + + for ( QList::iterator it = itemList.begin(); + it != itemList.end(); ++it, index++ ) + { + itemSizeHints[ index ] = ( *it )->sizeHint(); + } + + isDirty = false; +} /*! \param parent Parent widget @@ -104,36 +55,24 @@ public: \param spacing Spacing */ -QwtDynGridLayout::QwtDynGridLayout(QWidget *parent, - int margin, int spacing): - QLayout(parent) +QwtDynGridLayout::QwtDynGridLayout( QWidget *parent, + int margin, int spacing ): + QLayout( parent ) { init(); - setSpacing(spacing); - setMargin(margin); + setSpacing( spacing ); + setMargin( margin ); } -#if QT_VERSION < 0x040000 -/*! - \param parent Parent widget - \param spacing Spacing -*/ -QwtDynGridLayout::QwtDynGridLayout(QLayout *parent, int spacing): - QLayout(parent, spacing) -{ - init(); -} -#endif - /*! \param spacing Spacing */ -QwtDynGridLayout::QwtDynGridLayout(int spacing) +QwtDynGridLayout::QwtDynGridLayout( int spacing ) { init(); - setSpacing(spacing); + setSpacing( spacing ); } /*! @@ -142,24 +81,16 @@ QwtDynGridLayout::QwtDynGridLayout(int spacing) void QwtDynGridLayout::init() { d_data = new QwtDynGridLayout::PrivateData; - d_data->maxCols = d_data->numRows - = d_data->numCols = 0; - -#if QT_VERSION < 0x040000 - d_data->expanding = QSizePolicy::NoDirection; - setSupportsMargin(true); -#else + d_data->maxCols = d_data->numRows = d_data->numCols = 0; d_data->expanding = 0; -#endif } //! Destructor QwtDynGridLayout::~QwtDynGridLayout() { -#if QT_VERSION < 0x040000 - deleteAllItems(); -#endif + for ( int i = 0; i < d_data->itemList.size(); i++ ) + delete d_data->itemList[i]; delete d_data; } @@ -171,28 +102,12 @@ void QwtDynGridLayout::invalidate() QLayout::invalidate(); } -void QwtDynGridLayout::updateLayoutCache() -{ - d_data->itemSizeHints.resize(itemCount()); - - int index = 0; - - for (PrivateData::LayoutItemList::iterator it = d_data->itemList.begin(); - it != d_data->itemList.end(); ++it, index++) - { - d_data->itemSizeHints[int(index)] = (*it)->sizeHint(); - } - - d_data->isDirty = false; -} - /*! Limit the number of columns. \param maxCols upper limit, 0 means unlimited \sa maxCols() */ - -void QwtDynGridLayout::setMaxCols(uint maxCols) +void QwtDynGridLayout::setMaxCols( uint maxCols ) { d_data->maxCols = maxCols; } @@ -203,21 +118,21 @@ void QwtDynGridLayout::setMaxCols(uint maxCols) \sa setMaxCols() */ -uint QwtDynGridLayout::maxCols() const -{ - return d_data->maxCols; +uint QwtDynGridLayout::maxCols() const +{ + return d_data->maxCols; } //! Adds item to the next free position. -void QwtDynGridLayout::addItem(QLayoutItem *item) +void QwtDynGridLayout::addItem( QLayoutItem *item ) { - d_data->itemList.append(item); + d_data->itemList.append( item ); invalidate(); } -/*! - \return true if this layout is empty. +/*! + \return true if this layout is empty. */ bool QwtDynGridLayout::isEmpty() const @@ -225,7 +140,7 @@ bool QwtDynGridLayout::isEmpty() const return d_data->itemList.isEmpty(); } -/*! +/*! \return number of layout items */ @@ -234,29 +149,6 @@ uint QwtDynGridLayout::itemCount() const return d_data->itemList.count(); } -#if QT_VERSION < 0x040000 -/*! - \return An iterator over the children of this layout. -*/ - -QLayoutIterator QwtDynGridLayout::iterator() -{ - return QLayoutIterator( - new QwtDynGridLayout::PrivateData::LayoutIterator(d_data) ); -} - -void QwtDynGridLayout::setExpanding(QSizePolicy::ExpandData expanding) -{ - d_data->expanding = expanding; -} - -QSizePolicy::ExpandData QwtDynGridLayout::expanding() const -{ - return d_data->expanding; -} - -#else // QT_VERSION >= 0x040000 - /*! Find the item at a spcific index @@ -268,9 +160,9 @@ QLayoutItem *QwtDynGridLayout::itemAt( int index ) const if ( index < 0 || index >= d_data->itemList.count() ) return NULL; - return d_data->itemList.at(index); + return d_data->itemList.at( index ); } - + /*! Find the item at a spcific index and remove it from the layout @@ -281,9 +173,9 @@ QLayoutItem *QwtDynGridLayout::takeAt( int index ) { if ( index < 0 || index >= d_data->itemList.count() ) return NULL; - + d_data->isDirty = true; - return d_data->itemList.takeAt(index); + return d_data->itemList.takeAt( index ); } //! \return Number of items in the layout @@ -295,13 +187,13 @@ int QwtDynGridLayout::count() const /*! Set whether this layout can make use of more space than sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only - one dimension, while Qt::Vertical | Qt::Horizontal means that it wants + one dimension, while Qt::Vertical | Qt::Horizontal means that it wants to grow in both dimensions. The default value is 0. \param expanding Or'd orientations \sa expandingDirections() */ -void QwtDynGridLayout::setExpandingDirections(Qt::Orientations expanding) +void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding ) { d_data->expanding = expanding; } @@ -309,7 +201,7 @@ void QwtDynGridLayout::setExpandingDirections(Qt::Orientations expanding) /*! Returns whether this layout can make use of more space than sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only - one dimension, while Qt::Vertical | Qt::Horizontal means that it wants + one dimension, while Qt::Vertical | Qt::Horizontal means that it wants to grow in both dimensions. \sa setExpandingDirections() */ @@ -318,46 +210,40 @@ Qt::Orientations QwtDynGridLayout::expandingDirections() const return d_data->expanding; } -#endif - /*! - Reorganizes columns and rows and resizes managed widgets within - the rectangle rect. + Reorganizes columns and rows and resizes managed widgets within + the rectangle rect. \param rect Layout geometry */ -void QwtDynGridLayout::setGeometry(const QRect &rect) +void QwtDynGridLayout::setGeometry( const QRect &rect ) { - QLayout::setGeometry(rect); + QLayout::setGeometry( rect ); if ( isEmpty() ) return; - d_data->numCols = columnsForWidth(rect.width()); + d_data->numCols = columnsForWidth( rect.width() ); d_data->numRows = itemCount() / d_data->numCols; if ( itemCount() % d_data->numCols ) d_data->numRows++; -#if QT_VERSION < 0x040000 - QValueList itemGeometries = layoutItems(rect, d_data->numCols); -#else - QList itemGeometries = layoutItems(rect, d_data->numCols); -#endif + QList itemGeometries = layoutItems( rect, d_data->numCols ); int index = 0; - for (PrivateData::LayoutItemList::iterator it = d_data->itemList.begin(); - it != d_data->itemList.end(); ++it) + for ( QList::iterator it = d_data->itemList.begin(); + it != d_data->itemList.end(); ++it ) { - QWidget *w = (*it)->widget(); + QWidget *w = ( *it )->widget(); if ( w ) { - w->setGeometry(itemGeometries[index]); + w->setGeometry( itemGeometries[index] ); index++; } } } -/*! +/*! Calculate the number of columns for a given width. It tries to use as many columns as possible (limited by maxCols()) @@ -365,18 +251,18 @@ void QwtDynGridLayout::setGeometry(const QRect &rect) \sa maxCols(), setMaxCols() */ -uint QwtDynGridLayout::columnsForWidth(int width) const +uint QwtDynGridLayout::columnsForWidth( int width ) const { if ( isEmpty() ) return 0; - const int maxCols = (d_data->maxCols > 0) ? d_data->maxCols : itemCount(); - if ( maxRowWidth(maxCols) <= width ) + const int maxCols = ( d_data->maxCols > 0 ) ? d_data->maxCols : itemCount(); + if ( maxRowWidth( maxCols ) <= width ) return maxCols; - for (int numCols = 2; numCols <= maxCols; numCols++ ) + for ( int numCols = 2; numCols <= maxCols; numCols++ ) { - const int rowWidth = maxRowWidth(numCols); + const int rowWidth = maxRowWidth( numCols ); if ( rowWidth > width ) return numCols - 1; } @@ -384,34 +270,34 @@ uint QwtDynGridLayout::columnsForWidth(int width) const return 1; // At least 1 column } -/*! +/*! Calculate the width of a layout for a given number of columns. \param numCols Given number of columns \param itemWidth Array of the width hints for all items */ -int QwtDynGridLayout::maxRowWidth(int numCols) const +int QwtDynGridLayout::maxRowWidth( int numCols ) const { int col; - QwtArray colWidth(numCols); - for ( col = 0; col < (int)numCols; col++ ) + QVector colWidth( numCols ); + for ( col = 0; col < numCols; col++ ) colWidth[col] = 0; if ( d_data->isDirty ) - ((QwtDynGridLayout*)this)->updateLayoutCache(); + d_data->updateLayoutCache(); - for ( uint index = 0; - index < (uint)d_data->itemSizeHints.count(); index++ ) + for ( int index = 0; + index < d_data->itemSizeHints.count(); index++ ) { col = index % numCols; - colWidth[col] = qwtMax(colWidth[col], - d_data->itemSizeHints[int(index)].width()); + colWidth[col] = qMax( colWidth[col], + d_data->itemSizeHints[int( index )].width() ); } - int rowWidth = 2 * margin() + (numCols - 1) * spacing(); - for ( col = 0; col < (int)numCols; col++ ) + int rowWidth = 2 * margin() + ( numCols - 1 ) * spacing(); + for ( col = 0; col < numCols; col++ ) rowWidth += colWidth[col]; return rowWidth; @@ -426,12 +312,12 @@ int QwtDynGridLayout::maxItemWidth() const return 0; if ( d_data->isDirty ) - ((QwtDynGridLayout*)this)->updateLayoutCache(); + d_data->updateLayoutCache(); int w = 0; - for ( uint i = 0; i < (uint)d_data->itemSizeHints.count(); i++ ) + for ( int i = 0; i < d_data->itemSizeHints.count(); i++ ) { - const int itemW = d_data->itemSizeHints[int(i)].width(); + const int itemW = d_data->itemSizeHints[i].width(); if ( itemW > w ) w = itemW; } @@ -448,74 +334,59 @@ int QwtDynGridLayout::maxItemWidth() const \return item geometries */ -#if QT_VERSION < 0x040000 -QValueList QwtDynGridLayout::layoutItems(const QRect &rect, - uint numCols) const -#else -QList QwtDynGridLayout::layoutItems(const QRect &rect, - uint numCols) const -#endif +QList QwtDynGridLayout::layoutItems( const QRect &rect, + uint numCols ) const { -#if QT_VERSION < 0x040000 - QValueList itemGeometries; -#else QList itemGeometries; -#endif if ( numCols == 0 || isEmpty() ) return itemGeometries; uint numRows = itemCount() / numCols; if ( numRows % itemCount() ) numRows++; - - QwtArray rowHeight(numRows); - QwtArray colWidth(numCols); - - layoutGrid(numCols, rowHeight, colWidth); + + QVector rowHeight( numRows ); + QVector colWidth( numCols ); + + layoutGrid( numCols, rowHeight, colWidth ); bool expandH, expandV; -#if QT_VERSION >= 0x040000 expandH = expandingDirections() & Qt::Horizontal; expandV = expandingDirections() & Qt::Vertical; -#else - expandH = expanding() & QSizePolicy::Horizontally; - expandV = expanding() & QSizePolicy::Vertically; -#endif if ( expandH || expandV ) - stretchGrid(rect, numCols, rowHeight, colWidth); + stretchGrid( rect, numCols, rowHeight, colWidth ); - QwtDynGridLayout *that = (QwtDynGridLayout *)this; const int maxCols = d_data->maxCols; - that->d_data->maxCols = numCols; - const QRect alignedRect = alignmentRect(rect); - that->d_data->maxCols = maxCols; + d_data->maxCols = numCols; + const QRect alignedRect = alignmentRect( rect ); + d_data->maxCols = maxCols; const int xOffset = expandH ? 0 : alignedRect.x(); const int yOffset = expandV ? 0 : alignedRect.y(); - QwtArray colX(numCols); - QwtArray rowY(numRows); + QVector colX( numCols ); + QVector rowY( numRows ); const int xySpace = spacing(); rowY[0] = yOffset + margin(); - for ( int r = 1; r < (int)numRows; r++ ) + for ( int r = 1; r < ( int )numRows; r++ ) rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace; colX[0] = xOffset + margin(); - for ( int c = 1; c < (int)numCols; c++ ) + for ( int c = 1; c < ( int )numCols; c++ ) colX[c] = colX[c-1] + colWidth[c-1] + xySpace; - + const int itemCount = d_data->itemList.size(); for ( int i = 0; i < itemCount; i++ ) { const int row = i / numCols; const int col = i % numCols; - QRect itemGeometry(colX[col], rowY[row], - colWidth[col], rowHeight[row]); - itemGeometries.append(itemGeometry); + QRect itemGeometry( colX[col], rowY[row], + colWidth[col], rowHeight[row] ); + itemGeometries.append( itemGeometry ); } return itemGeometries; @@ -531,27 +402,27 @@ QList QwtDynGridLayout::layoutItems(const QRect &rect, \param colWidth Array where to fill in the calculated column widths. */ -void QwtDynGridLayout::layoutGrid(uint numCols, - QwtArray& rowHeight, QwtArray& colWidth) const +void QwtDynGridLayout::layoutGrid( uint numCols, + QVector& rowHeight, QVector& colWidth ) const { if ( numCols <= 0 ) return; if ( d_data->isDirty ) - ((QwtDynGridLayout*)this)->updateLayoutCache(); + d_data->updateLayoutCache(); - for ( uint index = 0; - index < (uint)d_data->itemSizeHints.count(); index++ ) + for ( uint index = 0; + index < ( uint )d_data->itemSizeHints.count(); index++ ) { const int row = index / numCols; const int col = index % numCols; - const QSize &size = d_data->itemSizeHints[int(index)]; + const QSize &size = d_data->itemSizeHints[int( index )]; - rowHeight[row] = (col == 0) - ? size.height() : qwtMax(rowHeight[row], size.height()); - colWidth[col] = (row == 0) - ? size.width() : qwtMax(colWidth[col], size.width()); + rowHeight[row] = ( col == 0 ) + ? size.height() : qMax( rowHeight[row], size.height() ); + colWidth[col] = ( row == 0 ) + ? size.width() : qMax( colWidth[col], size.width() ); } } @@ -565,26 +436,26 @@ bool QwtDynGridLayout::hasHeightForWidth() const } /*! - \return The preferred height for this layout, given the width w. + \return The preferred height for this layout, given the width w. \sa hasHeightForWidth() */ -int QwtDynGridLayout::heightForWidth(int width) const +int QwtDynGridLayout::heightForWidth( int width ) const { if ( isEmpty() ) return 0; - const uint numCols = columnsForWidth(width); + const uint numCols = columnsForWidth( width ); uint numRows = itemCount() / numCols; if ( itemCount() % numCols ) numRows++; - QwtArray rowHeight(numRows); - QwtArray colWidth(numCols); + QVector rowHeight( numRows ); + QVector colWidth( numCols ); - layoutGrid(numCols, rowHeight, colWidth); + layoutGrid( numCols, rowHeight, colWidth ); - int h = 2 * margin() + (numRows - 1) * spacing(); - for ( int row = 0; row < (int)numRows; row++ ) + int h = 2 * margin() + ( numRows - 1 ) * spacing(); + for ( int row = 0; row < ( int )numRows; row++ ) h += rowHeight[row]; return h; @@ -597,32 +468,27 @@ int QwtDynGridLayout::heightForWidth(int width) const \sa setExpanding(), expanding() */ -void QwtDynGridLayout::stretchGrid(const QRect &rect, - uint numCols, QwtArray& rowHeight, QwtArray& colWidth) const +void QwtDynGridLayout::stretchGrid( const QRect &rect, + uint numCols, QVector& rowHeight, QVector& colWidth ) const { if ( numCols == 0 || isEmpty() ) return; bool expandH, expandV; -#if QT_VERSION >= 0x040000 expandH = expandingDirections() & Qt::Horizontal; expandV = expandingDirections() & Qt::Vertical; -#else - expandH = expanding() & QSizePolicy::Horizontally; - expandV = expanding() & QSizePolicy::Vertically; -#endif if ( expandH ) { - int xDelta = rect.width() - 2 * margin() - (numCols - 1) * spacing(); - for ( int col = 0; col < (int)numCols; col++ ) + int xDelta = rect.width() - 2 * margin() - ( numCols - 1 ) * spacing(); + for ( int col = 0; col < ( int )numCols; col++ ) xDelta -= colWidth[col]; if ( xDelta > 0 ) { - for ( int col = 0; col < (int)numCols; col++ ) + for ( int col = 0; col < ( int )numCols; col++ ) { - const int space = xDelta / (numCols - col); + const int space = xDelta / ( numCols - col ); colWidth[col] += space; xDelta -= space; } @@ -635,15 +501,15 @@ void QwtDynGridLayout::stretchGrid(const QRect &rect, if ( itemCount() % numCols ) numRows++; - int yDelta = rect.height() - 2 * margin() - (numRows - 1) * spacing(); - for ( int row = 0; row < (int)numRows; row++ ) + int yDelta = rect.height() - 2 * margin() - ( numRows - 1 ) * spacing(); + for ( int row = 0; row < ( int )numRows; row++ ) yDelta -= rowHeight[row]; if ( yDelta > 0 ) { - for ( int row = 0; row < (int)numRows; row++ ) + for ( int row = 0; row < ( int )numRows; row++ ) { - const int space = yDelta / (numRows - row); + const int space = yDelta / ( numRows - row ); rowHeight[row] += space; yDelta -= space; } @@ -663,25 +529,25 @@ QSize QwtDynGridLayout::sizeHint() const if ( isEmpty() ) return QSize(); - const uint numCols = (d_data->maxCols > 0 ) ? d_data->maxCols : itemCount(); + const uint numCols = ( d_data->maxCols > 0 ) ? d_data->maxCols : itemCount(); uint numRows = itemCount() / numCols; if ( itemCount() % numCols ) numRows++; - QwtArray rowHeight(numRows); - QwtArray colWidth(numCols); + QVector rowHeight( numRows ); + QVector colWidth( numCols ); - layoutGrid(numCols, rowHeight, colWidth); + layoutGrid( numCols, rowHeight, colWidth ); - int h = 2 * margin() + (numRows - 1) * spacing(); - for ( int row = 0; row < (int)numRows; row++ ) + int h = 2 * margin() + ( numRows - 1 ) * spacing(); + for ( int row = 0; row < ( int )numRows; row++ ) h += rowHeight[row]; - int w = 2 * margin() + (numCols - 1) * spacing(); - for ( int col = 0; col < (int)numCols; col++ ) + int w = 2 * margin() + ( numCols - 1 ) * spacing(); + for ( int col = 0; col < ( int )numCols; col++ ) w += colWidth[col]; - return QSize(w, h); + return QSize( w, h ); } /*! @@ -689,9 +555,9 @@ QSize QwtDynGridLayout::sizeHint() const \sa numCols() \warning The number of rows might change whenever the geometry changes */ -uint QwtDynGridLayout::numRows() const -{ - return d_data->numRows; +uint QwtDynGridLayout::numRows() const +{ + return d_data->numRows; } /*! @@ -699,7 +565,7 @@ uint QwtDynGridLayout::numRows() const \sa numRows() \warning The number of columns might change whenever the geometry changes */ -uint QwtDynGridLayout::numCols() const -{ - return d_data->numCols; +uint QwtDynGridLayout::numCols() const +{ + return d_data->numCols; } diff --git a/qwt/src/qwt_dyngrid_layout.h b/qwt/src/qwt_dyngrid_layout.h index 0fa1cc22d..0b835f03a 100644 --- a/qwt/src/qwt_dyngrid_layout.h +++ b/qwt/src/qwt_dyngrid_layout.h @@ -10,22 +10,17 @@ #ifndef QWT_DYNGRID_LAYOUT_H #define QWT_DYNGRID_LAYOUT_H +#include "qwt_global.h" #include #include -#if QT_VERSION >= 0x040000 #include -#else -#include -#endif -#include "qwt_global.h" -#include "qwt_array.h" /*! \brief The QwtDynGridLayout class lays out widgets in a grid, adjusting the number of columns and rows to the current size. - - QwtDynGridLayout takes the space it gets, divides it up into rows and - columns, and puts each of the widgets it manages into the correct cell(s). + + QwtDynGridLayout takes the space it gets, divides it up into rows and + columns, and puts each of the widgets it manages into the correct cell(s). It lays out as many number of columns as possible (limited by maxCols()). */ @@ -33,74 +28,55 @@ class QWT_EXPORT QwtDynGridLayout : public QLayout { Q_OBJECT public: - explicit QwtDynGridLayout(QWidget *, int margin = 0, int space = -1); -#if QT_VERSION < 0x040000 - explicit QwtDynGridLayout(QLayout *, int space = -1); -#endif - explicit QwtDynGridLayout(int space = -1); + explicit QwtDynGridLayout( QWidget *, int margin = 0, int space = -1 ); + explicit QwtDynGridLayout( int space = -1 ); virtual ~QwtDynGridLayout(); virtual void invalidate(); - void setMaxCols(uint maxCols); + void setMaxCols( uint maxCols ); uint maxCols() const; - uint numRows () const; + uint numRows () const; uint numCols () const; - virtual void addItem(QLayoutItem *); + virtual void addItem( QLayoutItem * ); -#if QT_VERSION >= 0x040000 virtual QLayoutItem *itemAt( int index ) const; virtual QLayoutItem *takeAt( int index ); virtual int count() const; - void setExpandingDirections(Qt::Orientations); + void setExpandingDirections( Qt::Orientations ); virtual Qt::Orientations expandingDirections() const; - QList layoutItems(const QRect &, uint numCols) const; -#else - virtual QLayoutIterator iterator(); - - void setExpanding(QSizePolicy::ExpandData); - virtual QSizePolicy::ExpandData expanding() const; - QValueList layoutItems(const QRect &, uint numCols) const; -#endif + QList layoutItems( const QRect &, uint numCols ) const; virtual int maxItemWidth() const; - virtual void setGeometry(const QRect &rect); + virtual void setGeometry( const QRect &rect ); virtual bool hasHeightForWidth() const; - virtual int heightForWidth(int) const; + virtual int heightForWidth( int ) const; virtual QSize sizeHint() const; virtual bool isEmpty() const; uint itemCount() const; - virtual uint columnsForWidth(int width) const; + virtual uint columnsForWidth( int width ) const; protected: - void layoutGrid(uint numCols, - QwtArray& rowHeight, QwtArray& colWidth) const; - void stretchGrid(const QRect &rect, uint numCols, - QwtArray& rowHeight, QwtArray& colWidth) const; - + void layoutGrid( uint numCols, + QVector& rowHeight, QVector& colWidth ) const; + void stretchGrid( const QRect &rect, uint numCols, + QVector& rowHeight, QVector& colWidth ) const; private: void init(); - int maxRowWidth(int numCols) const; - void updateLayoutCache(); + int maxRowWidth( int numCols ) const; -#if QT_VERSION < 0x040000 -// xlC 5.1, the IBM/AIX C++ compiler, needs it to be public -public: -#endif - class PrivateData; - -private: + class PrivateData; PrivateData *d_data; }; diff --git a/qwt/src/qwt_event_pattern.cpp b/qwt/src/qwt_event_pattern.cpp index 73a51d228..2579616c1 100644 --- a/qwt/src/qwt_event_pattern.cpp +++ b/qwt/src/qwt_event_pattern.cpp @@ -7,21 +7,21 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -#include #include "qwt_event_pattern.h" +#include -/*! +/*! Constructor \sa MousePatternCode, KeyPatternCode */ QwtEventPattern::QwtEventPattern(): - d_mousePattern(MousePatternCount), - d_keyPattern(KeyPatternCount) + d_mousePattern( MousePatternCount ), + d_keyPattern( KeyPatternCount ) { initKeyPattern(); - initMousePattern(3); + initMousePattern( 3 ); } //! Destructor @@ -35,48 +35,42 @@ QwtEventPattern::~QwtEventPattern() \param numButtons Number of mouse buttons ( <= 3 ) \sa MousePatternCode */ -void QwtEventPattern::initMousePattern(int numButtons) +void QwtEventPattern::initMousePattern( int numButtons ) { -#if QT_VERSION < 0x040000 - const int altButton = Qt::AltButton; - const int controlButton = Qt::ControlButton; - const int shiftButton = Qt::ShiftButton; -#else const int altButton = Qt::AltModifier; const int controlButton = Qt::ControlModifier; const int shiftButton = Qt::ShiftModifier; -#endif - d_mousePattern.resize(MousePatternCount); + d_mousePattern.resize( MousePatternCount ); - switch(numButtons) + switch ( numButtons ) { case 1: { - setMousePattern(MouseSelect1, Qt::LeftButton); - setMousePattern(MouseSelect2, Qt::LeftButton, controlButton); - setMousePattern(MouseSelect3, Qt::LeftButton, altButton); + setMousePattern( MouseSelect1, Qt::LeftButton ); + setMousePattern( MouseSelect2, Qt::LeftButton, controlButton ); + setMousePattern( MouseSelect3, Qt::LeftButton, altButton ); break; } case 2: { - setMousePattern(MouseSelect1, Qt::LeftButton); - setMousePattern(MouseSelect2, Qt::RightButton); - setMousePattern(MouseSelect3, Qt::LeftButton, altButton); + setMousePattern( MouseSelect1, Qt::LeftButton ); + setMousePattern( MouseSelect2, Qt::RightButton ); + setMousePattern( MouseSelect3, Qt::LeftButton, altButton ); break; } default: { - setMousePattern(MouseSelect1, Qt::LeftButton); - setMousePattern(MouseSelect2, Qt::RightButton); - setMousePattern(MouseSelect3, Qt::MidButton); + setMousePattern( MouseSelect1, Qt::LeftButton ); + setMousePattern( MouseSelect2, Qt::RightButton ); + setMousePattern( MouseSelect3, Qt::MidButton ); } } for ( int i = 0; i < 3; i++ ) { - setMousePattern(MouseSelect4 + i, - d_mousePattern[MouseSelect1 + i].button, - d_mousePattern[MouseSelect1 + i].state | shiftButton); + setMousePattern( MouseSelect4 + i, + d_mousePattern[MouseSelect1 + i].button, + d_mousePattern[MouseSelect1 + i].state | shiftButton ); } } @@ -87,20 +81,20 @@ void QwtEventPattern::initMousePattern(int numButtons) */ void QwtEventPattern::initKeyPattern() { - d_keyPattern.resize(KeyPatternCount); + d_keyPattern.resize( KeyPatternCount ); - setKeyPattern(KeySelect1, Qt::Key_Return); - setKeyPattern(KeySelect2, Qt::Key_Space); - setKeyPattern(KeyAbort, Qt::Key_Escape); + setKeyPattern( KeySelect1, Qt::Key_Return ); + setKeyPattern( KeySelect2, Qt::Key_Space ); + setKeyPattern( KeyAbort, Qt::Key_Escape ); - setKeyPattern(KeyLeft, Qt::Key_Left); - setKeyPattern(KeyRight, Qt::Key_Right); - setKeyPattern(KeyUp, Qt::Key_Up); - setKeyPattern(KeyDown, Qt::Key_Down); + setKeyPattern( KeyLeft, Qt::Key_Left ); + setKeyPattern( KeyRight, Qt::Key_Right ); + setKeyPattern( KeyUp, Qt::Key_Up ); + setKeyPattern( KeyDown, Qt::Key_Down ); - setKeyPattern(KeyRedo, Qt::Key_Plus); - setKeyPattern(KeyUndo, Qt::Key_Minus); - setKeyPattern(KeyHome, Qt::Key_Escape); + setKeyPattern( KeyRedo, Qt::Key_Plus ); + setKeyPattern( KeyUndo, Qt::Key_Minus ); + setKeyPattern( KeyHome, Qt::Key_Escape ); } /*! @@ -112,12 +106,12 @@ void QwtEventPattern::initKeyPattern() \sa QMouseEvent */ -void QwtEventPattern::setMousePattern(uint pattern, int button, int state) +void QwtEventPattern::setMousePattern( uint pattern, int button, int state ) { - if ( pattern < (uint)d_mousePattern.count() ) + if ( pattern < ( uint )d_mousePattern.count() ) { - d_mousePattern[int(pattern)].button = button; - d_mousePattern[int(pattern)].state = state; + d_mousePattern[int( pattern )].button = button; + d_mousePattern[int( pattern )].state = state; } } @@ -130,159 +124,151 @@ void QwtEventPattern::setMousePattern(uint pattern, int button, int state) \sa QKeyEvent */ -void QwtEventPattern::setKeyPattern(uint pattern, int key, int state) +void QwtEventPattern::setKeyPattern( uint pattern, int key, int state ) { - if ( pattern < (uint)d_keyPattern.count() ) + if ( pattern < ( uint )d_keyPattern.count() ) { - d_keyPattern[int(pattern)].key = key; - d_keyPattern[int(pattern)].state = state; + d_keyPattern[int( pattern )].key = key; + d_keyPattern[int( pattern )].state = state; } } //! Change the mouse event patterns -void QwtEventPattern::setMousePattern(const QwtArray &pattern) +void QwtEventPattern::setMousePattern( const QVector &pattern ) { d_mousePattern = pattern; } //! Change the key event patterns -void QwtEventPattern::setKeyPattern(const QwtArray &pattern) +void QwtEventPattern::setKeyPattern( const QVector &pattern ) { d_keyPattern = pattern; } //! Return mouse patterns -const QwtArray & +const QVector & QwtEventPattern::mousePattern() const { return d_mousePattern; } //! Return key patterns -const QwtArray & +const QVector & QwtEventPattern::keyPattern() const { return d_keyPattern; } //! Return ,ouse patterns -QwtArray &QwtEventPattern::mousePattern() +QVector &QwtEventPattern::mousePattern() { return d_mousePattern; } //! Return Key patterns -QwtArray &QwtEventPattern::keyPattern() +QVector &QwtEventPattern::keyPattern() { return d_keyPattern; } /*! - \brief Compare a mouse event with an event pattern. + \brief Compare a mouse event with an event pattern. A mouse event matches the pattern when both have the same button value and in the state value the same key flags(Qt::KeyButtonMask) are set. - + \param pattern Index of the event pattern - \param e Mouse event + \param event Mouse event \return true if matches \sa keyMatch() */ -bool QwtEventPattern::mouseMatch(uint pattern, const QMouseEvent *e) const +bool QwtEventPattern::mouseMatch( uint pattern, + const QMouseEvent *event ) const { bool ok = false; - if ( e && pattern < (uint)d_mousePattern.count() ) - ok = mouseMatch(d_mousePattern[int(pattern)], e); + if ( event && pattern < ( uint )d_mousePattern.count() ) + ok = mouseMatch( d_mousePattern[int( pattern )], event ); return ok; } /*! - \brief Compare a mouse event with an event pattern. + \brief Compare a mouse event with an event pattern. A mouse event matches the pattern when both have the same button value and in the state value the same key flags(Qt::KeyButtonMask) are set. - + \param pattern Mouse event pattern - \param e Mouse event + \param event Mouse event \return true if matches \sa keyMatch() */ -bool QwtEventPattern::mouseMatch(const MousePattern &pattern, - const QMouseEvent *e) const +bool QwtEventPattern::mouseMatch( const MousePattern &pattern, + const QMouseEvent *event ) const { - if ( e->button() != pattern.button ) + if ( event->button() != pattern.button ) return false; const bool matched = -#if QT_VERSION < 0x040000 - (e->state() & Qt::KeyButtonMask) == - (pattern.state & Qt::KeyButtonMask); -#else - (e->modifiers() & Qt::KeyboardModifierMask) == - (int)(pattern.state & Qt::KeyboardModifierMask); -#endif + ( event->modifiers() & Qt::KeyboardModifierMask ) == + ( int )( pattern.state & Qt::KeyboardModifierMask ); return matched; } /*! - \brief Compare a key event with an event pattern. + \brief Compare a key event with an event pattern. A key event matches the pattern when both have the same key value and in the state value the same key flags (Qt::KeyButtonMask) are set. - + \param pattern Index of the event pattern - \param e Key event + \param event Key event \return true if matches \sa mouseMatch() */ -bool QwtEventPattern::keyMatch(uint pattern, const QKeyEvent *e) const +bool QwtEventPattern::keyMatch( uint pattern, + const QKeyEvent *event ) const { bool ok = false; - if ( e && pattern < (uint)d_keyPattern.count() ) - ok = keyMatch(d_keyPattern[int(pattern)], e); + if ( event && pattern < ( uint )d_keyPattern.count() ) + ok = keyMatch( d_keyPattern[int( pattern )], event ); return ok; } /*! - \brief Compare a key event with an event pattern. + \brief Compare a key event with an event pattern. A key event matches the pattern when both have the same key value and in the state value the same key flags (Qt::KeyButtonMask) are set. - + \param pattern Key event pattern - \param e Key event + \param event Key event \return true if matches \sa mouseMatch() */ bool QwtEventPattern::keyMatch( - const KeyPattern &pattern, const QKeyEvent *e) const + const KeyPattern &pattern, const QKeyEvent *event ) const { - if ( e->key() != pattern.key) + if ( event->key() != pattern.key ) return false; const bool matched = -#if QT_VERSION < 0x040000 - (e->state() & Qt::KeyButtonMask) == - (pattern.state & Qt::KeyButtonMask); -#else - (e->modifiers() & Qt::KeyboardModifierMask) == - (int)(pattern.state & Qt::KeyboardModifierMask); -#endif + ( event->modifiers() & Qt::KeyboardModifierMask ) == + ( int )( pattern.state & Qt::KeyboardModifierMask ); return matched; } diff --git a/qwt/src/qwt_event_pattern.h b/qwt/src/qwt_event_pattern.h index 546f3da67..a88f5f4a9 100644 --- a/qwt/src/qwt_event_pattern.h +++ b/qwt/src/qwt_event_pattern.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,8 +10,9 @@ #ifndef QWT_EVENT_PATTERN #define QWT_EVENT_PATTERN 1 +#include "qwt_global.h" #include -#include "qwt_array.h" +#include class QMouseEvent; class QKeyEvent; @@ -20,7 +21,7 @@ class QKeyEvent; \brief A collection of event patterns QwtEventPattern introduces an level of indirection for mouse and - keyboard inputs. Those are represented by symbolic names, so + keyboard inputs. Those are represented by symbolic names, so the application code can be configured by individual mappings. \sa QwtPicker, QwtPickerMachine, QwtPlotZoomer @@ -137,13 +138,17 @@ public: class MousePattern { public: - MousePattern(int btn = Qt::NoButton, int st = Qt::NoButton) - { + //! Constructor + MousePattern( int btn = Qt::NoButton, int st = Qt::NoButton ) + { button = btn; state = st; } + //! Button code int button; + + //! State int state; }; @@ -151,71 +156,70 @@ public: class KeyPattern { public: - KeyPattern(int k = 0, int st = Qt::NoButton) - { - key = k; + //! Constructor + KeyPattern( int k = 0, int st = Qt::NoButton ) + { + key = k; state = st; } + //! Key code int key; + + //! State int state; }; QwtEventPattern(); virtual ~QwtEventPattern(); - void initMousePattern(int numButtons); + void initMousePattern( int numButtons ); void initKeyPattern(); - void setMousePattern(uint pattern, int button, int state = Qt::NoButton); - void setKeyPattern(uint pattern, int key, int state = Qt::NoButton); + void setMousePattern( uint pattern, int button, int state = Qt::NoButton ); + void setKeyPattern( uint pattern, int key, int state = Qt::NoButton ); - void setMousePattern(const QwtArray &); - void setKeyPattern(const QwtArray &); + void setMousePattern( const QVector & ); + void setKeyPattern( const QVector & ); - const QwtArray &mousePattern() const; - const QwtArray &keyPattern() const; + const QVector &mousePattern() const; + const QVector &keyPattern() const; - QwtArray &mousePattern(); - QwtArray &keyPattern(); + QVector &mousePattern(); + QVector &keyPattern(); - bool mouseMatch(uint pattern, const QMouseEvent *) const; - bool keyMatch(uint pattern, const QKeyEvent *) const; + bool mouseMatch( uint pattern, const QMouseEvent * ) const; + bool keyMatch( uint pattern, const QKeyEvent * ) const; protected: - virtual bool mouseMatch(const MousePattern &, const QMouseEvent *) const; - virtual bool keyMatch(const KeyPattern &, const QKeyEvent *) const; - + virtual bool mouseMatch( const MousePattern &, const QMouseEvent * ) const; + virtual bool keyMatch( const KeyPattern &, const QKeyEvent * ) const; + private: #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable: 4251) #endif - QwtArray d_mousePattern; - QwtArray d_keyPattern; + QVector d_mousePattern; + QVector d_keyPattern; #if defined(_MSC_VER) #pragma warning(pop) #endif }; -inline bool operator==(QwtEventPattern::MousePattern b1, - QwtEventPattern::MousePattern b2) -{ - return b1.button == b2.button && b1.state == b2.state; +//! Compare operator +inline bool operator==( QwtEventPattern::MousePattern b1, + QwtEventPattern::MousePattern b2 ) +{ + return b1.button == b2.button && b1.state == b2.state; } -inline bool operator==(QwtEventPattern::KeyPattern b1, - QwtEventPattern::KeyPattern b2) -{ - return b1.key == b2.key && b1.state == b2.state; +//! Compare operator +inline bool operator==( QwtEventPattern::KeyPattern b1, + QwtEventPattern::KeyPattern b2 ) +{ + return b1.key == b2.key && b1.state == b2.state; } -#if defined(QWT_TEMPLATEDLL) -// MOC_SKIP_BEGIN -template class QWT_EXPORT QwtArray; -template class QWT_EXPORT QwtArray; -// MOC_SKIP_END -#endif - #endif diff --git a/qwt/src/qwt_global.h b/qwt/src/qwt_global.h index 217513502..cf3126b6a 100644 --- a/qwt/src/qwt_global.h +++ b/qwt/src/qwt_global.h @@ -2,27 +2,22 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_GLOBAL_H #define QWT_GLOBAL_H #include -#if QT_VERSION < 0x040000 -#include -#endif // QWT_VERSION is (major << 16) + (minor << 8) + patch. -#define QWT_VERSION 0x050201 -#define QWT_VERSION_STR "5.2.1" +#define QWT_VERSION 0x060001 +#define QWT_VERSION_STR "6.0.1" -#if defined(Q_WS_WIN) +#if defined(Q_WS_WIN) || defined(Q_WS_S60) #if defined(_MSC_VER) /* MSVC Compiler */ /* template-class specialization 'identifier' is already instantiated */ @@ -31,7 +26,7 @@ #ifdef QWT_DLL -#if defined(QWT_MAKEDLL) // create a Qwt DLL library +#if defined(QWT_MAKEDLL) // create a Qwt DLL library #define QWT_EXPORT __declspec(dllexport) #define QWT_TEMPLATEDLL #else // use a Qwt DLL library @@ -40,7 +35,7 @@ #endif // QWT_DLL -#endif // Q_WS_WIN +#endif // Q_WS_WIN || Q_WS_S60 #ifndef QWT_EXPORT #define QWT_EXPORT @@ -48,4 +43,4 @@ // #define QWT_NO_COMPAT 1 // disable withdrawn functionality -#endif // QWT_GLOBAL_H +#endif diff --git a/qwt/src/qwt_double_interval.cpp b/qwt/src/qwt_interval.cpp similarity index 60% rename from qwt/src/qwt_double_interval.cpp rename to qwt/src/qwt_interval.cpp index b8e2f412b..f8355671e 100644 --- a/qwt/src/qwt_double_interval.cpp +++ b/qwt/src/qwt_interval.cpp @@ -2,20 +2,14 @@ * 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 -#if QT_VERSION >= 0x040000 -#include -#else -#include -#endif - +#include "qwt_interval.h" #include "qwt_math.h" -#include "qwt_double_interval.h" +#include /*! \brief Normalize the limits of the interval @@ -25,7 +19,7 @@ \sa isValid(), inverted() */ -QwtDoubleInterval QwtDoubleInterval::normalized() const +QwtInterval QwtInterval::normalized() const { if ( d_minValue > d_maxValue ) { @@ -44,15 +38,15 @@ QwtDoubleInterval QwtDoubleInterval::normalized() const \return Inverted interval \sa normalized() */ -QwtDoubleInterval QwtDoubleInterval::inverted() const +QwtInterval QwtInterval::inverted() const { - int borderFlags = 0; + BorderFlags borderFlags = IncludeBorders; if ( d_borderFlags & ExcludeMinimum ) borderFlags |= ExcludeMaximum; if ( d_borderFlags & ExcludeMaximum ) borderFlags |= ExcludeMinimum; - return QwtDoubleInterval(d_maxValue, d_minValue, borderFlags); + return QwtInterval( d_maxValue, d_minValue, borderFlags ); } /*! @@ -61,7 +55,7 @@ QwtDoubleInterval QwtDoubleInterval::inverted() const \param value Value \return true, if value >= minValue() && value <= maxValue() */ -bool QwtDoubleInterval::contains(double value) const +bool QwtInterval::contains( double value ) const { if ( !isValid() ) return false; @@ -79,8 +73,7 @@ bool QwtDoubleInterval::contains(double value) const } //! Unite 2 intervals -QwtDoubleInterval QwtDoubleInterval::unite( - const QwtDoubleInterval &other) const +QwtInterval QwtInterval::unite( const QwtInterval &other ) const { /* If one of the intervals is invalid return the other one. @@ -89,80 +82,79 @@ QwtDoubleInterval QwtDoubleInterval::unite( if ( !isValid() ) { if ( !other.isValid() ) - return QwtDoubleInterval(); + return QwtInterval(); else return other; } if ( !other.isValid() ) return *this; - QwtDoubleInterval united; - int flags = 0; + QwtInterval united; + BorderFlags flags = IncludeBorders; // minimum if ( d_minValue < other.minValue() ) { - united.setMinValue(d_minValue); + united.setMinValue( d_minValue ); flags &= d_borderFlags & ExcludeMinimum; } else if ( other.minValue() < d_minValue ) { - united.setMinValue(other.minValue()); + united.setMinValue( other.minValue() ); flags &= other.borderFlags() & ExcludeMinimum; } else // d_minValue == other.minValue() { - united.setMinValue(d_minValue); - flags &= (d_borderFlags & other.borderFlags()) & ExcludeMinimum; + united.setMinValue( d_minValue ); + flags &= ( d_borderFlags & other.borderFlags() ) & ExcludeMinimum; } // maximum if ( d_maxValue > other.maxValue() ) { - united.setMaxValue(d_maxValue); + united.setMaxValue( d_maxValue ); flags &= d_borderFlags & ExcludeMaximum; } else if ( other.maxValue() > d_maxValue ) { - united.setMaxValue(other.maxValue()); + united.setMaxValue( other.maxValue() ); flags &= other.borderFlags() & ExcludeMaximum; } else // d_maxValue == other.maxValue() ) { - united.setMaxValue(d_maxValue); + united.setMaxValue( d_maxValue ); flags &= d_borderFlags & other.borderFlags() & ExcludeMaximum; } - united.setBorderFlags(flags); + united.setBorderFlags( flags ); return united; } //! Intersect 2 intervals -QwtDoubleInterval QwtDoubleInterval::intersect( - const QwtDoubleInterval &other) const +QwtInterval QwtInterval::intersect( const QwtInterval &other ) const { if ( !other.isValid() || !isValid() ) - return QwtDoubleInterval(); + return QwtInterval(); - QwtDoubleInterval i1 = *this; - QwtDoubleInterval i2 = other; + QwtInterval i1 = *this; + QwtInterval i2 = other; // swap i1/i2, so that the minimum of i1 // is smaller then the minimum of i2 - if ( i1.minValue() > i2.minValue() ) + if ( i1.minValue() > i2.minValue() ) { - qSwap(i1, i2); + qSwap( i1, i2 ); } else if ( i1.minValue() == i2.minValue() ) { if ( i1.borderFlags() & ExcludeMinimum ) - qSwap(i1, i2); + qSwap( i1, i2 ); } if ( i1.maxValue() < i2.minValue() ) { - return QwtDoubleInterval(); + return QwtInterval(); } if ( i1.maxValue() == i2.minValue() ) @@ -170,47 +162,45 @@ QwtDoubleInterval QwtDoubleInterval::intersect( if ( i1.borderFlags() & ExcludeMaximum || i2.borderFlags() & ExcludeMinimum ) { - return QwtDoubleInterval(); + return QwtInterval(); } } - QwtDoubleInterval intersected; - int flags = 0; + QwtInterval intersected; + BorderFlags flags = IncludeBorders; - intersected.setMinValue(i2.minValue()); + intersected.setMinValue( i2.minValue() ); flags |= i2.borderFlags() & ExcludeMinimum; if ( i1.maxValue() < i2.maxValue() ) { - intersected.setMaxValue(i1.maxValue()); + intersected.setMaxValue( i1.maxValue() ); flags |= i1.borderFlags() & ExcludeMaximum; } else if ( i2.maxValue() < i1.maxValue() ) { - intersected.setMaxValue(i2.maxValue()); + intersected.setMaxValue( i2.maxValue() ); flags |= i2.borderFlags() & ExcludeMaximum; } else // i1.maxValue() == i2.maxValue() { - intersected.setMaxValue(i1.maxValue() ); + intersected.setMaxValue( i1.maxValue() ); flags |= i1.borderFlags() & i2.borderFlags() & ExcludeMaximum; } - intersected.setBorderFlags(flags); + intersected.setBorderFlags( flags ); return intersected; } //! Unites this interval with the given interval. -QwtDoubleInterval& QwtDoubleInterval::operator|=( - const QwtDoubleInterval &interval) +QwtInterval& QwtInterval::operator|=( const QwtInterval & interval ) { *this = *this | interval; return *this; } //! Intersects this interval with the given interval. -QwtDoubleInterval& QwtDoubleInterval::operator&=( - const QwtDoubleInterval &interval) +QwtInterval& QwtInterval::operator&=( const QwtInterval & interval ) { *this = *this & interval; return *this; @@ -219,25 +209,25 @@ QwtDoubleInterval& QwtDoubleInterval::operator&=( /*! Test if two intervals overlap */ -bool QwtDoubleInterval::intersects(const QwtDoubleInterval &other) const +bool QwtInterval::intersects( const QwtInterval &other ) const { if ( !isValid() || !other.isValid() ) return false; - QwtDoubleInterval i1 = *this; - QwtDoubleInterval i2 = other; + QwtInterval i1 = *this; + QwtInterval i2 = other; // swap i1/i2, so that the minimum of i1 // is smaller then the minimum of i2 - if ( i1.minValue() > i2.minValue() ) + if ( i1.minValue() > i2.minValue() ) { - qSwap(i1, i2); + qSwap( i1, i2 ); } else if ( i1.minValue() == i2.minValue() && - i1.borderFlags() & ExcludeMinimum ) + i1.borderFlags() & ExcludeMinimum ) { - qSwap(i1, i2); + qSwap( i1, i2 ); } if ( i1.maxValue() > i2.minValue() ) @@ -246,8 +236,8 @@ bool QwtDoubleInterval::intersects(const QwtDoubleInterval &other) const } if ( i1.maxValue() == i2.minValue() ) { - return !( (i1.borderFlags() & ExcludeMaximum) || - (i2.borderFlags() & ExcludeMinimum) ); + return !( ( i1.borderFlags() & ExcludeMaximum ) || + ( i2.borderFlags() & ExcludeMinimum ) ); } return false; } @@ -259,15 +249,15 @@ bool QwtDoubleInterval::intersects(const QwtDoubleInterval &other) const \param value Center \return Interval with value as center */ -QwtDoubleInterval QwtDoubleInterval::symmetrize(double value) const +QwtInterval QwtInterval::symmetrize( double value ) const { if ( !isValid() ) return *this; const double delta = - qwtMax(qwtAbs(value - d_maxValue), qwtAbs(value - d_minValue)); + qMax( qAbs( value - d_maxValue ), qAbs( value - d_minValue ) ); - return QwtDoubleInterval(value - delta, value + delta); + return QwtInterval( value - delta, value + delta ); } /*! @@ -278,19 +268,18 @@ QwtDoubleInterval QwtDoubleInterval::symmetrize(double value) const \return Limited interval */ -QwtDoubleInterval QwtDoubleInterval::limited( - double lowerBound, double upperBound) const +QwtInterval QwtInterval::limited( double lowerBound, double upperBound ) const { if ( !isValid() || lowerBound > upperBound ) - return QwtDoubleInterval(); + return QwtInterval(); - double minValue = qwtMax(d_minValue, lowerBound); - minValue = qwtMin(minValue, upperBound); + double minValue = qMax( d_minValue, lowerBound ); + minValue = qMin( minValue, upperBound ); - double maxValue = qwtMax(d_maxValue, lowerBound); - maxValue = qwtMin(maxValue, upperBound); + double maxValue = qMax( d_maxValue, lowerBound ); + maxValue = qMin( maxValue, upperBound ); - return QwtDoubleInterval(minValue, maxValue, d_borderFlags); + return QwtInterval( minValue, maxValue, d_borderFlags ); } /*! @@ -304,17 +293,42 @@ QwtDoubleInterval QwtDoubleInterval::limited( \param value Value \sa isValid() */ -QwtDoubleInterval QwtDoubleInterval::extend(double value) const +QwtInterval QwtInterval::extend( double value ) const { if ( !isValid() ) return *this; - return QwtDoubleInterval( qwtMin(value, d_minValue), - qwtMax(value, d_maxValue), d_borderFlags ); + return QwtInterval( qMin( value, d_minValue ), + qMax( value, d_maxValue ), d_borderFlags ); } -QwtDoubleInterval& QwtDoubleInterval::operator|=(double value) +/*! + Extend an interval + + \param value Value + \return Reference of the extended interval + + \sa extend() +*/ +QwtInterval& QwtInterval::operator|=( double value ) { *this = *this | value; return *this; } + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<( QDebug debug, const QwtInterval &interval ) +{ + const int flags = interval.borderFlags(); + + debug.nospace() << "QwtInterval(" + << ( ( flags & QwtInterval::ExcludeMinimum ) ? "]" : "[" ) + << interval.minValue() << "," << interval.maxValue() + << ( ( flags & QwtInterval::ExcludeMaximum ) ? "[" : "]" ) + << ")"; + + return debug.space(); +} + +#endif diff --git a/qwt/src/qwt_interval.h b/qwt/src/qwt_interval.h new file mode 100644 index 000000000..74df2da55 --- /dev/null +++ b/qwt/src/qwt_interval.h @@ -0,0 +1,296 @@ +/* -*- 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_INTERVAL_H +#define QWT_INTERVAL_H + +#include "qwt_global.h" +#ifndef QT_NO_DEBUG_STREAM +#include +#endif + +/*! + \brief A class representing an interval + + The interval is represented by 2 doubles, the lower and the upper limit. +*/ + +class QWT_EXPORT QwtInterval +{ +public: + /*! + Flag indicating if a border is included or excluded + \sa setBorderFlags(), borderFlags() + */ + enum BorderFlag + { + //! Min/Max values are inside the interval + IncludeBorders = 0x00, + + //! Min value is not included in the interval + ExcludeMinimum = 0x01, + + //! Max value is not included in the interval + ExcludeMaximum = 0x02, + + //! Min/Max values are not included in the interval + ExcludeBorders = ExcludeMinimum | ExcludeMaximum + }; + + //! Border flags + typedef QFlags BorderFlags; + + QwtInterval(); + QwtInterval( double minValue, double maxValue, + BorderFlags = IncludeBorders ); + + void setInterval( double minValue, double maxValue, + BorderFlags = IncludeBorders ); + + QwtInterval normalized() const; + QwtInterval inverted() const; + QwtInterval limited( double minValue, double maxValue ) const; + + bool operator==( const QwtInterval & ) const; + bool operator!=( const QwtInterval & ) const; + + void setBorderFlags( BorderFlags ); + BorderFlags borderFlags() const; + + double minValue() const; + double maxValue() const; + + double width() const; + + void setMinValue( double ); + void setMaxValue( double ); + + bool contains( double value ) const; + + bool intersects( const QwtInterval & ) const; + QwtInterval intersect( const QwtInterval & ) const; + QwtInterval unite( const QwtInterval & ) const; + + QwtInterval operator|( const QwtInterval & ) const; + QwtInterval operator&( const QwtInterval & ) const; + + QwtInterval &operator|=( const QwtInterval & ); + QwtInterval &operator&=( const QwtInterval & ); + + QwtInterval extend( double value ) const; + QwtInterval operator|( double ) const; + QwtInterval &operator|=( double ); + + bool isValid() const; + bool isNull() const; + void invalidate(); + + QwtInterval symmetrize( double value ) const; + +private: + double d_minValue; + double d_maxValue; + BorderFlags d_borderFlags; +}; + +Q_DECLARE_TYPEINFO(QwtInterval, Q_MOVABLE_TYPE); + +/*! + \brief Default Constructor + + Creates an invalid interval [0.0, -1.0] + \sa setInterval(), isValid() +*/ +inline QwtInterval::QwtInterval(): + d_minValue( 0.0 ), + d_maxValue( -1.0 ), + d_borderFlags( IncludeBorders ) +{ +} + +/*! + Constructor + + Build an interval with from min/max values + + \param minValue Minimum value + \param maxValue Maximum value + \param borderFlags Include/Exclude borders +*/ +inline QwtInterval::QwtInterval( + double minValue, double maxValue, BorderFlags borderFlags ): + d_minValue( minValue ), + d_maxValue( maxValue ), + d_borderFlags( borderFlags ) +{ +} + +/*! + Assign the limits of the interval + + \param minValue Minimum value + \param maxValue Maximum value + \param borderFlags Include/Exclude borders +*/ +inline void QwtInterval::setInterval( + double minValue, double maxValue, BorderFlags borderFlags ) +{ + d_minValue = minValue; + d_maxValue = maxValue; + d_borderFlags = borderFlags; +} + +/*! + Change the border flags + + \param borderFlags Or'd BorderMode flags + \sa borderFlags() +*/ +inline void QwtInterval::setBorderFlags( BorderFlags borderFlags ) +{ + d_borderFlags = borderFlags; +} + +/*! + \return Border flags + \sa setBorderFlags() +*/ +inline QwtInterval::BorderFlags QwtInterval::borderFlags() const +{ + return d_borderFlags; +} + +/*! + Assign the lower limit of the interval + + \param minValue Minimum value +*/ +inline void QwtInterval::setMinValue( double minValue ) +{ + d_minValue = minValue; +} + +/*! + Assign the upper limit of the interval + + \param maxValue Maximum value +*/ +inline void QwtInterval::setMaxValue( double maxValue ) +{ + d_maxValue = maxValue; +} + +//! \return Lower limit of the interval +inline double QwtInterval::minValue() const +{ + return d_minValue; +} + +//! \return Upper limit of the interval +inline double QwtInterval::maxValue() const +{ + return d_maxValue; +} + +/*! + Return the width of an interval + The width of invalid intervals is 0.0, otherwise the result is + maxValue() - minValue(). + + \sa isValid() +*/ +inline double QwtInterval::width() const +{ + return isValid() ? ( d_maxValue - d_minValue ) : 0.0; +} + +/*! + Intersection of two intervals + \sa intersect() +*/ +inline QwtInterval QwtInterval::operator&( + const QwtInterval &interval ) const +{ + return intersect( interval ); +} + +/*! + Union of two intervals + \sa unite() +*/ +inline QwtInterval QwtInterval::operator|( + const QwtInterval &interval ) const +{ + return unite( interval ); +} + +//! Compare two intervals +inline bool QwtInterval::operator==( const QwtInterval &other ) const +{ + return ( d_minValue == other.d_minValue ) && + ( d_maxValue == other.d_maxValue ) && + ( d_borderFlags == other.d_borderFlags ); +} + +//! Compare two intervals +inline bool QwtInterval::operator!=( const QwtInterval &other ) const +{ + return ( !( *this == other ) ); +} + +/*! + Extend an interval + + \param value Value + \return Extended interval + \sa extend() +*/ +inline QwtInterval QwtInterval::operator|( double value ) const +{ + return extend( value ); +} + +//! \return true, if isValid() && (minValue() >= maxValue()) +inline bool QwtInterval::isNull() const +{ + return isValid() && d_minValue >= d_maxValue; +} + +/*! + A interval is valid when minValue() <= maxValue(). + In case of QwtInterval::ExcludeBorders it is true + when minValue() < maxValue() +*/ +inline bool QwtInterval::isValid() const +{ + if ( ( d_borderFlags & ExcludeBorders ) == 0 ) + return d_minValue <= d_maxValue; + else + return d_minValue < d_maxValue; +} + +/*! + Invalidate the interval + + The limits are set to interval [0.0, -1.0] + \sa isValid() +*/ +inline void QwtInterval::invalidate() +{ + d_minValue = 0.0; + d_maxValue = -1.0; +} + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtInterval::BorderFlags ) + +#ifndef QT_NO_DEBUG_STREAM +QWT_EXPORT QDebug operator<<( QDebug, const QwtInterval & ); +#endif + +#endif diff --git a/qwt/src/qwt_interval_data.cpp b/qwt/src/qwt_interval_data.cpp deleted file mode 100644 index 5283f95a2..000000000 --- a/qwt/src/qwt_interval_data.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#include "qwt_math.h" -#include "qwt_interval_data.h" - -//! Constructor -QwtIntervalData::QwtIntervalData() -{ -} - -//! Constructor -QwtIntervalData::QwtIntervalData( - const QwtArray &intervals, - const QwtArray &values): - d_intervals(intervals), - d_values(values) -{ -} - -//! Destructor -QwtIntervalData::~QwtIntervalData() -{ -} - -//! Assign samples -void QwtIntervalData::setData( - const QwtArray &intervals, - const QwtArray &values) -{ - d_intervals = intervals; - d_values = values; -} - -/*! - Calculate the bounding rectangle of the samples - - The x coordinates of the rectangle are built from the intervals, - the y coordinates from the values. - - \return Bounding rectangle -*/ -QwtDoubleRect QwtIntervalData::boundingRect() const -{ - double minX, maxX, minY, maxY; - minX = maxX = minY = maxY = 0.0; - - bool isValid = false; - - const size_t sz = size(); - for ( size_t i = 0; i < sz; i++ ) - { - const QwtDoubleInterval intv = interval(i); - if ( !intv.isValid() ) - continue; - - const double v = value(i); - - if ( !isValid ) - { - minX = intv.minValue(); - maxX = intv.maxValue(); - minY = maxY = v; - - isValid = true; - } - else - { - if ( intv.minValue() < minX ) - minX = intv.minValue(); - if ( intv.maxValue() > maxX ) - maxX = intv.maxValue(); - - if ( v < minY ) - minY = v; - if ( v > maxY ) - maxY = v; - } - } - if ( !isValid ) - return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid - - return QwtDoubleRect(minX, minY, maxX - minX, maxY - minY); -} diff --git a/qwt/src/qwt_interval_data.h b/qwt/src/qwt_interval_data.h deleted file mode 100644 index 5b042c01b..000000000 --- a/qwt/src/qwt_interval_data.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#ifndef QWT_INTERVAL_DATA_H -#define QWT_INTERVAL_DATA_H 1 - -#include "qwt_global.h" -#include "qwt_math.h" -#include "qwt_array.h" -#include "qwt_double_interval.h" -#include "qwt_double_rect.h" - -#if defined(_MSC_VER) && (_MSC_VER > 1310) -#include -#endif - -#if defined(QWT_TEMPLATEDLL) -// MOC_SKIP_BEGIN -template class QWT_EXPORT QwtArray; -template class QWT_EXPORT QwtArray; -// MOC_SKIP_END -#endif - -/*! - \brief Series of samples of a value and an interval - - QwtIntervalData is a series of samples of a value and an interval. - F.e. error bars are built from samples [x, y1-y2], while a - histogram might consist of [x1-x2, y] samples. -*/ -class QWT_EXPORT QwtIntervalData -{ -public: - QwtIntervalData(); - QwtIntervalData(const QwtArray &, - const QwtArray &); - - ~QwtIntervalData(); - - void setData(const QwtArray &, - const QwtArray &); - - size_t size() const; - const QwtDoubleInterval &interval(size_t i) const; - double value(size_t i) const; - - QwtDoubleRect boundingRect() const; - -private: - QwtArray d_intervals; - QwtArray d_values; -}; - -//! \return Number of samples -inline size_t QwtIntervalData::size() const -{ - return qwtMin(d_intervals.size(), d_values.size()); -} - -/*! - Interval of a sample - - \param i Sample index - \return Interval - \sa value(), size() -*/ -inline const QwtDoubleInterval &QwtIntervalData::interval(size_t i) const -{ - return d_intervals[int(i)]; -} - -/*! - Value of a sample - - \param i Sample index - \return Value - \sa interval(), size() -*/ -inline double QwtIntervalData::value(size_t i) const -{ - return d_values[int(i)]; -} - -#endif diff --git a/qwt/src/qwt_interval_symbol.cpp b/qwt/src/qwt_interval_symbol.cpp new file mode 100644 index 000000000..881acb4b2 --- /dev/null +++ b/qwt/src/qwt_interval_symbol.cpp @@ -0,0 +1,298 @@ +/* -*- 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_interval_symbol.h" +#include "qwt_painter.h" +#include "qwt_math.h" +#include + +#if QT_VERSION < 0x040601 +#define qAtan2(y, x) ::atan2(y, x) +#endif + +class QwtIntervalSymbol::PrivateData +{ +public: + PrivateData(): + style( QwtIntervalSymbol::NoSymbol ), + width( 6 ) + { + } + + bool operator==( const PrivateData &other ) const + { + return ( style == other.style ) + && ( width == other.width ) + && ( brush == other.brush ) + && ( pen == other.pen ); + } + + QwtIntervalSymbol::Style style; + int width; + + QPen pen; + QBrush brush; +}; + +/*! + Constructor + + \param style Style of the symbol + \sa setStyle(), style(), Style +*/ +QwtIntervalSymbol::QwtIntervalSymbol( Style style ) +{ + d_data = new PrivateData(); + d_data->style = style; +} + +//! Copy constructor +QwtIntervalSymbol::QwtIntervalSymbol( const QwtIntervalSymbol &other ) +{ + d_data = new PrivateData(); + *d_data = *other.d_data; +} + +//! Destructor +QwtIntervalSymbol::~QwtIntervalSymbol() +{ + delete d_data; +} + +//! \brief Assignment operator +QwtIntervalSymbol &QwtIntervalSymbol::operator=( + const QwtIntervalSymbol &other ) +{ + *d_data = *other.d_data; + return *this; +} + +//! \brief Compare two symbols +bool QwtIntervalSymbol::operator==( + const QwtIntervalSymbol &other ) const +{ + return *d_data == *other.d_data; +} + +//! \brief Compare two symbols +bool QwtIntervalSymbol::operator!=( + const QwtIntervalSymbol &other ) const +{ + return !( *d_data == *other.d_data ); +} + +/*! + Specify the symbol style + + \param style Style + \sa style(), Style +*/ +void QwtIntervalSymbol::setStyle( Style style ) +{ + d_data->style = style; +} + +/*! + \return Current symbol style + \sa setStyle() +*/ +QwtIntervalSymbol::Style QwtIntervalSymbol::style() const +{ + return d_data->style; +} + +/*! + Specify the width of the symbol + It is used depending on the style. + + \param width Width + \sa width(), setStyle() +*/ +void QwtIntervalSymbol::setWidth( int width ) +{ + d_data->width = width; +} + +/*! + \return Width of the symbol. + \sa setWidth(), setStyle() +*/ +int QwtIntervalSymbol::width() const +{ + return d_data->width; +} + +/*! + \brief Assign a brush + + The brush is used for the Box style. + + \param brush Brush + \sa brush() +*/ +void QwtIntervalSymbol::setBrush( const QBrush &brush ) +{ + d_data->brush = brush; +} + +/*! + \return Brush + \sa setBrush() +*/ +const QBrush& QwtIntervalSymbol::brush() const +{ + return d_data->brush; +} + +/*! + Assign a pen + + \param pen Pen + \sa pen(), setBrush() +*/ +void QwtIntervalSymbol::setPen( const QPen &pen ) +{ + d_data->pen = pen; +} + +/*! + \return Pen + \sa setPen(), brush() +*/ +const QPen& QwtIntervalSymbol::pen() const +{ + return d_data->pen; +} + +/*! + Draw a symbol depending on its style + + \param painter Painter + \param orientation Orientation + \param from Start point of the interval in target device coordinates + \param to End point of the interval in target device coordinates + + \sa setStyle() +*/ +void QwtIntervalSymbol::draw( QPainter *painter, Qt::Orientation orientation, + const QPointF &from, const QPointF &to ) const +{ + const qreal pw = qMax( painter->pen().widthF(), qreal( 1.0 ) ); + + QPointF p1 = from; + QPointF p2 = to; + if ( QwtPainter::roundingAlignment( painter ) ) + { + p1 = p1.toPoint(); + p2 = p2.toPoint(); + } + + switch ( d_data->style ) + { + case QwtIntervalSymbol::Bar: + { + QwtPainter::drawLine( painter, p1, p2 ); + if ( d_data->width > pw ) + { + if ( ( orientation == Qt::Horizontal ) + && ( p1.y() == p2.y() ) ) + { + const double sw = d_data->width; + + const double y = p1.y() - sw / 2; + QwtPainter::drawLine( painter, + p1.x(), y, p1.x(), y + sw ); + QwtPainter::drawLine( painter, + p2.x(), y, p2.x(), y + sw ); + } + else if ( ( orientation == Qt::Vertical ) + && ( p1.x() == p2.x() ) ) + { + const double sw = d_data->width; + + const double x = p1.x() - sw / 2; + QwtPainter::drawLine( painter, + x, p1.y(), x + sw, p1.y() ); + QwtPainter::drawLine( painter, + x, p2.y(), x + sw, p2.y() ); + } + else + { + const double sw = d_data->width; + + const double dx = p2.x() - p1.x(); + const double dy = p2.y() - p1.y(); + const double angle = qAtan2( dy, dx ) + M_PI_2; + double dw2 = sw / 2.0; + + const double cx = qCos( angle ) * dw2; + const double sy = qSin( angle ) * dw2; + + QwtPainter::drawLine( painter, + p1.x() - cx, p1.y() - sy, + p1.x() + cx, p1.y() + sy ); + QwtPainter::drawLine( painter, + p2.x() - cx, p2.y() - sy, + p2.x() + cx, p2.y() + sy ); + } + } + break; + } + case QwtIntervalSymbol::Box: + { + if ( d_data->width <= pw ) + { + QwtPainter::drawLine( painter, p1, p2 ); + } + else + { + if ( ( orientation == Qt::Horizontal ) + && ( p1.y() == p2.y() ) ) + { + const double sw = d_data->width; + + const double y = p1.y() - d_data->width / 2; + QwtPainter::drawRect( painter, + p1.x(), y, p2.x() - p1.x(), sw ); + } + else if ( ( orientation == Qt::Vertical ) + && ( p1.x() == p2.x() ) ) + { + const double sw = d_data->width; + + const double x = p1.x() - d_data->width / 2; + QwtPainter::drawRect( painter, + x, p1.y(), sw, p2.y() - p1.y() ); + } + else + { + const double sw = d_data->width; + + const double dx = p2.x() - p1.x(); + const double dy = p2.y() - p1.y(); + const double angle = qAtan2( dy, dx ) + M_PI_2; + double dw2 = sw / 2.0; + + const int cx = qCos( angle ) * dw2; + const int sy = qSin( angle ) * dw2; + + QPolygonF polygon; + polygon += QPointF( p1.x() - cx, p1.y() - sy ); + polygon += QPointF( p1.x() + cx, p1.y() + sy ); + polygon += QPointF( p2.x() + cx, p2.y() + sy ); + polygon += QPointF( p2.x() - cx, p2.y() - sy ); + + QwtPainter::drawPolygon( painter, polygon ); + } + } + break; + } + default:; + } +} diff --git a/qwt/src/qwt_interval_symbol.h b/qwt/src/qwt_interval_symbol.h new file mode 100644 index 000000000..3ea4fe4fa --- /dev/null +++ b/qwt/src/qwt_interval_symbol.h @@ -0,0 +1,86 @@ +/* -*- 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_INTERVAL_SYMBOL_H +#define QWT_INTERVAL_SYMBOL_H + +#include "qwt_global.h" +#include +#include + +class QPainter; +class QRect; +class QPointF; + +/*! + \brief A drawing primitive for displaying an interval like an error bar + + \sa QwtPlotIntervalCurve +*/ +class QWT_EXPORT QwtIntervalSymbol +{ +public: + //! Symbol style + enum Style + { + //! No Style. The symbol cannot be drawn. + NoSymbol = -1, + + /*! + The symbol displays a line with caps at the beginning/end. + The size of the caps depends on the symbol width(). + */ + Bar, + + /*! + The symbol displays a plain rectangle using pen() and brush(). + The size of the rectangle depends on the translated interval and + the width(), + */ + Box, + + /*! + Styles >= UserSymbol are reserved for derived + classes of QwtIntervalSymbol that overload draw() with + additional application specific symbol types. + */ + UserSymbol = 1000 + }; + +public: + QwtIntervalSymbol( Style = NoSymbol ); + QwtIntervalSymbol( const QwtIntervalSymbol & ); + virtual ~QwtIntervalSymbol(); + + QwtIntervalSymbol &operator=( const QwtIntervalSymbol & ); + bool operator==( const QwtIntervalSymbol & ) const; + bool operator!=( const QwtIntervalSymbol & ) const; + + void setWidth( int ); + int width() const; + + void setBrush( const QBrush& b ); + const QBrush& brush() const; + + void setPen( const QPen & ); + const QPen& pen() const; + + void setStyle( Style ); + Style style() const; + + virtual void draw( QPainter *, Qt::Orientation, + const QPointF& from, const QPointF& to ) const; + +private: + + class PrivateData; + PrivateData* d_data; +}; + +#endif diff --git a/qwt/src/qwt_knob.cpp b/qwt/src/qwt_knob.cpp index d489bd652..0cc8e4230 100644 --- a/qwt/src/qwt_knob.cpp +++ b/qwt/src/qwt_knob.cpp @@ -7,15 +7,24 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ +#include "qwt_knob.h" +#include "qwt_round_scale_draw.h" +#include "qwt_math.h" +#include "qwt_painter.h" #include #include #include +#include #include -#include "qwt_round_scale_draw.h" -#include "qwt_knob.h" -#include "qwt_math.h" -#include "qwt_painter.h" -#include "qwt_paint_buffer.h" +#include +#include + +#if QT_VERSION < 0x040601 +#define qAtan2(y, x) ::atan2(y, x) +#define qFabs(x) ::fabs(x) +#define qFastCos(x) ::cos(x) +#define qFastSin(x) ::sin(x) +#endif class QwtKnob::PrivateData { @@ -28,68 +37,53 @@ public: borderDist = 4; totalAngle = 270.0; scaleDist = 4; - symbol = Line; + markerStyle = QwtKnob::Notch; maxScaleTicks = 11; + knobStyle = QwtKnob::Raised; knobWidth = 50; - dotWidth = 8; + markerSize = 8; } + QwtKnob::KnobStyle knobStyle; + QwtKnob::MarkerStyle markerStyle; + int borderWidth; int borderDist; int scaleDist; int maxScaleTicks; int knobWidth; - int dotWidth; + int markerSize; - Symbol symbol; double angle; double totalAngle; double nTurns; - QRect knobRect; // bounding rect of the knob without scale + mutable QRectF knobRect; // bounding rect of the knob without scale }; /*! Constructor \param parent Parent widget */ -QwtKnob::QwtKnob(QWidget* parent): - QwtAbstractSlider(Qt::Horizontal, parent) +QwtKnob::QwtKnob( QWidget* parent ): + QwtAbstractSlider( Qt::Horizontal, parent ) { initKnob(); } -#if QT_VERSION < 0x040000 -/*! - Constructor - \param parent Parent widget - \param name Object name -*/ -QwtKnob::QwtKnob(QWidget* parent, const char *name): - QwtAbstractSlider(Qt::Horizontal, parent) -{ - setName(name); - initKnob(); -} -#endif - void QwtKnob::initKnob() { -#if QT_VERSION < 0x040000 - setWFlags(Qt::WNoAutoErase); -#endif - d_data = new PrivateData; - setScaleDraw(new QwtRoundScaleDraw()); + setScaleDraw( new QwtRoundScaleDraw() ); - setUpdateTime(50); + setUpdateTime( 50 ); setTotalAngle( 270.0 ); recalcAngle(); - setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); + setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) ); - setRange(0.0, 10.0, 1.0); - setValue(0.0); + setRange( 0.0, 10.0, 1.0 ); + setValue( 0.0 ); } //! Destructor @@ -99,25 +93,51 @@ QwtKnob::~QwtKnob() } /*! - \brief Set the symbol of the knob - \sa symbol() + \brief Set the knob type + + \param knobStyle Knob type + \sa knobStyle(), setBorderWidth() */ -void QwtKnob::setSymbol(QwtKnob::Symbol s) +void QwtKnob::setKnobStyle( KnobStyle knobStyle ) { - if ( d_data->symbol != s ) + if ( d_data->knobStyle != knobStyle ) { - d_data->symbol = s; + d_data->knobStyle = knobStyle; update(); } } -/*! - \return symbol of the knob - \sa setSymbol() +/*! + \return Marker type of the knob + \sa setKnobStyle(), setBorderWidth() */ -QwtKnob::Symbol QwtKnob::symbol() const +QwtKnob::KnobStyle QwtKnob::knobStyle() const { - return d_data->symbol; + return d_data->knobStyle; +} + +/*! + \brief Set the marker type of the knob + + \param markerStyle Marker type + \sa markerStyle(), setMarkerSize() +*/ +void QwtKnob::setMarkerStyle( MarkerStyle markerStyle ) +{ + if ( d_data->markerStyle != markerStyle ) + { + d_data->markerStyle = markerStyle; + update(); + } +} + +/*! + \return Marker type of the knob + \sa setMarkerStyle(), setMarkerSize() +*/ +QwtKnob::MarkerStyle QwtKnob::markerStyle() const +{ + return d_data->markerStyle; } /*! @@ -128,20 +148,20 @@ QwtKnob::Symbol QwtKnob::symbol() const an angle of more than 360 degrees so that the knob can be turned several times around its axis. */ -void QwtKnob::setTotalAngle (double angle) +void QwtKnob::setTotalAngle ( double angle ) { - if (angle < 10.0) - d_data->totalAngle = 10.0; + if ( angle < 10.0 ) + d_data->totalAngle = 10.0; else - d_data->totalAngle = angle; + d_data->totalAngle = angle; - scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle, - 0.5 * d_data->totalAngle); - layoutKnob(); + scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle, + 0.5 * d_data->totalAngle ); + layoutKnob( true ); } //! Return the total angle -double QwtKnob::totalAngle() const +double QwtKnob::totalAngle() const { return d_data->totalAngle; } @@ -151,86 +171,32 @@ double QwtKnob::totalAngle() const For changing the labels of the scales, it is necessary to derive from QwtRoundScaleDraw and - overload QwtRoundScaleDraw::label(). + overload QwtRoundScaleDraw::label(). \sa scaleDraw() */ -void QwtKnob::setScaleDraw(QwtRoundScaleDraw *scaleDraw) +void QwtKnob::setScaleDraw( QwtRoundScaleDraw *scaleDraw ) { - setAbstractScaleDraw(scaleDraw); - setTotalAngle(d_data->totalAngle); + setAbstractScaleDraw( scaleDraw ); + setTotalAngle( d_data->totalAngle ); } -/*! +/*! \return the scale draw of the knob \sa setScaleDraw() */ const QwtRoundScaleDraw *QwtKnob::scaleDraw() const { - return (QwtRoundScaleDraw *)abstractScaleDraw(); + return static_cast( abstractScaleDraw() ); } -/*! +/*! \return the scale draw of the knob \sa setScaleDraw() */ QwtRoundScaleDraw *QwtKnob::scaleDraw() { - return (QwtRoundScaleDraw *)abstractScaleDraw(); -} - -/*! - \brief Draw the knob - \param painter painter - \param r Bounding rectangle of the knob (without scale) -*/ -void QwtKnob::drawKnob(QPainter *painter, const QRect &r) -{ -#if QT_VERSION < 0x040000 - const QBrush buttonBrush = colorGroup().brush(QColorGroup::Button); - const QColor buttonTextColor = colorGroup().buttonText(); - const QColor lightColor = colorGroup().light(); - const QColor darkColor = colorGroup().dark(); -#else - const QBrush buttonBrush = palette().brush(QPalette::Button); - const QColor buttonTextColor = palette().color(QPalette::ButtonText); - const QColor lightColor = palette().color(QPalette::Light); - const QColor darkColor = palette().color(QPalette::Dark); -#endif - - const int bw2 = d_data->borderWidth / 2; - - const int radius = (qwtMin(r.width(), r.height()) - bw2) / 2; - - const QRect aRect( - r.center().x() - radius, r.center().y() - radius, - 2 * radius, 2 * radius); - - // - // draw button face - // - painter->setBrush(buttonBrush); - painter->drawEllipse(aRect); - - // - // draw button shades - // - QPen pn; - pn.setWidth(d_data->borderWidth); - - pn.setColor(lightColor); - painter->setPen(pn); - painter->drawArc(aRect, 45*16, 180*16); - - pn.setColor(darkColor); - painter->setPen(pn); - painter->drawArc(aRect, 225*16, 180*16); - - // - // draw marker - // - if ( isValid() ) - drawMarker(painter, d_data->angle, buttonTextColor); + return static_cast( abstractScaleDraw() ); } /*! @@ -250,65 +216,67 @@ void QwtKnob::valueChange() \brief Determine the value corresponding to a specified position Called by QwtAbstractSlider - \param p point + \param pos point */ -double QwtKnob::getValue(const QPoint &p) +double QwtKnob::getValue( const QPoint &pos ) { - const double dx = double((rect().x() + rect().width() / 2) - p.x() ); - const double dy = double((rect().y() + rect().height() / 2) - p.y() ); + const double dx = rect().center().x() - pos.x(); + const double dy = rect().center().y() - pos.y(); - const double arc = atan2(-dx,dy) * 180.0 / M_PI; + const double arc = qAtan2( -dx, dy ) * 180.0 / M_PI; - double newValue = 0.5 * (minValue() + maxValue()) - + (arc + d_data->nTurns * 360.0) * (maxValue() - minValue()) - / d_data->totalAngle; + double newValue = 0.5 * ( minValue() + maxValue() ) + + ( arc + d_data->nTurns * 360.0 ) * ( maxValue() - minValue() ) + / d_data->totalAngle; - const double oneTurn = fabs(maxValue() - minValue()) * 360.0 / d_data->totalAngle; + const double oneTurn = qFabs( maxValue() - minValue() ) * 360.0 / d_data->totalAngle; const double eqValue = value() + mouseOffset(); - if (fabs(newValue - eqValue) > 0.5 * oneTurn) + if ( qFabs( newValue - eqValue ) > 0.5 * oneTurn ) { - if (newValue < eqValue) - newValue += oneTurn; + if ( newValue < eqValue ) + newValue += oneTurn; else - newValue -= oneTurn; + newValue -= oneTurn; } - return newValue; + return newValue; } /*! \brief Set the scrolling mode and direction Called by QwtAbstractSlider - \param p Point in question + \param pos Point in question + \param scrollMode Scrolling mode + \param direction Direction */ -void QwtKnob::getScrollMode(const QPoint &p, int &scrollMode, int &direction) +void QwtKnob::getScrollMode( const QPoint &pos, + QwtAbstractSlider::ScrollMode &scrollMode, int &direction ) const { const int r = d_data->knobRect.width() / 2; - const int dx = d_data->knobRect.x() + r - p.x(); - const int dy = d_data->knobRect.y() + r - p.y(); + const int dx = d_data->knobRect.x() + r - pos.x(); + const int dy = d_data->knobRect.y() + r - pos.y(); - if ( (dx * dx) + (dy * dy) <= (r * r)) // point is inside the knob + if ( ( dx * dx ) + ( dy * dy ) <= ( r * r ) ) // point is inside the knob { - scrollMode = ScrMouse; + scrollMode = QwtAbstractSlider::ScrMouse; direction = 0; } else // point lies outside { - scrollMode = ScrTimer; - double arc = atan2(double(-dx),double(dy)) * 180.0 / M_PI; - if ( arc < d_data->angle) - direction = -1; - else if (arc > d_data->angle) - direction = 1; + scrollMode = QwtAbstractSlider::ScrTimer; + double arc = qAtan2( double( -dx ), double( dy ) ) * 180.0 / M_PI; + if ( arc < d_data->angle ) + direction = -1; + else if ( arc > d_data->angle ) + direction = 1; else - direction = 0; + direction = 0; } } - /*! \brief Notify a change of the range @@ -316,22 +284,41 @@ void QwtKnob::getScrollMode(const QPoint &p, int &scrollMode, int &direction) */ void QwtKnob::rangeChange() { - if (autoScale()) - rescale(minValue(), maxValue()); + if ( autoScale() ) + rescale( minValue(), maxValue() ); - layoutKnob(); + layoutKnob( true ); recalcAngle(); } /*! Qt Resize Event + \param event Resize event */ -void QwtKnob::resizeEvent(QResizeEvent *) +void QwtKnob::resizeEvent( QResizeEvent *event ) { + Q_UNUSED( event ); layoutKnob( false ); } -/*! +/*! + Handle QEvent::StyleChange and QEvent::FontChange; + \param event Change event +*/ +void QwtKnob::changeEvent( QEvent *event ) +{ + switch( event->type() ) + { + case QEvent::StyleChange: + case QEvent::FontChange: + layoutKnob( true ); + break; + default: + break; + } +} + +/*! Recalculate the knob's geometry and layout based on the current rect and fonts. @@ -340,15 +327,14 @@ void QwtKnob::resizeEvent(QResizeEvent *) */ void QwtKnob::layoutKnob( bool update_geometry ) { - const QRect r = rect(); - const int radius = d_data->knobWidth / 2; + const double d = d_data->knobWidth; - d_data->knobRect.setWidth(2 * radius); - d_data->knobRect.setHeight(2 * radius); - d_data->knobRect.moveCenter(r.center()); + d_data->knobRect.setWidth( d ); + d_data->knobRect.setHeight( d ); + d_data->knobRect.moveCenter( rect().center() ); - scaleDraw()->setRadius(radius + d_data->scaleDist); - scaleDraw()->moveCenter(r.center()); + scaleDraw()->setRadius( 0.5 * d + d_data->scaleDist ); + scaleDraw()->moveCenter( rect().center() ); if ( update_geometry ) { @@ -359,92 +345,214 @@ void QwtKnob::layoutKnob( bool update_geometry ) /*! Repaint the knob - - \param e Paint event + \param event Paint event */ -void QwtKnob::paintEvent(QPaintEvent *e) +void QwtKnob::paintEvent( QPaintEvent *event ) { - const QRect &ur = e->rect(); - if ( ur.isValid() ) - { -#if QT_VERSION < 0x040000 - QwtPaintBuffer paintBuffer(this, ur); - draw(paintBuffer.painter(), ur); -#else - QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); - draw(&painter, ur); -#endif - } + QPainter painter( this ); + painter.setClipRegion( event->region() ); + + QStyleOption opt; + opt.init(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); + + painter.setRenderHint( QPainter::Antialiasing, true ); + + if ( !d_data->knobRect.contains( event->region().boundingRect() ) ) + scaleDraw()->draw( &painter, palette() ); + + drawKnob( &painter, d_data->knobRect ); + drawMarker( &painter, d_data->knobRect, d_data->angle ); + + painter.setRenderHint( QPainter::Antialiasing, false ); + + if ( hasFocus() ) + QwtPainter::drawFocusRect( &painter, this ); } /*! - Repaint the knob - - \param painter Painter - \param rect Update rectangle + \brief Draw the knob + \param painter painter + \param knobRect Bounding rectangle of the knob (without scale) */ -void QwtKnob::draw(QPainter *painter, const QRect& rect) +void QwtKnob::drawKnob( QPainter *painter, + const QRectF &knobRect ) const { - if ( !d_data->knobRect.contains( rect ) ) // event from valueChange() + double dim = qMin( knobRect.width(), knobRect.height() ); + dim -= d_data->borderWidth * 0.5; + + QRectF aRect( 0, 0, dim, dim ); + aRect.moveCenter( knobRect.center() ); + + QPen pen( Qt::NoPen ); + if ( d_data->borderWidth > 0 ) { -#if QT_VERSION < 0x040000 - scaleDraw()->draw( painter, colorGroup() ); -#else - scaleDraw()->draw( painter, palette() ); -#endif + QColor c1 = palette().color( QPalette::Light ); + QColor c2 = palette().color( QPalette::Dark ); + + QLinearGradient gradient( aRect.topLeft(), aRect.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.3, c1 ); + gradient.setColorAt( 0.7, c2 ); + gradient.setColorAt( 1.0, c2 ); + + pen = QPen( gradient, d_data->borderWidth ); } - drawKnob( painter, d_data->knobRect ); + QBrush brush; + switch( d_data->knobStyle ) + { + case QwtKnob::Raised: + { + double off = 0.3 * knobRect.width(); + QRadialGradient gradient( knobRect.center(), + knobRect.width(), knobRect.topLeft() + QPoint( off, off ) ); - if ( hasFocus() ) - QwtPainter::drawFocusRect(painter, this); + gradient.setColorAt( 0.0, palette().color( QPalette::Midlight ) ); + gradient.setColorAt( 1.0, palette().color( QPalette::Button ) ); + + brush = QBrush( gradient ); + + break; + } + case QwtKnob::Sunken: + { + QLinearGradient gradient( + knobRect.topLeft(), knobRect.bottomRight() ); + gradient.setColorAt( 0.0, palette().color( QPalette::Mid ) ); + gradient.setColorAt( 0.5, palette().color( QPalette::Button ) ); + gradient.setColorAt( 1.0, palette().color( QPalette::Midlight ) ); + brush = QBrush( gradient ); + + break; + } + default: + brush = palette().brush( QPalette::Button ); + } + + painter->setPen( pen ); + painter->setBrush( brush ); + painter->drawEllipse( aRect ); } + /*! \brief Draw the marker at the knob's front - \param p Painter - \param arc Angle of the marker - \param c Marker color + \param painter Painter + \param rect Bounding rectangle of the knob without scale + \param angle Angle of the marker in degrees */ -void QwtKnob::drawMarker(QPainter *p, double arc, const QColor &c) +void QwtKnob::drawMarker( QPainter *painter, + const QRectF &rect, double angle ) const { - const double rarc = arc * M_PI / 180.0; - const double ca = cos(rarc); - const double sa = - sin(rarc); + if ( d_data->markerStyle == NoMarker || !isValid() ) + return; - int radius = d_data->knobRect.width() / 2 - d_data->borderWidth; - if (radius < 3) - radius = 3; + const double radians = angle * M_PI / 180.0; + const double sinA = -qFastSin( radians ); + const double cosA = qFastCos( radians ); - const int ym = d_data->knobRect.y() + radius + d_data->borderWidth; - const int xm = d_data->knobRect.x() + radius + d_data->borderWidth; + const double xm = rect.center().x(); + const double ym = rect.center().y(); + const double margin = 4.0; - switch (d_data->symbol) + double radius = 0.5 * ( rect.width() - d_data->borderWidth ) - margin; + if ( radius < 1.0 ) + radius = 1.0; + + switch ( d_data->markerStyle ) { + case Notch: + case Nub: + { + const double dotWidth = + qMin( double( d_data->markerSize ), radius); + + const double dotCenterDist = radius - 0.5 * dotWidth; + if ( dotCenterDist > 0.0 ) + { + const QPointF center( xm - sinA * dotCenterDist, + ym - cosA * dotCenterDist ); + + QRectF ellipse( 0.0, 0.0, dotWidth, dotWidth ); + ellipse.moveCenter( center ); + + QColor c1 = palette().color( QPalette::Light ); + QColor c2 = palette().color( QPalette::Mid ); + + if ( d_data->markerStyle == Notch ) + qSwap( c1, c2 ); + + QLinearGradient gradient( + ellipse.topLeft(), ellipse.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 1.0, c2 ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( gradient ); + + painter->drawEllipse( ellipse ); + } + break; + } case Dot: { - p->setBrush(c); - p->setPen(Qt::NoPen); + const double dotWidth = + qMin( double( d_data->markerSize ), radius); + + const double dotCenterDist = radius - 0.5 * dotWidth; + if ( dotCenterDist > 0.0 ) + { + const QPointF center( xm - sinA * dotCenterDist, + ym - cosA * dotCenterDist ); + + QRectF ellipse( 0.0, 0.0, dotWidth, dotWidth ); + ellipse.moveCenter( center ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().color( QPalette::ButtonText ) ); + painter->drawEllipse( ellipse ); + } - const double rb = double(qwtMax(radius - 4 - d_data->dotWidth / 2, 0)); - p->drawEllipse(xm - qRound(sa * rb) - d_data->dotWidth / 2, - ym - qRound(ca * rb) - d_data->dotWidth / 2, - d_data->dotWidth, d_data->dotWidth); break; } - case Line: + case Tick: { - p->setPen(QPen(c, 2)); + const double rb = qMax( radius - d_data->markerSize, 1.0 ); + const double re = radius; + + const QLine line( xm - sinA * rb, ym - cosA * rb, + xm - sinA * re, ym - cosA * re ); + + QPen pen( palette().color( QPalette::ButtonText ), 0 ); + pen.setCapStyle( Qt::FlatCap ); + painter->setPen( pen ); + painter->drawLine ( line ); - const double rb = qwtMax(double((radius - 4) / 3.0), 0.0); - const double re = qwtMax(double(radius - 4), 0.0); - - p->drawLine ( xm - qRound(sa * rb), ym - qRound(ca * rb), - xm - qRound(sa * re), ym - qRound(ca * re)); - break; } +#if 0 + case Triangle: + { + const double rb = qMax( radius - d_data->markerSize, 1.0 ); + const double re = radius; + + painter->translate( rect.center() ); + painter->rotate( angle - 90.0 ); + + QPolygonF polygon; + polygon += QPointF( re, 0.0 ); + polygon += QPointF( rb, 0.5 * ( re - rb ) ); + polygon += QPointF( rb, -0.5 * ( re - rb ) ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().color( QPalette::Text ) ); + painter->drawPolygon( polygon ); + break; + } +#endif + default: + break; } } @@ -452,36 +560,55 @@ void QwtKnob::drawMarker(QPainter *p, double arc, const QColor &c) \brief Change the knob's width. The specified width must be >= 5, or it will be clipped. - \param w New width + \param width New width */ -void QwtKnob::setKnobWidth(int w) +void QwtKnob::setKnobWidth( int width ) { - d_data->knobWidth = qwtMax(w,5); - layoutKnob(); + d_data->knobWidth = qMax( width, 5 ); + layoutKnob( true ); } //! Return the width of the knob -int QwtKnob::knobWidth() const +int QwtKnob::knobWidth() const { return d_data->knobWidth; } /*! \brief Set the knob's border width - \param bw new border width + \param borderWidth new border width */ -void QwtKnob::setBorderWidth(int bw) +void QwtKnob::setBorderWidth( int borderWidth ) { - d_data->borderWidth = qwtMax(bw, 0); - layoutKnob(); + d_data->borderWidth = qMax( borderWidth, 0 ); + layoutKnob( true ); } //! Return the border width -int QwtKnob::borderWidth() const +int QwtKnob::borderWidth() const { return d_data->borderWidth; } +/*! + \brief Set the size of the marker + \sa markerSize(), markerStyle() +*/ +void QwtKnob::setMarkerSize( int size ) +{ + if ( d_data->markerSize != size ) + { + d_data->markerSize = size; + update(); + } +} + +//! Return the marker size +int QwtKnob::markerSize() const +{ + return d_data->markerSize; +} + /*! \brief Recalculate the marker angle corresponding to the current value @@ -491,16 +618,16 @@ void QwtKnob::recalcAngle() // // calculate the angle corresponding to the value // - if (maxValue() == minValue()) + if ( maxValue() == minValue() ) { d_data->angle = 0; d_data->nTurns = 0; } else { - d_data->angle = (value() - 0.5 * (minValue() + maxValue())) - / (maxValue() - minValue()) * d_data->totalAngle; - d_data->nTurns = floor((d_data->angle + 180.0) / 360.0); + d_data->angle = ( value() - 0.5 * ( minValue() + maxValue() ) ) + / ( maxValue() - minValue() ) * d_data->totalAngle; + d_data->nTurns = qFloor( ( d_data->angle + 180.0 ) / 360.0 ); d_data->angle = d_data->angle - d_data->nTurns * 360.0; } } @@ -512,17 +639,7 @@ void QwtKnob::recalcAngle() */ void QwtKnob::scaleChange() { - layoutKnob(); -} - -/*! - Recalculates the layout - \sa layoutKnob() -*/ -void QwtKnob::fontChange(const QFont &f) -{ - QwtAbstractSlider::fontChange( f ); - layoutKnob(); + layoutKnob( true ); } /*! @@ -530,18 +647,19 @@ void QwtKnob::fontChange(const QFont &f) */ QSize QwtKnob::sizeHint() const { - return minimumSizeHint(); + const QSize hint = minimumSizeHint(); + return hint.expandedTo( QApplication::globalStrut() ); } /*! \brief Return a minimum size hint - \warning The return value of QwtKnob::minimumSizeHint() depends on the + \warning The return value of QwtKnob::minimumSizeHint() depends on the font and the scale. */ QSize QwtKnob::minimumSizeHint() const { // Add the scale radial thickness to the knobWidth - const int sh = scaleDraw()->extent( QPen(), font() ); + const int sh = qCeil( scaleDraw()->extent( font() ) ); const int d = 2 * sh + 2 * d_data->scaleDist + d_data->knobWidth; return QSize( d, d ); diff --git a/qwt/src/qwt_knob.h b/qwt/src/qwt_knob.h index 41ec1bdd9..735fff0e6 100644 --- a/qwt/src/qwt_knob.h +++ b/qwt/src/qwt_knob.h @@ -33,65 +33,124 @@ class QwtRoundScaleDraw; class QWT_EXPORT QwtKnob : public QwtAbstractSlider, public QwtAbstractScale { - Q_OBJECT - Q_ENUMS (Symbol) + Q_OBJECT + + Q_ENUMS ( KnobStyle ) + Q_ENUMS ( MarkerStyle ) + + Q_PROPERTY( KnobStyle knobStyle READ knobStyle WRITE setKnobStyle ) + Q_PROPERTY( MarkerStyle markerStyle READ markerStyle WRITE setMarkerStyle ) Q_PROPERTY( int knobWidth READ knobWidth WRITE setKnobWidth ) Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) Q_PROPERTY( double totalAngle READ totalAngle WRITE setTotalAngle ) - Q_PROPERTY( Symbol symbol READ symbol WRITE setSymbol ) + Q_PROPERTY( int markerSize READ markerSize WRITE setMarkerSize ) + Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) public: /*! - Symbol - \sa QwtKnob::QwtKnob() + \brief Style of the knob surface + + Depending on the KnobStyle the surface of the knob is + filled from the brushes of the widget palette(). + + \sa setKnobStyle(), knobStyle() + */ + enum KnobStyle + { + //! Fill the knob with a brush from QPalette::Button. + NoStyle = -1, + + //! Build a gradient from QPalette::Midlight and QPalette::Button + Raised, + + /*! + Build a gradient from QPalette::Midlight, QPalette::Button + and QPalette::Midlight + */ + Sunken + }; + + /*! + \brief Marker type + + The marker indicates the current value on the knob + The default setting is a Notch marker. + + \sa setMarkerStyle(), setMarkerSize() */ + enum MarkerStyle + { + //! Don't paint any marker + NoMarker = -1, - enum Symbol { Line, Dot }; + //! Paint a single tick in QPalette::ButtonText color + Tick, - explicit QwtKnob(QWidget* parent = NULL); -#if QT_VERSION < 0x040000 - explicit QwtKnob(QWidget* parent, const char *name); -#endif + //! Paint a circle in QPalette::ButtonText color + Dot, + + /*! + Draw a raised ellipse with a gradient build from + QPalette::Light and QPalette::Mid + */ + Nub, + + /*! + Draw a sunken ellipse with a gradient build from + QPalette::Light and QPalette::Mid + */ + Notch + }; + + explicit QwtKnob( QWidget* parent = NULL ); virtual ~QwtKnob(); - void setKnobWidth(int w); + void setKnobWidth( int w ); int knobWidth() const; - void setTotalAngle (double angle); + void setTotalAngle ( double angle ); double totalAngle() const; - void setBorderWidth(int bw); + void setKnobStyle( KnobStyle ); + KnobStyle knobStyle() const; + + void setBorderWidth( int bw ); int borderWidth() const; - void setSymbol(Symbol); - Symbol symbol() const; + void setMarkerStyle( MarkerStyle ); + MarkerStyle markerStyle() const; + + void setMarkerSize( int ); + int markerSize() const; virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; - - void setScaleDraw(QwtRoundScaleDraw *); + + void setScaleDraw( QwtRoundScaleDraw * ); const QwtRoundScaleDraw *scaleDraw() const; QwtRoundScaleDraw *scaleDraw(); protected: - virtual void paintEvent(QPaintEvent *e); - virtual void resizeEvent(QResizeEvent *e); + virtual void paintEvent( QPaintEvent * ); + virtual void resizeEvent( QResizeEvent * ); + virtual void changeEvent( QEvent * ); - void draw(QPainter *p, const QRect& ur); - void drawKnob(QPainter *p, const QRect &r); - void drawMarker(QPainter *p, double arc, const QColor &c); + virtual void drawKnob( QPainter *, const QRectF & ) const; + virtual void drawMarker( QPainter *, + const QRectF &, double arc ) const; + + virtual double getValue( const QPoint &p ); + virtual void getScrollMode( const QPoint &, + QwtAbstractSlider::ScrollMode &, int &direction ) const; private: void initKnob(); - void layoutKnob( bool update = true ); - double getValue(const QPoint &p); - void getScrollMode( const QPoint &p, int &scrollMode, int &direction ); + void layoutKnob( bool update ); void recalcAngle(); - + virtual void valueChange(); virtual void rangeChange(); virtual void scaleChange(); - virtual void fontChange(const QFont &oldFont); class PrivateData; PrivateData *d_data; diff --git a/qwt/src/qwt_layout_metrics.cpp b/qwt/src/qwt_layout_metrics.cpp deleted file mode 100644 index 2a87652e5..000000000 --- a/qwt/src/qwt_layout_metrics.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#include -#include -#if QT_VERSION < 0x040000 -#include -#include -#define QwtMatrix QWMatrix -#else -#include -#define QwtMatrix QMatrix -#endif -#include -#include -#include "qwt_math.h" -#include "qwt_polygon.h" -#include "qwt_layout_metrics.h" - -static QSize deviceDpi(const QPaintDevice *device) -{ - QSize dpi; -#if QT_VERSION < 0x040000 - const QPaintDeviceMetrics metrics(device); - dpi.setWidth(metrics.logicalDpiX()); - dpi.setHeight(metrics.logicalDpiY()); -#else - dpi.setWidth(device->logicalDpiX()); - dpi.setHeight(device->logicalDpiY()); -#endif - - return dpi; -} - -#if QT_VERSION < 0x040000 - -inline static const QWMatrix &matrix(const QPainter *painter) -{ - return painter->worldMatrix(); -} -inline static QWMatrix invMatrix(const QPainter *painter) -{ - return painter->worldMatrix().invert(); -} - -#else // QT_VERSION >= 0x040000 - -inline static const QMatrix &matrix(const QPainter *painter) -{ - return painter->matrix(); -} -inline static QMatrix invMatrix(const QPainter *painter) -{ - return painter->matrix().inverted(); -} - -#endif - -QwtMetricsMap::QwtMetricsMap() -{ - d_screenToLayoutX = d_screenToLayoutY = - d_deviceToLayoutX = d_deviceToLayoutY = 1.0; -} - -void QwtMetricsMap::setMetrics(const QPaintDevice *layoutDevice, - const QPaintDevice *paintDevice) -{ - const QSize screenDpi = deviceDpi(QApplication::desktop()); - const QSize layoutDpi = deviceDpi(layoutDevice); - const QSize paintDpi = deviceDpi(paintDevice); - - d_screenToLayoutX = double(layoutDpi.width()) / - double(screenDpi.width()); - d_screenToLayoutY = double(layoutDpi.height()) / - double(screenDpi.height()); - - d_deviceToLayoutX = double(layoutDpi.width()) / - double(paintDpi.width()); - d_deviceToLayoutY = double(layoutDpi.height()) / - double(paintDpi.height()); -} - -#ifndef QT_NO_TRANSFORMATIONS -QPoint QwtMetricsMap::layoutToDevice(const QPoint &point, - const QPainter *painter) const -#else -QPoint QwtMetricsMap::layoutToDevice(const QPoint &point, - const QPainter *) const -#endif -{ - if ( isIdentity() ) - return point; - - QPoint mappedPoint(point); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPoint = matrix(painter).map(mappedPoint); -#endif - - mappedPoint.setX(layoutToDeviceX(mappedPoint.x())); - mappedPoint.setY(layoutToDeviceY(mappedPoint.y())); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPoint = invMatrix(painter).map(mappedPoint); -#endif - - return mappedPoint; -} - -#ifndef QT_NO_TRANSFORMATIONS -QPoint QwtMetricsMap::deviceToLayout(const QPoint &point, - const QPainter *painter) const -#else -QPoint QwtMetricsMap::deviceToLayout(const QPoint &point, - const QPainter *) const -#endif -{ - if ( isIdentity() ) - return point; - - QPoint mappedPoint(point); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPoint = matrix(painter).map(mappedPoint); -#endif - - mappedPoint.setX(deviceToLayoutX(mappedPoint.x())); - mappedPoint.setY(deviceToLayoutY(mappedPoint.y())); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPoint = invMatrix(painter).map(mappedPoint); -#endif - - return mappedPoint; -} - -QPoint QwtMetricsMap::screenToLayout(const QPoint &point) const -{ - if ( d_screenToLayoutX == 1.0 && d_screenToLayoutY == 1.0 ) - return point; - - return QPoint(screenToLayoutX(point.x()), screenToLayoutY(point.y())); -} - -QPoint QwtMetricsMap::layoutToScreen(const QPoint &point) const -{ - if ( d_screenToLayoutX == 1.0 && d_screenToLayoutY == 1.0 ) - return point; - - return QPoint(layoutToScreenX(point.x()), layoutToScreenY(point.y())); -} - -#ifndef QT_NO_TRANSFORMATIONS -QRect QwtMetricsMap::layoutToDevice(const QRect &rect, - const QPainter *painter) const -#else -QRect QwtMetricsMap::layoutToDevice(const QRect &rect, - const QPainter *) const -#endif -{ - if ( isIdentity() ) - return rect; - - int dx = 0; - int dy = 0; - - QRect mappedRect(rect); -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - { - // only translations, but this code doesn't need to be perfect - // as it used for printing of stuff only, that is not on the canvas. - // Here we know we have translations only. - // As soon as Qt3 support is dropped, Qwt will use a floating point - // based layout and this class can die completely. - - dx = qRound(matrix(painter).dx()); - dy = qRound(matrix(painter).dy()); - - mappedRect = QRect(mappedRect.x() + dx, mappedRect.y() + dy, - mappedRect.width(), mappedRect.height() ); - } -#endif - - mappedRect = QRect( - layoutToDevice(mappedRect.topLeft()), - layoutToDevice(mappedRect.bottomRight()) - ); - - mappedRect = QRect(mappedRect.x() - dx, mappedRect.y() - dy, - mappedRect.width(), mappedRect.height() ); - - return mappedRect; -} - -#ifndef QT_NO_TRANSFORMATIONS -QRect QwtMetricsMap::deviceToLayout(const QRect &rect, - const QPainter *painter) const -#else -QRect QwtMetricsMap::deviceToLayout(const QRect &rect, - const QPainter *) const -#endif -{ - if ( isIdentity() ) - return rect; - - QRect mappedRect(rect); -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedRect = translate(matrix(painter), mappedRect); -#endif - - mappedRect = QRect( - deviceToLayout(mappedRect.topLeft()), - deviceToLayout(mappedRect.bottomRight()) - ); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedRect = translate(invMatrix(painter), mappedRect); -#endif - - return mappedRect; -} - -QRect QwtMetricsMap::screenToLayout(const QRect &rect) const -{ - if ( d_screenToLayoutX == 1.0 && d_screenToLayoutY == 1.0 ) - return rect; - - return QRect(screenToLayoutX(rect.x()), screenToLayoutY(rect.y()), - screenToLayoutX(rect.width()), screenToLayoutY(rect.height())); -} - -QRect QwtMetricsMap::layoutToScreen(const QRect &rect) const -{ - if ( d_screenToLayoutX == 1.0 && d_screenToLayoutY == 1.0 ) - return rect; - - return QRect(layoutToScreenX(rect.x()), layoutToScreenY(rect.y()), - layoutToScreenX(rect.width()), layoutToScreenY(rect.height())); -} - -#ifndef QT_NO_TRANSFORMATIONS -QwtPolygon QwtMetricsMap::layoutToDevice(const QwtPolygon &pa, - const QPainter *painter) const -#else -QwtPolygon QwtMetricsMap::layoutToDevice(const QwtPolygon &pa, - const QPainter *) const -#endif -{ - if ( isIdentity() ) - return pa; - - QwtPolygon mappedPa(pa); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPa = translate(matrix(painter), mappedPa); -#endif - - QwtMatrix m; - m.scale(1.0 / d_deviceToLayoutX, 1.0 / d_deviceToLayoutY); - mappedPa = translate(m, mappedPa); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPa = translate(invMatrix(painter), mappedPa); -#endif - - return mappedPa; -} - -#ifndef QT_NO_TRANSFORMATIONS -QwtPolygon QwtMetricsMap::deviceToLayout(const QwtPolygon &pa, - const QPainter *painter) const -#else -QwtPolygon QwtMetricsMap::deviceToLayout(const QwtPolygon &pa, - const QPainter *) const -#endif -{ - if ( isIdentity() ) - return pa; - - QwtPolygon mappedPa(pa); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPa = translate(matrix(painter), mappedPa); -#endif - - QwtMatrix m; - m.scale(d_deviceToLayoutX, d_deviceToLayoutY); - mappedPa = translate(m, mappedPa); - -#ifndef QT_NO_TRANSFORMATIONS - if ( painter ) - mappedPa = translate(invMatrix(painter), mappedPa); -#endif - - return mappedPa; -} - -/*! - Wrapper for QMatrix::mapRect. - - \param m Matrix - \param rect Rectangle to translate - \return Translated rectangle -*/ - -QRect QwtMetricsMap::translate( - const QwtMatrix &m, const QRect &rect) -{ - return m.mapRect(rect); -} - -/*! - Wrapper for QMatrix::map. - - \param m Matrix - \param pa Polygon to translate - \return Translated polygon -*/ -QwtPolygon QwtMetricsMap::translate( - const QwtMatrix &m, const QwtPolygon &pa) -{ - return m.map(pa); -} diff --git a/qwt/src/qwt_layout_metrics.h b/qwt/src/qwt_layout_metrics.h deleted file mode 100644 index b1cc29d5f..000000000 --- a/qwt/src/qwt_layout_metrics.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#ifndef QWT_LAYOUT_METRICS_H -#define QWT_LAYOUT_METRICS_H - -#include -#include -#include "qwt_polygon.h" -#include "qwt_global.h" - -class QPainter; -class QString; -class QFontMetrics; -#if QT_VERSION < 0x040000 -class QWMatrix; -#else -class QMatrix; -#endif -class QPaintDevice; - -/*! - \brief A Map to translate between layout, screen and paint device metrics - - Qt3 supports painting in integer coordinates only. Therefore it is not - possible to scale the layout in screen coordinates to layouts in higher - resolutions ( f.e printing ) without losing the higher precision. - QwtMetricsMap is used to incorporate the various widget attributes - ( always in screen resolution ) into the layout/printing code of QwtPlot. - - Qt4 is able to paint floating point based coordinates, what makes it - possible always to render in screen coordinates - ( with a common scale factor ). - QwtMetricsMap will be obsolete as soon as Qt3 support has been - dropped ( Qwt 6.x ). -*/ -class QWT_EXPORT QwtMetricsMap -{ -public: - QwtMetricsMap(); - - bool isIdentity() const; - - void setMetrics(const QPaintDevice *layoutMetrics, - const QPaintDevice *deviceMetrics); - - int layoutToDeviceX(int x) const; - int deviceToLayoutX(int x) const; - int screenToLayoutX(int x) const; - int layoutToScreenX(int x) const; - - int layoutToDeviceY(int y) const; - int deviceToLayoutY(int y) const; - int screenToLayoutY(int y) const; - int layoutToScreenY(int y) const; - - QPoint layoutToDevice(const QPoint &, const QPainter * = NULL) const; - QPoint deviceToLayout(const QPoint &, const QPainter * = NULL) const; - QPoint screenToLayout(const QPoint &) const; - QPoint layoutToScreen(const QPoint &point) const; - - - QSize layoutToDevice(const QSize &) const; - QSize deviceToLayout(const QSize &) const; - QSize screenToLayout(const QSize &) const; - QSize layoutToScreen(const QSize &) const; - - QRect layoutToDevice(const QRect &, const QPainter * = NULL) const; - QRect deviceToLayout(const QRect &, const QPainter * = NULL) const; - QRect screenToLayout(const QRect &) const; - QRect layoutToScreen(const QRect &) const; - - QwtPolygon layoutToDevice(const QwtPolygon &, - const QPainter * = NULL) const; - QwtPolygon deviceToLayout(const QwtPolygon &, - const QPainter * = NULL) const; - -#if QT_VERSION < 0x040000 - static QwtPolygon translate(const QWMatrix &, const QwtPolygon &); - static QRect translate(const QWMatrix &, const QRect &); -#else - static QwtPolygon translate(const QMatrix &, const QwtPolygon &); - static QRect translate(const QMatrix &, const QRect &); -#endif - -private: - double d_screenToLayoutX; - double d_screenToLayoutY; - - double d_deviceToLayoutX; - double d_deviceToLayoutY; -}; - -inline bool QwtMetricsMap::isIdentity() const -{ - return d_deviceToLayoutX == 1.0 && d_deviceToLayoutY == 1.0; -} - -inline int QwtMetricsMap::layoutToDeviceX(int x) const -{ - return qRound(x / d_deviceToLayoutX); -} - -inline int QwtMetricsMap::deviceToLayoutX(int x) const -{ - return qRound(x * d_deviceToLayoutX); -} - -inline int QwtMetricsMap::screenToLayoutX(int x) const -{ - return qRound(x * d_screenToLayoutX); -} - -inline int QwtMetricsMap::layoutToScreenX(int x) const -{ - return qRound(x / d_screenToLayoutX); -} - -inline int QwtMetricsMap::layoutToDeviceY(int y) const -{ - return qRound(y / d_deviceToLayoutY); -} - -inline int QwtMetricsMap::deviceToLayoutY(int y) const -{ - return qRound(y * d_deviceToLayoutY); -} - -inline int QwtMetricsMap::screenToLayoutY(int y) const -{ - return qRound(y * d_screenToLayoutY); -} - -inline int QwtMetricsMap::layoutToScreenY(int y) const -{ - return qRound(y / d_screenToLayoutY); -} - -inline QSize QwtMetricsMap::layoutToDevice(const QSize &size) const -{ - return QSize(layoutToDeviceX(size.width()), - layoutToDeviceY(size.height())); -} - -inline QSize QwtMetricsMap::deviceToLayout(const QSize &size) const -{ - return QSize(deviceToLayoutX(size.width()), - deviceToLayoutY(size.height())); -} - -inline QSize QwtMetricsMap::screenToLayout(const QSize &size) const -{ - return QSize(screenToLayoutX(size.width()), - screenToLayoutY(size.height())); -} - -inline QSize QwtMetricsMap::layoutToScreen(const QSize &size) const -{ - return QSize(layoutToScreenX(size.width()), - layoutToScreenY(size.height())); -} - -#endif diff --git a/qwt/src/qwt_legend.cpp b/qwt/src/qwt_legend.cpp index b910f6126..473ff34fc 100644 --- a/qwt/src/qwt_legend.cpp +++ b/qwt/src/qwt_legend.cpp @@ -2,23 +2,20 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - -#include -#include -#if QT_VERSION >= 0x040000 -#include -#endif -#include "qwt_math.h" -#include "qwt_dyngrid_layout.h" +#include "qwt_legend.h" #include "qwt_legend_itemmanager.h" #include "qwt_legend_item.h" -#include "qwt_legend.h" +#include "qwt_dyngrid_layout.h" +#include "qwt_math.h" +#include +#include +#include +#include class QwtLegend::PrivateData { @@ -26,20 +23,20 @@ public: class LegendMap { public: - void insert(const QwtLegendItemManager *, QWidget *); + void insert( const QwtLegendItemManager *, QWidget * ); - void remove(const QwtLegendItemManager *); - void remove(QWidget *); + void remove( const QwtLegendItemManager * ); + void remove( QWidget * ); void clear(); uint count() const; - inline const QWidget *find(const QwtLegendItemManager *) const; - inline QWidget *find(const QwtLegendItemManager *); + inline const QWidget *find( const QwtLegendItemManager * ) const; + inline QWidget *find( const QwtLegendItemManager * ); - inline const QwtLegendItemManager *find(const QWidget *) const; - inline QwtLegendItemManager *find(const QWidget *); + inline const QwtLegendItemManager *find( const QWidget * ) const; + inline QwtLegendItemManager *find( const QWidget * ); const QMap &widgetMap() const; QMap &widgetMap(); @@ -50,8 +47,6 @@ public: }; QwtLegend::LegendItemMode itemMode; - QwtLegend::LegendDisplayPolicy displayPolicy; - int identifierMode; LegendMap map; @@ -59,73 +54,45 @@ public: LegendView *view; }; -#if QT_VERSION < 0x040000 -#include - -class QwtLegend::PrivateData::LegendView: public QScrollView -{ -public: - LegendView(QWidget *parent): - QScrollView(parent) - { - setResizePolicy(Manual); - - viewport()->setBackgroundMode(Qt::NoBackground); // Avoid flicker - - contentsWidget = new QWidget(viewport()); - - addChild(contentsWidget); - } - - void viewportResizeEvent(QResizeEvent *e) - { - QScrollView::viewportResizeEvent(e); - - // It's not safe to update the layout now, because - // we are in an internal update of the scrollview framework. - // So we delay the update by posting a LayoutHint. - - QApplication::postEvent(contentsWidget, - new QEvent(QEvent::LayoutHint)); - } - - QWidget *contentsWidget; -}; - -#else // QT_VERSION >= 0x040000 - -#include - class QwtLegend::PrivateData::LegendView: public QScrollArea { public: - LegendView(QWidget *parent): - QScrollArea(parent) + LegendView( QWidget *parent ): + QScrollArea( parent ) { - contentsWidget = new QWidget(this); + setFocusPolicy( Qt::NoFocus ); - setWidget(contentsWidget); - setWidgetResizable(false); - setFocusPolicy(Qt::NoFocus); + contentsWidget = new QWidget( this ); + contentsWidget->setObjectName( "QwtLegendViewContents" ); + + setWidget( contentsWidget ); + setWidgetResizable( false ); + + viewport()->setObjectName( "QwtLegendViewport" ); + + // QScrollArea::setWidget internally sets autoFillBackground to true + // But we don't want a background. + contentsWidget->setAutoFillBackground( false ); + viewport()->setAutoFillBackground( false ); } - virtual bool viewportEvent(QEvent *e) + virtual bool viewportEvent( QEvent *e ) { - bool ok = QScrollArea::viewportEvent(e); + bool ok = QScrollArea::viewportEvent( e ); if ( e->type() == QEvent::Resize ) { - QEvent event(QEvent::LayoutRequest); - QApplication::sendEvent(contentsWidget, &event); + QEvent event( QEvent::LayoutRequest ); + QApplication::sendEvent( contentsWidget, &event ); } return ok; } - QSize viewportSize(int w, int h) const + QSize viewportSize( int w, int h ) const { const int sbHeight = horizontalScrollBar()->sizeHint().height(); const int sbWidth = verticalScrollBar()->sizeHint().width(); - + const int cw = contentsRect().width(); const int ch = contentsRect().height(); @@ -141,63 +108,52 @@ public: if ( w > vw && vh == ch ) vh -= sbHeight; } - return QSize(vw, vh); + return QSize( vw, vh ); } QWidget *contentsWidget; }; -#endif - - void QwtLegend::PrivateData::LegendMap::insert( - const QwtLegendItemManager *item, QWidget *widget) + const QwtLegendItemManager *item, QWidget *widget ) { - d_itemMap.insert(item, widget); - d_widgetMap.insert(widget, item); + d_itemMap.insert( item, widget ); + d_widgetMap.insert( widget, item ); } -void QwtLegend::PrivateData::LegendMap::remove(const QwtLegendItemManager *item) +void QwtLegend::PrivateData::LegendMap::remove( const QwtLegendItemManager *item ) { QWidget *widget = d_itemMap[item]; - d_itemMap.remove(item); - d_widgetMap.remove(widget); + d_itemMap.remove( item ); + d_widgetMap.remove( widget ); } -void QwtLegend::PrivateData::LegendMap::remove(QWidget *widget) +void QwtLegend::PrivateData::LegendMap::remove( QWidget *widget ) { const QwtLegendItemManager *item = d_widgetMap[widget]; - d_itemMap.remove(item); - d_widgetMap.remove(widget); + d_itemMap.remove( item ); + d_widgetMap.remove( widget ); } void QwtLegend::PrivateData::LegendMap::clear() { - + /* We can't delete the widgets in the following loop, because we would get ChildRemoved events, changing d_itemMap, while we are iterating. */ -#if QT_VERSION < 0x040000 - QValueList widgets; + QList widgets; QMap::const_iterator it; - for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it ) - widgets.append(it.data()); -#else - QList widgets; - - QMap::const_iterator it; - for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it ) - widgets.append(it.value()); -#endif + for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it ) + widgets.append( it.value() ); d_itemMap.clear(); d_widgetMap.clear(); - for ( int i = 0; i < (int)widgets.size(); i++ ) + for ( int i = 0; i < widgets.size(); i++ ) delete widgets[i]; } @@ -206,79 +162,82 @@ uint QwtLegend::PrivateData::LegendMap::count() const return d_itemMap.count(); } -inline const QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtLegendItemManager *item) const +inline const QWidget *QwtLegend::PrivateData::LegendMap::find( + const QwtLegendItemManager *item ) const { - if ( !d_itemMap.contains((QwtLegendItemManager *)item) ) + if ( !d_itemMap.contains( item ) ) return NULL; - return d_itemMap[(QwtLegendItemManager *)item]; + return d_itemMap[item]; } -inline QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtLegendItemManager *item) +inline QWidget *QwtLegend::PrivateData::LegendMap::find( + const QwtLegendItemManager *item ) { - if ( !d_itemMap.contains((QwtLegendItemManager *)item) ) + if ( !d_itemMap.contains( item ) ) return NULL; - return d_itemMap[(QwtLegendItemManager *)item]; + return d_itemMap[item]; } inline const QwtLegendItemManager *QwtLegend::PrivateData::LegendMap::find( - const QWidget *widget) const + const QWidget *widget ) const { - if ( !d_widgetMap.contains((QWidget *)widget) ) + QWidget *w = const_cast( widget ); + if ( !d_widgetMap.contains( w ) ) return NULL; - return d_widgetMap[(QWidget *)widget]; + return d_widgetMap[w]; } inline QwtLegendItemManager *QwtLegend::PrivateData::LegendMap::find( - const QWidget *widget) + const QWidget *widget ) { - if ( !d_widgetMap.contains((QWidget *)widget) ) + QWidget *w = const_cast( widget ); + if ( !d_widgetMap.contains( w ) ) return NULL; - return (QwtLegendItemManager *)d_widgetMap[(QWidget *)widget]; + return const_cast( d_widgetMap[w] ); } inline const QMap & - QwtLegend::PrivateData::LegendMap::widgetMap() const +QwtLegend::PrivateData::LegendMap::widgetMap() const { return d_widgetMap; -} +} inline QMap & - QwtLegend::PrivateData::LegendMap::widgetMap() +QwtLegend::PrivateData::LegendMap::widgetMap() { return d_widgetMap; -} +} /*! Constructor \param parent Parent widget */ -QwtLegend::QwtLegend(QWidget *parent): - QFrame(parent) +QwtLegend::QwtLegend( QWidget *parent ): + QFrame( parent ) { - setFrameStyle(NoFrame); + setFrameStyle( NoFrame ); d_data = new QwtLegend::PrivateData; d_data->itemMode = QwtLegend::ReadOnlyItem; - d_data->displayPolicy = QwtLegend::AutoIdentifier; - d_data->identifierMode = QwtLegendItem::ShowLine | - QwtLegendItem::ShowSymbol | QwtLegendItem::ShowText; - d_data->view = new QwtLegend::PrivateData::LegendView(this); - d_data->view->setFrameStyle(NoFrame); + d_data->view = new QwtLegend::PrivateData::LegendView( this ); + d_data->view->setObjectName( "QwtLegendView" ); + d_data->view->setFrameStyle( NoFrame ); - QwtDynGridLayout *layout = new QwtDynGridLayout( - d_data->view->contentsWidget); -#if QT_VERSION < 0x040000 - layout->setAutoAdd(true); -#endif - layout->setAlignment(Qt::AlignHCenter | Qt::AlignTop); + QwtDynGridLayout *gridLayout = new QwtDynGridLayout( + d_data->view->contentsWidget ); + gridLayout->setAlignment( Qt::AlignHCenter | Qt::AlignTop ); - d_data->view->contentsWidget->installEventFilter(this); + d_data->view->contentsWidget->installEventFilter( this ); + + QVBoxLayout *layout = new QVBoxLayout( this ); + layout->setContentsMargins( 0, 0, 0, 0 ); + layout->addWidget( d_data->view ); } //! Destructor @@ -287,49 +246,8 @@ QwtLegend::~QwtLegend() delete d_data; } -/*! - Set the legend display policy to: - - \param policy Legend display policy - \param mode Identifier mode (or'd ShowLine, ShowSymbol, ShowText) - - \sa displayPolicy(), LegendDisplayPolicy -*/ -void QwtLegend::setDisplayPolicy(LegendDisplayPolicy policy, int mode) -{ - d_data->displayPolicy = policy; - if (-1 != mode) - d_data->identifierMode = mode; - - QMap &map = - d_data->map.widgetMap(); - - QMap::iterator it; - for ( it = map.begin(); it != map.end(); ++it ) - { -#if QT_VERSION < 0x040000 - QwtLegendItemManager *item = (QwtLegendItemManager *)it.data(); -#else - QwtLegendItemManager *item = (QwtLegendItemManager *)it.value(); -#endif - if ( item ) - item->updateLegend(this); - } -} - -/*! - \return the legend display policy. - Default is LegendDisplayPolicy::Auto. - \sa setDisplayPolicy(), LegendDisplayPolicy -*/ - -QwtLegend::LegendDisplayPolicy QwtLegend::displayPolicy() const -{ - return d_data->displayPolicy; -} - //! \sa LegendItemMode -void QwtLegend::setItemMode(LegendItemMode mode) +void QwtLegend::setItemMode( LegendItemMode mode ) { d_data->itemMode = mode; } @@ -341,26 +259,17 @@ QwtLegend::LegendItemMode QwtLegend::itemMode() const } /*! - \return the IdentifierMode to be used in combination with - LegendDisplayPolicy::Fixed. + The contents widget is the only child of the viewport of + the internal QScrollArea and the parent widget of all legend items. - Default is ShowLine | ShowSymbol | ShowText. + \return Container widget of the legend items */ -int QwtLegend::identifierMode() const +QWidget *QwtLegend::contentsWidget() { - return d_data->identifierMode; + return d_data->view->contentsWidget; } -/*! - The contents widget is the only child of the viewport() and - the parent widget of all legend items. -*/ -QWidget *QwtLegend::contentsWidget() -{ - return d_data->view->contentsWidget; -} - -/*! +/*! \return Horizontal scrollbar \sa verticalScrollBar() */ @@ -369,7 +278,7 @@ QScrollBar *QwtLegend::horizontalScrollBar() const return d_data->view->horizontalScrollBar(); } -/*! +/*! \return Vertical scrollbar \sa horizontalScrollBar() */ @@ -378,22 +287,25 @@ QScrollBar *QwtLegend::verticalScrollBar() const return d_data->view->verticalScrollBar(); } -/*! - The contents widget is the only child of the viewport() and - the parent widget of all legend items. +/*! + The contents widget is the only child of the viewport of + the internal QScrollArea and the parent widget of all legend items. + + \return Container widget of the legend items + */ -const QWidget *QwtLegend::contentsWidget() const -{ - return d_data->view->contentsWidget; +const QWidget *QwtLegend::contentsWidget() const +{ + return d_data->view->contentsWidget; } /*! Insert a new item for a plot item \param plotItem Plot item \param legendItem New legend item - \note The parent of item will be changed to QwtLegend::contentsWidget() + \note The parent of item will be changed to contentsWidget() */ -void QwtLegend::insert(const QwtLegendItemManager *plotItem, QWidget *legendItem) +void QwtLegend::insert( const QwtLegendItemManager *plotItem, QWidget *legendItem ) { if ( legendItem == NULL || plotItem == NULL ) return; @@ -401,63 +313,41 @@ void QwtLegend::insert(const QwtLegendItemManager *plotItem, QWidget *legendItem QWidget *contentsWidget = d_data->view->contentsWidget; if ( legendItem->parent() != contentsWidget ) - { -#if QT_VERSION >= 0x040000 - legendItem->setParent(contentsWidget); -#else - legendItem->reparent(contentsWidget, QPoint(0, 0)); -#endif - } + legendItem->setParent( contentsWidget ); legendItem->show(); - d_data->map.insert(plotItem, legendItem); + d_data->map.insert( plotItem, legendItem ); layoutContents(); if ( contentsWidget->layout() ) { -#if QT_VERSION >= 0x040000 - contentsWidget->layout()->addWidget(legendItem); -#endif + contentsWidget->layout()->addWidget( legendItem ); // set tab focus chain QWidget *w = NULL; -#if QT_VERSION < 0x040000 - QLayoutIterator layoutIterator = - contentsWidget->layout()->iterator(); - for ( QLayoutItem *item = layoutIterator.current(); - item != 0; item = ++layoutIterator) + for ( int i = 0; i < contentsWidget->layout()->count(); i++ ) { -#else - for (int i = 0; i < contentsWidget->layout()->count(); i++) - { - QLayoutItem *item = contentsWidget->layout()->itemAt(i); -#endif + QLayoutItem *item = contentsWidget->layout()->itemAt( i ); if ( w && item->widget() ) - { - QWidget::setTabOrder(w, item->widget()); - w = item->widget(); - } + QWidget::setTabOrder( w, item->widget() ); + + w = item->widget(); } } if ( parentWidget() && parentWidget()->layout() == NULL ) { - /* - updateGeometry() doesn't post LayoutRequest in certain - situations, like when we are hidden. But we want the - parent widget notified, so it can show/hide the legend - depending on its items. - */ -#if QT_VERSION < 0x040000 - QApplication::postEvent(parentWidget(), - new QEvent(QEvent::LayoutHint)); -#else - QApplication::postEvent(parentWidget(), - new QEvent(QEvent::LayoutRequest)); -#endif + /* + updateGeometry() doesn't post LayoutRequest in certain + situations, like when we are hidden. But we want the + parent widget notified, so it can show/hide the legend + depending on its items. + */ + QApplication::postEvent( parentWidget(), + new QEvent( QEvent::LayoutRequest ) ); } } @@ -467,9 +357,9 @@ void QwtLegend::insert(const QwtLegendItemManager *plotItem, QWidget *legendItem \param plotItem Plot item \return Widget on the legend, or NULL */ -QWidget *QwtLegend::find(const QwtLegendItemManager *plotItem) const +QWidget *QwtLegend::find( const QwtLegendItemManager *plotItem ) const { - return d_data->map.find(plotItem); + return d_data->map.find( plotItem ); } /*! @@ -478,37 +368,36 @@ QWidget *QwtLegend::find(const QwtLegendItemManager *plotItem) const \param legendItem Legend item \return Widget on the legend, or NULL */ -QwtLegendItemManager *QwtLegend::find(const QWidget *legendItem) const +QwtLegendItemManager *QwtLegend::find( const QWidget *legendItem ) const { - return d_data->map.find(legendItem); + return d_data->map.find( legendItem ); } -/*! - Find the corresponding item for a plotItem and remove it +/*! + Find the corresponding item for a plotItem and remove it from the item list. \param plotItem Plot item */ -void QwtLegend::remove(const QwtLegendItemManager *plotItem) -{ - QWidget *legendItem = d_data->map.find(plotItem); - d_data->map.remove(legendItem); +void QwtLegend::remove( const QwtLegendItemManager *plotItem ) +{ + QWidget *legendItem = d_data->map.find( plotItem ); + d_data->map.remove( legendItem ); delete legendItem; } //! Remove all items. void QwtLegend::clear() { -#if QT_VERSION < 0x040000 - bool doUpdate = isUpdatesEnabled(); -#else bool doUpdate = updatesEnabled(); -#endif - setUpdatesEnabled(false); + if ( doUpdate ) + setUpdatesEnabled( false ); d_data->map.clear(); - setUpdatesEnabled(doUpdate); + if ( doUpdate ) + setUpdatesEnabled( true ); + update(); } @@ -516,7 +405,7 @@ void QwtLegend::clear() QSize QwtLegend::sizeHint() const { QSize hint = d_data->view->contentsWidget->sizeHint(); - hint += QSize(2 * frameWidth(), 2 * frameWidth()); + hint += QSize( 2 * frameWidth(), 2 * frameWidth() ); return hint; } @@ -525,22 +414,11 @@ QSize QwtLegend::sizeHint() const \return The preferred height, for the width w. \param width Width */ -int QwtLegend::heightForWidth(int width) const +int QwtLegend::heightForWidth( int width ) const { width -= 2 * frameWidth(); - int h = d_data->view->contentsWidget->heightForWidth(width); -#if QT_VERSION < 0x040000 - - // Asking the layout is the default implementation in Qt4 - - if ( h <= 0 ) - { - QLayout *l = d_data->view->contentsWidget->layout(); - if ( l && l->hasHeightForWidth() ) - h = l->heightForWidth(width); - } -#endif + int h = d_data->view->contentsWidget->heightForWidth( width ); if ( h >= 0 ) h += 2 * frameWidth(); @@ -552,73 +430,64 @@ int QwtLegend::heightForWidth(int width) const */ void QwtLegend::layoutContents() { - const QSize visibleSize = d_data->view->viewport()->size(); + const QSize visibleSize = + d_data->view->viewport()->contentsRect().size(); - const QLayout *l = d_data->view->contentsWidget->layout(); - if ( l && l->inherits("QwtDynGridLayout") ) + const QwtDynGridLayout *tl = qobject_cast( + d_data->view->contentsWidget->layout() ); + if ( tl ) { - const QwtDynGridLayout *tl = (const QwtDynGridLayout *)l; + const int minW = int( tl->maxItemWidth() ) + 2 * tl->margin(); - const int minW = int(tl->maxItemWidth()) + 2 * tl->margin(); + int w = qMax( visibleSize.width(), minW ); + int h = qMax( tl->heightForWidth( w ), visibleSize.height() ); - int w = qwtMax(visibleSize.width(), minW); - int h = qwtMax(tl->heightForWidth(w), visibleSize.height()); - - const int vpWidth = d_data->view->viewportSize(w, h).width(); + const int vpWidth = d_data->view->viewportSize( w, h ).width(); if ( w > vpWidth ) { - w = qwtMax(vpWidth, minW); - h = qwtMax(tl->heightForWidth(w), visibleSize.height()); + w = qMax( vpWidth, minW ); + h = qMax( tl->heightForWidth( w ), visibleSize.height() ); } - d_data->view->contentsWidget->resize(w, h); -#if QT_VERSION < 0x040000 - d_data->view->resizeContents(w, h); -#endif + d_data->view->contentsWidget->resize( w, h ); } } /*! - Filter layout related events of QwtLegend::contentsWidget(). + Handle QEvent::ChildRemoved andQEvent::LayoutRequest events + for the contentsWidget(). - \param o Object to be filtered - \param e Event + \param object Object to be filtered + \param event Event */ -bool QwtLegend::eventFilter(QObject *o, QEvent *e) +bool QwtLegend::eventFilter( QObject *object, QEvent *event ) { - if ( o == d_data->view->contentsWidget ) + if ( object == d_data->view->contentsWidget ) { - switch(e->type()) + switch ( event->type() ) { case QEvent::ChildRemoved: - { - const QChildEvent *ce = (const QChildEvent *)e; + { + const QChildEvent *ce = + static_cast(event); if ( ce->child()->isWidgetType() ) - d_data->map.remove((QWidget *)ce->child()); + { + QWidget *w = static_cast< QWidget * >( ce->child() ); + d_data->map.remove( w ); + } break; } -#if QT_VERSION < 0x040000 - case QEvent::LayoutHint: -#else case QEvent::LayoutRequest: -#endif { layoutContents(); break; } -#if QT_VERSION < 0x040000 - case QEvent::Resize: - { - updateGeometry(); - break; - } -#endif default: break; } } - - return QFrame::eventFilter(o, e); + + return QFrame::eventFilter( object, event ); } @@ -635,34 +504,16 @@ uint QwtLegend::itemCount() const } //! Return a list of all legend items -#if QT_VERSION < 0x040000 -QValueList QwtLegend::legendItems() const -#else QList QwtLegend::legendItems() const -#endif { - const QMap &map = + const QMap &map = d_data->map.widgetMap(); -#if QT_VERSION < 0x040000 - QValueList list; -#else QList list; -#endif QMap::const_iterator it; - for ( it = map.begin(); it != map.end(); ++it ) + for ( it = map.begin(); it != map.end(); ++it ) list += it.key(); return list; -} - -/*! - Resize event - \param e Resize event -*/ -void QwtLegend::resizeEvent(QResizeEvent *e) -{ - QFrame::resizeEvent(e); - d_data->view->setGeometry(contentsRect()); -} +} \ No newline at end of file diff --git a/qwt/src/qwt_legend.h b/qwt/src/qwt_legend.h index ffb16370b..56ffae217 100644 --- a/qwt/src/qwt_legend.h +++ b/qwt/src/qwt_legend.h @@ -7,18 +7,12 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_LEGEND_H #define QWT_LEGEND_H -#include #include "qwt_global.h" -#if QT_VERSION < 0x040000 -#include -#else +#include #include -#endif class QScrollBar; class QwtLegendItemManager; @@ -38,47 +32,11 @@ class QWT_EXPORT QwtLegend : public QFrame Q_OBJECT public: - /*! - \brief Display policy - - - NoIdentifier\n - The client code is responsible how to display of each legend item. - The Qwt library will not interfere. - - - FixedIdentifier\n - All legend items are displayed with the QwtLegendItem::IdentifierMode - to be passed in 'mode'. - - - AutoIdentifier\n - Each legend item is displayed with a mode that is a bitwise or of - - QwtLegendItem::ShowLine (if its curve is drawn with a line) and - - QwtLegendItem::ShowSymbol (if its curve is drawn with symbols) and - - QwtLegendItem::ShowText (if the has a title). - - Default is AutoIdentifier. - \sa setDisplayPolicy(), displayPolicy(), QwtLegendItem::IdentifierMode - */ - - enum LegendDisplayPolicy - { - NoIdentifier = 0, - FixedIdentifier = 1, - AutoIdentifier = 2 - }; - /*! \brief Interaction mode for the legend items - - ReadOnlyItem\n - The legend item is not interactive, like a label + The default is QwtLegend::ReadOnlyItem. - - ClickableItem\n - The legend item is clickable, like a push button - - - CheckableItem\n - The legend item is checkable, like a checkable button - - Default is ReadOnlyItem. \sa setItemMode(), itemMode(), QwtLegendItem::IdentifierMode QwtLegendItem::clicked(), QwtLegendItem::checked(), QwtPlot::legendClicked(), QwtPlot::legendChecked() @@ -86,52 +44,47 @@ public: enum LegendItemMode { + //! The legend item is not interactive, like a label ReadOnlyItem, + + //! The legend item is clickable, like a push button ClickableItem, + + //! The legend item is checkable, like a checkable button CheckableItem }; - explicit QwtLegend(QWidget *parent = NULL); + explicit QwtLegend( QWidget *parent = NULL ); virtual ~QwtLegend(); - - void setDisplayPolicy(LegendDisplayPolicy policy, int mode); - LegendDisplayPolicy displayPolicy() const; - void setItemMode(LegendItemMode); + void setItemMode( LegendItemMode ); LegendItemMode itemMode() const; - int identifierMode() const; - QWidget *contentsWidget(); const QWidget *contentsWidget() const; - void insert(const QwtLegendItemManager *, QWidget *); - void remove(const QwtLegendItemManager *); + void insert( const QwtLegendItemManager *, QWidget * ); + void remove( const QwtLegendItemManager * ); - QWidget *find(const QwtLegendItemManager *) const; - QwtLegendItemManager *find(const QWidget *) const; + QWidget *find( const QwtLegendItemManager * ) const; + QwtLegendItemManager *find( const QWidget * ) const; -#if QT_VERSION < 0x040000 - virtual QValueList legendItems() const; -#else virtual QList legendItems() const; -#endif void clear(); - + bool isEmpty() const; uint itemCount() const; - virtual bool eventFilter(QObject *, QEvent *); + virtual bool eventFilter( QObject *, QEvent * ); virtual QSize sizeHint() const; - virtual int heightForWidth(int w) const; + virtual int heightForWidth( int w ) const; QScrollBar *horizontalScrollBar() const; QScrollBar *verticalScrollBar() const; protected: - virtual void resizeEvent(QResizeEvent *); virtual void layoutContents(); private: @@ -139,4 +92,4 @@ private: PrivateData *d_data; }; -#endif // QWT_LEGEND_H +#endif diff --git a/qwt/src/qwt_legend_item.cpp b/qwt/src/qwt_legend_item.cpp index 8098bfcf6..81a30ac36 100644 --- a/qwt/src/qwt_legend_item.cpp +++ b/qwt/src/qwt_legend_item.cpp @@ -2,74 +2,54 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - +#include "qwt_legend_item.h" +#include "qwt_math.h" +#include "qwt_painter.h" +#include "qwt_symbol.h" #include #include #include #include -#if QT_VERSION >= 0x040000 #include #include -#endif -#include "qwt_math.h" -#include "qwt_painter.h" -#include "qwt_symbol.h" -#include "qwt_legend_item.h" +#include static const int ButtonFrame = 2; static const int Margin = 2; -static QSize buttonShift(const QwtLegendItem *w) +static QSize buttonShift( const QwtLegendItem *w ) { -#if QT_VERSION < 0x040000 - const int ph = w->style().pixelMetric( - QStyle::PM_ButtonShiftHorizontal, w); - const int pv = w->style().pixelMetric( - QStyle::PM_ButtonShiftVertical, w); -#else QStyleOption option; - option.init(w); + option.init( w ); const int ph = w->style()->pixelMetric( - QStyle::PM_ButtonShiftHorizontal, &option, w); + QStyle::PM_ButtonShiftHorizontal, &option, w ); const int pv = w->style()->pixelMetric( - QStyle::PM_ButtonShiftVertical, &option, w); -#endif - return QSize(ph, pv); + QStyle::PM_ButtonShiftVertical, &option, w ); + return QSize( ph, pv ); } class QwtLegendItem::PrivateData { public: PrivateData(): - itemMode(QwtLegend::ReadOnlyItem), - isDown(false), - identifierWidth(8), - identifierMode(QwtLegendItem::ShowLine | QwtLegendItem::ShowText), - curvePen(Qt::NoPen), - spacing(Margin) + itemMode( QwtLegend::ReadOnlyItem ), + isDown( false ), + identifierSize( 8, 8 ), + spacing( Margin ) { - symbol = new QwtSymbol(); - } - - ~PrivateData() - { - delete symbol; } QwtLegend::LegendItemMode itemMode; bool isDown; - int identifierWidth; - int identifierMode; - QwtSymbol *symbol; - QPen curvePen; + QSize identifierSize; + QPixmap identifier; int spacing; }; @@ -77,39 +57,12 @@ public: /*! \param parent Parent widget */ -QwtLegendItem::QwtLegendItem(QWidget *parent): - QwtTextLabel(parent) +QwtLegendItem::QwtLegendItem( QWidget *parent ): + QwtTextLabel( parent ) { d_data = new PrivateData; - init(QwtText()); -} - -/*! - \param symbol Curve symbol - \param curvePen Curve pen - \param text Label text - \param parent Parent widget -*/ -QwtLegendItem::QwtLegendItem(const QwtSymbol &symbol, - const QPen &curvePen, const QwtText &text, - QWidget *parent): - QwtTextLabel(parent) -{ - d_data = new PrivateData; - - delete d_data->symbol; - d_data->symbol = symbol.clone(); - - d_data->curvePen = curvePen; - - init(text); -} - -void QwtLegendItem::init(const QwtText &text) -{ - setMargin(Margin); - setIndent(margin() + d_data->identifierWidth + 2 * d_data->spacing); - setText(text); + setMargin( Margin ); + setIndent( Margin + d_data->identifierSize.width() + 2 * d_data->spacing ); } //! Destructor @@ -125,19 +78,15 @@ QwtLegendItem::~QwtLegendItem() \param text Text label \sa QwtTextLabel::text() */ -void QwtLegendItem::setText(const QwtText &text) +void QwtLegendItem::setText( const QwtText &text ) { const int flags = Qt::AlignLeft | Qt::AlignVCenter -#if QT_VERSION < 0x040000 - | Qt::WordBreak | Qt::ExpandTabs; -#else | Qt::TextExpandTabs | Qt::TextWordWrap; -#endif QwtText txt = text; - txt.setRenderFlags(flags); + txt.setRenderFlags( flags ); - QwtTextLabel::setText(txt); + QwtTextLabel::setText( txt ); } /*! @@ -147,81 +96,80 @@ void QwtLegendItem::setText(const QwtText &text) \param mode Item mode \sa itemMode() */ -void QwtLegendItem::setItemMode(QwtLegend::LegendItemMode mode) -{ - d_data->itemMode = mode; - d_data->isDown = false; - -#if QT_VERSION >= 0x040000 - using namespace Qt; -#endif - setFocusPolicy(mode != QwtLegend::ReadOnlyItem ? TabFocus : NoFocus); - setMargin(ButtonFrame + Margin); - - updateGeometry(); -} - -/*! - Return the item mode - - \sa setItemMode() -*/ -QwtLegend::LegendItemMode QwtLegendItem::itemMode() const -{ - return d_data->itemMode; -} - -/*! - Set identifier mode. - Default is ShowLine | ShowText. - \param mode Or'd values of IdentifierMode - - \sa identifierMode() -*/ -void QwtLegendItem::setIdentifierMode(int mode) +void QwtLegendItem::setItemMode( QwtLegend::LegendItemMode mode ) { - if ( mode != d_data->identifierMode ) + if ( mode != d_data->itemMode ) { - d_data->identifierMode = mode; - update(); + d_data->itemMode = mode; + d_data->isDown = false; + + setFocusPolicy( mode != QwtLegend::ReadOnlyItem ? Qt::TabFocus : Qt::NoFocus ); + setMargin( ButtonFrame + Margin ); + + updateGeometry(); } } /*! - Or'd values of IdentifierMode. - \sa setIdentifierMode(), IdentifierMode + Return the item mode + + \sa setItemMode() */ -int QwtLegendItem::identifierMode() const -{ - return d_data->identifierMode; +QwtLegend::LegendItemMode QwtLegendItem::itemMode() const +{ + return d_data->itemMode; } /*! - Set the width for the identifier - Default is 8 pixels + Assign the identifier + The identifier needs to be created according to the identifierWidth() - \param width New width + \param identifier Pixmap representing a plot item - \sa identifierMode(), identifierWidth() + \sa identifier(), identifierWidth() */ -void QwtLegendItem::setIdentifierWidth(int width) +void QwtLegendItem::setIdentifier( const QPixmap &identifier ) { - width = qwtMax(width, 0); - if ( width != d_data->identifierWidth ) + d_data->identifier = identifier; + update(); +} + +/*! + \return pixmap representing a plot item + \sa setIdentifier() +*/ +QPixmap QwtLegendItem::identifier() const +{ + return d_data->identifier; +} + +/*! + Set the size for the identifier + Default is 8x8 pixels + + \param size New size + + \sa identifierSize() +*/ +void QwtLegendItem::setIdentifierSize( const QSize &size ) +{ + QSize sz = size.expandedTo( QSize( 0, 0 ) ); + if ( sz != d_data->identifierSize ) { - d_data->identifierWidth = width; - setIndent(margin() + d_data->identifierWidth - + 2 * d_data->spacing); + d_data->identifierSize = sz; + setIndent( margin() + d_data->identifierSize.width() + + 2 * d_data->spacing ); + updateGeometry(); } } /*! Return the width of the identifier - \sa setIdentifierWidth() + \sa setIdentifierSize() */ -int QwtLegendItem::identifierWidth() const +QSize QwtLegendItem::identifierSize() const { - return d_data->identifierWidth; + return d_data->identifierSize; } /*! @@ -229,14 +177,14 @@ int QwtLegendItem::identifierWidth() const \param spacing Spacing \sa spacing(), identifierWidth(), QwtTextLabel::margin() */ -void QwtLegendItem::setSpacing(int spacing) +void QwtLegendItem::setSpacing( int spacing ) { - spacing = qwtMax(spacing, 0); + spacing = qMax( spacing, 0 ); if ( spacing != d_data->spacing ) { d_data->spacing = spacing; - setIndent(margin() + d_data->identifierWidth - + 2 * d_data->spacing); + setIndent( margin() + d_data->identifierSize.width() + + 2 * d_data->spacing ); } } @@ -249,292 +197,22 @@ int QwtLegendItem::spacing() const return d_data->spacing; } -/*! - Set curve symbol. - \param symbol Symbol - - \sa symbol() -*/ -void QwtLegendItem::setSymbol(const QwtSymbol &symbol) -{ - delete d_data->symbol; - d_data->symbol = symbol.clone(); - update(); -} - -/*! - \return The curve symbol. - \sa setSymbol() -*/ -const QwtSymbol& QwtLegendItem::symbol() const -{ - return *d_data->symbol; -} - - -/*! - Set curve pen. - \param pen Curve pen - - \sa curvePen() -*/ -void QwtLegendItem::setCurvePen(const QPen &pen) -{ - if ( pen != d_data->curvePen ) - { - d_data->curvePen = pen; - update(); - } -} - -/*! - \return The curve pen. - \sa setCurvePen() -*/ -const QPen& QwtLegendItem::curvePen() const -{ - return d_data->curvePen; -} - -/*! - Paint the identifier to a given rect. - \param painter Painter - \param rect Rect where to paint -*/ -void QwtLegendItem::drawIdentifier( - QPainter *painter, const QRect &rect) const -{ - if ( rect.isEmpty() ) - return; - - if ( (d_data->identifierMode & ShowLine ) && (d_data->curvePen.style() != Qt::NoPen) ) - { - painter->save(); - painter->setPen(QwtPainter::scaledPen(d_data->curvePen)); - QwtPainter::drawLine(painter, rect.left(), rect.center().y(), - rect.right(), rect.center().y()); - painter->restore(); - } - - if ( (d_data->identifierMode & ShowSymbol) - && (d_data->symbol->style() != QwtSymbol::NoSymbol) ) - { - QSize symbolSize = - QwtPainter::metricsMap().screenToLayout(d_data->symbol->size()); - - // scale the symbol size down if it doesn't fit into rect. - - if ( rect.width() < symbolSize.width() ) - { - const double ratio = - double(symbolSize.width()) / double(rect.width()); - symbolSize.setWidth(rect.width()); - symbolSize.setHeight(qRound(symbolSize.height() / ratio)); - } - if ( rect.height() < symbolSize.height() ) - { - const double ratio = - double(symbolSize.width()) / double(rect.width()); - symbolSize.setHeight(rect.height()); - symbolSize.setWidth(qRound(symbolSize.width() / ratio)); - } - - QRect symbolRect; - symbolRect.setSize(symbolSize); - symbolRect.moveCenter(rect.center()); - - painter->save(); - painter->setBrush(d_data->symbol->brush()); - painter->setPen(QwtPainter::scaledPen(d_data->symbol->pen())); - d_data->symbol->draw(painter, symbolRect); - painter->restore(); - } -} - -/*! - Draw the legend item to a given rect. - \param painter Painter - \param rect Rect where to paint the button -*/ - -void QwtLegendItem::drawItem(QPainter *painter, const QRect &rect) const -{ - painter->save(); - - const QwtMetricsMap &map = QwtPainter::metricsMap(); - - const int m = map.screenToLayoutX(margin()); - const int spacing = map.screenToLayoutX(d_data->spacing); - const int identifierWidth = map.screenToLayoutX(d_data->identifierWidth); - - const QRect identifierRect(rect.x() + m, rect.y(), - identifierWidth, rect.height()); - drawIdentifier(painter, identifierRect); - - // Label - - QRect titleRect = rect; - titleRect.setX(identifierRect.right() + 2 * spacing); - - text().draw(painter, titleRect); - - painter->restore(); -} - -//! Paint event -void QwtLegendItem::paintEvent(QPaintEvent *e) -{ - const QRect cr = contentsRect(); - - QPainter painter(this); - painter.setClipRegion(e->region()); - - if ( d_data->isDown ) - { - qDrawWinButton(&painter, 0, 0, width(), height(), -#if QT_VERSION < 0x040000 - colorGroup(), -#else - palette(), -#endif - true); - } - - painter.save(); - - if ( d_data->isDown ) - { - const QSize shiftSize = buttonShift(this); - painter.translate(shiftSize.width(), shiftSize.height()); - } - - painter.setClipRect(cr); - - drawContents(&painter); - - QRect rect = cr; - rect.setX(rect.x() + margin()); - if ( d_data->itemMode != QwtLegend::ReadOnlyItem ) - rect.setX(rect.x() + ButtonFrame); - - rect.setWidth(d_data->identifierWidth); - - drawIdentifier(&painter, rect); - - painter.restore(); -} - -//! Handle mouse press events -void QwtLegendItem::mousePressEvent(QMouseEvent *e) -{ - if ( e->button() == Qt::LeftButton ) - { - switch(d_data->itemMode) - { - case QwtLegend::ClickableItem: - { - setDown(true); - return; - } - case QwtLegend::CheckableItem: - { - setDown(!isDown()); - return; - } - default:; - } - } - QwtTextLabel::mousePressEvent(e); -} - -//! Handle mouse release events -void QwtLegendItem::mouseReleaseEvent(QMouseEvent *e) -{ - if ( e->button() == Qt::LeftButton ) - { - switch(d_data->itemMode) - { - case QwtLegend::ClickableItem: - { - setDown(false); - return; - } - case QwtLegend::CheckableItem: - { - return; // do nothing, but accept - } - default:; - } - } - QwtTextLabel::mouseReleaseEvent(e); -} - -//! Handle key press events -void QwtLegendItem::keyPressEvent(QKeyEvent *e) -{ - if ( e->key() == Qt::Key_Space ) - { - switch(d_data->itemMode) - { - case QwtLegend::ClickableItem: - { - if ( !e->isAutoRepeat() ) - setDown(true); - return; - } - case QwtLegend::CheckableItem: - { - if ( !e->isAutoRepeat() ) - setDown(!isDown()); - return; - } - default:; - } - } - - QwtTextLabel::keyPressEvent(e); -} - -//! Handle key release events -void QwtLegendItem::keyReleaseEvent(QKeyEvent *e) -{ - if ( e->key() == Qt::Key_Space ) - { - switch(d_data->itemMode) - { - case QwtLegend::ClickableItem: - { - if ( !e->isAutoRepeat() ) - setDown(false); - return; - } - case QwtLegend::CheckableItem: - { - return; // do nothing, but accept - } - default:; - } - } - - QwtTextLabel::keyReleaseEvent(e); -} - /*! Check/Uncheck a the item \param on check/uncheck \sa setItemMode() */ -void QwtLegendItem::setChecked(bool on) +void QwtLegendItem::setChecked( bool on ) { if ( d_data->itemMode == QwtLegend::CheckableItem ) { const bool isBlocked = signalsBlocked(); - blockSignals(true); + blockSignals( true ); - setDown(on); + setDown( on ); - blockSignals(isBlocked); + blockSignals( isBlocked ); } } @@ -545,7 +223,7 @@ bool QwtLegendItem::isChecked() const } //! Set the item being down -void QwtLegendItem::setDown(bool down) +void QwtLegendItem::setDown( bool down ) { if ( down == d_data->isDown ) return; @@ -556,16 +234,16 @@ void QwtLegendItem::setDown(bool down) if ( d_data->itemMode == QwtLegend::ClickableItem ) { if ( d_data->isDown ) - emit pressed(); + Q_EMIT pressed(); else { - emit released(); - emit clicked(); + Q_EMIT released(); + Q_EMIT clicked(); } } if ( d_data->itemMode == QwtLegend::CheckableItem ) - emit checked(d_data->isDown); + Q_EMIT checked( d_data->isDown ); } //! Return true, if the item is down @@ -578,13 +256,150 @@ bool QwtLegendItem::isDown() const QSize QwtLegendItem::sizeHint() const { QSize sz = QwtTextLabel::sizeHint(); + sz.setHeight( qMax( sz.height(), d_data->identifier.height() + 4 ) ); + if ( d_data->itemMode != QwtLegend::ReadOnlyItem ) - sz += buttonShift(this); + { + sz += buttonShift( this ); + sz = sz.expandedTo( QApplication::globalStrut() ); + } return sz; } -void QwtLegendItem::drawText(QPainter *painter, const QRect &rect) +//! Paint event +void QwtLegendItem::paintEvent( QPaintEvent *e ) { - QwtTextLabel::drawText(painter, rect); + const QRect cr = contentsRect(); + + QPainter painter( this ); + painter.setClipRegion( e->region() ); + + if ( d_data->isDown ) + { + qDrawWinButton( &painter, 0, 0, width(), height(), + palette(), true ); + } + + painter.save(); + + if ( d_data->isDown ) + { + const QSize shiftSize = buttonShift( this ); + painter.translate( shiftSize.width(), shiftSize.height() ); + } + + painter.setClipRect( cr ); + + drawContents( &painter ); + + if ( !d_data->identifier.isNull() ) + { + QRect identRect = cr; + identRect.setX( identRect.x() + margin() ); + if ( d_data->itemMode != QwtLegend::ReadOnlyItem ) + identRect.setX( identRect.x() + ButtonFrame ); + + identRect.setSize( d_data->identifier.size() ); + identRect.moveCenter( QPoint( identRect.center().x(), cr.center().y() ) ); + + painter.drawPixmap( identRect, d_data->identifier ); + } + + painter.restore(); } + +//! Handle mouse press events +void QwtLegendItem::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == Qt::LeftButton ) + { + switch ( d_data->itemMode ) + { + case QwtLegend::ClickableItem: + { + setDown( true ); + return; + } + case QwtLegend::CheckableItem: + { + setDown( !isDown() ); + return; + } + default:; + } + } + QwtTextLabel::mousePressEvent( e ); +} + +//! Handle mouse release events +void QwtLegendItem::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( e->button() == Qt::LeftButton ) + { + switch ( d_data->itemMode ) + { + case QwtLegend::ClickableItem: + { + setDown( false ); + return; + } + case QwtLegend::CheckableItem: + { + return; // do nothing, but accept + } + default:; + } + } + QwtTextLabel::mouseReleaseEvent( e ); +} + +//! Handle key press events +void QwtLegendItem::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Qt::Key_Space ) + { + switch ( d_data->itemMode ) + { + case QwtLegend::ClickableItem: + { + if ( !e->isAutoRepeat() ) + setDown( true ); + return; + } + case QwtLegend::CheckableItem: + { + if ( !e->isAutoRepeat() ) + setDown( !isDown() ); + return; + } + default:; + } + } + + QwtTextLabel::keyPressEvent( e ); +} + +//! Handle key release events +void QwtLegendItem::keyReleaseEvent( QKeyEvent *e ) +{ + if ( e->key() == Qt::Key_Space ) + { + switch ( d_data->itemMode ) + { + case QwtLegend::ClickableItem: + { + if ( !e->isAutoRepeat() ) + setDown( false ); + return; + } + case QwtLegend::CheckableItem: + { + return; // do nothing, but accept + } + default:; + } + } + + QwtTextLabel::keyReleaseEvent( e ); +} \ No newline at end of file diff --git a/qwt/src/qwt_legend_item.h b/qwt/src/qwt_legend_item.h index 2e6a461b0..75887fd57 100644 --- a/qwt/src/qwt_legend_item.h +++ b/qwt/src/qwt_legend_item.h @@ -7,8 +7,6 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_LEGEND_ITEM_H #define QWT_LEGEND_ITEM_H @@ -16,78 +14,40 @@ #include "qwt_legend.h" #include "qwt_text.h" #include "qwt_text_label.h" - -class QPainter; -class QPen; -class QwtSymbol; +#include /*! - \brief A legend label - - QwtLegendItem represents a curve on a legend. - It displays an curve identifier with an explaining text. - The identifier might be a combination of curve symbol and line. - In readonly mode it behaves like a label, otherwise like - an unstylish push button. - - \sa QwtLegend, QwtPlotCurve + \brief A widget representing something on a QwtLegend(). */ class QWT_EXPORT QwtLegendItem: public QwtTextLabel { Q_OBJECT public: - - /*! - \brief Identifier mode - - Default is ShowLine | ShowText - \sa identifierMode(), setIdentifierMode() - */ - - enum IdentifierMode - { - NoIdentifier = 0, - ShowLine = 1, - ShowSymbol = 2, - ShowText = 4 - }; - - explicit QwtLegendItem(QWidget *parent = 0); - explicit QwtLegendItem(const QwtSymbol &, const QPen &, - const QwtText &, QWidget *parent = 0); + explicit QwtLegendItem( QWidget *parent = 0 ); virtual ~QwtLegendItem(); - virtual void setText(const QwtText &); - - void setItemMode(QwtLegend::LegendItemMode); + void setItemMode( QwtLegend::LegendItemMode ); QwtLegend::LegendItemMode itemMode() const; - void setIdentifierMode(int); - int identifierMode() const; - - void setIdentifierWidth(int width); - int identifierWidth() const; - - void setSpacing(int spacing); + void setSpacing( int spacing ); int spacing() const; - void setSymbol(const QwtSymbol &); - const QwtSymbol& symbol() const; + virtual void setText( const QwtText & ); - void setCurvePen(const QPen &); - const QPen& curvePen() const; + void setIdentifier( const QPixmap & ); + QPixmap identifier() const; - virtual void drawIdentifier(QPainter *, const QRect &) const; - virtual void drawItem(QPainter *p, const QRect &) const; + void setIdentifierSize( const QSize & ); + QSize identifierSize() const; virtual QSize sizeHint() const; bool isChecked() const; -public slots: - void setChecked(bool on); +public Q_SLOTS: + void setChecked( bool on ); -signals: +Q_SIGNALS: //! Signal, when the legend item has been clicked void clicked(); @@ -98,25 +58,21 @@ signals: void released(); //! Signal, when the legend item has been toggled - void checked(bool); + void checked( bool ); protected: - void setDown(bool); + void setDown( bool ); bool isDown() const; - virtual void paintEvent(QPaintEvent *); - virtual void mousePressEvent(QMouseEvent *); - virtual void mouseReleaseEvent(QMouseEvent *); - virtual void keyPressEvent(QKeyEvent *); - virtual void keyReleaseEvent(QKeyEvent *); - - virtual void drawText(QPainter *, const QRect &); + virtual void paintEvent( QPaintEvent * ); + virtual void mousePressEvent( QMouseEvent * ); + virtual void mouseReleaseEvent( QMouseEvent * ); + virtual void keyPressEvent( QKeyEvent * ); + virtual void keyReleaseEvent( QKeyEvent * ); private: - void init(const QwtText &); - class PrivateData; PrivateData *d_data; }; -#endif // QWT_LEGEND_ITEM_H +#endif diff --git a/qwt/src/qwt_legend_itemmanager.h b/qwt/src/qwt_legend_itemmanager.h index 5d26e2b94..0d6b58d76 100644 --- a/qwt/src/qwt_legend_itemmanager.h +++ b/qwt/src/qwt_legend_itemmanager.h @@ -7,8 +7,6 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_LEGEND_ITEM_MANAGER_H #define QWT_LEGEND_ITEM_MANAGER_H @@ -16,6 +14,8 @@ class QwtLegend; class QWidget; +class QRectF; +class QPainter; /*! \brief Abstract API to bind plot items to the legend @@ -25,12 +25,12 @@ class QWT_EXPORT QwtLegendItemManager { public: //! Constructor - QwtLegendItemManager() + QwtLegendItemManager() { } //! Destructor - virtual ~QwtLegendItemManager() + virtual ~QwtLegendItemManager() { } @@ -39,7 +39,7 @@ public: \param legend Legend \sa legendItem() */ - virtual void updateLegend(QwtLegend *legend) const = 0; + virtual void updateLegend( QwtLegend *legend ) const = 0; /*! Allocate the widget that represents the item on the legend @@ -48,7 +48,18 @@ public: */ virtual QWidget *legendItem() const = 0; + + /*! + QwtLegendItem can display an icon-identifier followed + by a text. The icon helps to identify a plot item on + the plot canvas and depends on the type of information, + that is displayed. + + The default implementation paints nothing. + */ + virtual void drawLegendIdentifier( QPainter *, const QRectF & ) const + { + } }; #endif - diff --git a/qwt/src/qwt_magnifier.cpp b/qwt/src/qwt_magnifier.cpp index 44a4a2e7e..4cc93087e 100644 --- a/qwt/src/qwt_magnifier.cpp +++ b/qwt/src/qwt_magnifier.cpp @@ -7,35 +7,27 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - -#include +#include "qwt_magnifier.h" +#include "qwt_math.h" #include #include -#include "qwt_math.h" -#include "qwt_magnifier.h" class QwtMagnifier::PrivateData { public: PrivateData(): - isEnabled(false), - wheelFactor(0.9), - wheelButtonState(Qt::NoButton), - mouseFactor(0.95), - mouseButton(Qt::RightButton), - mouseButtonState(Qt::NoButton), - keyFactor(0.9), - zoomInKey(Qt::Key_Plus), - zoomOutKey(Qt::Key_Minus), -#if QT_VERSION < 0x040000 - zoomInKeyModifiers(Qt::NoButton), - zoomOutKeyModifiers(Qt::NoButton), -#else - zoomInKeyModifiers(Qt::NoModifier), - zoomOutKeyModifiers(Qt::NoModifier), -#endif - mousePressed(false) + isEnabled( false ), + wheelFactor( 0.9 ), + wheelButtonState( Qt::NoButton ), + mouseFactor( 0.95 ), + mouseButton( Qt::RightButton ), + mouseButtonState( Qt::NoButton ), + keyFactor( 0.9 ), + zoomInKey( Qt::Key_Plus ), + zoomOutKey( Qt::Key_Minus ), + zoomInKeyModifiers( Qt::NoModifier ), + zoomOutKeyModifiers( Qt::NoModifier ), + mousePressed( false ) { } @@ -59,15 +51,15 @@ public: QPoint mousePos; }; -/*! +/*! Constructor \param parent Widget to be magnified */ -QwtMagnifier::QwtMagnifier(QWidget *parent): - QObject(parent) +QwtMagnifier::QwtMagnifier( QWidget *parent ): + QObject( parent ) { d_data = new PrivateData(); - setEnabled(true); + setEnabled( true ); } //! Destructor @@ -85,7 +77,7 @@ QwtMagnifier::~QwtMagnifier() \param on true or false \sa isEnabled(), eventFilter() */ -void QwtMagnifier::setEnabled(bool on) +void QwtMagnifier::setEnabled( bool on ) { if ( d_data->isEnabled != on ) { @@ -95,9 +87,9 @@ void QwtMagnifier::setEnabled(bool on) if ( o ) { if ( d_data->isEnabled ) - o->installEventFilter(this); + o->installEventFilter( this ); else - o->removeEventFilter(this); + o->removeEventFilter( this ); } } } @@ -117,12 +109,12 @@ bool QwtMagnifier::isEnabled() const The wheel factor defines the ratio between the current range on the parent widget and the zoomed range for each step of the wheel. The default value is 0.9. - + \param factor Wheel factor - \sa wheelFactor(), setWheelButtonState(), + \sa wheelFactor(), setWheelButtonState(), setMouseFactor(), setKeyFactor() */ -void QwtMagnifier::setWheelFactor(double factor) +void QwtMagnifier::setWheelFactor( double factor ) { d_data->wheelFactor = factor; } @@ -143,7 +135,7 @@ double QwtMagnifier::wheelFactor() const \param buttonState Button state \sa wheelButtonState() */ -void QwtMagnifier::setWheelButtonState(int buttonState) +void QwtMagnifier::setWheelButtonState( int buttonState ) { d_data->wheelButtonState = buttonState; } @@ -157,17 +149,17 @@ int QwtMagnifier::wheelButtonState() const return d_data->wheelButtonState; } -/*! +/*! \brief Change the mouse factor The mouse factor defines the ratio between the current range on the parent widget and the zoomed range for each vertical mouse movement. The default value is 0.95. - + \param factor Wheel factor \sa mouseFactor(), setMouseButton(), setWheelFactor(), setKeyFactor() -*/ -void QwtMagnifier::setMouseFactor(double factor) +*/ +void QwtMagnifier::setMouseFactor( double factor ) { d_data->mouseFactor = factor; } @@ -189,7 +181,7 @@ double QwtMagnifier::mouseFactor() const \param buttonState Button state \sa getMouseButton() */ -void QwtMagnifier::setMouseButton(int button, int buttonState) +void QwtMagnifier::setMouseButton( int button, int buttonState ) { d_data->mouseButton = button; d_data->mouseButtonState = buttonState; @@ -197,7 +189,7 @@ void QwtMagnifier::setMouseButton(int button, int buttonState) //! \sa setMouseButton() void QwtMagnifier::getMouseButton( - int &button, int &buttonState) const + int &button, int &buttonState ) const { button = d_data->mouseButton; buttonState = d_data->mouseButtonState; @@ -209,12 +201,12 @@ void QwtMagnifier::getMouseButton( The key factor defines the ratio between the current range on the parent widget and the zoomed range for each key press of the zoom in/out keys. The default value is 0.9. - + \param factor Key factor \sa keyFactor(), setZoomInKey(), setZoomOutKey(), setWheelFactor, setMouseFactor() */ -void QwtMagnifier::setKeyFactor(double factor) +void QwtMagnifier::setKeyFactor( double factor ) { d_data->keyFactor = factor; } @@ -236,14 +228,14 @@ double QwtMagnifier::keyFactor() const \param modifiers \sa getZoomInKey(), setZoomOutKey() */ -void QwtMagnifier::setZoomInKey(int key, int modifiers) +void QwtMagnifier::setZoomInKey( int key, int modifiers ) { d_data->zoomInKey = key; d_data->zoomInKeyModifiers = modifiers; } //! \sa setZoomInKey() -void QwtMagnifier::getZoomInKey(int &key, int &modifiers) const +void QwtMagnifier::getZoomInKey( int &key, int &modifiers ) const { key = d_data->zoomInKey; modifiers = d_data->zoomInKeyModifiers; @@ -257,14 +249,14 @@ void QwtMagnifier::getZoomInKey(int &key, int &modifiers) const \param modifiers \sa getZoomOutKey(), setZoomOutKey() */ -void QwtMagnifier::setZoomOutKey(int key, int modifiers) +void QwtMagnifier::setZoomOutKey( int key, int modifiers ) { d_data->zoomOutKey = key; d_data->zoomOutKeyModifiers = modifiers; } //! \sa setZoomOutKey() -void QwtMagnifier::getZoomOutKey(int &key, int &modifiers) const +void QwtMagnifier::getZoomOutKey( int &key, int &modifiers ) const { key = d_data->zoomOutKey; modifiers = d_data->zoomOutKeyModifiers; @@ -275,198 +267,197 @@ void QwtMagnifier::getZoomOutKey(int &key, int &modifiers) const When isEnabled() the mouse events of the observed widget are filtered. + \param object Object to be filtered + \param event Event + \sa widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent() widgetKeyReleaseEvent() */ -bool QwtMagnifier::eventFilter(QObject *o, QEvent *e) +bool QwtMagnifier::eventFilter( QObject *object, QEvent *event ) { - if ( o && o == parent() ) + if ( object && object == parent() ) { - switch(e->type() ) + switch ( event->type() ) { case QEvent::MouseButtonPress: { - widgetMousePressEvent((QMouseEvent *)e); + widgetMousePressEvent( ( QMouseEvent * )event ); break; } case QEvent::MouseMove: { - widgetMouseMoveEvent((QMouseEvent *)e); + widgetMouseMoveEvent( ( QMouseEvent * )event ); break; } case QEvent::MouseButtonRelease: { - widgetMouseReleaseEvent((QMouseEvent *)e); + widgetMouseReleaseEvent( ( QMouseEvent * )event ); break; } case QEvent::Wheel: { - widgetWheelEvent((QWheelEvent *)e); + widgetWheelEvent( ( QWheelEvent * )event ); break; } case QEvent::KeyPress: { - widgetKeyPressEvent((QKeyEvent *)e); + widgetKeyPressEvent( ( QKeyEvent * )event ); break; } case QEvent::KeyRelease: { - widgetKeyReleaseEvent((QKeyEvent *)e); + widgetKeyReleaseEvent( ( QKeyEvent * )event ); break; } default:; } } - return QObject::eventFilter(o, e); + return QObject::eventFilter( object, event ); } /*! Handle a mouse press event for the observed widget. - \param me Mouse event - \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent() + \param mouseEvent Mouse event + \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent() */ -void QwtMagnifier::widgetMousePressEvent(QMouseEvent *me) +void QwtMagnifier::widgetMousePressEvent( QMouseEvent *mouseEvent ) { - if ( me->button() != d_data->mouseButton || parentWidget() == NULL ) + if ( ( mouseEvent->button() != d_data->mouseButton) + || parentWidget() == NULL ) + { return; + } -#if QT_VERSION < 0x040000 - if ( (me->state() & Qt::KeyButtonMask) != - (d_data->mouseButtonState & Qt::KeyButtonMask) ) -#else - if ( (me->modifiers() & Qt::KeyboardModifierMask) != - (int)(d_data->mouseButtonState & Qt::KeyboardModifierMask) ) -#endif + if ( ( mouseEvent->modifiers() & Qt::KeyboardModifierMask ) != + ( int )( d_data->mouseButtonState & Qt::KeyboardModifierMask ) ) { return; } d_data->hasMouseTracking = parentWidget()->hasMouseTracking(); - parentWidget()->setMouseTracking(true); - d_data->mousePos = me->pos(); + parentWidget()->setMouseTracking( true ); + d_data->mousePos = mouseEvent->pos(); d_data->mousePressed = true; } /*! Handle a mouse release event for the observed widget. + + \param mouseEvent Mouse event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseMoveEvent(), */ -void QwtMagnifier::widgetMouseReleaseEvent(QMouseEvent *) +void QwtMagnifier::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) { + Q_UNUSED( mouseEvent ); + if ( d_data->mousePressed && parentWidget() ) { d_data->mousePressed = false; - parentWidget()->setMouseTracking(d_data->hasMouseTracking); + parentWidget()->setMouseTracking( d_data->hasMouseTracking ); } } /*! Handle a mouse move event for the observed widget. - - \param me Mouse event + + \param mouseEvent Mouse event \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), -*/ -void QwtMagnifier::widgetMouseMoveEvent(QMouseEvent *me) +*/ +void QwtMagnifier::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) { if ( !d_data->mousePressed ) return; - const int dy = me->pos().y() - d_data->mousePos.y(); + const int dy = mouseEvent->pos().y() - d_data->mousePos.y(); if ( dy != 0 ) { double f = d_data->mouseFactor; if ( dy < 0 ) f = 1 / f; - rescale(f); + rescale( f ); } - d_data->mousePos = me->pos(); + d_data->mousePos = mouseEvent->pos(); } /*! Handle a wheel event for the observed widget. - \param we Wheel event + \param wheelEvent Wheel event \sa eventFilter() */ -void QwtMagnifier::widgetWheelEvent(QWheelEvent *we) +void QwtMagnifier::widgetWheelEvent( QWheelEvent *wheelEvent ) { -#if QT_VERSION < 0x040000 - if ( (we->state() & Qt::KeyButtonMask) != - (d_data->wheelButtonState & Qt::KeyButtonMask) ) -#else - if ( (we->modifiers() & Qt::KeyboardModifierMask) != - (int)(d_data->wheelButtonState & Qt::KeyboardModifierMask) ) -#endif + if ( ( wheelEvent->modifiers() & Qt::KeyboardModifierMask ) != + ( int )( d_data->wheelButtonState & Qt::KeyboardModifierMask ) ) { return; } if ( d_data->wheelFactor != 0.0 ) { - /* - A positive delta indicates that the wheel was - rotated forwards away from the user; a negative - value indicates that the wheel was rotated - backwards toward the user. - Most mouse types work in steps of 15 degrees, - in which case the delta value is a multiple - of 120 (== 15 * 8). - */ - double f = ::pow(d_data->wheelFactor, - qwtAbs(we->delta() / 120)); - if ( we->delta() > 0 ) + /* + A positive delta indicates that the wheel was + rotated forwards away from the user; a negative + value indicates that the wheel was rotated + backwards toward the user. + Most mouse types work in steps of 15 degrees, + in which case the delta value is a multiple + of 120 (== 15 * 8). + */ + double f = qPow( d_data->wheelFactor, + qAbs( wheelEvent->delta() / 120 ) ); + + if ( wheelEvent->delta() > 0 ) f = 1 / f; - rescale(f); + rescale( f ); } } /*! Handle a key press event for the observed widget. - \param ke Key event + \param keyEvent Key event \sa eventFilter(), widgetKeyReleaseEvent() */ -void QwtMagnifier::widgetKeyPressEvent(QKeyEvent *ke) +void QwtMagnifier::widgetKeyPressEvent( QKeyEvent *keyEvent ) { - const int key = ke->key(); -#if QT_VERSION < 0x040000 - const int state = ke->state(); -#else - const int state = ke->modifiers(); -#endif + const int key = keyEvent->key(); + const int state = keyEvent->modifiers(); - if ( key == d_data->zoomInKey && + if ( key == d_data->zoomInKey && state == d_data->zoomInKeyModifiers ) { - rescale(d_data->keyFactor); + rescale( d_data->keyFactor ); } - else if ( key == d_data->zoomOutKey && + else if ( key == d_data->zoomOutKey && state == d_data->zoomOutKeyModifiers ) { - rescale(1.0 / d_data->keyFactor); + rescale( 1.0 / d_data->keyFactor ); } } /*! Handle a key release event for the observed widget. - \param ke Key event + \param keyEvent Key event \sa eventFilter(), widgetKeyReleaseEvent() */ -void QwtMagnifier::widgetKeyReleaseEvent(QKeyEvent *) +void QwtMagnifier::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) { + Q_UNUSED( keyEvent ); } //! \return Parent widget, where the rescaling happens QWidget *QwtMagnifier::parentWidget() { - if ( parent()->inherits("QWidget") ) - return (QWidget *)parent(); + if ( parent()->inherits( "QWidget" ) ) + return ( QWidget * )parent(); return NULL; } @@ -474,9 +465,8 @@ QWidget *QwtMagnifier::parentWidget() //! \return Parent widget, where the rescaling happens const QWidget *QwtMagnifier::parentWidget() const { - if ( parent()->inherits("QWidget") ) - return (const QWidget *)parent(); + if ( parent()->inherits( "QWidget" ) ) + return ( const QWidget * )parent(); return NULL; } - diff --git a/qwt/src/qwt_magnifier.h b/qwt/src/qwt_magnifier.h index c50e34145..f2f4bbd98 100644 --- a/qwt/src/qwt_magnifier.h +++ b/qwt/src/qwt_magnifier.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -29,54 +29,54 @@ class QWT_EXPORT QwtMagnifier: public QObject Q_OBJECT public: - explicit QwtMagnifier(QWidget *); + explicit QwtMagnifier( QWidget * ); virtual ~QwtMagnifier(); QWidget *parentWidget(); const QWidget *parentWidget() const; - void setEnabled(bool); + void setEnabled( bool ); bool isEnabled() const; // mouse - void setMouseFactor(double); + void setMouseFactor( double ); double mouseFactor() const; - void setMouseButton(int button, int buttonState = Qt::NoButton); - void getMouseButton(int &button, int &buttonState) const; + void setMouseButton( int button, int buttonState = Qt::NoButton ); + void getMouseButton( int &button, int &buttonState ) const; // mouse wheel - void setWheelFactor(double); + void setWheelFactor( double ); double wheelFactor() const; - void setWheelButtonState(int buttonState); + void setWheelButtonState( int buttonState ); int wheelButtonState() const; // keyboard - void setKeyFactor(double); + void setKeyFactor( double ); double keyFactor() const; - void setZoomInKey(int key, int modifiers); - void getZoomInKey(int &key, int &modifiers) const; + void setZoomInKey( int key, int modifiers ); + void getZoomInKey( int &key, int &modifiers ) const; - void setZoomOutKey(int key, int modifiers); - void getZoomOutKey(int &key, int &modifiers) const; + void setZoomOutKey( int key, int modifiers ); + void getZoomOutKey( int &key, int &modifiers ) const; - virtual bool eventFilter(QObject *, QEvent *); + virtual bool eventFilter( QObject *, QEvent * ); protected: /*! Rescale the parent widget \param factor Scale factor */ - virtual void rescale(double factor) = 0; + virtual void rescale( double factor ) = 0; - virtual void widgetMousePressEvent(QMouseEvent *); - virtual void widgetMouseReleaseEvent(QMouseEvent *); - virtual void widgetMouseMoveEvent(QMouseEvent *); - virtual void widgetWheelEvent(QWheelEvent *); - virtual void widgetKeyPressEvent(QKeyEvent *); - virtual void widgetKeyReleaseEvent(QKeyEvent *); + virtual void widgetMousePressEvent( QMouseEvent * ); + virtual void widgetMouseReleaseEvent( QMouseEvent * ); + virtual void widgetMouseMoveEvent( QMouseEvent * ); + virtual void widgetWheelEvent( QWheelEvent * ); + virtual void widgetKeyPressEvent( QKeyEvent * ); + virtual void widgetKeyReleaseEvent( QKeyEvent * ); private: class PrivateData; diff --git a/qwt/src/qwt_math.cpp b/qwt/src/qwt_math.cpp index 45cda171a..06a039aec 100644 --- a/qwt/src/qwt_math.cpp +++ b/qwt/src/qwt_math.cpp @@ -2,13 +2,11 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #include "qwt_math.h" /*! @@ -16,14 +14,14 @@ \param array Pointer to an array \param size Array size */ -double qwtGetMin(const double *array, int size) +double qwtGetMin( const double *array, int size ) { - if (size <= 0) - return 0.0; + if ( size <= 0 ) + return 0.0; double rv = array[0]; - for (int i = 1; i < size; i++) - rv = qwtMin(rv, array[i]); + for ( int i = 1; i < size; i++ ) + rv = qMin( rv, array[i] ); return rv; } @@ -34,14 +32,14 @@ double qwtGetMin(const double *array, int size) \param array Pointer to an array \param size Array size */ -double qwtGetMax(const double *array, int size) +double qwtGetMax( const double *array, int size ) { - if (size <= 0) - return 0.0; - + if ( size <= 0 ) + return 0.0; + double rv = array[0]; - for (int i = 1; i < size; i++) - rv = qwtMax(rv, array[i]); + for ( int i = 1; i < size; i++ ) + rv = qMax( rv, array[i] ); return rv; } diff --git a/qwt/src/qwt_math.h b/qwt/src/qwt_math.h index 80c2f36af..fa1f0675b 100644 --- a/qwt/src/qwt_math.h +++ b/qwt/src/qwt_math.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,25 +10,23 @@ #ifndef QWT_MATH_H #define QWT_MATH_H -#include -#include #include "qwt_global.h" -#include "qwt_double_rect.h" -#if QT_VERSION < 0x040000 - -#define qwtMax QMAX -#define qwtMin QMIN -#define qwtAbs QABS - -#else // QT_VERSION >= 0x040000 - -#define qwtMax qMax -#define qwtMin qMin -#define qwtAbs qAbs +#if defined(_MSC_VER) +/* + Microsoft says: + Define _USE_MATH_DEFINES before including math.h to expose these macro + definitions for common math constants. These are placed under an #ifdef + since these commonly-defined names are not part of the C/C++ standards. +*/ +#define _USE_MATH_DEFINES 1 #endif +#include +#include +#include "qwt_global.h" + #ifndef LOG10_2 #define LOG10_2 0.30102999566398119802 /* log10(2) */ #endif @@ -107,86 +105,78 @@ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ #endif -QWT_EXPORT double qwtGetMin(const double *array, int size); -QWT_EXPORT double qwtGetMax(const double *array, int size); - - -//! Return the sign -inline int qwtSign(double x) -{ - if (x > 0.0) - return 1; - else if (x < 0.0) - return (-1); - else - return 0; -} - -//! Return the square of a number -inline double qwtSqr(const double x) -{ - return x*x; -} +QWT_EXPORT double qwtGetMin( const double *array, int size ); +QWT_EXPORT double qwtGetMax( const double *array, int size ); /*! - \brief Limit a value to fit into a specified interval - \param x Input value - \param x1 First interval boundary - \param x2 Second interval boundary + \brief Compare 2 values, relative to an interval + + Values are "equal", when : + \f$\cdot value2 - value1 <= abs(intervalSize * 10e^{-6})\f$ + + \param value1 First value to compare + \param value2 Second value to compare + \param intervalSize interval size + + \return 0: if equal, -1: if value2 > value1, 1: if value1 > value2 */ -template -T qwtLim(const T& x, const T& x1, const T& x2) +inline int qwtFuzzyCompare( double value1, double value2, double intervalSize ) { - T rv; - T xmin, xmax; - - xmin = qwtMin(x1, x2); - xmax = qwtMax(x1, x2); + const double eps = qAbs( 1.0e-6 * intervalSize ); - if ( x < xmin ) - rv = xmin; - else if ( x > xmax ) - rv = xmax; + if ( value2 - value1 > eps ) + return -1; + + if ( value1 - value2 > eps ) + return 1; + + return 0; +} + + +inline bool qwtFuzzyGreaterOrEqual( double d1, double d2 ) +{ + return ( d1 >= d2 ) || qFuzzyCompare( d1, d2 ); +} + +inline bool qwtFuzzyLessOrEqual( double d1, double d2 ) +{ + return ( d1 <= d2 ) || qFuzzyCompare( d1, d2 ); +} + +//! Return the sign +inline int qwtSign( double x ) +{ + if ( x > 0.0 ) + return 1; + else if ( x < 0.0 ) + return ( -1 ); else - rv = x; - - return rv; + return 0; } -inline QPoint qwtPolar2Pos(const QPoint &pole, - double radius, double angle) +//! Return the square of a number +inline double qwtSqr( double x ) { - const double x = pole.x() + radius * ::cos(angle); - const double y = pole.y() - radius * ::sin(angle); - - return QPoint(qRound(x), qRound(y)); + return x * x; } -inline QPoint qwtDegree2Pos(const QPoint &pole, - double radius, double angle) +//! Like qRound, but without converting the result to an int +inline double qwtRoundF(double d) { - return qwtPolar2Pos(pole, radius, angle / 180.0 * M_PI); + return ::floor( d + 0.5 ); } -inline QwtDoublePoint qwtPolar2Pos(const QwtDoublePoint &pole, - double radius, double angle) +//! Like qFloor, but without converting the result to an int +inline double qwtFloorF(double d) { - const double x = pole.x() + radius * ::cos(angle); - const double y = pole.y() - radius * ::sin(angle); - - return QPoint(qRound(x), qRound(y)); + return ::floor( d ); } -inline QwtDoublePoint qwtDegree2Pos(const QwtDoublePoint &pole, - double radius, double angle) +//! Like qCeil, but without converting the result to an int +inline double qwtCeilF(double d) { - return qwtPolar2Pos(pole, radius, angle / 180.0 * M_PI); -} - -//! Rounding of doubles, like qRound for integers -inline double qwtRound(double value) -{ - return ::floor(value + 0.5); // MSVC has no ::round(). + return ::ceil( d ); } #endif diff --git a/qwt/src/qwt_matrix_raster_data.cpp b/qwt/src/qwt_matrix_raster_data.cpp new file mode 100644 index 000000000..51216bb82 --- /dev/null +++ b/qwt/src/qwt_matrix_raster_data.cpp @@ -0,0 +1,270 @@ +/* -*- 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_matrix_raster_data.h" +#include +#include + +class QwtMatrixRasterData::PrivateData +{ +public: + PrivateData(): + resampleMode(QwtMatrixRasterData::NearestNeighbour), + numColumns(0) + { + } + + inline double value(size_t row, size_t col) const + { + return values.data()[ row * numColumns + col ]; + } + + QwtMatrixRasterData::ResampleMode resampleMode; + + QVector values; + size_t numColumns; + size_t numRows; + + double dx; + double dy; +}; + +//! Constructor +QwtMatrixRasterData::QwtMatrixRasterData() +{ + d_data = new PrivateData(); + update(); +} + +//! Destructor +QwtMatrixRasterData::~QwtMatrixRasterData() +{ + delete d_data; +} + +/*! + \brief Set the resampling algorithm + + \param mode Resampling mode + \sa resampleMode(), value() +*/ +void QwtMatrixRasterData::setResampleMode(ResampleMode mode) +{ + d_data->resampleMode = mode; +} + +/*! + \return resampling algorithm + \sa setResampleMode(), value() +*/ +QwtMatrixRasterData::ResampleMode QwtMatrixRasterData::resampleMode() const +{ + return d_data->resampleMode; +} + +/*! + \brief Assign the bounding interval for an axis + + Setting the bounding intervals for the X/Y axis is mandatory + to define the positions for the values of the value matrix. + The interval in Z direction defines the possible range for + the values in the matrix, what is f.e used by QwtPlotSpectrogram + to map values to colors. The Z-interval might be the bounding + interval of the values in the matrix, but usually it isn't. + ( f.e a interval of 0.0-100.0 for values in percentage ) + + \param axis X, Y or Z axis + \param interval Interval + + \sa QwtRasterData::interval(), setValueMatrix() +*/ +void QwtMatrixRasterData::setInterval( + Qt::Axis axis, const QwtInterval &interval ) +{ + QwtRasterData::setInterval( axis, interval ); + update(); +} + +/*! + \brief Assign a value matrix + + The positions of the values are calculated by dividing + the bounding rectangle of the X/Y intervals into equidistant + rectangles ( pixels ). Each value corresponds to the center of + a pixel. + + \param values Vector of values + \param numColumns Number of columns + + \sa valueMatrix(), numColumns(), numRows(), setInterval()() +*/ +void QwtMatrixRasterData::setValueMatrix( + const QVector &values, size_t numColumns ) +{ + d_data->values = values; + d_data->numColumns = numColumns; + update(); +} + +/*! + \return Value matrix + \sa setValueMatrix(), numColumns(), numRows(), setInterval() +*/ +const QVector QwtMatrixRasterData::valueMatrix() const +{ + return d_data->values; +} + +/*! + \return Number of columns of the value matrix + \sa valueMatrix(), numRows(), setValueMatrix() +*/ +size_t QwtMatrixRasterData::numColumns() const +{ + return d_data->numColumns; +} + +/*! + \return Number of rows of the value matrix + \sa valueMatrix(), numColumns(), setValueMatrix() +*/ +size_t QwtMatrixRasterData::numRows() const +{ + return d_data->numRows; +} + +/*! + \brief Pixel hint + + - NearestNeighbour\n + pixelHint() returns the surrounding pixel of the top left value + in the matrix. + + - BilinearInterpolation\n + Returns an empty rectangle recommending + to render in target device ( f.e. screen ) resolution. + + \sa ResampleMode, setMatrix(), setInterval() +*/ +QRectF QwtMatrixRasterData::pixelHint( const QRectF & ) const +{ + QRectF rect; + if ( d_data->resampleMode == NearestNeighbour ) + { + const QwtInterval intervalX = interval( Qt::XAxis ); + const QwtInterval intervalY = interval( Qt::YAxis ); + if ( intervalX.isValid() && intervalY.isValid() ) + { + rect = QRectF( intervalX.minValue(), intervalY.minValue(), + d_data->dx, d_data->dy ); + } + } + + return rect; +} + +/*! + \return the value at a raster position + + \param x X value in plot coordinates + \param y Y value in plot coordinates + + \sa ResampleMode +*/ +double QwtMatrixRasterData::value( double x, double y ) const +{ + const QwtInterval xInterval = interval( Qt::XAxis ); + const QwtInterval yInterval = interval( Qt::YAxis ); + + if ( !( xInterval.contains(x) && yInterval.contains(y) ) ) + return qQNaN(); + + double value; + + switch( d_data->resampleMode ) + { + case BilinearInterpolation: + { + int col1 = qRound( (x - xInterval.minValue() ) / d_data->dx ) - 1; + int row1 = qRound( (y - yInterval.minValue() ) / d_data->dy ) - 1; + int col2 = col1 + 1; + int row2 = row1 + 1; + + if ( col1 < 0 ) + col1 = col2; + else if ( col2 >= (int)d_data->numColumns ) + col2 = col1; + + if ( row1 < 0 ) + row1 = row2; + else if ( row2 >= (int)d_data->numRows ) + row2 = row1; + + const double v11 = d_data->value( row1, col1 ); + const double v21 = d_data->value( row1, col2 ); + const double v12 = d_data->value( row2, col1 ); + const double v22 = d_data->value( row2, col2 ); + + const double x2 = xInterval.minValue() + + ( col2 + 0.5 ) * d_data->dx; + const double y2 = yInterval.minValue() + + ( row2 + 0.5 ) * d_data->dy; + + const double rx = ( x2 - x ) / d_data->dx; + const double ry = ( y2 - y ) / d_data->dy; + + const double vr1 = rx * v11 + ( 1.0 - rx ) * v21; + const double vr2 = rx * v12 + ( 1.0 - rx ) * v22; + + value = ry * vr1 + ( 1.0 - ry ) * vr2; + + break; + } + case NearestNeighbour: + default: + { + uint row = uint( (y - yInterval.minValue() ) / d_data->dy ); + uint col = uint( (x - xInterval.minValue() ) / d_data->dx ); + + // In case of intervals, where the maximum is included + // we get out of bound for row/col, when the value for the + // maximum is requested. Instead we return the value + // from the last row/col + + if ( row >= d_data->numRows ) + row = d_data->numRows - 1; + + if ( col >= d_data->numColumns ) + col = d_data->numColumns - 1; + + value = d_data->value( row, col ); + } + } + + return value; +} + +void QwtMatrixRasterData::update() +{ + d_data->numRows = 0; + d_data->dx = 0.0; + d_data->dy = 0.0; + + if ( d_data->numColumns > 0 ) + { + d_data->numRows = d_data->values.size() / d_data->numColumns; + + const QwtInterval xInterval = interval( Qt::XAxis ); + const QwtInterval yInterval = interval( Qt::YAxis ); + if ( xInterval.isValid() ) + d_data->dx = xInterval.width() / d_data->numColumns; + if ( yInterval.isValid() ) + d_data->dy = yInterval.width() / d_data->numRows; + } +} diff --git a/qwt/src/qwt_matrix_raster_data.h b/qwt/src/qwt_matrix_raster_data.h new file mode 100644 index 000000000..9ead58733 --- /dev/null +++ b/qwt/src/qwt_matrix_raster_data.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_MATRIX_RASTER_DATA_H +#define QWT_MATRIX_RASTER_DATA_H 1 + +#include "qwt_global.h" +#include "qwt_raster_data.h" +#include + +/*! + \brief A class representing a matrix of values as raster data + + QwtMatrixRasterData implements an interface for a matrix of + equidistant values, that can be used by a QwtPlotRasterItem. + It implements a couple of resampling algorithms, to provide + values for positions, that or not on the value matrix. +*/ +class QWT_EXPORT QwtMatrixRasterData: public QwtRasterData +{ +public: + /*! + \brief Resampling algorithm + The default setting is NearestNeighbour; + */ + enum ResampleMode + { + /*! + Return the value from the matrix, that is nearest to the + the requested position. + */ + NearestNeighbour, + + /*! + Interpolate the value from the distances and values of the + 4 surrounding values in the matrix, + */ + BilinearInterpolation + }; + + QwtMatrixRasterData(); + virtual ~QwtMatrixRasterData(); + + void setResampleMode(ResampleMode mode); + ResampleMode resampleMode() const; + + virtual void setInterval( Qt::Axis, const QwtInterval & ); + void setValueMatrix( const QVector &values, size_t numColumns ); + + const QVector valueMatrix() const; + size_t numColumns() const; + size_t numRows() const; + + virtual QRectF pixelHint( const QRectF & ) const; + + virtual double value( double x, double y ) const; + +private: + void update(); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/qwt/src/qwt_null_paintdevice.cpp b/qwt/src/qwt_null_paintdevice.cpp new file mode 100644 index 000000000..1806a5649 --- /dev/null +++ b/qwt/src/qwt_null_paintdevice.cpp @@ -0,0 +1,428 @@ +/* -*- 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_null_paintdevice.h" +#include +#include + +class QwtNullPaintDevice::PrivateData +{ +public: + PrivateData(): + size( 0, 0 ) + { + } + + QSize size; +}; + +class QwtNullPaintDevice::PaintEngine: public QPaintEngine +{ +public: + PaintEngine( QPaintEngine::PaintEngineFeatures ); + + virtual bool begin( QPaintDevice * ); + virtual bool end(); + + virtual Type type () const; + virtual void updateState(const QPaintEngineState &); + + virtual void drawRects(const QRect *, int ); + virtual void drawRects(const QRectF *, int ); + + virtual void drawLines(const QLine *, int ); + virtual void drawLines(const QLineF *, int ); + + virtual void drawEllipse(const QRectF &); + virtual void drawEllipse(const QRect &); + + virtual void drawPath(const QPainterPath &); + + virtual void drawPoints(const QPointF *, int ); + virtual void drawPoints(const QPoint *, int ); + + virtual void drawPolygon(const QPointF *, int , PolygonDrawMode ); + virtual void drawPolygon(const QPoint *, int , PolygonDrawMode ); + + virtual void drawPixmap(const QRectF &, + const QPixmap &, const QRectF &); + + virtual void drawTextItem(const QPointF &, const QTextItem &); + virtual void drawTiledPixmap(const QRectF &, + const QPixmap &, const QPointF &s); + virtual void drawImage(const QRectF &, + const QImage &, const QRectF &, Qt::ImageConversionFlags ); + +private: + QwtNullPaintDevice *d_device; +}; + +QwtNullPaintDevice::PaintEngine::PaintEngine( + QPaintEngine::PaintEngineFeatures features ): + QPaintEngine( features ), + d_device(NULL) +{ +} + +bool QwtNullPaintDevice::PaintEngine::begin( + QPaintDevice *device ) +{ + d_device = static_cast( device ); + return true; +} + +bool QwtNullPaintDevice::PaintEngine::end() +{ + d_device = NULL; + return true; +} + +QPaintEngine::Type +QwtNullPaintDevice::PaintEngine::type () const +{ + return QPaintEngine::User; +} + +void QwtNullPaintDevice::PaintEngine::drawRects( + const QRect *rects, int rectCount) +{ + if ( d_device ) + d_device->drawRects( rects, rectCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawRects( + const QRectF *rects, int rectCount) +{ + if ( d_device ) + d_device->drawRects( rects, rectCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawLines( + const QLine *lines, int lineCount) +{ + if ( d_device ) + d_device->drawLines( lines, lineCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawLines( + const QLineF *lines, int lineCount) +{ + if ( d_device ) + d_device->drawLines( lines, lineCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawEllipse( + const QRectF &rect) +{ + if ( d_device ) + d_device->drawEllipse( rect ); +} + +void QwtNullPaintDevice::PaintEngine::drawEllipse( + const QRect &rect) +{ + if ( d_device ) + d_device->drawEllipse( rect ); +} + + +void QwtNullPaintDevice::PaintEngine::drawPath( + const QPainterPath &path) +{ + if ( d_device ) + d_device->drawPath( path ); +} + +void QwtNullPaintDevice::PaintEngine::drawPoints( + const QPointF *points, int pointCount) +{ + if ( d_device ) + d_device->drawPoints( points, pointCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawPoints( + const QPoint *points, int pointCount) +{ + if ( d_device ) + d_device->drawPoints( points, pointCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawPolygon( + const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + if ( d_device ) + d_device->drawPolygon( points, pointCount, mode ); +} + +void QwtNullPaintDevice::PaintEngine::drawPolygon( + const QPoint *points, int pointCount, PolygonDrawMode mode) +{ + if ( d_device ) + d_device->drawPolygon( points, pointCount, mode ); +} + +void QwtNullPaintDevice::PaintEngine::drawPixmap( + const QRectF &rect, const QPixmap &pm, const QRectF &subRect ) +{ + if ( d_device ) + d_device->drawPixmap( rect, pm, subRect ); +} + +void QwtNullPaintDevice::PaintEngine::drawTextItem( + const QPointF &pos, const QTextItem &textItem) +{ + if ( d_device ) + d_device->drawTextItem( pos, textItem ); +} + +void QwtNullPaintDevice::PaintEngine::drawTiledPixmap( + const QRectF &rect, const QPixmap &pixmap, + const QPointF &subRect) +{ + if ( d_device ) + d_device->drawTiledPixmap( rect, pixmap, subRect ); +} + +void QwtNullPaintDevice::PaintEngine::drawImage( + const QRectF &rect, const QImage &image, + const QRectF &subRect, Qt::ImageConversionFlags flags) +{ + if ( d_device ) + d_device->drawImage( rect, image, subRect, flags ); +} + +void QwtNullPaintDevice::PaintEngine::updateState( + const QPaintEngineState &state) +{ + if ( d_device ) + d_device->updateState( state ); +} + +//! Constructor +QwtNullPaintDevice::QwtNullPaintDevice( + QPaintEngine::PaintEngineFeatures features ) +{ + init( features ); +} + +//! Constructor +QwtNullPaintDevice::QwtNullPaintDevice( const QSize &size, + QPaintEngine::PaintEngineFeatures features ) +{ + init( features ); + d_data->size = size; +} + +void QwtNullPaintDevice::init( + QPaintEngine::PaintEngineFeatures features ) +{ + d_engine = new PaintEngine( features ); + d_data = new PrivateData; +} + +//! Destructor +QwtNullPaintDevice::~QwtNullPaintDevice() +{ + delete d_engine; + delete d_data; +} + +/*! + Set the size of the paint device + + \param size Size + \sa size() +*/ +void QwtNullPaintDevice::setSize( const QSize & size ) +{ + d_data->size = size; +} + +/*! + \return Size of the paint device + \sa setSize() +*/ +QSize QwtNullPaintDevice::size() const +{ + return d_data->size; +} + +//! See QPaintDevice::paintEngine() +QPaintEngine *QwtNullPaintDevice::paintEngine() const +{ + return d_engine; +} + +/*! + See QPaintDevice::metric() + \sa setSize() +*/ +int QwtNullPaintDevice::metric( PaintDeviceMetric metric ) const +{ + static QPixmap pm; + + int value; + + switch ( metric ) + { + case PdmWidth: + value = qMax( d_data->size.width(), 0 ); + break; + case PdmHeight: + value = qMax( d_data->size.height(), 0 ); + break; + case PdmNumColors: + value = 16777216; + break; + case PdmDepth: + value = 24; + break; + case PdmPhysicalDpiX: + case PdmDpiY: + case PdmPhysicalDpiY: + case PdmWidthMM: + case PdmHeightMM: + case PdmDpiX: + default: + value = 0; + } + return value; + +} + +//! See QPaintEngine::drawRects() +void QwtNullPaintDevice::drawRects( + const QRect *rects, int rectCount) +{ + Q_UNUSED(rects); + Q_UNUSED(rectCount); +} + +//! See QPaintEngine::drawRects() +void QwtNullPaintDevice::drawRects( + const QRectF *rects, int rectCount) +{ + Q_UNUSED(rects); + Q_UNUSED(rectCount); +} + +//! See QPaintEngine::drawLines() +void QwtNullPaintDevice::drawLines( + const QLine *lines, int lineCount) +{ + Q_UNUSED(lines); + Q_UNUSED(lineCount); +} + +//! See QPaintEngine::drawLines() +void QwtNullPaintDevice::drawLines( + const QLineF *lines, int lineCount) +{ + Q_UNUSED(lines); + Q_UNUSED(lineCount); +} + +//! See QPaintEngine::drawEllipse() +void QwtNullPaintDevice::drawEllipse( const QRectF &rect ) +{ + Q_UNUSED(rect); +} + +//! See QPaintEngine::drawEllipse() +void QwtNullPaintDevice::drawEllipse( const QRect &rect ) +{ + Q_UNUSED(rect); +} + +//! See QPaintEngine::drawPath() +void QwtNullPaintDevice::drawPath( const QPainterPath &path ) +{ + Q_UNUSED(path); +} + +//! See QPaintEngine::drawPoints() +void QwtNullPaintDevice::drawPoints( + const QPointF *points, int pointCount) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); +} + +//! See QPaintEngine::drawPoints() +void QwtNullPaintDevice::drawPoints( + const QPoint *points, int pointCount) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); +} + +//! See QPaintEngine::drawPolygon() +void QwtNullPaintDevice::drawPolygon( + const QPointF *points, int pointCount, + QPaintEngine::PolygonDrawMode mode) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); + Q_UNUSED(mode); +} + +//! See QPaintEngine::drawPolygon() +void QwtNullPaintDevice::drawPolygon( + const QPoint *points, int pointCount, + QPaintEngine::PolygonDrawMode mode) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); + Q_UNUSED(mode); +} + +//! See QPaintEngine::drawPixmap() +void QwtNullPaintDevice::drawPixmap( const QRectF &rect, + const QPixmap &pm, const QRectF &subRect ) +{ + Q_UNUSED(rect); + Q_UNUSED(pm); + Q_UNUSED(subRect); +} + +//! See QPaintEngine::drawTextItem() +void QwtNullPaintDevice::drawTextItem( + const QPointF &pos, const QTextItem &textItem) +{ + Q_UNUSED(pos); + Q_UNUSED(textItem); +} + +//! See QPaintEngine::drawTiledPixmap() +void QwtNullPaintDevice::drawTiledPixmap( + const QRectF &rect, const QPixmap &pixmap, + const QPointF &subRect) +{ + Q_UNUSED(rect); + Q_UNUSED(pixmap); + Q_UNUSED(subRect); +} + +//! See QPaintEngine::drawImage() +void QwtNullPaintDevice::drawImage( + const QRectF &rect, const QImage &image, + const QRectF &subRect, Qt::ImageConversionFlags flags) +{ + Q_UNUSED(rect); + Q_UNUSED(image); + Q_UNUSED(subRect); + Q_UNUSED(flags); +} + +//! See QPaintEngine::updateState() +void QwtNullPaintDevice::updateState( + const QPaintEngineState &state ) +{ + Q_UNUSED(state); +} diff --git a/qwt/src/qwt_null_paintdevice.h b/qwt/src/qwt_null_paintdevice.h new file mode 100644 index 000000000..f103eb79f --- /dev/null +++ b/qwt/src/qwt_null_paintdevice.h @@ -0,0 +1,89 @@ +/* -*- 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_NULL_PAINT_DEVICE_H +#define QWT_NULL_PAINT_DEVICE_H 1 + +#include "qwt_global.h" +#include +#include + +/*! + \brief A null paint device doing nothing + + Sometimes important layout/rendering geometries are not + available or changable from the public Qt class interface. + ( f.e hidden in the style implementation ). + + QwtNullPaintDevice can be used to manipulate or filter out + these informations by analyzing the stream of paint primitives. + + F.e. QwtNullPaintDevice is used by QwtPlotCanvas to identify + styled backgrounds with rounded corners. +*/ + +class QWT_EXPORT QwtNullPaintDevice: public QPaintDevice +{ +public: + QwtNullPaintDevice( QPaintEngine::PaintEngineFeatures ); + QwtNullPaintDevice( const QSize &size, + QPaintEngine::PaintEngineFeatures ); + + virtual ~QwtNullPaintDevice(); + + void setSize( const QSize &); + QSize size() const; + + virtual QPaintEngine *paintEngine() const; + virtual int metric( PaintDeviceMetric metric ) const; + + virtual void drawRects(const QRect *, int ); + virtual void drawRects(const QRectF *, int ); + + virtual void drawLines(const QLine *, int ); + virtual void drawLines(const QLineF *, int ); + + virtual void drawEllipse(const QRectF &); + virtual void drawEllipse(const QRect &); + + virtual void drawPath(const QPainterPath &); + + virtual void drawPoints(const QPointF *, int ); + virtual void drawPoints(const QPoint *, int ); + + virtual void drawPolygon( + const QPointF *, int , QPaintEngine::PolygonDrawMode ); + + virtual void drawPolygon( + const QPoint *, int , QPaintEngine::PolygonDrawMode ); + + virtual void drawPixmap(const QRectF &, + const QPixmap &, const QRectF &); + + virtual void drawTextItem(const QPointF &, const QTextItem &); + + virtual void drawTiledPixmap(const QRectF &, + const QPixmap &, const QPointF &s); + + virtual void drawImage(const QRectF &, + const QImage &, const QRectF &, Qt::ImageConversionFlags ); + + virtual void updateState( const QPaintEngineState &state ); + +private: + void init( QPaintEngine::PaintEngineFeatures ); + + class PaintEngine; + PaintEngine *d_engine; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/qwt/src/qwt_paint_buffer.cpp b/qwt/src/qwt_paint_buffer.cpp deleted file mode 100644 index 3d8c6a1e5..000000000 --- a/qwt/src/qwt_paint_buffer.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - - -#include -#if QT_VERSION < 0x040000 - -#include -#include -#include "qwt_paint_buffer.h" - -bool QwtPaintBuffer::d_enabled = true; - -//! Default constructor -QwtPaintBuffer::QwtPaintBuffer(): - d_device(0), - d_painter(0), - d_devicePainter(0) -{ -} - -/*! - Create an open paint buffer - \param device Device to paint on - \param rect Rect to paint on - \param painter Painter to paint on device. In case of 0 - QwtPaintBuffer uses an internal painter - - \sa open() -*/ - -QwtPaintBuffer::QwtPaintBuffer(QPaintDevice *device, - const QRect &rect, QPainter *painter): - d_device(0), - d_painter(0), - d_devicePainter(0) -{ - open(device, rect, painter); -} - -/*! - Closes the buffer - \sa close() -*/ -QwtPaintBuffer::~QwtPaintBuffer() -{ - close(); -} - -/*! - \return Depending on isEnabled() the painter - connected to an internal pixmap buffer - otherwise the painter connected to the device. -*/ - -QPainter *QwtPaintBuffer::painter() -{ - return d_painter; -} - -/*! - \return Device to paint on -*/ -const QPaintDevice *QwtPaintBuffer::device() -{ - return d_device; -} - -/*! - Enable/Disable double buffering. Please note that - this is a global switch for all QwtPaintBuffers, but - won't change opened buffers. -*/ -void QwtPaintBuffer::setEnabled(bool enable) -{ - d_enabled = enable; -} - -/*! - \return true if double buffering is enabled, false otherwise. -*/ -bool QwtPaintBuffer::isEnabled() -{ - return d_enabled; -} - -/*! - Open the buffer - \param device Device to paint on - \param rect Rect to paint on - \param painter Painter to paint on device. In case of 0 - QwtPaintBuffer uses an internal painter -*/ - -void QwtPaintBuffer::open(QPaintDevice *device, - const QRect &rect, QPainter *painter) -{ - close(); - - if ( device == 0 || !rect.isValid() ) - return; - - d_device = device; - d_devicePainter = painter; - d_rect = rect; - - if ( isEnabled() ) - { -#ifdef Q_WS_X11 - if ( d_pixBuffer.x11Screen() != d_device->x11Screen() ) - d_pixBuffer.x11SetScreen(d_device->x11Screen()); -#endif - d_pixBuffer.resize(d_rect.size()); - - d_painter = new QPainter(); - if ( d_device->devType() == QInternal::Widget ) - { - QWidget *w = (QWidget *)d_device; - d_pixBuffer.fill(w, d_rect.topLeft()); - d_painter->begin(&d_pixBuffer, w); - d_painter->translate(-d_rect.x(), -d_rect.y()); - } - else - { - d_painter->begin(&d_pixBuffer); - } - } - else - { - if ( d_devicePainter ) - d_painter = d_devicePainter; - else - d_painter = new QPainter(d_device); - - if ( d_device->devType() == QInternal::Widget ) - { - QWidget *w = (QWidget *)d_device; - if ( w->testWFlags( Qt::WNoAutoErase ) ) - d_painter->eraseRect(d_rect); - } - } -} - -/*! - Flush the internal pixmap buffer to the device. -*/ -void QwtPaintBuffer::flush() -{ - if ( d_enabled && d_device != 0 && d_rect.isValid()) - { - // We need a painter to find out if - // there is a painter redirection for d_device. - - QPainter *p; - if ( d_devicePainter == 0 ) - p = new QPainter(d_device); - else - p = d_devicePainter; - - QPaintDevice *device = p->device(); - if ( device->isExtDev() ) - d_devicePainter->drawPixmap(d_rect.topLeft(), d_pixBuffer); - else - bitBlt(device, d_rect.topLeft(), &d_pixBuffer ); - - if ( d_devicePainter == 0 ) - delete p; - } -} - -/*! - Flush the internal pixmap buffer to the device and close the buffer. -*/ -void QwtPaintBuffer::close() -{ - flush(); - - if ( d_painter ) - { - if ( d_painter->isActive() ) - d_painter->end(); - - if ( d_painter != d_devicePainter ) - delete d_painter; - } - - if ( !d_pixBuffer.isNull() ) - d_pixBuffer = QPixmap(); - - d_device = 0; - d_painter = 0; - d_devicePainter = 0; -} - -#endif // QT_VERSION < 0x040000 diff --git a/qwt/src/qwt_paint_buffer.h b/qwt/src/qwt_paint_buffer.h deleted file mode 100644 index 2fc196903..000000000 --- a/qwt/src/qwt_paint_buffer.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#ifndef QWT_PAINT_BUFFER_H -#define QWT_PAINT_BUFFER_H 1 - -#include -#if QT_VERSION < 0x040000 - -#include -#include "qwt_global.h" - -class QPainter; - -/*! - \brief Paint buffer for Qwt widgets - - QwtPaintBuffer offers a simple way to en/disable double buffering. - Double buffering is enabled as default and in general there will be - no reason to change this. -*/ - -class QWT_EXPORT QwtPaintBuffer -{ -public: - explicit QwtPaintBuffer(); - explicit QwtPaintBuffer(QPaintDevice *, const QRect &, QPainter *p = NULL); - - virtual ~QwtPaintBuffer(); - - void open(QPaintDevice *, const QRect &, QPainter *p = NULL); - void close(); - - QPainter *painter(); - const QPaintDevice *device(); - - static void setEnabled(bool enable); - static bool isEnabled(); - - //! Return Buffer used for double buffering - const QPixmap &buffer() const { return d_pixBuffer; } - -protected: - void flush(); - -private: - QPixmap d_pixBuffer; - QRect d_rect; - - QPaintDevice *d_device; // use QGuardedPtr - QPainter *d_painter; // use QGuardedPtr - QPainter *d_devicePainter; // use QGuardedPtr - - static bool d_enabled; -}; - -#endif // QT_VERSION < 0x040000 - -#endif diff --git a/qwt/src/qwt_painter.cpp b/qwt/src/qwt_painter.cpp index c8b066919..0da97014d 100644 --- a/qwt/src/qwt_painter.cpp +++ b/qwt/src/qwt_painter.cpp @@ -7,52 +7,35 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - +#include "qwt_painter.h" +#include "qwt_math.h" +#include "qwt_clipper.h" +#include "qwt_color_map.h" +#include "qwt_scale_map.h" #include #include +#include #include #include #include #include #include #include -#if QT_VERSION < 0x040000 -#include -#else #include #include #include #include -#endif +#include +#include -#include "qwt_math.h" -#include "qwt_clipper.h" -#include "qwt_color_map.h" -#include "qwt_scale_map.h" -#include "qwt_painter.h" +bool QwtPainter::d_polylineSplitting = true; +bool QwtPainter::d_roundingAlignment = true; -QwtMetricsMap QwtPainter::d_metricsMap; - -#if defined(Q_WS_X11) -bool QwtPainter::d_deviceClipping = true; -#else -bool QwtPainter::d_deviceClipping = false; -#endif - -#if QT_VERSION < 0x040000 -bool QwtPainter::d_SVGMode = false; -#endif - -static inline bool isClippingNeeded(const QPainter *painter, QRect &clipRect) +static inline bool isClippingNeeded( const QPainter *painter, QRectF &clipRect ) { bool doClipping = false; -#if QT_VERSION >= 0x040000 const QPaintEngine *pe = painter->paintEngine(); if ( pe && pe->type() == QPaintEngine::SVG ) -#else - if ( painter->device()->devType() == QInternal::Picture ) -#endif { // The SVG paint engine ignores any clipping, @@ -63,189 +46,175 @@ static inline bool isClippingNeeded(const QPainter *painter, QRect &clipRect) } } - if ( QwtPainter::deviceClipping() ) - { - if (painter->device()->devType() == QInternal::Widget || - painter->device()->devType() == QInternal::Pixmap ) - { - if ( doClipping ) - { - clipRect &= QwtPainter::deviceClipRect(); - } - else - { - doClipping = true; - clipRect = QwtPainter::deviceClipRect(); - } - } - } - return doClipping; } -/*! - \brief En/Disable device clipping. - - On X11 the default for device clipping is enabled, - otherwise it is disabled. - \sa QwtPainter::deviceClipping() -*/ -void QwtPainter::setDeviceClipping(bool enable) +static inline void drawPolyline( QPainter *painter, + const QPointF *points, int pointCount, bool polylineSplitting ) { - d_deviceClipping = enable; -} - -/*! - Returns rect for device clipping - \sa QwtPainter::setDeviceClipping() -*/ -const QRect &QwtPainter::deviceClipRect() -{ - static QRect clip; - - if ( !clip.isValid() ) + bool doSplit = false; + if ( polylineSplitting ) { - clip.setCoords(QWT_COORD_MIN, QWT_COORD_MIN, - QWT_COORD_MAX, QWT_COORD_MAX); + const QPaintEngine *pe = painter->paintEngine(); + if ( pe && pe->type() == QPaintEngine::Raster ) + { + /* + The raster paint engine seems to use some algo with O(n*n). + ( Qt 4.3 is better than Qt 4.2, but remains unacceptable) + To work around this problem, we have to split the polygon into + smaller pieces. + */ + doSplit = true; + } } - return clip; + + if ( doSplit ) + { + const int splitSize = 20; + for ( int i = 0; i < pointCount; i += splitSize ) + { + const int n = qMin( splitSize + 1, pointCount - i ); + painter->drawPolyline( points + i, n ); + } + } + else + painter->drawPolyline( points, pointCount ); } -#if QT_VERSION < 0x040000 - -/*! - \brief En/Disable SVG mode. - - When saving a QPicture to a SVG some texts are misaligned. - In SVGMode QwtPainter tries to fix them. - - \sa QwtPainter::isSVGMode() - \note A QPicture that is created in SVG mode and saved to the - native format, will be misaligned. Also it is not possible to - reload and play a SVG document, that was created in SVG mode. -*/ -void QwtPainter::setSVGMode(bool on) +static inline void unscaleFont( QPainter *painter ) { - d_SVGMode = on; -} + if ( painter->font().pixelSize() >= 0 ) + return; -bool QwtPainter::isSVGMode() -{ - return d_SVGMode; -} + static QSize screenResolution; + if ( !screenResolution.isValid() ) + { + QDesktopWidget *desktop = QApplication::desktop(); + if ( desktop ) + { + screenResolution.setWidth( desktop->logicalDpiX() ); + screenResolution.setHeight( desktop->logicalDpiY() ); + } + } -#endif // QT_VERSION < 0x040000 + const QPaintDevice *pd = painter->device(); + if ( pd->logicalDpiX() != screenResolution.width() || + pd->logicalDpiY() != screenResolution.height() ) + { + QFont pixelFont( painter->font(), QApplication::desktop() ); + pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() ); -/*! - Scale all QwtPainter drawing operations using the ratio - QwtPaintMetrics(from).logicalDpiX() / QwtPaintMetrics(to).logicalDpiX() - and QwtPaintMetrics(from).logicalDpiY() / QwtPaintMetrics(to).logicalDpiY() - - \sa QwtPainter::resetScaleMetrics(), QwtPainter::scaleMetricsX(), - QwtPainter::scaleMetricsY() -*/ -void QwtPainter::setMetricsMap(const QPaintDevice *layout, - const QPaintDevice *device) -{ - d_metricsMap.setMetrics(layout, device); -} - -/*! - Change the metrics map - \sa QwtPainter::resetMetricsMap(), QwtPainter::metricsMap() -*/ -void QwtPainter::setMetricsMap(const QwtMetricsMap &map) -{ - d_metricsMap = map; -} - -/*! - Reset the metrics map to the ratio 1:1 - \sa QwtPainter::setMetricsMap(), QwtPainter::resetMetricsMap() -*/ -void QwtPainter::resetMetricsMap() -{ - d_metricsMap = QwtMetricsMap(); + painter->setFont( pixelFont ); + } } /*! - \return Metrics map + Check if the painter is using a paint engine, that aligns + coordinates to integers. Today these are all paint engines + beside QPaintEngine::Pdf and QPaintEngine::SVG. + + \param painter Painter + \return true, when the paint engine is aligning + + \sa setRoundingAlignment() */ -const QwtMetricsMap &QwtPainter::metricsMap() +bool QwtPainter::isAligning( QPainter *painter ) { - return d_metricsMap; + if ( painter && painter->isActive() ) + { + switch ( painter->paintEngine()->type() ) + { + case QPaintEngine::Pdf: + case QPaintEngine::SVG: + return false; + + default:; + } + } + + return true; } /*! - Wrapper for QPainter::setClipRect() + Enable whether coordinates should be rounded, before they are painted + to a paint engine that floors to integer values. For other paint engines + this ( Pdf, SVG ), this flag has no effect. + QwtPainter stores this flag only, the rounding itsself is done in + the painting code ( f.e the plot items ). + + The default setting is true. + + \sa roundingAlignment(), isAligning() */ -void QwtPainter::setClipRect(QPainter *painter, const QRect &rect) +void QwtPainter::setRoundingAlignment( bool enable ) { - painter->setClipRect(d_metricsMap.layoutToDevice(rect, painter)); + d_roundingAlignment = enable; } /*! - Wrapper for QPainter::drawRect() + \brief En/Disable line splitting for the raster paint engine + + The raster paint engine paints polylines of many points + much faster when they are splitted in smaller chunks. + + \sa polylineSplitting() */ -void QwtPainter::drawRect(QPainter *painter, int x, int y, int w, int h) +void QwtPainter::setPolylineSplitting( bool enable ) { - drawRect(painter, QRect(x, y, w, h)); + d_polylineSplitting = enable; } -/*! - Wrapper for QPainter::drawRect() -*/ -void QwtPainter::drawRect(QPainter *painter, const QRect &rect) +//! Wrapper for QPainter::drawPath() +void QwtPainter::drawPath( QPainter *painter, const QPainterPath &path ) { - const QRect r = d_metricsMap.layoutToDevice(rect, painter); + painter->drawPath( path ); +} - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); +//! Wrapper for QPainter::drawRect() +void QwtPainter::drawRect( QPainter *painter, double x, double y, double w, double h ) +{ + drawRect( painter, QRectF( x, y, w, h ) ); +} + +//! Wrapper for QPainter::drawRect() +void QwtPainter::drawRect( QPainter *painter, const QRectF &rect ) +{ + const QRectF r = rect; + + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); if ( deviceClipping ) { - if ( !clipRect.intersects(r) ) + if ( !clipRect.intersects( r ) ) return; - if ( !clipRect.contains(r) ) + if ( !clipRect.contains( r ) ) { - fillRect(painter, r & clipRect, painter->brush()); - - int pw = painter->pen().width(); - pw = pw % 2 + pw / 2; - - QwtPolygon pa(5); - pa.setPoint(0, r.left(), r.top()); - pa.setPoint(1, r.right() - pw, r.top()); - pa.setPoint(2, r.right() - pw, r.bottom() - pw); - pa.setPoint(3, r.left(), r.bottom() - pw); - pa.setPoint(4, r.left(), r.top()); + fillRect( painter, r & clipRect, painter->brush() ); painter->save(); - painter->setBrush(Qt::NoBrush); - drawPolyline(painter, pa); + painter->setBrush( Qt::NoBrush ); + drawPolyline( painter, QPolygonF( r ) ); painter->restore(); return; } } - painter->drawRect(r); + painter->drawRect( r ); } -/*! - Wrapper for QPainter::fillRect() -*/ -void QwtPainter::fillRect(QPainter *painter, - const QRect &rect, const QBrush &brush) +//! Wrapper for QPainter::fillRect() +void QwtPainter::fillRect( QPainter *painter, + const QRectF &rect, const QBrush &brush ) { if ( !rect.isValid() ) return; - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); -#if QT_VERSION >= 0x040000 /* Performance of Qt4 is horrible for non trivial brushs. Without clipping expect minutes or hours for repainting large rects @@ -259,510 +228,477 @@ void QwtPainter::fillRect(QPainter *painter, if ( painter->hasClipping() ) clipRect &= painter->clipRegion().boundingRect(); -#endif - QRect r = d_metricsMap.layoutToDevice(rect, painter); + QRectF r = rect; if ( deviceClipping ) - r = r.intersect(clipRect); + r = r.intersect( clipRect ); if ( r.isValid() ) - painter->fillRect(r, brush); + painter->fillRect( r, brush ); } -/*! - Wrapper for QPainter::drawPie() -*/ -void QwtPainter::drawPie(QPainter *painter, const QRect &rect, - int a, int alen) +//! Wrapper for QPainter::drawPie() +void QwtPainter::drawPie( QPainter *painter, const QRectF &rect, + int a, int alen ) { - const QRect r = d_metricsMap.layoutToDevice(rect, painter); - - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); - if ( deviceClipping && !clipRect.contains(r) ) + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); + if ( deviceClipping && !clipRect.contains( rect ) ) return; - painter->drawPie(r, a, alen); + painter->drawPie( rect, a, alen ); } -/*! - Wrapper for QPainter::drawEllipse() -*/ -void QwtPainter::drawEllipse(QPainter *painter, const QRect &rect) +//! Wrapper for QPainter::drawEllipse() +void QwtPainter::drawEllipse( QPainter *painter, const QRectF &rect ) { - QRect r = d_metricsMap.layoutToDevice(rect, painter); + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); - - if ( deviceClipping && !clipRect.contains(r) ) + if ( deviceClipping && !clipRect.contains( rect ) ) return; -#if QT_VERSION >= 0x040000 - if ( painter->pen().style() != Qt::NoPen && - painter->pen().color().isValid() ) - { - // Qt4 adds the pen to the rect, Qt3 not. - int pw = painter->pen().width(); - if ( pw == 0 ) - pw = 1; - - r.setWidth(r.width() - pw); - r.setHeight(r.height() - pw); - } -#endif - - painter->drawEllipse(r); + painter->drawEllipse( rect ); } -/*! - Wrapper for QPainter::drawText() -*/ -void QwtPainter::drawText(QPainter *painter, int x, int y, - const QString &text) +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, double x, double y, + const QString &text ) { - drawText(painter, QPoint(x, y), text); + drawText( painter, QPointF( x, y ), text ); } -/*! - Wrapper for QPainter::drawText() -*/ -void QwtPainter::drawText(QPainter *painter, const QPoint &pos, - const QString &text) +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, const QPointF &pos, + const QString &text ) { - const QPoint p = d_metricsMap.layoutToDevice(pos, painter); + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); - - if ( deviceClipping && !clipRect.contains(p) ) + if ( deviceClipping && !clipRect.contains( pos ) ) return; - painter->drawText(p, text); + + painter->save(); + unscaleFont( painter ); + painter->drawText( pos, text ); + painter->restore(); } -/*! - Wrapper for QPainter::drawText() -*/ -void QwtPainter::drawText(QPainter *painter, int x, int y, int w, int h, - int flags, const QString &text) +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, + double x, double y, double w, double h, + int flags, const QString &text ) { - drawText(painter, QRect(x, y, w, h), flags, text); + drawText( painter, QRectF( x, y, w, h ), flags, text ); } -/*! - Wrapper for QPainter::drawText() -*/ -void QwtPainter::drawText(QPainter *painter, const QRect &rect, - int flags, const QString &text) +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, const QRectF &rect, + int flags, const QString &text ) { - QRect textRect = d_metricsMap.layoutToDevice(rect, painter); -#if QT_VERSION < 0x040000 - if ( d_SVGMode && - ( flags == 0 || flags & Qt::AlignVCenter ) - && painter->device()->devType() == QInternal::Picture ) - { - /* - Qt3 misalignes texts, when saving a text - to a SVG image. - */ - textRect.setY(textRect.y() - painter->fontMetrics().height() / 4); - } -#endif - painter->drawText(textRect, flags, text); + painter->save(); + unscaleFont( painter ); + painter->drawText( rect, flags, text ); + painter->restore(); } #ifndef QT_NO_RICHTEXT /*! - Wrapper for QSimpleRichText::draw() + Draw a text document into a rectangle + + \param painter Painter + \param rect Traget rectangle + \param flags Alignments/Text flags, see QPainter::drawText() + \param text Text document */ -#if QT_VERSION < 0x040000 - -void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect, - int flags, QSimpleRichText &text) +void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect, + int flags, const QTextDocument &text ) { - QColorGroup cg; - cg.setColor(QColorGroup::Text, painter->pen().color()); - - const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter); - - text.setWidth(painter, scaledRect.width()); - - // QSimpleRichText is Qt::AlignTop by default - - int y = scaledRect.y(); - if (flags & Qt::AlignBottom) - y += (scaledRect.height() - text.height()); - else if (flags & Qt::AlignVCenter) - y += (scaledRect.height() - text.height())/2; - - text.draw(painter, scaledRect.x(), y, scaledRect, cg); -} -#else -void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect, - int flags, QTextDocument &text) -{ - const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter); - text.setPageSize(QSize(scaledRect.width(), QWIDGETSIZE_MAX)); - - QAbstractTextDocumentLayout* layout = text.documentLayout(); - - const int height = qRound(layout->documentSize().height()); - int y = scaledRect.y(); - if (flags & Qt::AlignBottom) - y += (scaledRect.height() - height); - else if (flags & Qt::AlignVCenter) - y += (scaledRect.height() - height)/2; - - QAbstractTextDocumentLayout::PaintContext context; - context.palette.setColor(QPalette::Text, painter->pen().color()); + QTextDocument *txt = text.clone(); painter->save(); - painter->translate(scaledRect.x(), y); - layout->draw(painter, context); + painter->setFont( txt->defaultFont() ); + unscaleFont( painter ); + + txt->setDefaultFont( painter->font() ); + txt->setPageSize( QSizeF( rect.width(), QWIDGETSIZE_MAX ) ); + + QAbstractTextDocumentLayout* layout = txt->documentLayout(); + + const double height = layout->documentSize().height(); + double y = rect.y(); + if ( flags & Qt::AlignBottom ) + y += ( rect.height() - height ); + else if ( flags & Qt::AlignVCenter ) + y += ( rect.height() - height ) / 2; + + QAbstractTextDocumentLayout::PaintContext context; + context.palette.setColor( QPalette::Text, painter->pen().color() ); + + painter->translate( rect.x(), y ); + layout->draw( painter, context ); painter->restore(); + delete txt; } -#endif #endif // !QT_NO_RICHTEXT -/*! - Wrapper for QPainter::drawLine() -*/ -void QwtPainter::drawLine(QPainter *painter, int x1, int y1, int x2, int y2) +//! Wrapper for QPainter::drawLine() +void QwtPainter::drawLine( QPainter *painter, + const QPointF &p1, const QPointF &p2 ) { - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); - if ( deviceClipping && - !(clipRect.contains(x1, y1) && clipRect.contains(x2, y2)) ) + if ( deviceClipping && + !( clipRect.contains( p1 ) && clipRect.contains( p2 ) ) ) { - QwtPolygon pa(2); - pa.setPoint(0, x1, y1); - pa.setPoint(1, x2, y2); - drawPolyline(painter, pa); + QPolygonF polygon; + polygon += p1; + polygon += p2; + drawPolyline( painter, polygon ); return; } - if ( d_metricsMap.isIdentity() ) - { -#if QT_VERSION >= 0x030200 && QT_VERSION < 0x040000 - if ( !painter->device()->isExtDev() ) -#endif - { - painter->drawLine(x1, y1, x2, y2); - return; - } - } - - const QPoint p1 = d_metricsMap.layoutToDevice(QPoint(x1, y1)); - const QPoint p2 = d_metricsMap.layoutToDevice(QPoint(x2, y2)); - -#if QT_VERSION >= 0x030200 && QT_VERSION < 0x040000 - if ( painter->device()->isExtDev() ) - { - // Strange: the postscript driver of QPrinter adds an offset - // of 0.5 to the start/endpoint when using drawLine, but not - // for lines painted with drawLineSegments. - - QwtPolygon pa(2); - pa.setPoint(0, p1); - pa.setPoint(1, p2); - painter->drawLineSegments(pa); - } - else - painter->drawLine(p1, p2); -#else - painter->drawLine(p1, p2); -#endif + painter->drawLine( p1, p2 ); } -/*! - Wrapper for QPainter::drawPolygon() -*/ -void QwtPainter::drawPolygon(QPainter *painter, const QwtPolygon &pa) +//! Wrapper for QPainter::drawPolygon() +void QwtPainter::drawPolygon( QPainter *painter, const QPolygonF &polygon ) { - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); + + QPolygonF cpa = polygon; + if ( deviceClipping ) + cpa = QwtClipper::clipPolygonF( clipRect, polygon ); + + painter->drawPolygon( cpa ); +} + +//! Wrapper for QPainter::drawPolyline() +void QwtPainter::drawPolyline( QPainter *painter, const QPolygonF &polygon ) +{ + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); + + QPolygonF cpa = polygon; + if ( deviceClipping ) + cpa = QwtClipper::clipPolygonF( clipRect, cpa ); + + ::drawPolyline( painter, + cpa.constData(), cpa.size(), d_polylineSplitting ); +} + +//! Wrapper for QPainter::drawPolyline() +void QwtPainter::drawPolyline( QPainter *painter, + const QPointF *points, int pointCount ) +{ + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); - QwtPolygon cpa = d_metricsMap.layoutToDevice(pa); if ( deviceClipping ) { -#ifdef __GNUC__ -#warning clipping ignores painter transformations -#endif - cpa = QwtClipper::clipPolygon(clipRect, cpa); - } - painter->drawPolygon(cpa); -} + QPolygonF polygon( pointCount ); + qMemCopy( polygon.data(), points, pointCount * sizeof( QPointF ) ); -/*! - Wrapper for QPainter::drawPolyline() -*/ -void QwtPainter::drawPolyline(QPainter *painter, const QwtPolygon &pa) -{ - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); - - QwtPolygon cpa = d_metricsMap.layoutToDevice(pa); - if ( deviceClipping ) - cpa = QwtClipper::clipPolygon(clipRect, cpa); - -#if QT_VERSION >= 0x040000 - bool doSplit = false; - - const QPaintEngine *pe = painter->paintEngine(); - if ( pe && pe->type() == QPaintEngine::Raster && - painter->pen().width() >= 2 ) - { - /* - The raster paint engine seems to use some algo with O(n*n). - ( Qt 4.3 is better than Qt 4.2, but remains unacceptable) - To work around this problem, we have to split the polygon into - smaller pieces. - */ - doSplit = true; - } - - if ( doSplit ) - { - const int numPoints = cpa.size(); - const QPoint *points = cpa.data(); - - const int splitSize = 20; - for ( int i = 0; i < numPoints; i += splitSize ) - { - const int n = qwtMin(splitSize + 1, cpa.size() - i); - painter->drawPolyline(points + i, n); - } + polygon = QwtClipper::clipPolygonF( clipRect, polygon ); + ::drawPolyline( painter, + polygon.constData(), polygon.size(), d_polylineSplitting ); } else -#endif - painter->drawPolyline(cpa); + ::drawPolyline( painter, points, pointCount, d_polylineSplitting ); } -/*! - Wrapper for QPainter::drawPoint() -*/ - -void QwtPainter::drawPoint(QPainter *painter, int x, int y) +//! Wrapper for QPainter::drawPoint() +void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos ) { - QRect clipRect; - const bool deviceClipping = isClippingNeeded(painter, clipRect); + QRectF clipRect; + const bool deviceClipping = isClippingNeeded( painter, clipRect ); - const QPoint pos = d_metricsMap.layoutToDevice(QPoint(x, y)); - - if ( deviceClipping && !clipRect.contains(pos) ) + if ( deviceClipping && !clipRect.contains( pos ) ) return; - painter->drawPoint(pos); + painter->drawPoint( pos ); } -void QwtPainter::drawColoredArc(QPainter *painter, const QRect &rect, - int peak, int arc, int interval, const QColor &c1, const QColor &c2) +//! Wrapper for QPainter::drawImage() +void QwtPainter::drawImage( QPainter *painter, + const QRectF &rect, const QImage &image ) { - int h1, s1, v1; - int h2, s2, v2; + const QRect alignedRect = rect.toAlignedRect(); -#if QT_VERSION < 0x040000 - c1.hsv(&h1, &s1, &v1); - c2.hsv(&h2, &s2, &v2); -#else - c1.getHsv(&h1, &s1, &v1); - c2.getHsv(&h2, &s2, &v2); -#endif - - arc /= 2; - for ( int angle = -arc; angle < arc; angle += interval) + if ( alignedRect != rect ) { - double ratio; - if ( angle >= 0 ) - ratio = 1.0 - angle / double(arc); - else - ratio = 1.0 + angle / double(arc); - + const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); - QColor c; - c.setHsv( h1 + qRound(ratio * (h2 - h1)), - s1 + qRound(ratio * (s2 - s1)), - v1 + qRound(ratio * (v2 - v1)) ); - - painter->setPen(QPen(c, painter->pen().width())); - painter->drawArc(rect, (peak + angle) * 16, interval * 16); - } -} - -void QwtPainter::drawFocusRect(QPainter *painter, QWidget *widget) -{ - drawFocusRect(painter, widget, widget->rect()); -} - -void QwtPainter::drawFocusRect(QPainter *painter, QWidget *widget, - const QRect &rect) -{ -#if QT_VERSION < 0x040000 - widget->style().drawPrimitive(QStyle::PE_FocusRect, painter, - rect, widget->colorGroup()); -#else - QStyleOptionFocusRect opt; - opt.init(widget); - opt.rect = rect; - opt.state |= QStyle::State_HasFocus; - - widget->style()->drawPrimitive(QStyle::PE_FrameFocusRect, - &opt, painter, widget); -#endif - -} - -//! Draw a round frame -#if QT_VERSION < 0x040000 -void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect, - int width, const QColorGroup &cg, bool sunken) -#else -void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect, - int width, const QPalette &palette, bool sunken) -#endif -{ - -#if QT_VERSION < 0x040000 - QColor c0 = cg.mid(); - QColor c1, c2; - if ( sunken ) - { - c1 = cg.dark(); - c2 = cg.light(); + painter->save(); + painter->setClipRect( clipRect, Qt::IntersectClip ); + painter->drawImage( alignedRect, image ); + painter->restore(); } else { - c1 = cg.light(); - c2 = cg.dark(); + painter->drawImage( alignedRect, image ); } -#else - QColor c0 = palette.color(QPalette::Mid); - QColor c1, c2; - if ( sunken ) +} + +//! Wrapper for QPainter::drawPixmap() +void QwtPainter::drawPixmap( QPainter *painter, + const QRectF &rect, const QPixmap &pixmap ) +{ + const QRect alignedRect = rect.toAlignedRect(); + + if ( alignedRect != rect ) { - c1 = palette.color(QPalette::Dark); - c2 = palette.color(QPalette::Light); + const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); + + painter->save(); + painter->setClipRect( clipRect, Qt::IntersectClip ); + painter->drawPixmap( alignedRect, pixmap ); + painter->restore(); } else { - c1 = palette.color(QPalette::Light); - c2 = palette.color(QPalette::Dark); + painter->drawPixmap( alignedRect, pixmap ); } -#endif - - painter->setPen(QPen(c0, width)); - painter->drawArc(rect, 0, 360 * 16); // full - - const int peak = 150; - const int interval = 2; - - if ( c0 != c1 ) - drawColoredArc(painter, rect, peak, 160, interval, c0, c1); - if ( c0 != c2 ) - drawColoredArc(painter, rect, peak + 180, 120, interval, c0, c2); } -void QwtPainter::drawColorBar(QPainter *painter, - const QwtColorMap &colorMap, const QwtDoubleInterval &interval, +//! Draw a focus rectangle on a widget using its style. +void QwtPainter::drawFocusRect( QPainter *painter, QWidget *widget ) +{ + drawFocusRect( painter, widget, widget->rect() ); +} + +//! Draw a focus rectangle on a widget using its style. +void QwtPainter::drawFocusRect( QPainter *painter, QWidget *widget, + const QRect &rect ) +{ + QStyleOptionFocusRect opt; + opt.init( widget ); + opt.rect = rect; + opt.state |= QStyle::State_HasFocus; + + widget->style()->drawPrimitive( QStyle::PE_FrameFocusRect, + &opt, painter, widget ); +} + +/*! + Draw a frame with rounded borders + + \param painter Painter + \param rect Frame rectangle + \param xRadius x-radius of the ellipses defining the corners + \param yRadius y-radius of the ellipses defining the corners + \param palette QPalette::WindowText is used for plain borders + QPalette::Dark and QPalette::Light for raised + or sunken borders + \param lineWidth Line width + \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow +*/ + +void QwtPainter::drawRoundedFrame( QPainter *painter, + const QRectF &rect, double xRadius, double yRadius, + const QPalette &palette, int lineWidth, int frameStyle ) +{ + painter->save(); + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->setBrush( Qt::NoBrush ); + + double lw2 = lineWidth * 0.5; + QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 ); + + QPainterPath path; + path.addRoundedRect( r, xRadius, yRadius ); + + enum Style + { + Plain, + Sunken, + Raised + }; + + Style style = Plain; + if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken ) + style = Sunken; + else if ( (frameStyle & QFrame::Raised) == QFrame::Raised ) + style = Raised; + + if ( style != Plain && path.elementCount() == 17 ) + { + // move + 4 * ( cubicTo + lineTo ) + QPainterPath pathList[8]; + + for ( int i = 0; i < 4; i++ ) + { + const int j = i * 4 + 1; + + pathList[ 2 * i ].moveTo( + path.elementAt(j - 1).x, path.elementAt( j - 1 ).y + ); + + pathList[ 2 * i ].cubicTo( + path.elementAt(j + 0).x, path.elementAt(j + 0).y, + path.elementAt(j + 1).x, path.elementAt(j + 1).y, + path.elementAt(j + 2).x, path.elementAt(j + 2).y ); + + pathList[ 2 * i + 1 ].moveTo( + path.elementAt(j + 2).x, path.elementAt(j + 2).y + ); + pathList[ 2 * i + 1 ].lineTo( + path.elementAt(j + 3).x, path.elementAt(j + 3).y + ); + } + + QColor c1( palette.color( QPalette::Dark ) ); + QColor c2( palette.color( QPalette::Light ) ); + + if ( style == Raised ) + qSwap( c1, c2 ); + + for ( int i = 0; i < 4; i++ ) + { + QRectF r = pathList[2 * i].controlPointRect(); + + QPen arcPen; + arcPen.setWidth( lineWidth ); + + QPen linePen; + linePen.setWidth( lineWidth ); + + switch( i ) + { + case 0: + { + arcPen.setColor( c1 ); + linePen.setColor( c1 ); + break; + } + case 1: + { + QLinearGradient gradient; + gradient.setStart( r.topLeft() ); + gradient.setFinalStop( r.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 1.0, c2 ); + + arcPen.setBrush( gradient ); + linePen.setColor( c2 ); + break; + } + case 2: + { + arcPen.setColor( c2 ); + linePen.setColor( c2 ); + break; + } + case 3: + { + QLinearGradient gradient; + + gradient.setStart( r.bottomRight() ); + gradient.setFinalStop( r.topLeft() ); + gradient.setColorAt( 0.0, c2 ); + gradient.setColorAt( 1.0, c1 ); + + arcPen.setBrush( gradient ); + linePen.setColor( c1 ); + break; + } + } + + + painter->setPen( arcPen ); + painter->drawPath( pathList[ 2 * i] ); + + painter->setPen( linePen ); + painter->drawPath( pathList[ 2 * i + 1] ); + } + } + else + { + QPen pen( palette.color( QPalette::WindowText ), lineWidth ); + painter->setPen( pen ); + painter->drawPath( path ); + } + + painter->restore(); +} + +/*! + Draw a color bar into a rectangle + + \param painter Painter + \param colorMap Color map + \param interval Value range + \param scaleMap Scale map + \param orientation Orientation + \param rect Traget rectangle +*/ +void QwtPainter::drawColorBar( QPainter *painter, + const QwtColorMap &colorMap, const QwtInterval &interval, const QwtScaleMap &scaleMap, Qt::Orientation orientation, - const QRect &rect) + const QRectF &rect ) { -#if QT_VERSION < 0x040000 - QValueVector colorTable; -#else QVector colorTable; -#endif if ( colorMap.format() == QwtColorMap::Indexed ) - colorTable = colorMap.colorTable(interval); + colorTable = colorMap.colorTable( interval ); QColor c; - const QRect devRect = d_metricsMap.layoutToDevice(rect); + const QRect devRect = rect.toAlignedRect(); /* We paint to a pixmap first to have something scalable for printing ( f.e. in a Pdf document ) */ - - QPixmap pixmap(devRect.size()); - QPainter pmPainter(&pixmap); - pmPainter.translate(-devRect.x(), -devRect.y()); + + QPixmap pixmap( devRect.size() ); + QPainter pmPainter( &pixmap ); + pmPainter.translate( -devRect.x(), -devRect.y() ); if ( orientation == Qt::Horizontal ) { QwtScaleMap sMap = scaleMap; - sMap.setPaintInterval(devRect.left(), devRect.right()); + sMap.setPaintInterval( rect.left(), rect.right() ); for ( int x = devRect.left(); x <= devRect.right(); x++ ) { - const double value = sMap.invTransform(x); + const double value = sMap.invTransform( x ); if ( colorMap.format() == QwtColorMap::RGB ) - c.setRgb(colorMap.rgb(interval, value)); + c.setRgb( colorMap.rgb( interval, value ) ); else - c = colorTable[colorMap.colorIndex(interval, value)]; + c = colorTable[colorMap.colorIndex( interval, value )]; - pmPainter.setPen(c); - pmPainter.drawLine(x, devRect.top(), x, devRect.bottom()); + pmPainter.setPen( c ); + pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() ); } } else // Vertical { QwtScaleMap sMap = scaleMap; - sMap.setPaintInterval(devRect.bottom(), devRect.top()); + sMap.setPaintInterval( rect.bottom(), rect.top() ); for ( int y = devRect.top(); y <= devRect.bottom(); y++ ) { - const double value = sMap.invTransform(y); + const double value = sMap.invTransform( y ); if ( colorMap.format() == QwtColorMap::RGB ) - c.setRgb(colorMap.rgb(interval, value)); + c.setRgb( colorMap.rgb( interval, value ) ); else - c = colorTable[colorMap.colorIndex(interval, value)]; + c = colorTable[colorMap.colorIndex( interval, value )]; - pmPainter.setPen(c); - pmPainter.drawLine(devRect.left(), y, devRect.right(), y); + pmPainter.setPen( c ); + pmPainter.drawLine( devRect.left(), y, devRect.right(), y ); } } pmPainter.end(); - painter->drawPixmap(devRect, pixmap); + + drawPixmap( painter, rect, pixmap ); } - -/*! - \brief Scale a pen according to the layout metrics - - The width of non cosmetic pens is scaled from screen to layout metrics, - so that they look similar on paint devices with different resolutions. - - \param pen Unscaled pen - \return Scaled pen -*/ - -QPen QwtPainter::scaledPen(const QPen &pen) -{ -#if QT_VERSION < 0x040300 - return pen; -#else - QPen sPen = pen; - - if ( !pen.isCosmetic() ) - { - int pw = pen.width(); - if ( pw == 0 ) - pw = 1; - - sPen.setWidth(QwtPainter::metricsMap().screenToLayoutX(pw)); - sPen.setCosmetic(true); - } - - return sPen; -#endif -} - diff --git a/qwt/src/qwt_painter.h b/qwt/src/qwt_painter.h index ce9c74e86..91a867d7b 100644 --- a/qwt/src/qwt_painter.h +++ b/qwt/src/qwt_painter.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,150 +10,140 @@ #ifndef QWT_PAINTER_H #define QWT_PAINTER_H +#include "qwt_global.h" + #include #include #include -#include "qwt_global.h" -#include "qwt_layout_metrics.h" -#include "qwt_polygon.h" +#include class QPainter; class QBrush; class QColor; class QWidget; +class QPolygonF; +class QRectF; +class QImage; +class QPixmap; class QwtScaleMap; class QwtColorMap; -class QwtDoubleInterval; +class QwtInterval; -#if QT_VERSION < 0x040000 -class QColorGroup; -class QSimpleRichText; -#else class QPalette; class QTextDocument; -#endif - -#if defined(Q_WS_X11) -// Warning: QCOORD_MIN, QCOORD_MAX are wrong on X11. -#define QWT_COORD_MAX 16384 -#define QWT_COORD_MIN (-QWT_COORD_MAX - 1) -#else -#define QWT_COORD_MAX 2147483647 -#define QWT_COORD_MIN -QWT_COORD_MAX - 1 -#endif +class QPainterPath; /*! \brief A collection of QPainter workarounds - - 1) Clipping to coordinate system limits (Qt3 only) - - On X11 pixel coordinates are stored in shorts. Qt - produces overruns when mapping QCOORDS to shorts. - - 2) Scaling to device metrics - - QPainter scales fonts, line and fill patterns to the metrics - of the paint device. Other values like the geometries of rects, points - remain device independend. To enable a device independent widget - implementation, QwtPainter adds scaling of these geometries. - (Unfortunately QPainter::scale scales both types of paintings, - so the objects of the first type would be scaled twice). */ - class QWT_EXPORT QwtPainter { public: - static void setMetricsMap(const QPaintDevice *layout, - const QPaintDevice *device); - static void setMetricsMap(const QwtMetricsMap &); - static void resetMetricsMap(); - static const QwtMetricsMap &metricsMap(); + static void setPolylineSplitting( bool ); + static bool polylineSplitting(); - static void setDeviceClipping(bool); - static bool deviceClipping(); - static const QRect &deviceClipRect(); + static void setRoundingAlignment( bool ); + static bool roundingAlignment(); + static bool roundingAlignment(QPainter *); - static void setClipRect(QPainter *, const QRect &); - - static void drawText(QPainter *, int x, int y, - const QString &); - static void drawText(QPainter *, const QPoint &, - const QString &); - static void drawText(QPainter *, int x, int y, int w, int h, - int flags, const QString &); - static void drawText(QPainter *, const QRect &, - int flags, const QString &); + static void drawText( QPainter *, double x, double y, const QString & ); + static void drawText( QPainter *, const QPointF &, const QString & ); + static void drawText( QPainter *, double x, double y, double w, double h, + int flags, const QString & ); + static void drawText( QPainter *, const QRectF &, + int flags, const QString & ); #ifndef QT_NO_RICHTEXT -#if QT_VERSION < 0x040000 - static void drawSimpleRichText(QPainter *, const QRect &, - int flags, QSimpleRichText &); -#else - static void drawSimpleRichText(QPainter *, const QRect &, - int flags, QTextDocument &); -#endif + static void drawSimpleRichText( QPainter *, const QRectF &, + int flags, const QTextDocument & ); #endif - static void drawRect(QPainter *, int x, int y, int w, int h); - static void drawRect(QPainter *, const QRect &rect); - static void fillRect(QPainter *, const QRect &, const QBrush &); + static void drawRect( QPainter *, double x, double y, double w, double h ); + static void drawRect( QPainter *, const QRectF &rect ); + static void fillRect( QPainter *, const QRectF &, const QBrush & ); - static void drawEllipse(QPainter *, const QRect &); - static void drawPie(QPainter *, const QRect & r, int a, int alen); + static void drawEllipse( QPainter *, const QRectF & ); + static void drawPie( QPainter *, const QRectF & r, int a, int alen ); - static void drawLine(QPainter *, int x1, int y1, int x2, int y2); - static void drawLine(QPainter *, const QPoint &p1, const QPoint &p2); - static void drawPolygon(QPainter *, const QwtPolygon &pa); - static void drawPolyline(QPainter *, const QwtPolygon &pa); - static void drawPoint(QPainter *, int x, int y); + static void drawLine( QPainter *, double x1, double y1, double x2, double y2 ); + static void drawLine( QPainter *, const QPointF &p1, const QPointF &p2 ); + static void drawLine( QPainter *, const QLineF & ); -#if QT_VERSION < 0x040000 - static void drawRoundFrame(QPainter *, const QRect &, - int width, const QColorGroup &cg, bool sunken); -#else - static void drawRoundFrame(QPainter *, const QRect &, - int width, const QPalette &, bool sunken); -#endif - static void drawFocusRect(QPainter *, QWidget *); - static void drawFocusRect(QPainter *, QWidget *, const QRect &); + static void drawPolygon( QPainter *, const QPolygonF &pa ); + static void drawPolyline( QPainter *, const QPolygonF &pa ); + static void drawPolyline( QPainter *, const QPointF *, int pointCount ); - static void drawColorBar(QPainter *painter, - const QwtColorMap &, const QwtDoubleInterval &, - const QwtScaleMap &, Qt::Orientation, const QRect &); + static void drawPoint( QPainter *, double x, double y ); + static void drawPoint( QPainter *, const QPointF & ); -#if QT_VERSION < 0x040000 - static void setSVGMode(bool on); - static bool isSVGMode(); -#endif + static void drawPath( QPainter *, const QPainterPath & ); + static void drawImage( QPainter *, const QRectF &, const QImage & ); + static void drawPixmap( QPainter *, const QRectF &, const QPixmap & ); - static QPen scaledPen(const QPen &); + static void drawRoundedFrame( QPainter *, + const QRectF &, double xRadius, double yRadius, + const QPalette &, int lineWidth, int frameStyle ); + + static void drawFocusRect( QPainter *, QWidget * ); + static void drawFocusRect( QPainter *, QWidget *, const QRect & ); + + static void drawColorBar( QPainter *painter, + const QwtColorMap &, const QwtInterval &, + const QwtScaleMap &, Qt::Orientation, const QRectF & ); + + static bool isAligning( QPainter *painter ); private: - static void drawColoredArc(QPainter *, const QRect &, - int peak, int arc, int intervall, const QColor &c1, const QColor &c2); - - static bool d_deviceClipping; - static QwtMetricsMap d_metricsMap; -#if QT_VERSION < 0x040000 - static bool d_SVGMode; -#endif + static bool d_polylineSplitting; + static bool d_roundingAlignment; }; -//! Wrapper for QPainter::drawLine() -inline void QwtPainter::drawLine(QPainter *painter, - const QPoint &p1, const QPoint &p2) +//! Wrapper for QPainter::drawPoint() +inline void QwtPainter::drawPoint( QPainter *painter, double x, double y ) { - drawLine(painter, p1.x(), p1.y(), p2.x(), p2.y()); + QwtPainter::drawPoint( painter, QPointF( x, y ) ); +} + +//! Wrapper for QPainter::drawLine() +inline void QwtPainter::drawLine( QPainter *painter, + double x1, double y1, double x2, double y2 ) +{ + QwtPainter::drawLine( painter, QPointF( x1, y1 ), QPointF( x2, y2 ) ); +} + +//! Wrapper for QPainter::drawLine() +inline void QwtPainter::drawLine( QPainter *painter, const QLineF &line ) +{ + QwtPainter::drawLine( painter, line.p1(), line.p2() ); } /*! - Returns whether device clipping is enabled. On X11 the default - is enabled, otherwise it is disabled. - \sa QwtPainter::setDeviceClipping() + Returns whether line splitting for the raster paint engine is enabled. + \sa setPolylineSplitting() */ -inline bool QwtPainter::deviceClipping() +inline bool QwtPainter::polylineSplitting() { - return d_deviceClipping; + return d_polylineSplitting; } +/*! + Returns whether coordinates should be rounded, before they are painted + to a paint engine that floors to integer values. For other paint engines + this ( Pdf, SVG ), this flag has no effect. + + \sa setRoundingAlignment(), isAligning() +*/ +inline bool QwtPainter::roundingAlignment() +{ + return d_roundingAlignment; +} + +/*! + \return roundingAlignment() && isAligning(painter); + \param painter Painter +*/ +inline bool QwtPainter::roundingAlignment(QPainter *painter) +{ + return d_roundingAlignment && isAligning(painter); +} #endif diff --git a/qwt/src/qwt_panner.cpp b/qwt/src/qwt_panner.cpp index 4ed819fde..32768060d 100644 --- a/qwt/src/qwt_panner.cpp +++ b/qwt/src/qwt_panner.cpp @@ -7,55 +7,29 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - +#include "qwt_panner.h" +#include "qwt_picker.h" #include #include #include -#include #include -#if QT_VERSION < 0x040000 -#include -#endif -#include "qwt_picker.h" -#include "qwt_array.h" -#include "qwt_panner.h" +#include -static QwtArray activePickers(QWidget *w) +static QVector qwtActivePickers( QWidget *w ) { - QwtArray pickers; + QVector pickers; -#if QT_VERSION >= 0x040000 QObjectList children = w->children(); for ( int i = 0; i < children.size(); i++ ) { QObject *obj = children[i]; - if ( obj->inherits("QwtPicker") ) + if ( obj->inherits( "QwtPicker" ) ) { - QwtPicker *picker = (QwtPicker *)obj; + QwtPicker *picker = ( QwtPicker * )obj; if ( picker->isEnabled() ) pickers += picker; } } -#else - QObjectList *children = (QObjectList *)w->children(); - if ( children ) - { - for ( QObjectListIterator it(*children); it.current(); ++it ) - { - QObject *obj = (QObject *)it.current(); - if ( obj->inherits("QwtPicker") ) - { - QwtPicker *picker = (QwtPicker *)obj; - if ( picker->isEnabled() ) - { - pickers.resize(pickers.size() + 1); - pickers[int(pickers.size()) - 1] = picker; - } - } - } - } -#endif return pickers; } @@ -64,23 +38,18 @@ class QwtPanner::PrivateData { public: PrivateData(): - button(Qt::LeftButton), - buttonState(Qt::NoButton), - abortKey(Qt::Key_Escape), - abortKeyState(Qt::NoButton), + button( Qt::LeftButton ), + buttonState( Qt::NoButton ), + abortKey( Qt::Key_Escape ), + abortKeyState( Qt::NoButton ), #ifndef QT_NO_CURSOR - cursor(NULL), - restoreCursor(NULL), - hasCursor(false), + cursor( NULL ), + restoreCursor( NULL ), + hasCursor( false ), #endif - isEnabled(false) + isEnabled( false ) { -#if QT_VERSION >= 0x040000 orientations = Qt::Vertical | Qt::Horizontal; -#else - orientations[Qt::Vertical] = true; - orientations[Qt::Horizontal] = true; -#endif } ~PrivateData() @@ -90,7 +59,7 @@ public: delete restoreCursor; #endif } - + int button; int buttonState; int abortKey; @@ -100,17 +69,15 @@ public: QPoint pos; QPixmap pixmap; + QBitmap contentsMask; + #ifndef QT_NO_CURSOR QCursor *cursor; QCursor *restoreCursor; bool hasCursor; #endif bool isEnabled; -#if QT_VERSION >= 0x040000 Qt::Orientations orientations; -#else - bool orientations[2]; -#endif }; /*! @@ -118,22 +85,17 @@ public: \param parent Parent widget to be panned */ -QwtPanner::QwtPanner(QWidget *parent): - QWidget(parent) +QwtPanner::QwtPanner( QWidget *parent ): + QWidget( parent ) { d_data = new PrivateData(); -#if QT_VERSION >= 0x040000 - setAttribute(Qt::WA_TransparentForMouseEvents); - setAttribute(Qt::WA_NoSystemBackground); - setFocusPolicy(Qt::NoFocus); -#else - setBackgroundMode(Qt::NoBackground); - setFocusPolicy(QWidget::NoFocus); -#endif + setAttribute( Qt::WA_TransparentForMouseEvents ); + setAttribute( Qt::WA_NoSystemBackground ); + setFocusPolicy( Qt::NoFocus ); hide(); - setEnabled(true); + setEnabled( true ); } //! Destructor @@ -146,14 +108,14 @@ QwtPanner::~QwtPanner() Change the mouse button The defaults are Qt::LeftButton and Qt::NoButton */ -void QwtPanner::setMouseButton(int button, int buttonState) +void QwtPanner::setMouseButton( int button, int buttonState ) { d_data->button = button; d_data->buttonState = buttonState; } //! Get the mouse button -void QwtPanner::getMouseButton(int &button, int &buttonState) const +void QwtPanner::getMouseButton( int &button, int &buttonState ) const { button = d_data->button; buttonState = d_data->buttonState; @@ -166,14 +128,14 @@ void QwtPanner::getMouseButton(int &button, int &buttonState) const \param key Key ( See Qt::Keycode ) \param state State */ -void QwtPanner::setAbortKey(int key, int state) +void QwtPanner::setAbortKey( int key, int state ) { d_data->abortKey = key; d_data->abortKeyState = state; } //! Get the abort key -void QwtPanner::getAbortKey(int &key, int &state) const +void QwtPanner::getAbortKey( int &key, int &state ) const { key = d_data->abortKey; state = d_data->abortKeyState; @@ -188,9 +150,9 @@ void QwtPanner::getAbortKey(int &key, int &state) const \sa setCursor() */ #ifndef QT_NO_CURSOR -void QwtPanner::setCursor(const QCursor &cursor) +void QwtPanner::setCursor( const QCursor &cursor ) { - d_data->cursor = new QCursor(cursor); + d_data->cursor = new QCursor( cursor ); } #endif @@ -211,16 +173,16 @@ const QCursor QwtPanner::cursor() const } #endif -/*! +/*! \brief En/disable the panner - + When enabled is true an event filter is installed for the observed widget, otherwise the event filter is removed. \param on true or false \sa isEnabled(), eventFilter() */ -void QwtPanner::setEnabled(bool on) +void QwtPanner::setEnabled( bool on ) { if ( d_data->isEnabled != on ) { @@ -231,25 +193,24 @@ void QwtPanner::setEnabled(bool on) { if ( d_data->isEnabled ) { - w->installEventFilter(this); + w->installEventFilter( this ); } else { - w->removeEventFilter(this); + w->removeEventFilter( this ); hide(); } } } } -#if QT_VERSION >= 0x040000 /*! Set the orientations, where panning is enabled The default value is in both directions: Qt::Horizontal | Qt::Vertical /param o Orientation */ -void QwtPanner::setOrientations(Qt::Orientations o) +void QwtPanner::setOrientations( Qt::Orientations o ) { d_data->orientations = o; } @@ -260,27 +221,13 @@ Qt::Orientations QwtPanner::orientations() const return d_data->orientations; } -#else -void QwtPanner::enableOrientation(Qt::Orientation o, bool enable) -{ - if ( o == Qt::Vertical || o == Qt::Horizontal ) - d_data->orientations[o] = enable; -} -#endif - -/*! +/*! Return true if a orientatio is enabled \sa orientations(), setOrientations() */ -bool QwtPanner::isOrientationEnabled(Qt::Orientation o) const +bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const { -#if QT_VERSION >= 0x040000 return d_data->orientations & o; -#else - if ( o == Qt::Vertical || o == Qt::Horizontal ) - return d_data->orientations[o]; - return false; -#endif } /*! @@ -300,77 +247,103 @@ bool QwtPanner::isEnabled() const \param pe Paint event */ -void QwtPanner::paintEvent(QPaintEvent *pe) +void QwtPanner::paintEvent( QPaintEvent *pe ) { - QPixmap pm(size()); - - QPainter painter(&pm); - - const QColor bg = -#if QT_VERSION < 0x040000 - parentWidget()->palette().color( - QPalette::Normal, QColorGroup::Background); -#else - parentWidget()->palette().color( - QPalette::Normal, QPalette::Background); -#endif - - painter.setPen(Qt::NoPen); - painter.setBrush(QBrush(bg)); - painter.drawRect(0, 0, pm.width(), pm.height()); - int dx = d_data->pos.x() - d_data->initialPos.x(); int dy = d_data->pos.y() - d_data->initialPos.y(); - QRect r(0, 0, d_data->pixmap.width(), d_data->pixmap.height()); - r.moveCenter(QPoint(r.center().x() + dx, r.center().y() + dy)); + QRect r( 0, 0, d_data->pixmap.width(), d_data->pixmap.height() ); + r.moveCenter( QPoint( r.center().x() + dx, r.center().y() + dy ) ); + + QPixmap pm( size() ); + pm.fill( parentWidget(), 0, 0 ); + + QPainter painter( &pm ); + + if ( !d_data->contentsMask.isNull() ) + { + QPixmap masked = d_data->pixmap; + masked.setMask( d_data->contentsMask ); + painter.drawPixmap( r, masked ); + } + else + { + painter.drawPixmap( r, d_data->pixmap ); + } - painter.drawPixmap(r, d_data->pixmap); painter.end(); - painter.begin(this); - painter.setClipRegion(pe->region()); - painter.drawPixmap(0, 0, pm); + if ( !d_data->contentsMask.isNull() ) + pm.setMask( d_data->contentsMask ); + + painter.begin( this ); + painter.setClipRegion( pe->region() ); + painter.drawPixmap( 0, 0, pm ); } -/*! +/*! + \brief Calculate a mask for the contents of the panned widget + + Sometimes only parts of the contents of a widget should be + panned. F.e. for a widget with a styled background with rounded borders + only the area inside of the border should be panned. + + \return An empty bitmap, indicating no mask +*/ +QBitmap QwtPanner::contentsMask() const +{ + return QBitmap(); +} + +/*! + Grab the widget into a pixmap. +*/ +QPixmap QwtPanner::grab() const +{ + return QPixmap::grabWidget( parentWidget() ); +} + +/*! \brief Event filter When isEnabled() the mouse events of the observed widget are filtered. + \param object Object to be filtered + \param event Event + \sa widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseMoveEvent() */ -bool QwtPanner::eventFilter(QObject *o, QEvent *e) +bool QwtPanner::eventFilter( QObject *object, QEvent *event ) { - if ( o == NULL || o != parentWidget() ) + if ( object == NULL || object != parentWidget() ) return false; - switch(e->type()) + switch ( event->type() ) { case QEvent::MouseButtonPress: { - widgetMousePressEvent((QMouseEvent *)e); + widgetMousePressEvent( ( QMouseEvent * )event ); break; } case QEvent::MouseMove: { - widgetMouseMoveEvent((QMouseEvent *)e); + widgetMouseMoveEvent( ( QMouseEvent * )event ); break; } case QEvent::MouseButtonRelease: { - widgetMouseReleaseEvent((QMouseEvent *)e); + widgetMouseReleaseEvent( ( QMouseEvent * )event ); break; } case QEvent::KeyPress: { - widgetKeyPressEvent((QKeyEvent *)e); + widgetKeyPressEvent( ( QKeyEvent * )event ); break; } case QEvent::KeyRelease: { - widgetKeyReleaseEvent((QKeyEvent *)e); + widgetKeyReleaseEvent( ( QKeyEvent * )event ); break; } case QEvent::Paint: @@ -388,54 +361,43 @@ bool QwtPanner::eventFilter(QObject *o, QEvent *e) /*! Handle a mouse press event for the observed widget. - \param me Mouse event + \param mouseEvent Mouse event \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent(), */ -void QwtPanner::widgetMousePressEvent(QMouseEvent *me) +void QwtPanner::widgetMousePressEvent( QMouseEvent *mouseEvent ) { - if ( me->button() != d_data->button ) + if ( mouseEvent->button() != d_data->button ) return; QWidget *w = parentWidget(); if ( w == NULL ) return; -#if QT_VERSION < 0x040000 - if ( (me->state() & Qt::KeyButtonMask) != - (d_data->buttonState & Qt::KeyButtonMask) ) -#else - if ( (me->modifiers() & Qt::KeyboardModifierMask) != - (int)(d_data->buttonState & Qt::KeyboardModifierMask) ) -#endif + if ( ( mouseEvent->modifiers() & Qt::KeyboardModifierMask ) != + ( int )( d_data->buttonState & Qt::KeyboardModifierMask ) ) { return; } #ifndef QT_NO_CURSOR - showCursor(true); + showCursor( true ); #endif - d_data->initialPos = d_data->pos = me->pos(); + d_data->initialPos = d_data->pos = mouseEvent->pos(); - QRect cr = parentWidget()->rect(); - if ( parentWidget()->inherits("QFrame") ) - { - const QFrame* frame = (QFrame*)parentWidget(); - cr = frame->contentsRect(); - } - setGeometry(cr); + setGeometry( parentWidget()->rect() ); // We don't want to grab the picker ! - QwtArray pickers = activePickers(parentWidget()); - for ( int i = 0; i < (int)pickers.size(); i++ ) - pickers[i]->setEnabled(false); + QVector pickers = qwtActivePickers( parentWidget() ); + for ( int i = 0; i < ( int )pickers.size(); i++ ) + pickers[i]->setEnabled( false ); - d_data->pixmap = QPixmap::grabWidget(parentWidget(), - cr.x(), cr.y(), cr.width(), cr.height()); + d_data->pixmap = grab(); + d_data->contentsMask = contentsMask(); - for ( int i = 0; i < (int)pickers.size(); i++ ) - pickers[i]->setEnabled(true); + for ( int i = 0; i < ( int )pickers.size(); i++ ) + pickers[i]->setEnabled( true ); show(); } @@ -443,59 +405,60 @@ void QwtPanner::widgetMousePressEvent(QMouseEvent *me) /*! Handle a mouse move event for the observed widget. - \param me Mouse event + \param mouseEvent Mouse event \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent() */ -void QwtPanner::widgetMouseMoveEvent(QMouseEvent *me) +void QwtPanner::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) { if ( !isVisible() ) return; - QPoint pos = me->pos(); - if ( !isOrientationEnabled(Qt::Horizontal) ) - pos.setX(d_data->initialPos.x()); - if ( !isOrientationEnabled(Qt::Vertical) ) - pos.setY(d_data->initialPos.y()); + QPoint pos = mouseEvent->pos(); + if ( !isOrientationEnabled( Qt::Horizontal ) ) + pos.setX( d_data->initialPos.x() ); + if ( !isOrientationEnabled( Qt::Vertical ) ) + pos.setY( d_data->initialPos.y() ); - if ( pos != d_data->pos && rect().contains(pos) ) + if ( pos != d_data->pos && rect().contains( pos ) ) { d_data->pos = pos; update(); - emit moved(d_data->pos.x() - d_data->initialPos.x(), - d_data->pos.y() - d_data->initialPos.y()); + Q_EMIT moved( d_data->pos.x() - d_data->initialPos.x(), + d_data->pos.y() - d_data->initialPos.y() ); } } /*! Handle a mouse release event for the observed widget. - \param me Mouse event + \param mouseEvent Mouse event \sa eventFilter(), widgetMousePressEvent(), widgetMouseMoveEvent(), */ -void QwtPanner::widgetMouseReleaseEvent(QMouseEvent *me) +void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) { if ( isVisible() ) { hide(); #ifndef QT_NO_CURSOR - showCursor(false); + showCursor( false ); #endif - QPoint pos = me->pos(); - if ( !isOrientationEnabled(Qt::Horizontal) ) - pos.setX(d_data->initialPos.x()); - if ( !isOrientationEnabled(Qt::Vertical) ) - pos.setY(d_data->initialPos.y()); + QPoint pos = mouseEvent->pos(); + if ( !isOrientationEnabled( Qt::Horizontal ) ) + pos.setX( d_data->initialPos.x() ); + if ( !isOrientationEnabled( Qt::Vertical ) ) + pos.setY( d_data->initialPos.y() ); d_data->pixmap = QPixmap(); + d_data->contentsMask = QBitmap(); d_data->pos = pos; if ( d_data->pos != d_data->initialPos ) { - emit panned(d_data->pos.x() - d_data->initialPos.x(), - d_data->pos.y() - d_data->initialPos.y()); + Q_EMIT panned( d_data->pos.x() - d_data->initialPos.x(), + d_data->pos.y() - d_data->initialPos.y() ); } } } @@ -503,26 +466,21 @@ void QwtPanner::widgetMouseReleaseEvent(QMouseEvent *me) /*! Handle a key press event for the observed widget. - \param ke Key event + \param keyEvent Key event \sa eventFilter(), widgetKeyReleaseEvent() */ -void QwtPanner::widgetKeyPressEvent(QKeyEvent *ke) +void QwtPanner::widgetKeyPressEvent( QKeyEvent *keyEvent ) { - if ( ke->key() == d_data->abortKey ) + if ( keyEvent->key() == d_data->abortKey ) { const bool matched = -#if QT_VERSION < 0x040000 - (ke->state() & Qt::KeyButtonMask) == - (d_data->abortKeyState & Qt::KeyButtonMask); -#else - (ke->modifiers() & Qt::KeyboardModifierMask) == - (int)(d_data->abortKeyState & Qt::KeyboardModifierMask); -#endif + ( keyEvent->modifiers() & Qt::KeyboardModifierMask ) == + ( int )( d_data->abortKeyState & Qt::KeyboardModifierMask ); if ( matched ) { hide(); #ifndef QT_NO_CURSOR - showCursor(false); + showCursor( false ); #endif d_data->pixmap = QPixmap(); } @@ -531,14 +489,17 @@ void QwtPanner::widgetKeyPressEvent(QKeyEvent *ke) /*! Handle a key release event for the observed widget. + + \param keyEvent Key event \sa eventFilter(), widgetKeyReleaseEvent() */ -void QwtPanner::widgetKeyReleaseEvent(QKeyEvent *) +void QwtPanner::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) { + Q_UNUSED( keyEvent ); } #ifndef QT_NO_CURSOR -void QwtPanner::showCursor(bool on) +void QwtPanner::showCursor( bool on ) { if ( on == d_data->hasCursor ) return; @@ -551,22 +512,18 @@ void QwtPanner::showCursor(bool on) if ( on ) { -#if QT_VERSION < 0x040000 - if ( w->testWState(WState_OwnCursor) ) -#else - if ( w->testAttribute(Qt::WA_SetCursor) ) -#endif + if ( w->testAttribute( Qt::WA_SetCursor ) ) { delete d_data->restoreCursor; - d_data->restoreCursor = new QCursor(w->cursor()); + d_data->restoreCursor = new QCursor( w->cursor() ); } - w->setCursor(*d_data->cursor); + w->setCursor( *d_data->cursor ); } else { - if ( d_data->restoreCursor ) + if ( d_data->restoreCursor ) { - w->setCursor(*d_data->restoreCursor); + w->setCursor( *d_data->restoreCursor ); delete d_data->restoreCursor; d_data->restoreCursor = NULL; } diff --git a/qwt/src/qwt_panner.h b/qwt/src/qwt_panner.h index 13590a5cb..247d4a393 100644 --- a/qwt/src/qwt_panner.h +++ b/qwt/src/qwt_panner.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,9 +10,9 @@ #ifndef QWT_PANNER_H #define QWT_PANNER_H 1 -#include -#include #include "qwt_global.h" +#include +#include class QCursor; @@ -22,12 +22,12 @@ class QCursor; QwtPanner grabs the contents of a widget, that can be dragged in all directions. The offset between the start and the end position is emitted by the panned signal. - + QwtPanner grabs the content of the widget into a pixmap and moves the pixmap around, without initiating any repaint events for the widget. - Areas, that are not part of content are not painted while panning - in in process. This makes panning fast enough for widgets, where - repaints are too slow for mouse movements. + Areas, that are not part of content are not painted while panning. + This makes panning fast enough for widgets, where + repaints are too slow for mouse movements. For widgets, where repaints are very fast it might be better to implement panning manually by mapping mouse events into paint events. @@ -37,39 +37,35 @@ class QWT_EXPORT QwtPanner: public QWidget Q_OBJECT public: - QwtPanner(QWidget* parent); + QwtPanner( QWidget* parent ); virtual ~QwtPanner(); - void setEnabled(bool); + void setEnabled( bool ); bool isEnabled() const; - void setMouseButton(int button, int buttonState = Qt::NoButton); - void getMouseButton(int &button, int &buttonState) const; - void setAbortKey(int key, int state = Qt::NoButton); - void getAbortKey(int &key, int &state) const; + void setMouseButton( int button, int buttonState = Qt::NoButton ); + void getMouseButton( int &button, int &buttonState ) const; + void setAbortKey( int key, int state = Qt::NoButton ); + void getAbortKey( int &key, int &state ) const; - void setCursor(const QCursor &); + void setCursor( const QCursor & ); const QCursor cursor() const; -#if QT_VERSION >= 0x040000 - void setOrientations(Qt::Orientations); + void setOrientations( Qt::Orientations ); Qt::Orientations orientations() const; -#else - void enableOrientation(Qt::Orientation, bool enable); -#endif - bool isOrientationEnabled(Qt::Orientation) const; + bool isOrientationEnabled( Qt::Orientation ) const; - virtual bool eventFilter(QObject *, QEvent *); + virtual bool eventFilter( QObject *, QEvent * ); -signals: +Q_SIGNALS: /*! Signal emitted, when panning is done \param dx Offset in horizontal direction \param dy Offset in vertical direction */ - void panned(int dx, int dy); + void panned( int dx, int dy ); /*! Signal emitted, while the widget moved, but panning @@ -78,20 +74,23 @@ signals: \param dx Offset in horizontal direction \param dy Offset in vertical direction */ - void moved(int dx, int dy); + void moved( int dx, int dy ); protected: - virtual void widgetMousePressEvent(QMouseEvent *); - virtual void widgetMouseReleaseEvent(QMouseEvent *); - virtual void widgetMouseMoveEvent(QMouseEvent *); - virtual void widgetKeyPressEvent(QKeyEvent *); - virtual void widgetKeyReleaseEvent(QKeyEvent *); + virtual void widgetMousePressEvent( QMouseEvent * ); + virtual void widgetMouseReleaseEvent( QMouseEvent * ); + virtual void widgetMouseMoveEvent( QMouseEvent * ); + virtual void widgetKeyPressEvent( QKeyEvent * ); + virtual void widgetKeyReleaseEvent( QKeyEvent * ); - virtual void paintEvent(QPaintEvent *); + virtual void paintEvent( QPaintEvent * ); + + virtual QBitmap contentsMask() const; + virtual QPixmap grab() const; private: #ifndef QT_NO_CURSOR - void showCursor(bool); + void showCursor( bool ); #endif class PrivateData; diff --git a/qwt/src/qwt_picker.cpp b/qwt/src/qwt_picker.cpp index 71717e272..8e1f1a11f 100644 --- a/qwt/src/qwt_picker.cpp +++ b/qwt/src/qwt_picker.cpp @@ -7,22 +7,19 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ +#include "qwt_picker.h" +#include "qwt_picker_machine.h" +#include "qwt_painter.h" +#include "qwt_math.h" #include #include #include #include #include #include -#include "qwt_math.h" -#include "qwt_painter.h" -#include "qwt_picker_machine.h" -#include "qwt_picker.h" -#if QT_VERSION < 0x040000 -#include -#else #include #include -#endif +#include class QwtPicker::PickerWidget: public QWidget { @@ -33,18 +30,18 @@ public: Text }; - PickerWidget(QwtPicker *, QWidget *, Type); - virtual void updateMask(); + PickerWidget( QwtPicker *, QWidget *, Type ); + void updateMask(); /* - For a tracker text with a background we can use the background + For a tracker text with a background we can use the background rect as mask. Also for "regular" Qt widgets >= 4.3.0 we don't need to mask the text anymore. */ bool d_hasTextMask; protected: - virtual void paintEvent(QPaintEvent *); + virtual void paintEvent( QPaintEvent * ); QwtPicker *d_picker; Type d_type; @@ -57,7 +54,6 @@ public: QwtPickerMachine *stateMachine; - int selectionFlags; QwtPicker::ResizeMode resizeMode; QwtPicker::RubberBand rubberBand; @@ -67,7 +63,7 @@ public: QPen trackerPen; QFont trackerFont; - QwtPolygon selection; + QPolygon pickedPoints; bool isActive; QPoint trackerPosition; @@ -79,33 +75,21 @@ public: In case of (f.e) a CrossRubberBand and a text this creates complete repaints of the widget. So we better use two different widgets. */ - -#if QT_VERSION < 0x040000 - QGuardedPtr rubberBandWidget; - QGuardedPtr trackerWidget; -#else + QPointer rubberBandWidget; QPointer trackerWidget; -#endif }; QwtPicker::PickerWidget::PickerWidget( - QwtPicker *picker, QWidget *parent, Type type): - QWidget(parent), - d_hasTextMask(false), - d_picker(picker), - d_type(type) + QwtPicker *picker, QWidget *parent, Type type ): + QWidget( parent ), + d_hasTextMask( false ), + d_picker( picker ), + d_type( type ) { -#if QT_VERSION >= 0x040000 - setAttribute(Qt::WA_TransparentForMouseEvents); - setAttribute(Qt::WA_NoSystemBackground); - setFocusPolicy(Qt::NoFocus); -#else - setBackgroundMode(Qt::NoBackground); - setFocusPolicy(QWidget::NoFocus); - setMouseTracking(true); -#endif - hide(); + setAttribute( Qt::WA_TransparentForMouseEvents ); + setAttribute( Qt::WA_NoSystemBackground ); + setFocusPolicy( Qt::NoFocus ); } void QwtPicker::PickerWidget::updateMask() @@ -114,103 +98,83 @@ void QwtPicker::PickerWidget::updateMask() if ( d_type == RubberBand ) { - QBitmap bm(width(), height()); - bm.fill(Qt::color0); + QBitmap bm( width(), height() ); + bm.fill( Qt::color0 ); - QPainter painter(&bm); + QPainter painter( &bm ); QPen pen = d_picker->rubberBandPen(); - pen.setColor(Qt::color1); - painter.setPen(pen); + pen.setColor( Qt::color1 ); + painter.setPen( pen ); - d_picker->drawRubberBand(&painter); + d_picker->drawRubberBand( &painter ); - mask = QRegion(bm); + mask = QRegion( bm ); } if ( d_type == Text ) { - d_hasTextMask = true; -#if QT_VERSION >= 0x040300 - if ( !parentWidget()->testAttribute(Qt::WA_PaintOnScreen) ) - { -#if 0 - if ( parentWidget()->paintEngine()->type() != QPaintEngine::OpenGL ) -#endif - { - // With Qt >= 4.3 drawing of the tracker can be implemented in an - // easier way, using the textRect as mask. + d_hasTextMask = parentWidget()->testAttribute( Qt::WA_PaintOnScreen ); - d_hasTextMask = false; - } - } -#endif - if ( d_hasTextMask ) { const QwtText label = d_picker->trackerText( - d_picker->trackerPosition()); - if ( label.testPaintAttribute(QwtText::PaintBackground) + d_picker->trackerPosition() ); + + if ( label.testPaintAttribute( QwtText::PaintBackground ) && label.backgroundBrush().style() != Qt::NoBrush ) { -#if QT_VERSION >= 0x040300 if ( label.backgroundBrush().color().alpha() > 0 ) -#endif - // We don't need a text mask, when we have a background - d_hasTextMask = false; + { + // We don't need a text mask, when we have a background + d_hasTextMask = false; + } } } if ( d_hasTextMask ) { - QBitmap bm(width(), height()); - bm.fill(Qt::color0); + QBitmap bm( width(), height() ); + bm.fill( Qt::color0 ); - QPainter painter(&bm); - painter.setFont(font()); + QPainter painter( &bm ); + painter.setFont( font() ); QPen pen = d_picker->trackerPen(); - pen.setColor(Qt::color1); - painter.setPen(pen); + pen.setColor( Qt::color1 ); + painter.setPen( pen ); - d_picker->drawTracker(&painter); + d_picker->drawTracker( &painter ); - mask = QRegion(bm); + mask = QRegion( bm ); } else { - mask = d_picker->trackerRect(font()); + mask = d_picker->trackerRect( font() ); } } -#if QT_VERSION < 0x040000 QWidget *w = parentWidget(); - const bool doUpdate = w->isUpdatesEnabled(); - const Qt::BackgroundMode bgMode = w->backgroundMode(); - w->setUpdatesEnabled(false); - if ( bgMode != Qt::NoBackground ) - w->setBackgroundMode(Qt::NoBackground); -#endif + if ( w && !w->testAttribute( Qt::WA_PaintOnScreen ) ) + { + // The parent widget gets an update for its complete rectangle + // when the mask is changed in visible state. + // With this hide/show we only get an update for the + // previous mask. - setMask(mask); - -#if QT_VERSION < 0x040000 - if ( bgMode != Qt::NoBackground ) - w->setBackgroundMode(bgMode); - - w->setUpdatesEnabled(doUpdate); -#endif - - setShown(!mask.isEmpty()); + hide(); + } + setMask( mask ); + setVisible( !mask.isEmpty() ); } -void QwtPicker::PickerWidget::paintEvent(QPaintEvent *e) +void QwtPicker::PickerWidget::paintEvent( QPaintEvent *e ) { - QPainter painter(this); - painter.setClipRegion(e->region()); + QPainter painter( this ); + painter.setClipRegion( e->region() ); if ( d_type == RubberBand ) { - painter.setPen(d_picker->rubberBandPen()); - d_picker->drawRubberBand(&painter); + painter.setPen( d_picker->rubberBandPen() ); + d_picker->drawRubberBand( &painter ); } if ( d_type == Text ) @@ -219,59 +183,52 @@ void QwtPicker::PickerWidget::paintEvent(QPaintEvent *e) If we have a text mask we simply fill the region of the mask. This gives better results for antialiased fonts. */ - bool doDrawTracker = !d_hasTextMask; -#if QT_VERSION < 0x040000 - if ( !doDrawTracker && QPainter::redirect(this) ) + if ( d_hasTextMask ) { - // setMask + painter redirection doesn't work - doDrawTracker = true; - } -#endif - if ( doDrawTracker ) - { - painter.setPen(d_picker->trackerPen()); - d_picker->drawTracker(&painter); + painter.fillRect( e->rect(), + QBrush( d_picker->trackerPen().color() ) ); } else - painter.fillRect(e->rect(), QBrush(d_picker->trackerPen().color())); + { + painter.setPen( d_picker->trackerPen() ); + d_picker->drawTracker( &painter ); + } } } /*! Constructor - Creates an picker that is enabled, but where selection flag - is set to NoSelection, rubberband and tracker are disabled. - + Creates an picker that is enabled, but without a state machine. + rubberband and tracker are disabled. + \param parent Parent widget, that will be observed */ -QwtPicker::QwtPicker(QWidget *parent): - QObject(parent) +QwtPicker::QwtPicker( QWidget *parent ): + QObject( parent ) { - init(parent, NoSelection, NoRubberBand, AlwaysOff); + init( parent, NoRubberBand, AlwaysOff ); } /*! Constructor - \param selectionFlags Or'd value of SelectionType, RectSelectionType and - SelectionMode \param rubberBand Rubberband style \param trackerMode Tracker mode \param parent Parent widget, that will be observed */ -QwtPicker::QwtPicker(int selectionFlags, RubberBand rubberBand, - DisplayMode trackerMode, QWidget *parent): - QObject(parent) +QwtPicker::QwtPicker( RubberBand rubberBand, + DisplayMode trackerMode, QWidget *parent ): + QObject( parent ) { - init(parent, selectionFlags, rubberBand, trackerMode); + init( parent, rubberBand, trackerMode ); } //! Destructor QwtPicker::~QwtPicker() { - setMouseTracking(false); + setMouseTracking( false ); delete d_data->stateMachine; delete d_data->rubberBandWidget; delete d_data->trackerWidget; @@ -279,8 +236,8 @@ QwtPicker::~QwtPicker() } //! Init the picker, used by the constructors -void QwtPicker::init(QWidget *parent, int selectionFlags, - RubberBand rubberBand, DisplayMode trackerMode) +void QwtPicker::init( QWidget *parent, + RubberBand rubberBand, DisplayMode trackerMode ) { d_data = new PrivateData; @@ -292,33 +249,30 @@ void QwtPicker::init(QWidget *parent, int selectionFlags, d_data->resizeMode = Stretch; d_data->trackerMode = AlwaysOff; d_data->isActive = false; - d_data->trackerPosition = QPoint(-1, -1); + d_data->trackerPosition = QPoint( -1, -1 ); d_data->mouseTracking = false; d_data->stateMachine = NULL; - setSelectionFlags(selectionFlags); if ( parent ) { -#if QT_VERSION >= 0x040000 if ( parent->focusPolicy() == Qt::NoFocus ) - parent->setFocusPolicy(Qt::WheelFocus); -#else - if ( parent->focusPolicy() == QWidget::NoFocus ) - parent->setFocusPolicy(QWidget::WheelFocus); -#endif + parent->setFocusPolicy( Qt::WheelFocus ); d_data->trackerFont = parent->font(); d_data->mouseTracking = parent->hasMouseTracking(); - setEnabled(true); + setEnabled( true ); } - setTrackerMode(trackerMode); + setTrackerMode( trackerMode ); } /*! - Set a state machine and delete the previous one + Set a state machine and delete the previous one + + \param stateMachine State machine + \sa stateMachine() */ -void QwtPicker::setStateMachine(QwtPickerMachine *stateMachine) +void QwtPicker::setStateMachine( QwtPickerMachine *stateMachine ) { if ( d_data->stateMachine != stateMachine ) { @@ -333,42 +287,21 @@ void QwtPicker::setStateMachine(QwtPickerMachine *stateMachine) } /*! - Create a state machine depending on the selection flags. - - - PointSelection | ClickSelection\n - QwtPickerClickPointMachine() - - PointSelection | DragSelection\n - QwtPickerDragPointMachine() - - RectSelection | ClickSelection\n - QwtPickerClickRectMachine() - - RectSelection | DragSelection\n - QwtPickerDragRectMachine() - - PolygonSelection\n - QwtPickerPolygonMachine() - - \sa setSelectionFlags() + \return Assigned state machine + \sa setStateMachine() */ -QwtPickerMachine *QwtPicker::stateMachine(int flags) const +QwtPickerMachine *QwtPicker::stateMachine() { - if ( flags & PointSelection ) - { - if ( flags & ClickSelection ) - return new QwtPickerClickPointMachine; - else - return new QwtPickerDragPointMachine; - } - if ( flags & RectSelection ) - { - if ( flags & ClickSelection ) - return new QwtPickerClickRectMachine; - else - return new QwtPickerDragRectMachine; - } - if ( flags & PolygonSelection ) - { - return new QwtPickerPolygonMachine(); - } - return NULL; + return d_data->stateMachine; +} + +/*! + \return Assigned state machine + \sa setStateMachine() +*/ +const QwtPickerMachine *QwtPicker::stateMachine() const +{ + return d_data->stateMachine; } //! Return the parent widget, where the selection happens @@ -376,7 +309,7 @@ QWidget *QwtPicker::parentWidget() { QObject *obj = parent(); if ( obj && obj->isWidgetType() ) - return (QWidget *)obj; + return static_cast( obj ); return NULL; } @@ -386,45 +319,20 @@ const QWidget *QwtPicker::parentWidget() const { QObject *obj = parent(); if ( obj && obj->isWidgetType() ) - return (QWidget *)obj; + return static_cast< const QWidget *>( obj ); return NULL; } /*! - Set the selection flags - - \param flags Or'd value of SelectionType, RectSelectionType and - SelectionMode. The default value is NoSelection. - - \sa selectionFlags(), SelectionType, RectSelectionType, SelectionMode -*/ - -void QwtPicker::setSelectionFlags(int flags) -{ - d_data->selectionFlags = flags; - setStateMachine(stateMachine(flags)); -} - -/*! - \return Selection flags, an Or'd value of SelectionType, RectSelectionType and - SelectionMode. - \sa setSelectionFlags(), SelectionType, RectSelectionType, SelectionMode -*/ -int QwtPicker::selectionFlags() const -{ - return d_data->selectionFlags; -} - -/*! - Set the rubberband style + Set the rubberband style \param rubberBand Rubberband style The default value is NoRubberBand. \sa rubberBand(), RubberBand, setRubberBandPen() */ -void QwtPicker::setRubberBand(RubberBand rubberBand) +void QwtPicker::setRubberBand( RubberBand rubberBand ) { d_data->rubberBand = rubberBand; } @@ -446,7 +354,7 @@ QwtPicker::RubberBand QwtPicker::rubberBand() const if the tracker has to be displayed whenever the observed widget has focus and cursor (AlwaysOn), never (AlwaysOff), or only when the selection is active (ActiveOnly). - + \param mode Tracker display mode \warning In case of AlwaysOn, mouseTracking will be enabled @@ -454,23 +362,23 @@ QwtPicker::RubberBand QwtPicker::rubberBand() const \sa trackerMode(), DisplayMode */ -void QwtPicker::setTrackerMode(DisplayMode mode) -{ +void QwtPicker::setTrackerMode( DisplayMode mode ) +{ if ( d_data->trackerMode != mode ) { d_data->trackerMode = mode; - setMouseTracking(d_data->trackerMode == AlwaysOn); + setMouseTracking( d_data->trackerMode == AlwaysOn ); } -} +} /*! \return Tracker display mode \sa setTrackerMode(), DisplayMode */ QwtPicker::DisplayMode QwtPicker::trackerMode() const -{ +{ return d_data->trackerMode; -} +} /*! \brief Set the resize mode. @@ -486,10 +394,10 @@ QwtPicker::DisplayMode QwtPicker::trackerMode() const \param mode Resize mode \sa resizeMode(), ResizeMode */ -void QwtPicker::setResizeMode(ResizeMode mode) +void QwtPicker::setResizeMode( ResizeMode mode ) { d_data->resizeMode = mode; -} +} /*! \return Resize mode @@ -497,7 +405,7 @@ void QwtPicker::setResizeMode(ResizeMode mode) */ QwtPicker::ResizeMode QwtPicker::resizeMode() const -{ +{ return d_data->resizeMode; } @@ -510,7 +418,7 @@ QwtPicker::ResizeMode QwtPicker::resizeMode() const \param enabled true or false \sa isEnabled(), eventFilter() */ -void QwtPicker::setEnabled(bool enabled) +void QwtPicker::setEnabled( bool enabled ) { if ( d_data->enabled != enabled ) { @@ -520,9 +428,9 @@ void QwtPicker::setEnabled(bool enabled) if ( w ) { if ( enabled ) - w->installEventFilter(this); + w->installEventFilter( this ); else - w->removeEventFilter(this); + w->removeEventFilter( this ); } updateDisplay(); @@ -545,7 +453,7 @@ bool QwtPicker::isEnabled() const \param font Tracker font \sa trackerFont(), setTrackerMode(), setTrackerPen() */ -void QwtPicker::setTrackerFont(const QFont &font) +void QwtPicker::setTrackerFont( const QFont &font ) { if ( font != d_data->trackerFont ) { @@ -570,7 +478,7 @@ QFont QwtPicker::trackerFont() const \param pen Tracker pen \sa trackerPen(), setTrackerMode(), setTrackerFont() */ -void QwtPicker::setTrackerPen(const QPen &pen) +void QwtPicker::setTrackerPen( const QPen &pen ) { if ( pen != d_data->trackerPen ) { @@ -594,7 +502,7 @@ QPen QwtPicker::trackerPen() const \param pen Rubberband pen \sa rubberBandPen(), setRubberBand() */ -void QwtPicker::setRubberBandPen(const QPen &pen) +void QwtPicker::setRubberBandPen( const QPen &pen ) { if ( pen != d_data->rubberBandPen ) { @@ -625,117 +533,112 @@ QPen QwtPicker::rubberBandPen() const \return Converted position as string */ -QwtText QwtPicker::trackerText(const QPoint &pos) const +QwtText QwtPicker::trackerText( const QPoint &pos ) const { QString label; - switch(rubberBand()) + switch ( rubberBand() ) { case HLineRubberBand: - label.sprintf("%d", pos.y()); + label.sprintf( "%d", pos.y() ); break; case VLineRubberBand: - label.sprintf("%d", pos.x()); + label.sprintf( "%d", pos.x() ); break; default: - label.sprintf("%d, %d", pos.x(), pos.y()); + label.sprintf( "%d, %d", pos.x(), pos.y() ); } return label; } /*! - Draw a rubberband , depending on rubberBand() and selectionFlags() + Draw a rubberband, depending on rubberBand() - \param painter Painter, initialized with clip rect + \param painter Painter, initialized with clip rect - \sa rubberBand(), RubberBand, selectionFlags() + \sa rubberBand(), RubberBand */ -void QwtPicker::drawRubberBand(QPainter *painter) const +void QwtPicker::drawRubberBand( QPainter *painter ) const { - if ( !isActive() || rubberBand() == NoRubberBand || + if ( !isActive() || rubberBand() == NoRubberBand || rubberBandPen().style() == Qt::NoPen ) { return; } const QRect &pRect = pickRect(); - const QwtPolygon &pa = d_data->selection; + const QPolygon pa = adjustedPoints( d_data->pickedPoints ); - if ( selectionFlags() & PointSelection ) + QwtPickerMachine::SelectionType selectionType = + QwtPickerMachine::NoSelection; + + if ( d_data->stateMachine ) + selectionType = d_data->stateMachine->selectionType(); + + switch ( selectionType ) { - if ( pa.count() < 1 ) - return; - - const QPoint pos = pa[0]; - - switch(rubberBand()) + case QwtPickerMachine::NoSelection: + case QwtPickerMachine::PointSelection: { - case VLineRubberBand: - QwtPainter::drawLine(painter, pos.x(), - pRect.top(), pos.x(), pRect.bottom()); - break; + if ( pa.count() < 1 ) + return; - case HLineRubberBand: - QwtPainter::drawLine(painter, pRect.left(), - pos.y(), pRect.right(), pos.y()); - break; + const QPoint pos = pa[0]; - case CrossRubberBand: - QwtPainter::drawLine(painter, pos.x(), - pRect.top(), pos.x(), pRect.bottom()); - QwtPainter::drawLine(painter, pRect.left(), - pos.y(), pRect.right(), pos.y()); - break; - default: - break; + switch ( rubberBand() ) + { + case VLineRubberBand: + QwtPainter::drawLine( painter, pos.x(), + pRect.top(), pos.x(), pRect.bottom() ); + break; + + case HLineRubberBand: + QwtPainter::drawLine( painter, pRect.left(), + pos.y(), pRect.right(), pos.y() ); + break; + + case CrossRubberBand: + QwtPainter::drawLine( painter, pos.x(), + pRect.top(), pos.x(), pRect.bottom() ); + QwtPainter::drawLine( painter, pRect.left(), + pos.y(), pRect.right(), pos.y() ); + break; + default: + break; + } + break; } - } - - else if ( selectionFlags() & RectSelection ) - { - if ( pa.count() < 2 ) - return; - - QPoint p1 = pa[0]; - QPoint p2 = pa[int(pa.count() - 1)]; - - if ( selectionFlags() & CenterToCorner ) + case QwtPickerMachine::RectSelection: { - p1.setX(p1.x() - (p2.x() - p1.x())); - p1.setY(p1.y() - (p2.y() - p1.y())); - } - else if ( selectionFlags() & CenterToRadius ) - { - const int radius = qwtMax(qwtAbs(p2.x() - p1.x()), - qwtAbs(p2.y() - p1.y())); - p2.setX(p1.x() + radius); - p2.setY(p1.y() + radius); - p1.setX(p1.x() - radius); - p1.setY(p1.y() - radius); - } + if ( pa.count() < 2 ) + return; -#if QT_VERSION < 0x040000 - const QRect rect = QRect(p1, p2).normalize(); -#else - const QRect rect = QRect(p1, p2).normalized(); -#endif - switch(rubberBand()) - { - case EllipseRubberBand: - QwtPainter::drawEllipse(painter, rect); - break; - case RectRubberBand: - QwtPainter::drawRect(painter, rect); - break; - default: - break; + const QPoint p1 = pa[0]; + const QPoint p2 = pa[int( pa.count() - 1 )]; + + const QRect rect = QRect( p1, p2 ).normalized(); + switch ( rubberBand() ) + { + case EllipseRubberBand: + QwtPainter::drawEllipse( painter, rect ); + break; + case RectRubberBand: + QwtPainter::drawRect( painter, rect ); + break; + default: + break; + } + break; } - } - else if ( selectionFlags() & PolygonSelection ) - { - if ( rubberBand() == PolygonRubberBand ) - painter->drawPolyline(pa); + case QwtPickerMachine::PolygonSelection: + { + if ( rubberBand() == PolygonRubberBand ) + painter->drawPolyline( pa ); + break; + } + default: + break; } } @@ -746,35 +649,67 @@ void QwtPicker::drawRubberBand(QPainter *painter) const \sa trackerRect(), trackerText() */ -void QwtPicker::drawTracker(QPainter *painter) const +void QwtPicker::drawTracker( QPainter *painter ) const { - const QRect textRect = trackerRect(painter->font()); + const QRect textRect = trackerRect( painter->font() ); if ( !textRect.isEmpty() ) { - QwtText label = trackerText(d_data->trackerPosition); + const QwtText label = trackerText( d_data->trackerPosition ); if ( !label.isEmpty() ) - { - painter->save(); - -#if defined(Q_WS_MAC) - // Antialiased fonts are broken on the Mac. -#if QT_VERSION >= 0x040000 - painter->setRenderHint(QPainter::TextAntialiasing, false); -#else - QFont fnt = label.usedFont(painter->font()); - fnt.setStyleStrategy(QFont::NoAntialias); - label.setFont(fnt); -#endif -#endif - label.draw(painter, textRect); - - painter->restore(); - } + label.draw( painter, textRect ); } } +/*! + \brief Map the pickedPoints() into a selection() + + adjustedPoints() maps the points, that have been collected on + the parentWidget() into a selection(). The default implementation + simply returns the points unmodified. + + The reason, why a selection() differs from the picked points + depends on the application requirements. F.e. : + + - A rectangular selection might need to have a specific aspect ratio only.\n + - A selection could accept non intersecting polygons only.\n + - ...\n + + The example below is for a rectangular selection, where the first + point is the center of the selected rectangle. + \par Example + \verbatim QPolygon MyPicker::adjustedPoints(const QPolygon &points) const +{ + QPolygon adjusted; + if ( points.size() == 2 ) + { + const int width = qAbs(points[1].x() - points[0].x()); + const int height = qAbs(points[1].y() - points[0].y()); + + QRect rect(0, 0, 2 * width, 2 * height); + rect.moveCenter(points[0]); + + adjusted += rect.topLeft(); + adjusted += rect.bottomRight(); + } + return adjusted; +}\endverbatim\n +*/ +QPolygon QwtPicker::adjustedPoints( const QPolygon &points ) const +{ + return points; +} + +/*! + \return Selected points + \sa pickedPoints(), adjustedPoints() +*/ +QPolygon QwtPicker::selection() const +{ + return adjustedPoints( d_data->pickedPoints ); +} + //! \return Current position of the tracker -QPoint QwtPicker::trackerPosition() const +QPoint QwtPicker::trackerPosition() const { return d_data->trackerPosition; } @@ -788,10 +723,10 @@ QPoint QwtPicker::trackerPosition() const \sa trackerPosition() */ -QRect QwtPicker::trackerRect(const QFont &font) const +QRect QwtPicker::trackerRect( const QFont &font ) const { - if ( trackerMode() == AlwaysOff || - (trackerMode() == ActiveOnly && !isActive() ) ) + if ( trackerMode() == AlwaysOff || + ( trackerMode() == ActiveOnly && !isActive() ) ) { return QRect(); } @@ -799,23 +734,24 @@ QRect QwtPicker::trackerRect(const QFont &font) const if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) return QRect(); - QwtText text = trackerText(d_data->trackerPosition); + QwtText text = trackerText( d_data->trackerPosition ); if ( text.isEmpty() ) return QRect(); - QRect textRect(QPoint(0, 0), text.textSize(font)); + const QSizeF textSize = text.textSize( font ); + QRect textRect( 0, 0, qCeil( textSize.width() ), qCeil( textSize.height() ) ); const QPoint &pos = d_data->trackerPosition; int alignment = 0; - if ( isActive() && d_data->selection.count() > 1 + if ( isActive() && d_data->pickedPoints.count() > 1 && rubberBand() != NoRubberBand ) { - const QPoint last = - d_data->selection[int(d_data->selection.count()) - 2]; + const QPoint last = + d_data->pickedPoints[int( d_data->pickedPoints.count() ) - 2]; - alignment |= (pos.x() >= last.x()) ? Qt::AlignRight : Qt::AlignLeft; - alignment |= (pos.y() > last.y()) ? Qt::AlignBottom : Qt::AlignTop; + alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft; + alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop; } else alignment = Qt::AlignTop | Qt::AlignRight; @@ -833,16 +769,16 @@ QRect QwtPicker::trackerRect(const QFont &font) const y += margin; else if ( alignment & Qt::AlignTop ) y -= textRect.height() + margin; - - textRect.moveTopLeft(QPoint(x, y)); - int right = qwtMin(textRect.right(), pickRect().right() - margin); - int bottom = qwtMin(textRect.bottom(), pickRect().bottom() - margin); - textRect.moveBottomRight(QPoint(right, bottom)); + textRect.moveTopLeft( QPoint( x, y ) ); - int left = qwtMax(textRect.left(), pickRect().left() + margin); - int top = qwtMax(textRect.top(), pickRect().top() + margin); - textRect.moveTopLeft(QPoint(left, top)); + int right = qMin( textRect.right(), pickRect().right() - margin ); + int bottom = qMin( textRect.bottom(), pickRect().bottom() - margin ); + textRect.moveBottomRight( QPoint( right, bottom ) ); + + int left = qMax( textRect.left(), pickRect().left() + margin ); + int top = qMax( textRect.top(), pickRect().top() + margin ); + textRect.moveTopLeft( QPoint( left, top ) ); return textRect; } @@ -852,55 +788,63 @@ QRect QwtPicker::trackerRect(const QFont &font) const When isEnabled() == true all events of the observed widget are filtered. Mouse and keyboard events are translated into widgetMouse- and widgetKey- - and widgetWheel-events. Paint and Resize events are handled to keep + and widgetWheel-events. Paint and Resize events are handled to keep rubberband and tracker up to date. - \sa event(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + \param object Object to be filtered + \param event Event + + \sa widgetEnterEvent(), widgetLeaveEvent(), + widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), - widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent(), + QObject::installEventFilter(), QObject::event() */ -bool QwtPicker::eventFilter(QObject *o, QEvent *e) +bool QwtPicker::eventFilter( QObject *object, QEvent *event ) { - if ( o && o == parentWidget() ) + if ( object && object == parentWidget() ) { - switch(e->type()) + switch ( event->type() ) { case QEvent::Resize: { - const QResizeEvent *re = (QResizeEvent *)e; + const QResizeEvent *re = ( QResizeEvent * )event; if ( d_data->resizeMode == Stretch ) - stretchSelection(re->oldSize(), re->size()); + stretchSelection( re->oldSize(), re->size() ); if ( d_data->rubberBandWidget ) - d_data->rubberBandWidget->resize(re->size()); - + d_data->rubberBandWidget->resize( re->size() ); + if ( d_data->trackerWidget ) - d_data->trackerWidget->resize(re->size()); + d_data->trackerWidget->resize( re->size() ); break; } + case QEvent::Enter: + widgetEnterEvent( event ); + break; case QEvent::Leave: - widgetLeaveEvent(e); + widgetLeaveEvent( event ); break; case QEvent::MouseButtonPress: - widgetMousePressEvent((QMouseEvent *)e); + widgetMousePressEvent( ( QMouseEvent * )event ); break; case QEvent::MouseButtonRelease: - widgetMouseReleaseEvent((QMouseEvent *)e); + widgetMouseReleaseEvent( ( QMouseEvent * )event ); break; case QEvent::MouseButtonDblClick: - widgetMouseDoubleClickEvent((QMouseEvent *)e); + widgetMouseDoubleClickEvent( ( QMouseEvent * )event ); break; case QEvent::MouseMove: - widgetMouseMoveEvent((QMouseEvent *)e); + widgetMouseMoveEvent( ( QMouseEvent * )event ); break; case QEvent::KeyPress: - widgetKeyPressEvent((QKeyEvent *)e); + widgetKeyPressEvent( ( QKeyEvent * )event ); break; case QEvent::KeyRelease: - widgetKeyReleaseEvent((QKeyEvent *)e); + widgetKeyReleaseEvent( ( QKeyEvent * )event ); break; case QEvent::Wheel: - widgetWheelEvent((QWheelEvent *)e); + widgetWheelEvent( ( QWheelEvent * )event ); break; default: break; @@ -912,50 +856,67 @@ bool QwtPicker::eventFilter(QObject *o, QEvent *e) /*! Handle a mouse press event for the observed widget. - Begin and/or end a selection depending on the selection flags. + \param mouseEvent Mouse event - \sa QwtPicker, selectionFlags() \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() */ -void QwtPicker::widgetMousePressEvent(QMouseEvent *e) +void QwtPicker::widgetMousePressEvent( QMouseEvent *mouseEvent ) { - transition(e); + transition( mouseEvent ); } /*! Handle a mouse move event for the observed widget. - Move the last point of the selection in case of isActive() == true + \param mouseEvent Mouse event \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() */ -void QwtPicker::widgetMouseMoveEvent(QMouseEvent *e) +void QwtPicker::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) { - if ( pickRect().contains(e->pos()) ) - d_data->trackerPosition = e->pos(); + if ( pickRect().contains( mouseEvent->pos() ) ) + d_data->trackerPosition = mouseEvent->pos(); else - d_data->trackerPosition = QPoint(-1, -1); + d_data->trackerPosition = QPoint( -1, -1 ); if ( !isActive() ) updateDisplay(); - transition(e); + transition( mouseEvent ); +} + +/*! + Handle a enter event for the observed widget. + + \param event Qt event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetEnterEvent( QEvent *event ) +{ + transition( event ); } /*! Handle a leave event for the observed widget. + \param event Qt event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() */ -void QwtPicker::widgetLeaveEvent(QEvent *) +void QwtPicker::widgetLeaveEvent( QEvent *event ) { - d_data->trackerPosition = QPoint(-1, -1); + transition( event ); + + d_data->trackerPosition = QPoint( -1, -1 ); if ( !isActive() ) updateDisplay(); } @@ -963,52 +924,53 @@ void QwtPicker::widgetLeaveEvent(QEvent *) /*! Handle a mouse relase event for the observed widget. - End a selection depending on the selection flags. + \param mouseEvent Mouse event - \sa QwtPicker, selectionFlags() - \sa eventFilter(), widgetMousePressEvent(), + \sa eventFilter(), widgetMousePressEvent(), widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() */ -void QwtPicker::widgetMouseReleaseEvent(QMouseEvent *e) +void QwtPicker::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) { - transition(e); + transition( mouseEvent ); } /*! Handle mouse double click event for the observed widget. - Empty implementation, does nothing. + \param mouseEvent Mouse event \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() */ -void QwtPicker::widgetMouseDoubleClickEvent(QMouseEvent *me) +void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent *mouseEvent ) { - transition(me); + transition( mouseEvent ); } - + /*! Handle a wheel event for the observed widget. Move the last point of the selection in case of isActive() == true + \param wheelEvent Wheel event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() */ -void QwtPicker::widgetWheelEvent(QWheelEvent *e) +void QwtPicker::widgetWheelEvent( QWheelEvent *wheelEvent ) { - if ( pickRect().contains(e->pos()) ) - d_data->trackerPosition = e->pos(); + if ( pickRect().contains( wheelEvent->pos() ) ) + d_data->trackerPosition = wheelEvent->pos(); else - d_data->trackerPosition = QPoint(-1, -1); + d_data->trackerPosition = QPoint( -1, -1 ); updateDisplay(); - transition(e); + transition( wheelEvent ); } /*! @@ -1018,101 +980,105 @@ void QwtPicker::widgetWheelEvent(QWheelEvent *e) move the cursor, the abort key aborts a selection. All other keys are handled by the current state machine. - \sa QwtPicker, selectionFlags() + \param keyEvent Key event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyReleaseEvent(), stateMachine(), QwtEventPattern::KeyPatternCode */ -void QwtPicker::widgetKeyPressEvent(QKeyEvent *ke) +void QwtPicker::widgetKeyPressEvent( QKeyEvent *keyEvent ) { int dx = 0; int dy = 0; int offset = 1; - if ( ke->isAutoRepeat() ) + if ( keyEvent->isAutoRepeat() ) offset = 5; - if ( keyMatch(KeyLeft, ke) ) + if ( keyMatch( KeyLeft, keyEvent ) ) dx = -offset; - else if ( keyMatch(KeyRight, ke) ) + else if ( keyMatch( KeyRight, keyEvent ) ) dx = offset; - else if ( keyMatch(KeyUp, ke) ) + else if ( keyMatch( KeyUp, keyEvent ) ) dy = -offset; - else if ( keyMatch(KeyDown, ke) ) + else if ( keyMatch( KeyDown, keyEvent ) ) dy = offset; - else if ( keyMatch(KeyAbort, ke) ) + else if ( keyMatch( KeyAbort, keyEvent ) ) { reset(); } else - transition(ke); + transition( keyEvent ); if ( dx != 0 || dy != 0 ) { const QRect rect = pickRect(); - const QPoint pos = parentWidget()->mapFromGlobal(QCursor::pos()); + const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() ); int x = pos.x() + dx; - x = qwtMax(rect.left(), x); - x = qwtMin(rect.right(), x); + x = qMax( rect.left(), x ); + x = qMin( rect.right(), x ); int y = pos.y() + dy; - y = qwtMax(rect.top(), y); - y = qwtMin(rect.bottom(), y); + y = qMax( rect.top(), y ); + y = qMin( rect.bottom(), y ); - QCursor::setPos(parentWidget()->mapToGlobal(QPoint(x, y))); + QCursor::setPos( parentWidget()->mapToGlobal( QPoint( x, y ) ) ); } } - + /*! Handle a key release event for the observed widget. Passes the event to the state machine. + \param keyEvent Key event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent(), stateMachine() */ -void QwtPicker::widgetKeyReleaseEvent(QKeyEvent *ke) +void QwtPicker::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) { - transition(ke); + transition( keyEvent ); } /*! - Passes an event to the state machine and executes the resulting + Passes an event to the state machine and executes the resulting commands. Append and Move commands use the current position of the cursor (QCursor::pos()). - \param e Event + \param event Event */ -void QwtPicker::transition(const QEvent *e) +void QwtPicker::transition( const QEvent *event ) { if ( !d_data->stateMachine ) return; - QwtPickerMachine::CommandList commandList = - d_data->stateMachine->transition(*this, e); + const QList commandList = + d_data->stateMachine->transition( *this, event ); QPoint pos; - switch(e->type()) + switch ( event->type() ) { case QEvent::MouseButtonDblClick: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { - const QMouseEvent *me = (QMouseEvent *)e; + const QMouseEvent *me = + static_cast< const QMouseEvent * >( event ); pos = me->pos(); break; } default: - pos = parentWidget()->mapFromGlobal(QCursor::pos()); + pos = parentWidget()->mapFromGlobal( QCursor::pos() ); } - for ( uint i = 0; i < (uint)commandList.count(); i++ ) + for ( int i = 0; i < commandList.count(); i++ ) { - switch(commandList[i]) + switch ( commandList[i] ) { case QwtPickerMachine::Begin: { @@ -1121,12 +1087,17 @@ void QwtPicker::transition(const QEvent *e) } case QwtPickerMachine::Append: { - append(pos); + append( pos ); break; } case QwtPickerMachine::Move: { - move(pos); + move( pos ); + break; + } + case QwtPickerMachine::Remove: + { + remove(); break; } case QwtPickerMachine::End: @@ -1148,51 +1119,53 @@ void QwtPicker::begin() if ( d_data->isActive ) return; - d_data->selection.resize(0); + d_data->pickedPoints.resize( 0 ); d_data->isActive = true; + Q_EMIT activated( true ); if ( trackerMode() != AlwaysOff ) { - if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) + if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) { QWidget *w = parentWidget(); if ( w ) - d_data->trackerPosition = w->mapFromGlobal(QCursor::pos()); + d_data->trackerPosition = w->mapFromGlobal( QCursor::pos() ); } } updateDisplay(); - setMouseTracking(true); + setMouseTracking( true ); } /*! \brief Close a selection setting the state to inactive. - The selection is validated and maybe fixed by QwtPicker::accept(). + The selection is validated and maybe fixed by accept(). \param ok If true, complete the selection and emit a selected signal otherwise discard the selection. \return true if the selection is accepted, false otherwise \sa isActive(), begin(), append(), move(), selected(), accept() */ -bool QwtPicker::end(bool ok) +bool QwtPicker::end( bool ok ) { if ( d_data->isActive ) { - setMouseTracking(false); + setMouseTracking( false ); d_data->isActive = false; + Q_EMIT activated( false ); if ( trackerMode() == ActiveOnly ) - d_data->trackerPosition = QPoint(-1, -1); + d_data->trackerPosition = QPoint( -1, -1 ); if ( ok ) - ok = accept(d_data->selection); + ok = accept( d_data->pickedPoints ); if ( ok ) - emit selected(d_data->selection); + Q_EMIT selected( d_data->pickedPoints ); else - d_data->selection.resize(0); + d_data->pickedPoints.resize( 0 ); updateDisplay(); } @@ -1210,8 +1183,8 @@ void QwtPicker::reset() if ( d_data->stateMachine ) d_data->stateMachine->reset(); - if (isActive()) - end(false); + if ( isActive() ) + end( false ); } /*! @@ -1222,17 +1195,16 @@ void QwtPicker::reset() \sa isActive(), begin(), end(), move(), appended() */ -void QwtPicker::append(const QPoint &pos) +void QwtPicker::append( const QPoint &pos ) { if ( d_data->isActive ) { - const int idx = d_data->selection.count(); - d_data->selection.resize(idx + 1); - d_data->selection[idx] = pos; + const int idx = d_data->pickedPoints.count(); + d_data->pickedPoints.resize( idx + 1 ); + d_data->pickedPoints[idx] = pos; updateDisplay(); - - emit appended(pos); + Q_EMIT appended( pos ); } } @@ -1242,29 +1214,60 @@ void QwtPicker::append(const QPoint &pos) \param pos New position \sa isActive(), begin(), end(), append() - */ -void QwtPicker::move(const QPoint &pos) +void QwtPicker::move( const QPoint &pos ) { if ( d_data->isActive ) { - const int idx = d_data->selection.count() - 1; + const int idx = d_data->pickedPoints.count() - 1; if ( idx >= 0 ) { - if ( d_data->selection[idx] != pos ) + if ( d_data->pickedPoints[idx] != pos ) { - d_data->selection[idx] = pos; + d_data->pickedPoints[idx] = pos; updateDisplay(); - - emit moved(pos); + Q_EMIT moved( pos ); } } } } -bool QwtPicker::accept(QwtPolygon &) const +/*! + Remove the last point of the selection + The removed() signal is emitted. + + \sa isActive(), begin(), end(), append(), move() +*/ +void QwtPicker::remove() { + if ( d_data->isActive ) + { + const int idx = d_data->pickedPoints.count() - 1; + if ( idx > 0 ) + { + const int idx = d_data->pickedPoints.count(); + + const QPoint pos = d_data->pickedPoints[idx - 1]; + d_data->pickedPoints.resize( idx - 1 ); + + updateDisplay(); + Q_EMIT removed( pos ); + } + } +} + +/*! + \brief Validate and fixup the selection + + Accepts all selections unmodified + + \param selection Selection to validate and fixup + \return true, when accepted, false otherwise +*/ +bool QwtPicker::accept( QPolygon &selection ) const +{ + Q_UNUSED( selection ); return true; } @@ -1272,15 +1275,19 @@ bool QwtPicker::accept(QwtPolygon &) const A picker is active between begin() and end(). \return true if the selection is active. */ -bool QwtPicker::isActive() const +bool QwtPicker::isActive() const { return d_data->isActive; } -//! Return Selected points -const QwtPolygon &QwtPicker::selection() const +/*! + Return the points, that have been collected so far. The selection() + is calculated from the pickedPoints() in adjustedPoints(). + \return Picked points +*/ +const QPolygon &QwtPicker::pickedPoints() const { - return d_data->selection; + return d_data->pickedPoints; } /*! @@ -1292,27 +1299,27 @@ const QwtPolygon &QwtPicker::selection() const \sa ResizeMode, setResizeMode(), resizeMode() */ -void QwtPicker::stretchSelection(const QSize &oldSize, const QSize &newSize) +void QwtPicker::stretchSelection( const QSize &oldSize, const QSize &newSize ) { if ( oldSize.isEmpty() ) { - // avoid division by zero. But scaling for small sizes also + // avoid division by zero. But scaling for small sizes also // doesn't make much sense, because of rounding losses. TODO ... return; } const double xRatio = - double(newSize.width()) / double(oldSize.width()); + double( newSize.width() ) / double( oldSize.width() ); const double yRatio = - double(newSize.height()) / double(oldSize.height()); + double( newSize.height() ) / double( oldSize.height() ); - for ( int i = 0; i < int(d_data->selection.count()); i++ ) + for ( int i = 0; i < int( d_data->pickedPoints.count() ); i++ ) { - QPoint &p = d_data->selection[i]; - p.setX(qRound(p.x() * xRatio)); - p.setY(qRound(p.y() * yRatio)); + QPoint &p = d_data->pickedPoints[i]; + p.setX( qRound( p.x() * xRatio ) ); + p.setY( qRound( p.y() * yRatio ) ); - emit changed(d_data->selection); + Q_EMIT changed( d_data->pickedPoints ); } } @@ -1329,7 +1336,7 @@ void QwtPicker::stretchSelection(const QSize &oldSize, const QSize &newSize) be restored. */ -void QwtPicker::setMouseTracking(bool enable) +void QwtPicker::setMouseTracking( bool enable ) { QWidget *widget = parentWidget(); if ( !widget ) @@ -1338,33 +1345,26 @@ void QwtPicker::setMouseTracking(bool enable) if ( enable ) { d_data->mouseTracking = widget->hasMouseTracking(); - widget->setMouseTracking(true); + widget->setMouseTracking( true ); } else { - widget->setMouseTracking(d_data->mouseTracking); + widget->setMouseTracking( d_data->mouseTracking ); } } /*! Find the area of the observed widget, where selection might happen. - \return QFrame::contentsRect() if it is a QFrame, QWidget::rect() otherwise. + \return parentWidget()->contentsRect() */ QRect QwtPicker::pickRect() const { - QRect rect; - const QWidget *widget = parentWidget(); - if ( !widget ) - return rect; + if ( widget ) + return widget->contentsRect(); - if ( widget->inherits("QFrame") ) - rect = ((QFrame *)widget)->contentsRect(); - else - rect = widget->rect(); - - return rect; + return QRect(); } //! Update the state of rubberband and tracker label @@ -1383,24 +1383,20 @@ void QwtPicker::updateDisplay() } if ( trackerMode() == AlwaysOn || - (trackerMode() == ActiveOnly && isActive() ) ) + ( trackerMode() == ActiveOnly && isActive() ) ) { if ( trackerPen() != Qt::NoPen ) showTracker = true; } } -#if QT_VERSION < 0x040000 - QGuardedPtr &rw = d_data->rubberBandWidget; -#else QPointer &rw = d_data->rubberBandWidget; -#endif if ( showRubberband ) { if ( rw.isNull() ) { - rw = new PickerWidget( this, w, PickerWidget::RubberBand); - rw->resize(w->size()); + rw = new PickerWidget( this, w, PickerWidget::RubberBand ); + rw->resize( w->size() ); } rw->updateMask(); rw->update(); // Needed, when the mask doesn't change @@ -1408,18 +1404,15 @@ void QwtPicker::updateDisplay() else delete rw; -#if QT_VERSION < 0x040000 - QGuardedPtr &tw = d_data->trackerWidget; -#else QPointer &tw = d_data->trackerWidget; -#endif if ( showTracker ) { if ( tw.isNull() ) { - tw = new PickerWidget( this, w, PickerWidget::Text); - tw->resize(w->size()); + tw = new PickerWidget( this, w, PickerWidget::Text ); + tw->resize( w->size() ); } + tw->setFont( d_data->trackerFont ); tw->updateMask(); tw->update(); // Needed, when the mask doesn't change } @@ -1438,4 +1431,3 @@ const QWidget *QwtPicker::trackerWidget() const { return d_data->trackerWidget; } - diff --git a/qwt/src/qwt_picker.h b/qwt/src/qwt_picker.h index ef1edc867..c0b22dcdf 100644 --- a/qwt/src/qwt_picker.h +++ b/qwt/src/qwt_picker.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,14 +10,13 @@ #ifndef QWT_PICKER #define QWT_PICKER 1 +#include "qwt_global.h" +#include "qwt_text.h" +#include "qwt_event_pattern.h" #include #include #include #include -#include "qwt_global.h" -#include "qwt_text.h" -#include "qwt_polygon.h" -#include "qwt_event_pattern.h" class QWidget; class QMouseEvent; @@ -28,41 +27,55 @@ class QwtPickerMachine; /*! \brief QwtPicker provides selections on a widget - QwtPicker filters all mouse and keyboard events of a widget - and translates them into an array of selected points. Depending - on the QwtPicker::SelectionType the selection might be a single point, - a rectangle or a polygon. The selection process is supported by - optional rubberbands (rubberband selection) and position trackers. + QwtPicker filters all enter, leave, mouse and keyboard events of a widget + and translates them into an array of selected points. - QwtPicker is useful for widgets where the event handlers - can't be overloaded, like for components of composite widgets. - It offers alternative handlers for mouse and key events. + The way how the points are collected depends on type of state machine + that is connected to the picker. Qwt offers a couple of predefined + state machines for selecting: - \par Example + - Nothing\n + QwtPickerTrackerMachine + - Single points\n + QwtPickerClickPointMachine, QwtPickerDragPointMachine + - Rectangles\n + QwtPickerClickRectMachine, QwtPickerDragRectMachine + - Polygons\n + QwtPickerPolygonMachine + + While these state machines cover the most common ways to collect points + it is also possible to implement individual machines as well. + + QwtPicker translates the picked points into a selection using the + adjustedPoints method. adjustedPoints is intended to be reimplemented + to fixup the selection according to application specific requirements. + (F.e. when an application accepts rectangles of a fixed aspect ratio only.) + + Optionally QwtPicker support the process of collecting points by a + rubberband and tracker displaying a text for the current mouse + position. + + \par Example \verbatim #include +#include QwtPicker *picker = new QwtPicker(widget); +picker->setStateMachine(new QwtPickerDragRectMachine); picker->setTrackerMode(QwtPicker::ActiveOnly); -connect(picker, SIGNAL(selected(const QwtPolygon &)), ...); - -// emit the position of clicks on widget -picker->setSelectionFlags(QwtPicker::PointSelection | QwtPicker::ClickSelection); - - ... - -// now select rectangles -picker->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); picker->setRubberBand(QwtPicker::RectRubberBand); \endverbatim\n - The selection process uses the commands begin(), append(), move() and end(). - append() adds a new point to the selection, move() changes the position of - the latest point. + The state machine triggers the following commands: - The commands are initiated from a small state machine (QwtPickerMachine) - that translates mouse and key events. There are a couple of predefined - state machines for point, rect and polygon selections. The selectionFlags() - control which one should be used. It is possible to use other machines - by overloading stateMachine(). + - begin()\n + Activate/Initialize the selection. + - append()\n + Add a new point + - move() \n + Change the position of the last point. + - remove()\n + Remove the last point. + - end()\n + Terminate the selection and call accept to validate the picked points. The picker is active (isActive()), between begin() and end(). In active state the rubberband is displayed, and the tracker is visible @@ -73,7 +86,7 @@ picker->setRubberBand(QwtPicker::RectRubberBand); \endverbatim\n \warning In case of QWidget::NoFocus the focus policy of the observed widget is set to QWidget::WheelFocus and mouse tracking - will be manipulated for ClickSelection while the picker is active, + will be manipulated while the picker is active, or if trackerMode() is AlwayOn. */ @@ -81,220 +94,158 @@ class QWT_EXPORT QwtPicker: public QObject, public QwtEventPattern { Q_OBJECT - Q_ENUMS(RubberBand) - Q_ENUMS(DisplayMode) - Q_ENUMS(ResizeMode) + Q_ENUMS( RubberBand ) + Q_ENUMS( DisplayMode ) + Q_ENUMS( ResizeMode ) - Q_PROPERTY(int selectionFlags READ selectionFlags WRITE setSelectionFlags) - Q_PROPERTY(DisplayMode trackerMode READ trackerMode WRITE setTrackerMode) - Q_PROPERTY(QFont trackerFont READ trackerFont WRITE setTrackerFont) - Q_PROPERTY(RubberBand rubberBand READ rubberBand WRITE setRubberBand) - Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode) - Q_PROPERTY(bool isEnabled READ isEnabled WRITE setEnabled) + Q_PROPERTY( bool isEnabled READ isEnabled WRITE setEnabled ) + Q_PROPERTY( ResizeMode resizeMode READ resizeMode WRITE setResizeMode ) - Q_PROPERTY(QPen trackerPen READ trackerPen WRITE setTrackerPen) - Q_PROPERTY(QPen rubberBandPen READ rubberBandPen WRITE setRubberBandPen) + Q_PROPERTY( DisplayMode trackerMode READ trackerMode WRITE setTrackerMode ) + Q_PROPERTY( QPen trackerPen READ trackerPen WRITE setTrackerPen ) + Q_PROPERTY( QFont trackerFont READ trackerFont WRITE setTrackerFont ) + + Q_PROPERTY( RubberBand rubberBand READ rubberBand WRITE setRubberBand ) + Q_PROPERTY( QPen rubberBandPen READ rubberBandPen WRITE setRubberBandPen ) public: - /*! - This enum type describes the type of a selection. It can be or'd - with QwtPicker::RectSelectionType and QwtPicker::SelectionMode - and passed to QwtPicker::setSelectionFlags() - - NoSelection\n - Selection is disabled. Note this is different to the disabled - state, as you might have a tracker. - - PointSelection\n - Select a single point. - - RectSelection\n - Select a rectangle. - - PolygonSelection\n - Select a polygon. - - The default value is NoSelection. - \sa QwtPicker::setSelectionFlags(), QwtPicker::selectionFlags() - */ - - enum SelectionType - { - NoSelection = 0, - PointSelection = 1, - RectSelection = 2, - PolygonSelection = 4 - }; - - /*! - \brief Selection subtype for RectSelection - This enum type describes the type of rectangle selections. - It can be or'd with QwtPicker::RectSelectionType and - QwtPicker::SelectionMode and passed to QwtPicker::setSelectionFlags(). - - CornerToCorner\n - The first and the second selected point are the corners - of the rectangle. - - CenterToCorner\n - The first point is the center, the second a corner of the - rectangle. - - CenterToRadius\n - The first point is the center of a quadrat, calculated by the maximum - of the x- and y-distance. - - The default value is CornerToCorner. - \sa QwtPicker::setSelectionFlags(), QwtPicker::selectionFlags() - */ - enum RectSelectionType - { - CornerToCorner = 64, - CenterToCorner = 128, - CenterToRadius = 256 - }; - - /*! - Values of this enum type or'd together with a SelectionType value - identifies which state machine should be used for the selection. - - The default value is ClickSelection. - \sa stateMachine() - */ - enum SelectionMode - { - ClickSelection = 1024, - DragSelection = 2048 - }; - - /*! + /*! Rubberband style - - NoRubberBand\n - No rubberband. - - HLineRubberBand & PointSelection\n - A horizontal line. - - VLineRubberBand & PointSelection\n - A vertical line. - - CrossRubberBand & PointSelection\n - A horizontal and a vertical line. - - RectRubberBand & RectSelection\n - A rectangle. - - EllipseRubberBand & RectSelection\n - An ellipse. - - PolygonRubberBand &PolygonSelection\n - A polygon. - - UserRubberBand\n - Values >= UserRubberBand can be used to define additional - rubber bands. - The default value is NoRubberBand. - \sa QwtPicker::setRubberBand(), QwtPicker::rubberBand() + The default value is QwtPicker::NoRubberBand. + \sa setRubberBand(), rubberBand() */ enum RubberBand { + //! No rubberband. NoRubberBand = 0, - // Point + //! A horizontal line ( only for QwtPicker::PointSelection ) HLineRubberBand, + + //! A vertical line ( only for QwtPicker::PointSelection ) VLineRubberBand, + + //! A crosshair ( only for QwtPicker::PointSelection ) CrossRubberBand, - // Rect + //! A rectangle ( only for QwtPicker::RectSelection ) RectRubberBand, + + //! An ellipse ( only for QwtPicker::RectSelection ) EllipseRubberBand, - // Polygon + //! A polygon ( only for QwtPicker::&PolygonSelection ) PolygonRubberBand, + /*! + Values >= UserRubberBand can be used to define additional + rubber bands. + */ UserRubberBand = 100 }; - /*! - - AlwaysOff\n - Display never. - - AlwaysOn\n - Display always. - - ActiveOnly\n - Display only when the selection is active. - - \sa QwtPicker::setTrackerMode(), QwtPicker::trackerMode(), - QwtPicker::isActive() + /*! + \brief Display mode + \sa setTrackerMode(), trackerMode(), isActive() */ enum DisplayMode { + //! Display never AlwaysOff, + + //! Display always AlwaysOn, + + //! Display only when the selection is active ActiveOnly }; - /*! + /*! Controls what to do with the selected points of an active selection when the observed widget is resized. - - Stretch\n - All points are scaled according to the new size, - - KeepSize\n - All points remain unchanged. - The default value is Stretch. - \sa QwtPicker::setResizeMode(), QwtPicker::resize() + The default value is QwtPicker::Stretch. + \sa setResizeMode() */ enum ResizeMode { + //! All points are scaled according to the new size, Stretch, + + //! All points remain unchanged. KeepSize }; - explicit QwtPicker(QWidget *parent); - explicit QwtPicker(int selectionFlags, RubberBand rubberBand, - DisplayMode trackerMode, QWidget *); + explicit QwtPicker( QWidget *parent ); + explicit QwtPicker( RubberBand rubberBand, + DisplayMode trackerMode, QWidget * ); virtual ~QwtPicker(); - virtual void setSelectionFlags(int); - int selectionFlags() const; + void setStateMachine( QwtPickerMachine * ); + const QwtPickerMachine *stateMachine() const; + QwtPickerMachine *stateMachine(); - virtual void setRubberBand(RubberBand); + void setRubberBand( RubberBand ); RubberBand rubberBand() const; - virtual void setTrackerMode(DisplayMode); + void setTrackerMode( DisplayMode ); DisplayMode trackerMode() const; - virtual void setResizeMode(ResizeMode); + void setResizeMode( ResizeMode ); ResizeMode resizeMode() const; - virtual void setRubberBandPen(const QPen &); + void setRubberBandPen( const QPen & ); QPen rubberBandPen() const; - virtual void setTrackerPen(const QPen &); + void setTrackerPen( const QPen & ); QPen trackerPen() const; - virtual void setTrackerFont(const QFont &); + void setTrackerFont( const QFont & ); QFont trackerFont() const; bool isEnabled() const; - virtual void setEnabled(bool); - bool isActive() const; - virtual bool eventFilter(QObject *, QEvent *); + virtual bool eventFilter( QObject *, QEvent * ); QWidget *parentWidget(); const QWidget *parentWidget() const; virtual QRect pickRect() const; - const QwtPolygon &selection() const; - virtual void drawRubberBand(QPainter *) const; - virtual void drawTracker(QPainter *) const; + virtual void drawRubberBand( QPainter * ) const; + virtual void drawTracker( QPainter * ) const; - virtual QwtText trackerText(const QPoint &pos) const; + virtual QwtText trackerText( const QPoint &pos ) const; QPoint trackerPosition() const; - QRect trackerRect(const QFont &) const; + virtual QRect trackerRect( const QFont & ) const; + QPolygon selection() const; -signals: +public Q_SLOTS: + void setEnabled( bool ); + +Q_SIGNALS: /*! - A signal emitting the selected points, + A signal indicating, when the picker has been activated. + Together with setEnabled() it can be used to implement + selections with more than one picker. + + \param on True, when the picker has been activated + */ + void activated( bool on ); + + /*! + A signal emitting the selected points, at the end of a selection. - \param pa Selected points + \param polygon Selected points */ - void selected(const QwtPolygon &pa); + void selected( const QPolygon &polygon ); /*! A signal emitted when a point has been appended to the selection @@ -302,75 +253,75 @@ signals: \param pos Position of the appended point. \sa append(). moved() */ - void appended(const QPoint &pos); + void appended( const QPoint &pos ); /*! - A signal emitted whenever the last appended point of the + A signal emitted whenever the last appended point of the selection has been moved. \param pos Position of the moved last point of the selection. \sa move(), appended() */ - void moved(const QPoint &pos); + void moved( const QPoint &pos ); + /*! + A signal emitted whenever the last appended point of the + selection has been removed. + + \sa remove(), appended() + */ + void removed( const QPoint &pos ); /*! A signal emitted when the active selection has been changed. This might happen when the observed widget is resized. - \param pa Changed selection + \param selection Changed selection \sa stretchSelection() */ - void changed(const QwtPolygon &pa); + void changed( const QPolygon &selection ); protected: - /*! - \brief Validate and fixup the selection + virtual QPolygon adjustedPoints( const QPolygon & ) const; - Accepts all selections unmodified - - \param selection Selection to validate and fixup - \return true, when accepted, false otherwise - */ - virtual bool accept(QwtPolygon &selection) const; - - virtual void transition(const QEvent *); + virtual void transition( const QEvent * ); virtual void begin(); - virtual void append(const QPoint &); - virtual void move(const QPoint &); - virtual bool end(bool ok = true); + virtual void append( const QPoint & ); + virtual void move( const QPoint & ); + virtual void remove(); + virtual bool end( bool ok = true ); + virtual bool accept( QPolygon & ) const; virtual void reset(); - virtual void widgetMousePressEvent(QMouseEvent *); - virtual void widgetMouseReleaseEvent(QMouseEvent *); - virtual void widgetMouseDoubleClickEvent(QMouseEvent *); - virtual void widgetMouseMoveEvent(QMouseEvent *); - virtual void widgetWheelEvent(QWheelEvent *); - virtual void widgetKeyPressEvent(QKeyEvent *); - virtual void widgetKeyReleaseEvent(QKeyEvent *); - virtual void widgetLeaveEvent(QEvent *); + virtual void widgetMousePressEvent( QMouseEvent * ); + virtual void widgetMouseReleaseEvent( QMouseEvent * ); + virtual void widgetMouseDoubleClickEvent( QMouseEvent * ); + virtual void widgetMouseMoveEvent( QMouseEvent * ); + virtual void widgetWheelEvent( QWheelEvent * ); + virtual void widgetKeyPressEvent( QKeyEvent * ); + virtual void widgetKeyReleaseEvent( QKeyEvent * ); + virtual void widgetEnterEvent( QEvent * ); + virtual void widgetLeaveEvent( QEvent * ); - virtual void stretchSelection(const QSize &oldSize, - const QSize &newSize); - - virtual QwtPickerMachine *stateMachine(int) const; + virtual void stretchSelection( const QSize &oldSize, + const QSize &newSize ); virtual void updateDisplay(); const QWidget *rubberBandWidget() const; const QWidget *trackerWidget() const; -private: - void init(QWidget *, int selectionFlags, RubberBand rubberBand, - DisplayMode trackerMode); + const QPolygon &pickedPoints() const; - void setStateMachine(QwtPickerMachine *); - void setMouseTracking(bool); +private: + void init( QWidget *, RubberBand rubberBand, DisplayMode trackerMode ); + + void setMouseTracking( bool ); class PickerWidget; class PrivateData; PrivateData *d_data; }; - + #endif diff --git a/qwt/src/qwt_picker_machine.cpp b/qwt/src/qwt_picker_machine.cpp index ac4edc3b2..97d890ec1 100644 --- a/qwt/src/qwt_picker_machine.cpp +++ b/qwt/src/qwt_picker_machine.cpp @@ -7,13 +7,14 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -#include -#include "qwt_event_pattern.h" #include "qwt_picker_machine.h" +#include "qwt_event_pattern.h" +#include //! Constructor -QwtPickerMachine::QwtPickerMachine(): - d_state(0) +QwtPickerMachine::QwtPickerMachine( SelectionType type ): + d_selectionType( type ), + d_state( 0 ) { } @@ -22,6 +23,12 @@ QwtPickerMachine::~QwtPickerMachine() { } +//! Return the selection type +QwtPickerMachine::SelectionType QwtPickerMachine::selectionType() const +{ + return d_selectionType; +} + //! Return the current state int QwtPickerMachine::state() const { @@ -29,29 +36,77 @@ int QwtPickerMachine::state() const } //! Change the current state -void QwtPickerMachine::setState(int state) +void QwtPickerMachine::setState( int state ) { d_state = state; } //! Set the current state to 0. -void QwtPickerMachine::reset() +void QwtPickerMachine::reset() +{ + setState( 0 ); +} + +//! Constructor +QwtPickerTrackerMachine::QwtPickerTrackerMachine(): + QwtPickerMachine( NoSelection ) { - setState(0); } //! Transition -QwtPickerMachine::CommandList QwtPickerClickPointMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *e) -{ - QwtPickerMachine::CommandList cmdList; +QList QwtPickerTrackerMachine::transition( + const QwtEventPattern &, const QEvent *e ) +{ + QList cmdList; - switch(e->type()) + switch ( e->type() ) + { + case QEvent::Enter: + case QEvent::MouseMove: + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + setState( 1 ); + } + else + { + cmdList += Move; + } + break; + } + case QEvent::Leave: + { + cmdList += Remove; + cmdList += End; + setState( 0 ); + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerClickPointMachine::QwtPickerClickPointMachine(): + QwtPickerMachine( PointSelection ) +{ +} + +//! Transition +QList QwtPickerClickPointMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *e ) +{ + QList cmdList; + + switch ( e->type() ) { case QEvent::MouseButtonPress: { if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect1, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect1, ( const QMouseEvent * )e ) ) { cmdList += Begin; cmdList += Append; @@ -60,14 +115,14 @@ QwtPickerMachine::CommandList QwtPickerClickPointMachine::transition( break; } case QEvent::KeyPress: - { + { if ( eventPattern.keyMatch( - QwtEventPattern::KeySelect1, (const QKeyEvent *)e) ) + QwtEventPattern::KeySelect1, ( const QKeyEvent * )e ) ) { cmdList += Begin; cmdList += Append; cmdList += End; - } + } break; } default: @@ -77,24 +132,30 @@ QwtPickerMachine::CommandList QwtPickerClickPointMachine::transition( return cmdList; } -//! Transition -QwtPickerMachine::CommandList QwtPickerDragPointMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *e) -{ - QwtPickerMachine::CommandList cmdList; +//! Constructor +QwtPickerDragPointMachine::QwtPickerDragPointMachine(): + QwtPickerMachine( PointSelection ) +{ +} - switch(e->type()) +//! Transition +QList QwtPickerDragPointMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *e ) +{ + QList cmdList; + + switch ( e->type() ) { case QEvent::MouseButtonPress: { if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect1, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect1, ( const QMouseEvent * )e ) ) { if ( state() == 0 ) { cmdList += Begin; cmdList += Append; - setState(1); + setState( 1 ); } } break; @@ -111,25 +172,25 @@ QwtPickerMachine::CommandList QwtPickerDragPointMachine::transition( if ( state() != 0 ) { cmdList += End; - setState(0); + setState( 0 ); } break; } case QEvent::KeyPress: { if ( eventPattern.keyMatch( - QwtEventPattern::KeySelect1, (const QKeyEvent *)e) ) + QwtEventPattern::KeySelect1, ( const QKeyEvent * )e ) ) { if ( state() == 0 ) { cmdList += Begin; cmdList += Append; - setState(1); + setState( 1 ); } else { cmdList += End; - setState(0); + setState( 0 ); } } break; @@ -141,37 +202,43 @@ QwtPickerMachine::CommandList QwtPickerDragPointMachine::transition( return cmdList; } -//! Transition -QwtPickerMachine::CommandList QwtPickerClickRectMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *e) -{ - QwtPickerMachine::CommandList cmdList; +//! Constructor +QwtPickerClickRectMachine::QwtPickerClickRectMachine(): + QwtPickerMachine( RectSelection ) +{ +} - switch(e->type()) +//! Transition +QList QwtPickerClickRectMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *e ) +{ + QList cmdList; + + switch ( e->type() ) { case QEvent::MouseButtonPress: { if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect1, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect1, ( const QMouseEvent * )e ) ) { - switch(state()) + switch ( state() ) { case 0: - { + { cmdList += Begin; cmdList += Append; - setState(1); + setState( 1 ); break; } case 1: { // Uh, strange we missed the MouseButtonRelease - break; + break; } default: { cmdList += End; - setState(0); + setState( 0 ); } } } @@ -186,41 +253,41 @@ QwtPickerMachine::CommandList QwtPickerClickRectMachine::transition( case QEvent::MouseButtonRelease: { if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect1, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect1, ( const QMouseEvent * )e ) ) { if ( state() == 1 ) { cmdList += Append; - setState(2); + setState( 2 ); } } break; } case QEvent::KeyPress: - { + { if ( eventPattern.keyMatch( - QwtEventPattern::KeySelect1, (const QKeyEvent *)e) ) + QwtEventPattern::KeySelect1, ( const QKeyEvent * )e ) ) { if ( state() == 0 ) { cmdList += Begin; cmdList += Append; - setState(1); + setState( 1 ); } else { if ( state() == 1 ) { cmdList += Append; - setState(2); + setState( 2 ); } else if ( state() == 2 ) { cmdList += End; - setState(0); + setState( 0 ); } } - } + } break; } default: @@ -230,25 +297,31 @@ QwtPickerMachine::CommandList QwtPickerClickRectMachine::transition( return cmdList; } -//! Transition -QwtPickerMachine::CommandList QwtPickerDragRectMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *e) -{ - QwtPickerMachine::CommandList cmdList; +//! Constructor +QwtPickerDragRectMachine::QwtPickerDragRectMachine(): + QwtPickerMachine( RectSelection ) +{ +} - switch(e->type()) +//! Transition +QList QwtPickerDragRectMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *e ) +{ + QList cmdList; + + switch ( e->type() ) { case QEvent::MouseButtonPress: { if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect1, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect1, ( const QMouseEvent * )e ) ) { if ( state() == 0 ) { cmdList += Begin; cmdList += Append; cmdList += Append; - setState(2); + setState( 2 ); } } break; @@ -265,26 +338,26 @@ QwtPickerMachine::CommandList QwtPickerDragRectMachine::transition( if ( state() == 2 ) { cmdList += End; - setState(0); + setState( 0 ); } break; } case QEvent::KeyPress: { if ( eventPattern.keyMatch( - QwtEventPattern::KeySelect1, (const QKeyEvent *)e) ) + QwtEventPattern::KeySelect1, ( const QKeyEvent * )e ) ) { if ( state() == 0 ) { cmdList += Begin; cmdList += Append; cmdList += Append; - setState(2); + setState( 2 ); } else { cmdList += End; - setState(0); + setState( 0 ); } } break; @@ -296,36 +369,42 @@ QwtPickerMachine::CommandList QwtPickerDragRectMachine::transition( return cmdList; } -//! Transition -QwtPickerMachine::CommandList QwtPickerPolygonMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *e) +//! Constructor +QwtPickerPolygonMachine::QwtPickerPolygonMachine(): + QwtPickerMachine( PolygonSelection ) { - QwtPickerMachine::CommandList cmdList; +} - switch(e->type()) +//! Transition +QList QwtPickerPolygonMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *e ) +{ + QList cmdList; + + switch ( e->type() ) { case QEvent::MouseButtonPress: { if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect1, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect1, ( const QMouseEvent * )e ) ) { - if (state() == 0) + if ( state() == 0 ) { cmdList += Begin; cmdList += Append; cmdList += Append; - setState(1); + setState( 1 ); } else { cmdList += End; - setState(0); + setState( 0 ); } } if ( eventPattern.mouseMatch( - QwtEventPattern::MouseSelect2, (const QMouseEvent *)e) ) + QwtEventPattern::MouseSelect2, ( const QMouseEvent * )e ) ) { - if (state() == 1) + if ( state() == 1 ) cmdList += Append; } break; @@ -340,23 +419,23 @@ QwtPickerMachine::CommandList QwtPickerPolygonMachine::transition( case QEvent::KeyPress: { if ( eventPattern.keyMatch( - QwtEventPattern::KeySelect1, (const QKeyEvent *)e) ) + QwtEventPattern::KeySelect1, ( const QKeyEvent * )e ) ) { if ( state() == 0 ) { cmdList += Begin; cmdList += Append; cmdList += Append; - setState(1); + setState( 1 ); } else { cmdList += End; - setState(0); + setState( 0 ); } } else if ( eventPattern.keyMatch( - QwtEventPattern::KeySelect2, (const QKeyEvent *)e) ) + QwtEventPattern::KeySelect2, ( const QKeyEvent * )e ) ) { if ( state() == 1 ) cmdList += Append; diff --git a/qwt/src/qwt_picker_machine.h b/qwt/src/qwt_picker_machine.h index aadda004d..8527115de 100644 --- a/qwt/src/qwt_picker_machine.h +++ b/qwt/src/qwt_picker_machine.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -11,11 +11,7 @@ #define QWT_PICKER_MACHINE 1 #include "qwt_global.h" -#if QT_VERSION < 0x040000 -#include -#else #include -#endif class QEvent; class QwtEventPattern; @@ -24,7 +20,7 @@ class QwtEventPattern; \brief A state machine for QwtPicker selections QwtPickerMachine accepts key and mouse events and translates them - into selection commands. + into selection commands. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ @@ -32,42 +28,73 @@ class QwtEventPattern; class QWT_EXPORT QwtPickerMachine { public: - //! Commands - the output of the state machine + /*! + Type of a selection. + \sa selectionType() + */ + enum SelectionType + { + //! The state machine not usable for any type of selection. + NoSelection = -1, + + //! The state machine is for selecting a single point. + PointSelection, + + //! The state machine is for selecting a rectangle (2 points). + RectSelection, + + //! The state machine is for selecting a polygon (many points). + PolygonSelection + }; + + //! Commands - the output of a state machine enum Command { Begin, Append, Move, + Remove, End }; -#if QT_VERSION < 0x040000 - typedef QValueList CommandList; -#else - typedef QList CommandList; -#endif - + QwtPickerMachine( SelectionType ); virtual ~QwtPickerMachine(); //! Transition - virtual CommandList transition( - const QwtEventPattern &, const QEvent *) = 0; - void reset(); + virtual QList transition( + const QwtEventPattern &, const QEvent * ) = 0; + void reset(); int state() const; - void setState(int); + void setState( int ); -protected: - QwtPickerMachine(); + SelectionType selectionType() const; private: + const SelectionType d_selectionType; int d_state; }; +/*! + \brief A state machine for indicating mouse movements + + QwtPickerTrackerMachine supports displaying information + corresponding to mouse movements, but is not intended for + selecting anything. Begin/End are related to Enter/Leave events. +*/ +class QWT_EXPORT QwtPickerTrackerMachine: public QwtPickerMachine +{ +public: + QwtPickerTrackerMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + /*! \brief A state machine for point selections - Pressing QwtEventPattern::MouseSelect1 or + Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 selects a point. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode @@ -75,22 +102,26 @@ private: class QWT_EXPORT QwtPickerClickPointMachine: public QwtPickerMachine { public: - virtual CommandList transition( - const QwtEventPattern &, const QEvent *); + QwtPickerClickPointMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); }; /*! \brief A state machine for point selections - Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 - starts the selection, releasing QwtEventPattern::MouseSelect1 or + Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 + starts the selection, releasing QwtEventPattern::MouseSelect1 or a second press of QwtEventPattern::KeySelect1 terminates it. */ class QWT_EXPORT QwtPickerDragPointMachine: public QwtPickerMachine { public: - virtual CommandList transition( - const QwtEventPattern &, const QEvent *); + QwtPickerDragPointMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); }; /*! @@ -99,9 +130,9 @@ public: Pressing QwtEventPattern::MouseSelect1 starts the selection, releasing it selects the first point. Pressing it again selects the second point and terminates the selection. - Pressing QwtEventPattern::KeySelect1 also starts the - selection, a second press selects the first point. A third one selects - the second point and terminates the selection. + Pressing QwtEventPattern::KeySelect1 also starts the + selection, a second press selects the first point. A third one selects + the second point and terminates the selection. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ @@ -109,8 +140,10 @@ public: class QWT_EXPORT QwtPickerClickRectMachine: public QwtPickerMachine { public: - virtual CommandList transition( - const QwtEventPattern &, const QEvent *); + QwtPickerClickRectMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); }; /*! @@ -118,8 +151,8 @@ public: Pressing QwtEventPattern::MouseSelect1 selects the first point, releasing it the second point. - Pressing QwtEventPattern::KeySelect1 also selects the - first point, a second press selects the second point and terminates + Pressing QwtEventPattern::KeySelect1 also selects the + first point, a second press selects the second point and terminates the selection. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode @@ -128,16 +161,18 @@ public: class QWT_EXPORT QwtPickerDragRectMachine: public QwtPickerMachine { public: - virtual CommandList transition( - const QwtEventPattern &, const QEvent *); + QwtPickerDragRectMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); }; /*! \brief A state machine for polygon selections - Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 - starts the selection and selects the first point, or appends a point. - Pressing QwtEventPattern::MouseSelect2 or QwtEventPattern::KeySelect2 + Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 + starts the selection and selects the first point, or appends a point. + Pressing QwtEventPattern::MouseSelect2 or QwtEventPattern::KeySelect2 appends the last point and terminates the selection. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode @@ -146,8 +181,10 @@ public: class QWT_EXPORT QwtPickerPolygonMachine: public QwtPickerMachine { public: - virtual CommandList transition( - const QwtEventPattern &, const QEvent *); + QwtPickerPolygonMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); }; #endif diff --git a/qwt/src/qwt_plot.cpp b/qwt/src/qwt_plot.cpp index 508ee7d1e..467223f2f 100644 --- a/qwt/src/qwt_plot.cpp +++ b/qwt/src/qwt_plot.cpp @@ -7,16 +7,6 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -#include -#if QT_VERSION < 0x040000 -#include -#include -#else -#include -#include -#endif -#include -#include #include "qwt_plot.h" #include "qwt_plot_dict.h" #include "qwt_plot_layout.h" @@ -26,20 +16,18 @@ #include "qwt_legend.h" #include "qwt_dyngrid_layout.h" #include "qwt_plot_canvas.h" -#include "qwt_paint_buffer.h" +#include +#include +#include +#include +#include class QwtPlot::PrivateData { public: -#if QT_VERSION < 0x040000 - QGuardedPtr lblTitle; - QGuardedPtr canvas; - QGuardedPtr legend; -#else QPointer lblTitle; QPointer canvas; QPointer legend; -#endif QwtPlotLayout *layout; bool autoReplot; @@ -49,10 +37,10 @@ public: \brief Constructor \param parent Parent widget */ -QwtPlot::QwtPlot(QWidget *parent): - QFrame(parent) +QwtPlot::QwtPlot( QWidget *parent ): + QFrame( parent ) { - initPlot(QwtText()); + initPlot( QwtText() ); } /*! @@ -60,30 +48,16 @@ QwtPlot::QwtPlot(QWidget *parent): \param title Title text \param parent Parent widget */ -QwtPlot::QwtPlot(const QwtText &title, QWidget *parent): - QFrame(parent) +QwtPlot::QwtPlot( const QwtText &title, QWidget *parent ): + QFrame( parent ) { - initPlot(title); + initPlot( title ); } -#if QT_VERSION < 0x040000 -/*! - \brief Constructor - \param parent Parent widget - \param name Object name - */ -QwtPlot::QwtPlot(QWidget *parent, const char *name): - QFrame(parent, name) -{ - initPlot(QwtText()); -} -#endif - - //! Destructor QwtPlot::~QwtPlot() { - detachItems(QwtPlotItem::Rtti_PlotItem, autoDelete()); + detachItems( QwtPlotItem::Rtti_PlotItem, autoDelete() ); delete d_data->layout; deleteAxesData(); @@ -94,75 +68,63 @@ QwtPlot::~QwtPlot() \brief Initializes a QwtPlot instance \param title Title text */ -void QwtPlot::initPlot(const QwtText &title) +void QwtPlot::initPlot( const QwtText &title ) { d_data = new PrivateData; -#if QT_VERSION < 0x040000 - setWFlags(Qt::WNoAutoErase); -#endif - d_data->layout = new QwtPlotLayout; - d_data->autoReplot = false; - d_data->lblTitle = new QwtTextLabel(title, this); - d_data->lblTitle->setFont(QFont(fontInfo().family(), 14, QFont::Bold)); + d_data->lblTitle = new QwtTextLabel( title, this ); + d_data->lblTitle->setObjectName( "QwtPlotTitle" ); - QwtText text(title); - int flags = Qt::AlignCenter; -#if QT_VERSION < 0x040000 - flags |= Qt::WordBreak | Qt::ExpandTabs; -#else - flags |= Qt::TextWordWrap; -#endif - text.setRenderFlags(flags); - d_data->lblTitle->setText(text); + d_data->lblTitle->setFont( QFont( fontInfo().family(), 14, QFont::Bold ) ); + + QwtText text( title ); + text.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap ); + d_data->lblTitle->setText( text ); d_data->legend = NULL; initAxesData(); - d_data->canvas = new QwtPlotCanvas(this); - d_data->canvas->setFrameStyle(QFrame::Panel|QFrame::Sunken); - d_data->canvas->setLineWidth(2); - d_data->canvas->setMidLineWidth(0); + d_data->canvas = new QwtPlotCanvas( this ); + d_data->canvas->setObjectName( "QwtPlotCanvas" ); + d_data->canvas->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + d_data->canvas->setLineWidth( 2 ); updateTabOrder(); - setSizePolicy(QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding); + setSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding ); + + resize( 200, 200 ); } /*! \brief Adds handling of layout requests + \param event Event */ -bool QwtPlot::event(QEvent *e) +bool QwtPlot::event( QEvent *event ) { - bool ok = QFrame::event(e); - switch(e->type()) + bool ok = QFrame::event( event ); + switch ( event->type() ) { -#if QT_VERSION < 0x040000 - case QEvent::LayoutHint: -#else case QEvent::LayoutRequest: -#endif updateLayout(); break; -#if QT_VERSION >= 0x040000 case QEvent::PolishRequest: - polish(); + replot(); break; -#endif default:; } return ok; } -//! Replots the plot if QwtPlot::autoReplot() is \c true. +//! Replots the plot if autoReplot() is \c true. void QwtPlot::autoRefresh() { - if (d_data->autoReplot) + if ( d_data->autoReplot ) replot(); } @@ -181,26 +143,29 @@ void QwtPlot::autoRefresh() \param tf \c true or \c false. Defaults to \c true. \sa replot() */ -void QwtPlot::setAutoReplot(bool tf) +void QwtPlot::setAutoReplot( bool tf ) { d_data->autoReplot = tf; } -//! \return true if the autoReplot option is set. +/*! + \return true if the autoReplot option is set. + \sa setAutoReplot() +*/ bool QwtPlot::autoReplot() const { - return d_data->autoReplot; + return d_data->autoReplot; } /*! Change the plot's title \param title New title */ -void QwtPlot::setTitle(const QString &title) +void QwtPlot::setTitle( const QString &title ) { if ( title != d_data->lblTitle->text().text() ) { - d_data->lblTitle->setText(title); + d_data->lblTitle->setText( title ); updateLayout(); } } @@ -209,11 +174,11 @@ void QwtPlot::setTitle(const QString &title) Change the plot's title \param title New title */ -void QwtPlot::setTitle(const QwtText &title) +void QwtPlot::setTitle( const QwtText &title ) { if ( title != d_data->lblTitle->text() ) { - d_data->lblTitle->setText(title); + d_data->lblTitle->setText( title ); updateLayout(); } } @@ -255,47 +220,37 @@ const QwtTextLabel *QwtPlot::titleLabel() const \sa insertLegend() */ QwtLegend *QwtPlot::legend() -{ +{ return d_data->legend; -} +} /*! \return the plot's legend \sa insertLegend() */ const QwtLegend *QwtPlot::legend() const -{ +{ return d_data->legend; -} +} /*! \return the plot's canvas */ QwtPlotCanvas *QwtPlot::canvas() -{ +{ return d_data->canvas; -} +} /*! \return the plot's canvas */ const QwtPlotCanvas *QwtPlot::canvas() const -{ +{ return d_data->canvas; } -//! Polish -void QwtPlot::polish() -{ - replot(); - -#if QT_VERSION < 0x040000 - QFrame::polish(); -#endif -} - -/*! +/*! Return sizeHint \sa minimumSizeHint() */ @@ -306,33 +261,33 @@ QSize QwtPlot::sizeHint() const int dh = 0; for ( int axisId = 0; axisId < axisCnt; axisId++ ) { - if ( axisEnabled(axisId) ) - { + if ( axisEnabled( axisId ) ) + { const int niceDist = 40; - const QwtScaleWidget *scaleWidget = axisWidget(axisId); + const QwtScaleWidget *scaleWidget = axisWidget( axisId ); const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv(); - const int majCnt = scaleDiv.ticks(QwtScaleDiv::MajorTick).count(); + const int majCnt = scaleDiv.ticks( QwtScaleDiv::MajorTick ).count(); if ( axisId == yLeft || axisId == yRight || axisId == yLeft1 || axisId == yRight1 || axisId == yLeft2 || axisId == yRight2 || axisId == yLeft3 || axisId == yRight3 ) { - int hDiff = (majCnt - 1) * niceDist + int hDiff = ( majCnt - 1 ) * niceDist - scaleWidget->minimumSizeHint().height(); if ( hDiff > dh ) dh = hDiff; } else { - int wDiff = (majCnt - 1) * niceDist + int wDiff = ( majCnt - 1 ) * niceDist - scaleWidget->minimumSizeHint().width(); if ( wDiff > dw ) dw = wDiff; } } } - return minimumSizeHint() + QSize(dw, dh); + return minimumSizeHint() + QSize( dw, dh ); } /*! @@ -340,19 +295,19 @@ QSize QwtPlot::sizeHint() const */ QSize QwtPlot::minimumSizeHint() const { - QSize hint = d_data->layout->minimumSizeHint(this); - hint += QSize(2 * frameWidth(), 2 * frameWidth()); + QSize hint = d_data->layout->minimumSizeHint( this ); + hint += QSize( 2 * frameWidth(), 2 * frameWidth() ); return hint; } -/*! +/*! Resize and update internal layout \param e Resize event */ -void QwtPlot::resizeEvent(QResizeEvent *e) +void QwtPlot::resizeEvent( QResizeEvent *e ) { - QFrame::resizeEvent(e); + QFrame::resizeEvent( e ); updateLayout(); } @@ -369,7 +324,7 @@ void QwtPlot::resizeEvent(QResizeEvent *e) void QwtPlot::replot() { bool doAutoReplot = autoReplot(); - setAutoReplot(false); + setAutoReplot( false ); updateAxes(); @@ -378,15 +333,11 @@ void QwtPlot::replot() axes labels. We need to process them here before painting to avoid that scales and canvas get out of sync. */ -#if QT_VERSION >= 0x040000 - QApplication::sendPostedEvents(this, QEvent::LayoutRequest); -#else - QApplication::sendPostedEvents(this, QEvent::LayoutHint); -#endif + QApplication::sendPostedEvents( this, QEvent::LayoutRequest ); d_data->canvas->replot(); - setAutoReplot(doAutoReplot); + setAutoReplot( doAutoReplot ); } /*! @@ -395,73 +346,84 @@ void QwtPlot::replot() */ void QwtPlot::updateLayout() { - d_data->layout->activate(this, contentsRect()); + d_data->layout->activate( this, contentsRect() ); + + QRect titleRect = d_data->layout->titleRect().toRect(); + QRect scaleRect[QwtPlot::axisCnt]; + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + scaleRect[axisId] = d_data->layout->scaleRect( axisId ).toRect(); + QRect legendRect = d_data->layout->legendRect().toRect(); + QRect canvasRect = d_data->layout->canvasRect().toRect(); // // resize and show the visible widgets // - if (!d_data->lblTitle->text().isEmpty()) + if ( !d_data->lblTitle->text().isEmpty() ) { - d_data->lblTitle->setGeometry(d_data->layout->titleRect()); - if (!d_data->lblTitle->isVisible()) + d_data->lblTitle->setGeometry( titleRect ); + if ( !d_data->lblTitle->isVisibleTo( this ) ) d_data->lblTitle->show(); } else d_data->lblTitle->hide(); - for (int axisId = 0; axisId < axisCnt; axisId++ ) + for ( int axisId = 0; axisId < axisCnt; axisId++ ) { - if (axisEnabled(axisId) ) + if ( axisEnabled( axisId ) ) { - axisWidget(axisId)->setGeometry(d_data->layout->scaleRect(axisId)); + axisWidget( axisId )->setGeometry( scaleRect[axisId] ); if ( axisId == xBottom || axisId == xTop ) { - QRegion r(d_data->layout->scaleRect(axisId)); - if ( axisEnabled(yLeft) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft))); - if ( axisEnabled(yLeft1) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft1))); - if ( axisEnabled(yLeft2) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft2))); - if ( axisEnabled(yLeft3) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft3))); - if ( axisEnabled(yRight) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yRight))); - if ( axisEnabled(yRight1) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yRight1))); - if ( axisEnabled(yRight2) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yRight2))); - if ( axisEnabled(yRight3) ) - r = r.subtract(QRegion(d_data->layout->scaleRect(yRight3))); - r.translate(-d_data->layout->scaleRect(axisId).x(), - -d_data->layout->scaleRect(axisId).y()); + QRegion r( scaleRect[axisId] ); + if ( axisEnabled( yLeft ) ) + r = r.subtract( QRegion( scaleRect[yLeft] ) ); - axisWidget(axisId)->setMask(r); + if ( axisEnabled( yLeft1 ) ) + r = r.subtract( QRegion( scaleRect[yLeft1] ) ); + if ( axisEnabled( yLeft2 ) ) + r = r.subtract( QRegion( scaleRect[yLeft2] ) ); + if ( axisEnabled( yLeft3 ) ) + r = r.subtract( QRegion( scaleRect[yLeft3] ) ); + + if ( axisEnabled( yRight ) ) + r = r.subtract( QRegion( scaleRect[yRight] ) ); + + if ( axisEnabled( yRight1 ) ) + r = r.subtract( QRegion( scaleRect[yRight1] ) ); + if ( axisEnabled( yRight2 ) ) + r = r.subtract( QRegion( scaleRect[yRight2] ) ); + if ( axisEnabled( yRight3 ) ) + r = r.subtract( QRegion( scaleRect[yRight3] ) ); + + r.translate( -d_data->layout->scaleRect( axisId ).x(), + -scaleRect[axisId].y() ); + + axisWidget( axisId )->setMask( r ); } - if (!axisWidget(axisId)->isVisible()) - axisWidget(axisId)->show(); + if ( !axisWidget( axisId )->isVisibleTo( this ) ) + axisWidget( axisId )->show(); } else - axisWidget(axisId)->hide(); + axisWidget( axisId )->hide(); } - if ( d_data->legend && + if ( d_data->legend && d_data->layout->legendPosition() != ExternalLegend ) { - if (d_data->legend->itemCount() > 0) + if ( d_data->legend->itemCount() > 0 ) { - d_data->legend->setGeometry(d_data->layout->legendRect()); + d_data->legend->setGeometry( legendRect ); d_data->legend->show(); } else d_data->legend->hide(); } - d_data->canvas->setGeometry(d_data->layout->canvasRect()); + d_data->canvas->setGeometry( canvasRect ); } -/*! +/*! Update the focus tab order The order is changed so that the canvas will be in front of the @@ -471,44 +433,31 @@ void QwtPlot::updateLayout() void QwtPlot::updateTabOrder() { -#if QT_VERSION >= 0x040000 - using namespace Qt; // QWidget::NoFocus/Qt::NoFocus -#else - if ( d_data->canvas->focusPolicy() == NoFocus ) + if ( d_data->canvas->focusPolicy() == Qt::NoFocus ) return; -#endif - if ( d_data->legend.isNull() + if ( d_data->legend.isNull() || d_data->layout->legendPosition() == ExternalLegend || d_data->legend->legendItems().count() == 0 ) { return; } - // Depending on the position of the legend the + // Depending on the position of the legend the // tab order will be changed that the canvas is // next to the last legend item, or before - // the first one. + // the first one. - const bool canvasFirst = + const bool canvasFirst = d_data->layout->legendPosition() == QwtPlot::BottomLegend || d_data->layout->legendPosition() == QwtPlot::RightLegend; - QWidget *previous = NULL; + QWidget *previous = NULL; - QWidget *w; -#if QT_VERSION >= 0x040000 - w = d_data->canvas; + QWidget *w = d_data->canvas; while ( ( w = w->nextInFocusChain() ) != d_data->canvas ) -#else - if ( focusData() == NULL ) - return; - - while ( focusData()->next() != d_data->canvas ); - while ( (w = focusData()->next()) != d_data->canvas ) -#endif { bool isLegendItem = false; - if ( w->focusPolicy() != NoFocus + if ( w->focusPolicy() != Qt::NoFocus && w->parent() && w->parent() == d_data->legend->contentsWidget() ) { isLegendItem = true; @@ -533,11 +482,11 @@ void QwtPlot::updateTabOrder() } } - if ( previous && previous != d_data->canvas) - setTabOrder(previous, d_data->canvas); + if ( previous && previous != d_data->canvas ) + setTabOrder( previous, d_data->canvas ); } -/*! +/*! Redraw the canvas. \param painter Painter used for drawing @@ -546,27 +495,24 @@ void QwtPlot::updateTabOrder() plot items better overload drawItems() \sa drawItems() */ -void QwtPlot::drawCanvas(QPainter *painter) +void QwtPlot::drawCanvas( QPainter *painter ) { QwtScaleMap maps[axisCnt]; for ( int axisId = 0; axisId < axisCnt; axisId++ ) - maps[axisId] = canvasMap(axisId); + maps[axisId] = canvasMap( axisId ); - drawItems(painter, - d_data->canvas->contentsRect(), maps, QwtPlotPrintFilter()); + drawItems( painter, d_data->canvas->contentsRect(), maps ); } -/*! +/*! Redraw the canvas items. \param painter Painter used for drawing - \param rect Bounding rectangle where to paint + \param canvasRect Bounding rectangle where to paint \param map QwtPlot::axisCnt maps, mapping between plot and paint device coordinates - \param pfilter Plot print filter */ -void QwtPlot::drawItems(QPainter *painter, const QRect &rect, - const QwtScaleMap map[axisCnt], - const QwtPlotPrintFilter &pfilter) const +void QwtPlot::drawItems( QPainter *painter, const QRectF &canvasRect, + const QwtScaleMap map[axisCnt] ) const { const QwtPlotItemList& itmList = itemList(); for ( QwtPlotItemIterator it = itmList.begin(); @@ -575,22 +521,14 @@ void QwtPlot::drawItems(QPainter *painter, const QRect &rect, QwtPlotItem *item = *it; if ( item && item->isVisible() ) { - if ( !(pfilter.options() & QwtPlotPrintFilter::PrintGrid) - && item->rtti() == QwtPlotItem::Rtti_PlotGrid ) - { - continue; - } - painter->save(); -#if QT_VERSION >= 0x040000 - painter->setRenderHint(QPainter::Antialiasing, - item->testRenderHint(QwtPlotItem::RenderAntialiased) ); -#endif + painter->setRenderHint( QPainter::Antialiasing, + item->testRenderHint( QwtPlotItem::RenderAntialiased ) ); - item->draw(painter, + item->draw( painter, map[item->xAxis()], map[item->yAxis()], - rect); + canvasRect ); painter->restore(); } @@ -602,149 +540,117 @@ void QwtPlot::drawItems(QPainter *painter, const QRect &rect, \return Map for the axis on the canvas. With this map pixel coordinates can translated to plot coordinates and vice versa. \sa QwtScaleMap, transform(), invTransform() - + */ -QwtScaleMap QwtPlot::canvasMap(int axisId) const +QwtScaleMap QwtPlot::canvasMap( int axisId ) const { QwtScaleMap map; if ( !d_data->canvas ) return map; - map.setTransformation(axisScaleEngine(axisId)->transformation()); + map.setTransformation( axisScaleEngine( axisId )->transformation() ); - const QwtScaleDiv *sd = axisScaleDiv(axisId); - map.setScaleInterval(sd->lowerBound(), sd->upperBound()); + const QwtScaleDiv *sd = axisScaleDiv( axisId ); + map.setScaleInterval( sd->lowerBound(), sd->upperBound() ); - if ( axisEnabled(axisId) ) + if ( axisEnabled( axisId ) ) { - const QwtScaleWidget *s = axisWidget(axisId); + const QwtScaleWidget *s = axisWidget( axisId ); if ( axisId == yLeft || axisId == yRight || axisId == yLeft1 || axisId == yRight1 || axisId == yLeft2 || axisId == yRight2 || axisId == yLeft3 || axisId == yRight3 ) { - int y = s->y() + s->startBorderDist() - d_data->canvas->y(); - int h = s->height() - s->startBorderDist() - s->endBorderDist(); - map.setPaintInterval(y + h, y); + double y = s->y() + s->startBorderDist() - d_data->canvas->y(); + double h = s->height() - s->startBorderDist() - s->endBorderDist(); + map.setPaintInterval( y + h, y ); } else { - int x = s->x() + s->startBorderDist() - d_data->canvas->x(); - int w = s->width() - s->startBorderDist() - s->endBorderDist(); - map.setPaintInterval(x, x + w); + double x = s->x() + s->startBorderDist() - d_data->canvas->x(); + double w = s->width() - s->startBorderDist() - s->endBorderDist(); + map.setPaintInterval( x, x + w ); } } else { - const int margin = plotLayout()->canvasMargin(axisId); + int margin = 0; + if ( !plotLayout()->alignCanvasToScales() ) + margin = plotLayout()->canvasMargin( axisId ); const QRect &canvasRect = d_data->canvas->contentsRect(); - if ( axisId == yLeft || axisId == yRight || axisId == yLeft1 || axisId == yRight1 || axisId == yLeft2 || axisId == yRight2 || axisId == yLeft3 || axisId == yRight3 ) { - map.setPaintInterval(canvasRect.bottom() - margin, - canvasRect.top() + margin); + map.setPaintInterval( canvasRect.bottom() - margin, + canvasRect.top() + margin ); } else { - map.setPaintInterval(canvasRect.left() + margin, - canvasRect.right() - margin); + map.setPaintInterval( canvasRect.left() + margin, + canvasRect.right() - margin ); } } return map; } -/*! - Change the margin of the plot. The margin is the space - around all components. - - \param margin new margin - \sa QwtPlotLayout::setMargin(), margin(), plotLayout() -*/ -void QwtPlot::setMargin(int margin) -{ - if ( margin < 0 ) - margin = 0; - - if ( margin != d_data->layout->margin() ) - { - d_data->layout->setMargin(margin); - updateLayout(); - } -} - -/*! - \return margin - \sa setMargin(), QwtPlotLayout::margin(), plotLayout() -*/ -int QwtPlot::margin() const -{ - return d_data->layout->margin(); -} - /*! \brief Change the background of the plotting area - - Sets c to QColorGroup::Background of all colorgroups of + + Sets brush to QPalette::Window of all colorgroups of the palette of the canvas. Using canvas()->setPalette() is a more powerful way to set these colors. - \param c new background color + + \param brush New background brush + \sa canvasBackground() */ -void QwtPlot::setCanvasBackground(const QColor &c) +void QwtPlot::setCanvasBackground( const QBrush &brush ) { - QPalette p = d_data->canvas->palette(); + QPalette pal = d_data->canvas->palette(); for ( int i = 0; i < QPalette::NColorGroups; i++ ) - { -#if QT_VERSION < 0x040000 - p.setColor((QPalette::ColorGroup)i, QColorGroup::Background, c); -#else - p.setColor((QPalette::ColorGroup)i, QPalette::Background, c); -#endif - } + pal.setBrush( ( QPalette::ColorGroup )i, QPalette::Window, brush ); - canvas()->setPalette(p); + canvas()->setPalette( pal ); } /*! - Nothing else than: canvas()->palette().color( - QPalette::Normal, QColorGroup::Background); - - \return the background color of the plotting area. + Nothing else than: canvas()->palette().brush( + QPalette::Normal, QPalette::Window); + + \return Background brush of the plotting area. + \sa setCanvasBackground() */ -const QColor & QwtPlot::canvasBackground() const +QBrush QwtPlot::canvasBackground() const { -#if QT_VERSION < 0x040000 - return canvas()->palette().color( - QPalette::Normal, QColorGroup::Background); -#else - return canvas()->palette().color( - QPalette::Normal, QPalette::Background); -#endif + return canvas()->palette().brush( + QPalette::Normal, QPalette::Window ); } /*! \brief Change the border width of the plotting area - Nothing else than canvas()->setLineWidth(w), + + Nothing else than canvas()->setLineWidth(w), left for compatibility only. - \param w new border width + + \param width New border width */ -void QwtPlot::setCanvasLineWidth(int w) +void QwtPlot::setCanvasLineWidth( int width ) { - canvas()->setLineWidth(w); + canvas()->setLineWidth( width ); updateLayout(); } - -/*! - Nothing else than: canvas()->lineWidth(), + +/*! + Nothing else than: canvas()->lineWidth(), left for compatibility only. + \return the border width of the plotting area */ int QwtPlot::canvasLineWidth() const -{ +{ return canvas()->lineWidth(); } @@ -752,9 +658,9 @@ int QwtPlot::canvasLineWidth() const \return \c true if the specified axis exists, otherwise \c false \param axisId axis index */ -bool QwtPlot::axisValid(int axisId) +bool QwtPlot::axisValid( int axisId ) { - return ((axisId >= QwtPlot::yLeft) && (axisId < QwtPlot::axisCnt)); + return ( ( axisId >= QwtPlot::yLeft ) && ( axisId < QwtPlot::axisCnt ) ); } /*! @@ -765,10 +671,10 @@ void QwtPlot::legendItemClicked() { if ( d_data->legend && sender()->isWidgetType() ) { - QwtPlotItem *plotItem = - (QwtPlotItem*)d_data->legend->find((QWidget *)sender()); + QwtPlotItem *plotItem = + ( QwtPlotItem* )d_data->legend->find( ( QWidget * )sender() ); if ( plotItem ) - emit legendClicked(plotItem); + Q_EMIT legendClicked( plotItem ); } } @@ -776,43 +682,33 @@ void QwtPlot::legendItemClicked() Called internally when the legend has been checked Emits a legendClicked() signal. */ -void QwtPlot::legendItemChecked(bool on) +void QwtPlot::legendItemChecked( bool on ) { if ( d_data->legend && sender()->isWidgetType() ) { - QwtPlotItem *plotItem = - (QwtPlotItem*)d_data->legend->find((QWidget *)sender()); + QwtPlotItem *plotItem = + ( QwtPlotItem* )d_data->legend->find( ( QWidget * )sender() ); if ( plotItem ) - emit legendChecked(plotItem, on); + Q_EMIT legendChecked( plotItem, on ); } } -/*! - Remove all curves and markers - \deprecated Use QwtPlotDeict::detachItems instead -*/ -void QwtPlot::clear() -{ - detachItems(QwtPlotItem::Rtti_PlotCurve); - detachItems(QwtPlotItem::Rtti_PlotMarker); -} - /*! \brief Insert a legend If the position legend is \c QwtPlot::LeftLegend or \c QwtPlot::RightLegend - the legend will be organized in one column from top to down. - Otherwise the legend items will be placed in a table + the legend will be organized in one column from top to down. + Otherwise the legend items will be placed in a table with a best fit number of columns from left to right. - If pos != QwtPlot::ExternalLegend the plot widget will become - parent of the legend. It will be deleted when the plot is deleted, + If pos != QwtPlot::ExternalLegend the plot widget will become + parent of the legend. It will be deleted when the plot is deleted, or another legend is set with insertLegend(). - + \param legend Legend \param pos The legend's position. For top/left position the number of colums will be limited to 1, otherwise it will be set to - unlimited. + unlimited. \param ratio Ratio between legend and the bounding rect of title, canvas and axes. The legend will be shrinked @@ -821,13 +717,13 @@ void QwtPlot::clear() it will be reset to the default ratio. The default vertical/horizontal ratio is 0.33/0.5. - \sa legend(), QwtPlotLayout::legendPosition(), + \sa legend(), QwtPlotLayout::legendPosition(), QwtPlotLayout::setLegendPosition() */ -void QwtPlot::insertLegend(QwtLegend *legend, - QwtPlot::LegendPosition pos, double ratio) +void QwtPlot::insertLegend( QwtLegend *legend, + QwtPlot::LegendPosition pos, double ratio ) { - d_data->layout->setLegendPosition(pos, ratio); + d_data->layout->setLegendPosition( pos, ratio ); if ( legend != d_data->legend ) { @@ -841,35 +737,29 @@ void QwtPlot::insertLegend(QwtLegend *legend, if ( pos != ExternalLegend ) { if ( d_data->legend->parent() != this ) - { -#if QT_VERSION < 0x040000 - d_data->legend->reparent(this, QPoint(0, 0)); -#else - d_data->legend->setParent(this); -#endif - } + d_data->legend->setParent( this ); } const QwtPlotItemList& itmList = itemList(); for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); ++it ) { - (*it)->updateLegend(d_data->legend); + ( *it )->updateLegend( d_data->legend ); } - QLayout *l = d_data->legend->contentsWidget()->layout(); - if ( l && l->inherits("QwtDynGridLayout") ) + QwtDynGridLayout *tl = qobject_cast( + d_data->legend->contentsWidget()->layout() ); + if ( tl ) { - QwtDynGridLayout *tl = (QwtDynGridLayout *)l; - switch(d_data->layout->legendPosition()) + switch ( d_data->layout->legendPosition() ) { case LeftLegend: case RightLegend: - tl->setMaxCols(1); // 1 column: align vertical + tl->setMaxCols( 1 ); // 1 column: align vertical break; case TopLegend: case BottomLegend: - tl->setMaxCols(0); // unlimited + tl->setMaxCols( 0 ); // unlimited break; case ExternalLegend: break; diff --git a/qwt/src/qwt_plot.h b/qwt/src/qwt_plot.h index 0db472b80..211a8b00e 100644 --- a/qwt/src/qwt_plot.h +++ b/qwt/src/qwt_plot.h @@ -10,13 +10,12 @@ #ifndef QWT_PLOT_H #define QWT_PLOT_H -#include #include "qwt_global.h" -#include "qwt_array.h" #include "qwt_text.h" #include "qwt_plot_dict.h" #include "qwt_scale_map.h" -#include "qwt_plot_printfilter.h" +#include "qwt_interval.h" +#include class QwtPlotLayout; class QwtLegend; @@ -26,20 +25,19 @@ class QwtScaleDiv; class QwtScaleDraw; class QwtTextLabel; class QwtPlotCanvas; -class QwtPlotPrintFilter; /*! \brief A 2-D plotting widget QwtPlot is a widget for plotting two-dimensional graphs. - An unlimited number of plot items can be displayed on - its canvas. Plot items might be curves (QwtPlotCurve), markers - (QwtPlotMarker), the grid (QwtPlotGrid), or anything else derived + An unlimited number of plot items can be displayed on + its canvas. Plot items might be curves (QwtPlotCurve), markers + (QwtPlotMarker), the grid (QwtPlotGrid), or anything else derived from QwtPlotItem. A plot can have up to four axes, with each plot item attached to an x- and a y axis. The scales at the axes can be explicitely set (QwtScaleDiv), or - are calculated from the plot items, using algorithms (QwtScaleEngine) which - can be configured separately for each axis. + are calculated from the plot items, using algorithms (QwtScaleEngine) which + can be configured separately for each axis. \image html plot.png @@ -72,96 +70,87 @@ myPlot->replot(); class QWT_EXPORT QwtPlot: public QFrame, public QwtPlotDict { Q_OBJECT - Q_PROPERTY( QString propertiesDocument + Q_PROPERTY( QString propertiesDocument READ grabProperties WRITE applyProperties ) public: - /*! - Axis index + //! \brief Axis index + enum Axis + { + //! Y axis left of the canvas + yLeft, - - yLeft\n - - yRight\n - - xBottom\n - - xTop\n - */ - enum Axis - { - yLeft, - yLeft1, - yLeft2, - yLeft3, - yRight, - yRight1, - yRight2, - yRight3, - xBottom, - xTop, - axisCnt + yLeft1, + yLeft2, + yLeft3, + + //! Y axis right of the canvas + yRight, + + yRight1, + yRight2, + yRight3, + + //! X axis below the canvas + xBottom, + + //! X axis above the canvas + xTop, + + //! Number of axes + axisCnt }; - /*! + /*! Position of the legend, relative to the canvas. - - LeftLegend\n - The legend will be left from the yLeft axis. - - RightLegend\n - The legend will be right from the yLeft axis. - - BottomLegend\n - The legend will be right below the xBottom axis. - - TopLegend\n - The legend will be between xTop axis and the title. - - ExternalLegend\n - External means that only the content of the legend - will be handled by QwtPlot, but not its geometry. - This might be interesting if an application wants to - have a legend in an external window ( or on the canvas ). - - \note In case of ExternalLegend, the legend is not - printed by print(). - \sa insertLegend() + \note In case of ExternalLegend, the legend is not + handled by QwtPlotRenderer */ - enum LegendPosition + enum LegendPosition { + //! The legend will be left from the QwtPlot::yLeft axis. LeftLegend, + + //! The legend will be right from the QwtPlot::yRight axis. RightLegend, + + //! The legend will be below QwtPlot::xBottom axis. BottomLegend, + + //! The legend will be between QwtPlot::xTop axis and the title. TopLegend, - + + /*! + External means that only the content of the legend + will be handled by QwtPlot, but not its geometry. + This type can be used to have a legend in an + external window ( or on the canvas ). + */ ExternalLegend }; - explicit QwtPlot(QWidget * = NULL); - explicit QwtPlot(const QwtText &title, QWidget *p = NULL); -#if QT_VERSION < 0x040000 - explicit QwtPlot(QWidget *, const char* name); -#endif + explicit QwtPlot( QWidget * = NULL ); + explicit QwtPlot( const QwtText &title, QWidget *p = NULL ); virtual ~QwtPlot(); - void applyProperties(const QString &); + void applyProperties( const QString & ); QString grabProperties() const; - void setAutoReplot(bool tf = true); + void setAutoReplot( bool tf = true ); bool autoReplot() const; - void print(QPaintDevice &p, - const QwtPlotPrintFilter & = QwtPlotPrintFilter()) const; - virtual void print(QPainter *, const QRect &rect, - const QwtPlotPrintFilter & = QwtPlotPrintFilter()) const; - // Layout QwtPlotLayout *plotLayout(); const QwtPlotLayout *plotLayout() const; - void setMargin(int margin); - int margin() const; - // Title - void setTitle(const QString &); - void setTitle(const QwtText &t); + void setTitle( const QString & ); + void setTitle( const QwtText &t ); QwtText title() const; QwtTextLabel *titleLabel(); @@ -172,88 +161,88 @@ public: QwtPlotCanvas *canvas(); const QwtPlotCanvas *canvas() const; - void setCanvasBackground (const QColor &c); - const QColor& canvasBackground() const; + void setCanvasBackground( const QBrush & ); + QBrush canvasBackground() const; - void setCanvasLineWidth(int w); + void setCanvasLineWidth( int w ); int canvasLineWidth() const; - virtual QwtScaleMap canvasMap(int axisId) const; + virtual QwtScaleMap canvasMap( int axisId ) const; - double invTransform(int axisId, int pos) const; - int transform(int axisId, double value) const; + double invTransform( int axisId, int pos ) const; + double transform( int axisId, double value ) const; // Axes - QwtScaleEngine *axisScaleEngine(int axisId); - const QwtScaleEngine *axisScaleEngine(int axisId) const; - void setAxisScaleEngine(int axisId, QwtScaleEngine *); + QwtScaleEngine *axisScaleEngine( int axisId ); + const QwtScaleEngine *axisScaleEngine( int axisId ) const; + void setAxisScaleEngine( int axisId, QwtScaleEngine * ); - void setAxisAutoScale(int axisId); - bool axisAutoScale(int axisId) const; + void setAxisAutoScale( int axisId, bool on = true ); + bool axisAutoScale( int axisId ) const; - void enableAxis(int axisId, bool tf = true); - bool axisEnabled(int axisId) const; + void enableAxis( int axisId, bool tf = true ); + bool axisEnabled( int axisId ) const; - void setAxisFont(int axisId, const QFont &f); - QFont axisFont(int axisId) const; + void setAxisFont( int axisId, const QFont &f ); + QFont axisFont( int axisId ) const; - void setAxisScale(int axisId, double min, double max, double step = 0); - void setAxisScaleDiv(int axisId, const QwtScaleDiv &); - void setAxisScaleDraw(int axisId, QwtScaleDraw *); + void setAxisScale( int axisId, double min, double max, double step = 0 ); + void setAxisScaleDiv( int axisId, const QwtScaleDiv & ); + void setAxisScaleDraw( int axisId, QwtScaleDraw * ); - double axisStepSize(int axisId) const; + double axisStepSize( int axisId ) const; + QwtInterval axisInterval( int axisId ) const; - const QwtScaleDiv *axisScaleDiv(int axisId) const; - QwtScaleDiv *axisScaleDiv(int axisId); + const QwtScaleDiv *axisScaleDiv( int axisId ) const; + QwtScaleDiv *axisScaleDiv( int axisId ); - const QwtScaleDraw *axisScaleDraw(int axisId) const; - QwtScaleDraw *axisScaleDraw(int axisId); + const QwtScaleDraw *axisScaleDraw( int axisId ) const; + QwtScaleDraw *axisScaleDraw( int axisId ); - const QwtScaleWidget *axisWidget(int axisId) const; - QwtScaleWidget *axisWidget(int axisId); + const QwtScaleWidget *axisWidget( int axisId ) const; + QwtScaleWidget *axisWidget( int axisId ); -#if QT_VERSION < 0x040000 - void setAxisLabelAlignment(int axisId, int); -#else - void setAxisLabelAlignment(int axisId, Qt::Alignment); -#endif - void setAxisLabelRotation(int axisId, double rotation); + void setAxisLabelAlignment( int axisId, Qt::Alignment ); + void setAxisLabelRotation( int axisId, double rotation ); - void setAxisTitle(int axisId, const QString &); - void setAxisTitle(int axisId, const QwtText &); - QwtText axisTitle(int axisId) const; + void setAxisTitle( int axisId, const QString & ); + void setAxisTitle( int axisId, const QwtText & ); + QwtText axisTitle( int axisId ) const; - void setAxisMaxMinor(int axisId, int maxMinor); - int axisMaxMajor(int axisId) const; - void setAxisMaxMajor(int axisId, int maxMajor); - int axisMaxMinor(int axisId) const; + void setAxisMaxMinor( int axisId, int maxMinor ); + int axisMaxMinor( int axisId ) const; - // Legend + void setAxisMaxMajor( int axisId, int maxMajor ); + int axisMaxMajor( int axisId ) const; - void insertLegend(QwtLegend *, LegendPosition = QwtPlot::RightLegend, - double ratio = -1.0); + // Legend + + void insertLegend( QwtLegend *, LegendPosition = QwtPlot::RightLegend, + double ratio = -1.0 ); QwtLegend *legend(); const QwtLegend *legend() const; // Misc - virtual void polish(); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; virtual void updateLayout(); - virtual void drawCanvas(QPainter *); + virtual void drawCanvas( QPainter * ); void updateAxes(); - virtual bool event(QEvent *); + virtual bool event( QEvent * ); -signals: + virtual void drawItems( QPainter *, const QRectF &, + const QwtScaleMap maps[axisCnt] ) const; + +Q_SIGNALS: /*! - A signal which is emitted when the user has clicked on - a legend item, which is in QwtLegend::ClickableItem mode. + A signal which is emitted when the user has clicked on + a legend item, which is in QwtLegend::ClickableItem mode. \param plotItem Corresponding plot item of the selected legend item @@ -261,10 +250,10 @@ signals: \note clicks are disabled as default \sa QwtLegend::setItemMode(), QwtLegend::itemMode() */ - void legendClicked(QwtPlotItem *plotItem); + void legendClicked( QwtPlotItem *plotItem ); /*! - A signal which is emitted when the user has clicked on + A signal which is emitted when the user has clicked on a legend item, which is in QwtLegend::CheckableItem mode \param plotItem Corresponding plot item of the @@ -275,49 +264,29 @@ signals: \sa QwtLegend::setItemMode(), QwtLegend::itemMode() */ - void legendChecked(QwtPlotItem *plotItem, bool on); - -public slots: - virtual void clear(); + void legendChecked( QwtPlotItem *plotItem, bool on ); +public Q_SLOTS: virtual void replot(); void autoRefresh(); -protected slots: +protected Q_SLOTS: virtual void legendItemClicked(); - virtual void legendItemChecked(bool); + virtual void legendItemChecked( bool ); protected: - static bool axisValid(int axisId); - - virtual void drawItems(QPainter *, const QRect &, - const QwtScaleMap maps[axisCnt], - const QwtPlotPrintFilter &) const; + static bool axisValid( int axisId ); virtual void updateTabOrder(); - virtual void resizeEvent(QResizeEvent *e); - - virtual void printLegendItem(QPainter *, - const QWidget *, const QRect &) const; - - virtual void printTitle(QPainter *, const QRect &) const; - - virtual void printScale(QPainter *, int axisId, int startDist, int endDist, - int baseDist, const QRect &) const; - - virtual void printCanvas(QPainter *, - const QRect &boundingRect, const QRect &canvasRect, - const QwtScaleMap maps[axisCnt], const QwtPlotPrintFilter &) const; - - virtual void printLegend(QPainter *, const QRect &) const; + virtual void resizeEvent( QResizeEvent *e ); private: void initAxesData(); void deleteAxesData(); void updateScaleDiv(); - void initPlot(const QwtText &title); + void initPlot( const QwtText &title ); class AxisData; AxisData *d_axisData[axisCnt]; diff --git a/qwt/src/qwt_plot_axis.cpp b/qwt/src/qwt_plot_axis.cpp index 6432e4cf8..2ce25fd21 100644 --- a/qwt/src/qwt_plot_axis.cpp +++ b/qwt/src/qwt_plot_axis.cpp @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -36,44 +36,62 @@ void QwtPlot::initAxesData() { int axisId; - for( axisId = 0; axisId < axisCnt; axisId++) + for ( axisId = 0; axisId < axisCnt; axisId++ ) d_axisData[axisId] = new AxisData; - d_axisData[yLeft]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::LeftScale, this); - d_axisData[yLeft1]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::LeftScale, this); - d_axisData[yLeft2]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::LeftScale, this); - d_axisData[yLeft3]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::LeftScale, this); - d_axisData[yRight]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::RightScale, this); - d_axisData[yRight1]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::RightScale, this); - d_axisData[yRight2]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::RightScale, this); - d_axisData[yRight3]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::RightScale, this); - d_axisData[xTop]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::TopScale, this); - d_axisData[xBottom]->scaleWidget = - new QwtScaleWidget(QwtScaleDraw::BottomScale, this); + d_axisData[yLeft]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::LeftScale, this ); + d_axisData[yLeft1]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::LeftScale, this ); + d_axisData[yLeft2]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::LeftScale, this ); + d_axisData[yLeft3]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::LeftScale, this ); - QFont fscl(fontInfo().family(), 10); - QFont fttl(fontInfo().family(), 12, QFont::Bold); + d_axisData[yRight]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::RightScale, this ); - for(axisId = 0; axisId < axisCnt; axisId++) + d_axisData[yRight1]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::RightScale, this ); + d_axisData[yRight2]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::RightScale, this ); + d_axisData[yRight3]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::RightScale, this ); + + d_axisData[xTop]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::TopScale, this ); + d_axisData[xBottom]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::BottomScale, this ); + + d_axisData[yLeft]->scaleWidget->setObjectName( "QwtPlotAxisYLeft" ); + + d_axisData[yLeft1]->scaleWidget->setObjectName( "QwtPlotAxisYLeft1" ); + d_axisData[yLeft2]->scaleWidget->setObjectName( "QwtPlotAxisYLeft2" ); + d_axisData[yLeft3]->scaleWidget->setObjectName( "QwtPlotAxisYLeft3" ); + + d_axisData[yRight]->scaleWidget->setObjectName( "QwtPlotAxisYRight" ); + + d_axisData[yRight1]->scaleWidget->setObjectName( "QwtPlotAxisYRight1" ); + d_axisData[yRight2]->scaleWidget->setObjectName( "QwtPlotAxisYRight2" ); + d_axisData[yRight3]->scaleWidget->setObjectName( "QwtPlotAxisYRight3" ); + + d_axisData[xTop]->scaleWidget->setObjectName( "QwtPlotAxisXTop" ); + d_axisData[xBottom]->scaleWidget->setObjectName( "QwtPlotAxisXBottom" ); + + QFont fscl( fontInfo().family(), 10 ); + QFont fttl( fontInfo().family(), 12, QFont::Bold ); + + for ( axisId = 0; axisId < axisCnt; axisId++ ) { AxisData &d = *d_axisData[axisId]; - d.scaleWidget->setFont(fscl); - d.scaleWidget->setMargin(2); + d.scaleWidget->setFont( fscl ); + d.scaleWidget->setMargin( 2 ); QwtText text = d.scaleWidget->title(); - text.setFont(fttl); - d.scaleWidget->setTitle(text); + text.setFont( fttl ); + d.scaleWidget->setTitle( text ); d.doAutoScale = true; @@ -90,20 +108,24 @@ void QwtPlot::initAxesData() } d_axisData[yLeft]->isEnabled = true; + d_axisData[yLeft1]->isEnabled = false; d_axisData[yLeft2]->isEnabled = false; d_axisData[yLeft3]->isEnabled = false; + d_axisData[yRight]->isEnabled = false; + d_axisData[yRight1]->isEnabled = false; d_axisData[yRight2]->isEnabled = false; d_axisData[yRight3]->isEnabled = false; + d_axisData[xBottom]->isEnabled = true; d_axisData[xTop]->isEnabled = false; } void QwtPlot::deleteAxesData() { - for( int axisId = 0; axisId < axisCnt; axisId++) + for ( int axisId = 0; axisId < axisCnt; axisId++ ) { delete d_axisData[axisId]->scaleEngine; delete d_axisData[axisId]; @@ -115,9 +137,9 @@ void QwtPlot::deleteAxesData() \return specified axis, or NULL if axisId is invalid. \param axisId axis index */ -const QwtScaleWidget *QwtPlot::axisWidget(int axisId) const +const QwtScaleWidget *QwtPlot::axisWidget( int axisId ) const { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->scaleWidget; return NULL; @@ -127,9 +149,9 @@ const QwtScaleWidget *QwtPlot::axisWidget(int axisId) const \return specified axis, or NULL if axisId is invalid. \param axisId axis index */ -QwtScaleWidget *QwtPlot::axisWidget(int axisId) +QwtScaleWidget *QwtPlot::axisWidget( int axisId ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->scaleWidget; return NULL; @@ -143,9 +165,9 @@ QwtScaleWidget *QwtPlot::axisWidget(int axisId) \sa axisScaleEngine() */ -void QwtPlot::setAxisScaleEngine(int axisId, QwtScaleEngine *scaleEngine) +void QwtPlot::setAxisScaleEngine( int axisId, QwtScaleEngine *scaleEngine ) { - if (axisValid(axisId) && scaleEngine != NULL ) + if ( axisValid( axisId ) && scaleEngine != NULL ) { AxisData &d = *d_axisData[axisId]; @@ -158,25 +180,25 @@ void QwtPlot::setAxisScaleEngine(int axisId, QwtScaleEngine *scaleEngine) } } -/*! +/*! \param axisId axis index \return Scale engine for a specific axis */ -QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId) +QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->scaleEngine; else return NULL; } -/*! +/*! \param axisId axis index \return Scale engine for a specific axis */ -const QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId) const +const QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) const { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->scaleEngine; else return NULL; @@ -185,22 +207,22 @@ const QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId) const \return \c true if autoscaling is enabled \param axisId axis index */ -bool QwtPlot::axisAutoScale(int axisId) const +bool QwtPlot::axisAutoScale( int axisId ) const { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->doAutoScale; else return false; - + } /*! \return \c true if a specified axis is enabled \param axisId axis index */ -bool QwtPlot::axisEnabled(int axisId) const +bool QwtPlot::axisEnabled( int axisId ) const { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->isEnabled; else return false; @@ -210,23 +232,23 @@ bool QwtPlot::axisEnabled(int axisId) const \return the font of the scale labels for a specified axis \param axisId axis index */ -QFont QwtPlot::axisFont(int axisId) const +QFont QwtPlot::axisFont( int axisId ) const { - if (axisValid(axisId)) - return axisWidget(axisId)->font(); + if ( axisValid( axisId ) ) + return axisWidget( axisId )->font(); else return QFont(); - + } /*! \return the maximum number of major ticks for a specified axis \param axisId axis index - sa setAxisMaxMajor() + \sa setAxisMaxMajor() */ -int QwtPlot::axisMaxMajor(int axisId) const +int QwtPlot::axisMaxMajor( int axisId ) const { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->maxMajor; else return 0; @@ -235,11 +257,11 @@ int QwtPlot::axisMaxMajor(int axisId) const /*! \return the maximum number of minor ticks for a specified axis \param axisId axis index - sa setAxisMaxMinor() + \sa setAxisMaxMinor() */ -int QwtPlot::axisMaxMinor(int axisId) const +int QwtPlot::axisMaxMinor( int axisId ) const { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) return d_axisData[axisId]->maxMinor; else return 0; @@ -252,13 +274,13 @@ int QwtPlot::axisMaxMinor(int axisId) const are the current limits of the axis scale. \param axisId axis index - \return Scale division + \return Scale division \sa QwtScaleDiv, setAxisScaleDiv() */ -const QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId) const +const QwtScaleDiv *QwtPlot::axisScaleDiv( int axisId ) const { - if (!axisValid(axisId)) + if ( !axisValid( axisId ) ) return NULL; return &d_axisData[axisId]->scaleDiv; @@ -271,13 +293,13 @@ const QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId) const are the current limits of the axis scale. \param axisId axis index - \return Scale division + \return Scale division \sa QwtScaleDiv, setAxisScaleDiv() */ -QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId) +QwtScaleDiv *QwtPlot::axisScaleDiv( int axisId ) { - if (!axisValid(axisId)) + if ( !axisValid( axisId ) ) return NULL; return &d_axisData[axisId]->scaleDiv; @@ -289,12 +311,12 @@ QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId) \return specified scaleDraw for axis, or NULL if axis is invalid. \sa QwtScaleDraw */ -const QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId) const +const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const { - if (!axisValid(axisId)) + if ( !axisValid( axisId ) ) return NULL; - return axisWidget(axisId)->scaleDraw(); + return axisWidget( axisId )->scaleDraw(); } /*! @@ -303,40 +325,58 @@ const QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId) const \return specified scaleDraw for axis, or NULL if axis is invalid. \sa QwtScaleDraw */ -QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId) +QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) { - if (!axisValid(axisId)) + if ( !axisValid( axisId ) ) return NULL; - return axisWidget(axisId)->scaleDraw(); + return axisWidget( axisId )->scaleDraw(); } /*! Return the step size parameter, that has been set - in setAxisScale. This doesn't need to be the step size + in setAxisScale. This doesn't need to be the step size of the current scale. \param axisId axis index \return step size parameter value \sa setAxisScale() -*/ -double QwtPlot::axisStepSize(int axisId) const +*/ +double QwtPlot::axisStepSize( int axisId ) const { - if (!axisValid(axisId)) + if ( !axisValid( axisId ) ) return 0; return d_axisData[axisId]->stepSize; } +/*! + \brief Return the current interval of the specified axis + + This is only a convenience function for axisScaleDiv( axisId )->interval(); + + \param axisId axis index + \return Scale interval + + \sa QwtScaleDiv, axisScaleDiv() +*/ +QwtInterval QwtPlot::axisInterval( int axisId ) const +{ + if ( !axisValid( axisId ) ) + return QwtInterval(); + + return d_axisData[axisId]->scaleDiv.interval(); +} + /*! \return the title of a specified axis \param axisId axis index */ -QwtText QwtPlot::axisTitle(int axisId) const +QwtText QwtPlot::axisTitle( int axisId ) const { - if (axisValid(axisId)) - return axisWidget(axisId)->title(); + if ( axisValid( axisId ) ) + return axisWidget( axisId )->title(); else return QwtText(); } @@ -353,9 +393,9 @@ QwtText QwtPlot::axisTitle(int axisId) const \param axisId axis index \param tf \c true (enabled) or \c false (disabled) */ -void QwtPlot::enableAxis(int axisId, bool tf) +void QwtPlot::enableAxis( int axisId, bool tf ) { - if (axisValid(axisId) && tf != d_axisData[axisId]->isEnabled) + if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled ) { d_axisData[axisId]->isEnabled = tf; updateLayout(); @@ -370,12 +410,12 @@ void QwtPlot::enableAxis(int axisId, bool tf) \warning The position can be an x or a y coordinate, depending on the specified axis. */ -double QwtPlot::invTransform(int axisId, int pos) const +double QwtPlot::invTransform( int axisId, int pos ) const { - if (axisValid(axisId)) - return(canvasMap(axisId).invTransform(pos)); + if ( axisValid( axisId ) ) + return( canvasMap( axisId ).invTransform( pos ) ); else - return 0.0; + return 0.0; } @@ -386,13 +426,12 @@ double QwtPlot::invTransform(int axisId, int pos) const \return X or y coordinate in the plotting region corresponding to the value. */ -int QwtPlot::transform(int axisId, double value) const +double QwtPlot::transform( int axisId, double value ) const { - if (axisValid(axisId)) - return(canvasMap(axisId).transform(value)); + if ( axisValid( axisId ) ) + return( canvasMap( axisId ).transform( value ) ); else - return 0; - + return 0.0; } /*! @@ -402,10 +441,10 @@ int QwtPlot::transform(int axisId, double value) const \warning This function changes the font of the tick labels, not of the axis title. */ -void QwtPlot::setAxisFont(int axisId, const QFont &f) +void QwtPlot::setAxisFont( int axisId, const QFont &f ) { - if (axisValid(axisId)) - axisWidget(axisId)->setFont(f); + if ( axisValid( axisId ) ) + axisWidget( axisId )->setFont( f ); } /*! @@ -415,13 +454,17 @@ void QwtPlot::setAxisFont(int axisId, const QFont &f) after a fixed scale has been set. Autoscaling is enabled by default. \param axisId axis index - \sa QwtPlot::setAxisScale(), QwtPlot::setAxisScaleDiv() + \param on On/Off + \sa setAxisScale(), setAxisScaleDiv(), updateAxes() + + \note The autoscaling flag has no effect until updateAxes() is executed + ( called by replot() ). */ -void QwtPlot::setAxisAutoScale(int axisId) +void QwtPlot::setAxisAutoScale( int axisId, bool on ) { - if (axisValid(axisId) && !d_axisData[axisId]->doAutoScale ) + if ( axisValid( axisId ) && ( d_axisData[axisId]->doAutoScale != on ) ) { - d_axisData[axisId]->doAutoScale = true; + d_axisData[axisId]->doAutoScale = on; autoRefresh(); } } @@ -433,11 +476,11 @@ void QwtPlot::setAxisAutoScale(int axisId) \param max minimum and maximum of the scale \param stepSize Major step size. If step == 0, the step size is calculated automatically using the maxMajor setting. - \sa setAxisMaxMajor(), setAxisAutoScale() + \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize() */ -void QwtPlot::setAxisScale(int axisId, double min, double max, double stepSize) +void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) { AxisData &d = *d_axisData[axisId]; @@ -447,7 +490,7 @@ void QwtPlot::setAxisScale(int axisId, double min, double max, double stepSize) d.minValue = min; d.maxValue = max; d.stepSize = stepSize; - + autoRefresh(); } } @@ -458,9 +501,9 @@ void QwtPlot::setAxisScale(int axisId, double min, double max, double stepSize) \param scaleDiv Scale division \sa setAxisScale(), setAxisAutoScale() */ -void QwtPlot::setAxisScaleDiv(int axisId, const QwtScaleDiv &scaleDiv) +void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) { AxisData &d = *d_axisData[axisId]; @@ -482,15 +525,15 @@ void QwtPlot::setAxisScaleDiv(int axisId, const QwtScaleDiv &scaleDiv) by the corresponding QwtScale member ( like a child object ). \sa QwtScaleDraw, QwtScaleWidget - \warning The attributes of scaleDraw will be overwritten by those of the - previous QwtScaleDraw. + \warning The attributes of scaleDraw will be overwritten by those of the + previous QwtScaleDraw. */ -void QwtPlot::setAxisScaleDraw(int axisId, QwtScaleDraw *scaleDraw) +void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) { - axisWidget(axisId)->setScaleDraw(scaleDraw); + axisWidget( axisId )->setScaleDraw( scaleDraw ); autoRefresh(); } } @@ -498,17 +541,13 @@ void QwtPlot::setAxisScaleDraw(int axisId, QwtScaleDraw *scaleDraw) /*! Change the alignment of the tick labels \param axisId axis index - \param alignment Or'd Qt::AlignmentFlags + \param alignment Or'd Qt::AlignmentFlags see \sa QwtScaleDraw::setLabelAlignment() */ -#if QT_VERSION < 0x040000 -void QwtPlot::setAxisLabelAlignment(int axisId, int alignment) -#else -void QwtPlot::setAxisLabelAlignment(int axisId, Qt::Alignment alignment) -#endif +void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment ) { - if (axisValid(axisId)) - axisWidget(axisId)->setLabelAlignment(alignment); + if ( axisValid( axisId ) ) + axisWidget( axisId )->setLabelAlignment( alignment ); } /*! @@ -518,10 +557,10 @@ void QwtPlot::setAxisLabelAlignment(int axisId, Qt::Alignment alignment) the label alignment might be adjusted too. \sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment() */ -void QwtPlot::setAxisLabelRotation(int axisId, double rotation) +void QwtPlot::setAxisLabelRotation( int axisId, double rotation ) { - if (axisValid(axisId)) - axisWidget(axisId)->setLabelRotation(rotation); + if ( axisValid( axisId ) ) + axisWidget( axisId )->setLabelRotation( rotation ); } /*! @@ -531,17 +570,13 @@ void QwtPlot::setAxisLabelRotation(int axisId, double rotation) \param maxMinor maximum number of minor steps \sa axisMaxMinor() */ -void QwtPlot::setAxisMaxMinor(int axisId, int maxMinor) +void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) { - if ( maxMinor < 0 ) - maxMinor = 0; - if ( maxMinor > 100 ) - maxMinor = 100; - - AxisData &d = *d_axisData[axisId]; + maxMinor = qBound( 0, maxMinor, 100 ); + AxisData &d = *d_axisData[axisId]; if ( maxMinor != d.maxMinor ) { d.maxMinor = maxMinor; @@ -558,15 +593,12 @@ void QwtPlot::setAxisMaxMinor(int axisId, int maxMinor) \param maxMajor maximum number of major steps \sa axisMaxMajor() */ -void QwtPlot::setAxisMaxMajor(int axisId, int maxMajor) +void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor ) { - if (axisValid(axisId)) + if ( axisValid( axisId ) ) { - if ( maxMajor < 1 ) - maxMajor = 1; - if ( maxMajor > 1000 ) - maxMajor = 10000; - + maxMajor = qBound( 1, maxMajor, 10000 ); + AxisData &d = *d_axisData[axisId]; if ( maxMajor != d.maxMajor ) { @@ -582,10 +614,10 @@ void QwtPlot::setAxisMaxMajor(int axisId, int maxMajor) \param axisId axis index \param title axis title */ -void QwtPlot::setAxisTitle(int axisId, const QString &title) +void QwtPlot::setAxisTitle( int axisId, const QString &title ) { - if (axisValid(axisId)) - axisWidget(axisId)->setTitle(title); + if ( axisValid( axisId ) ) + axisWidget( axisId )->setTitle( title ); } /*! @@ -593,19 +625,19 @@ void QwtPlot::setAxisTitle(int axisId, const QString &title) \param axisId axis index \param title axis title */ -void QwtPlot::setAxisTitle(int axisId, const QwtText &title) +void QwtPlot::setAxisTitle( int axisId, const QwtText &title ) { - if (axisValid(axisId)) - axisWidget(axisId)->setTitle(title); + if ( axisValid( axisId ) ) + axisWidget( axisId )->setTitle( title ); } //! Rebuild the scales -void QwtPlot::updateAxes() +void QwtPlot::updateAxes() { // Find bounding interval of the item data // for all axes, where autoscaling is enabled - - QwtDoubleInterval intv[axisCnt]; + + QwtInterval intv[axisCnt]; const QwtPlotItemList& itmList = itemList(); @@ -614,20 +646,23 @@ void QwtPlot::updateAxes() { const QwtPlotItem *item = *it; - if ( !item->testItemAttribute(QwtPlotItem::AutoScale) ) + if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) ) continue; - if ( axisAutoScale(item->xAxis()) || axisAutoScale(item->yAxis()) ) + if ( !item->isVisible() ) + continue; + + if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) ) { - const QwtDoubleRect rect = item->boundingRect(); - intv[item->xAxis()] |= QwtDoubleInterval(rect.left(), rect.right()); - intv[item->yAxis()] |= QwtDoubleInterval(rect.top(), rect.bottom()); + const QRectF rect = item->boundingRect(); + intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() ); + intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() ); } } // Adjust scales - for (int axisId = 0; axisId < axisCnt; axisId++) + for ( int axisId = 0; axisId < axisCnt; axisId++ ) { AxisData &d = *d_axisData[axisId]; @@ -642,30 +677,29 @@ void QwtPlot::updateAxes() minValue = intv[axisId].minValue(); maxValue = intv[axisId].maxValue(); - d.scaleEngine->autoScale(d.maxMajor, - minValue, maxValue, stepSize); + d.scaleEngine->autoScale( d.maxMajor, + minValue, maxValue, stepSize ); } if ( !d.scaleDiv.isValid() ) { d.scaleDiv = d.scaleEngine->divideScale( - minValue, maxValue, - d.maxMajor, d.maxMinor, stepSize); + minValue, maxValue, + d.maxMajor, d.maxMinor, stepSize ); } - QwtScaleWidget *scaleWidget = axisWidget(axisId); + QwtScaleWidget *scaleWidget = axisWidget( axisId ); scaleWidget->setScaleDiv( - d.scaleEngine->transformation(), d.scaleDiv); + d.scaleEngine->transformation(), d.scaleDiv ); int startDist, endDist; - scaleWidget->getBorderDistHint(startDist, endDist); - scaleWidget->setBorderDist(startDist, endDist); + scaleWidget->getBorderDistHint( startDist, endDist ); + scaleWidget->setBorderDist( startDist, endDist ); } for ( it = itmList.begin(); it != itmList.end(); ++it ) { QwtPlotItem *item = *it; - item->updateScaleDiv( *axisScaleDiv(item->xAxis()), - *axisScaleDiv(item->yAxis())); + item->updateScaleDiv( *axisScaleDiv( item->xAxis() ), + *axisScaleDiv( item->yAxis() ) ); } } - diff --git a/qwt/src/qwt_plot_canvas.cpp b/qwt/src/qwt_plot_canvas.cpp index e56106c14..5fd70d98a 100644 --- a/qwt/src/qwt_plot_canvas.cpp +++ b/qwt/src/qwt_plot_canvas.cpp @@ -7,68 +7,532 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - +#include "qwt_plot_canvas.h" +#include "qwt_painter.h" +#include "qwt_null_paintdevice.h" +#include "qwt_math.h" +#include "qwt_plot.h" #include #include -#if QT_VERSION >= 0x040000 #include #include +#include +#include #ifdef Q_WS_X11 #include #endif + +class QwtStyleSheetRecorder: public QwtNullPaintDevice +{ +public: + QwtStyleSheetRecorder( const QSize &size ): + QwtNullPaintDevice( QPaintEngine::AllFeatures ) + { + setSize( size ); + } + + virtual void updateState( const QPaintEngineState &state ) + { + if ( state.state() & QPaintEngine::DirtyPen ) + { + d_pen = state.pen(); + } + if ( state.state() & QPaintEngine::DirtyBrush ) + { + d_brush = state.brush(); + } + if ( state.state() & QPaintEngine::DirtyBrushOrigin ) + { + d_origin = state.brushOrigin(); + } + } + + virtual void drawRects(const QRectF *rects, int count ) + { + for ( int i = 0; i < count; i++ ) + border.rectList += rects[i]; + } + + virtual void drawPath( const QPainterPath &path ) + { + const QRectF rect( QPointF( 0.0, 0.0 ) , size() ); + if ( path.controlPointRect().contains( rect.center() ) ) + { + setCornerRects( path ); + alignCornerRects( rect ); + + background.path = path; + background.brush = d_brush; + background.origin = d_origin; + } + else + { + border.pathList += path; + } + } + + void setCornerRects( const QPainterPath &path ) + { + QPointF pos( 0.0, 0.0 ); + + for ( int i = 0; i < path.elementCount(); i++ ) + { + QPainterPath::Element el = path.elementAt(i); + switch( el.type ) + { + case QPainterPath::MoveToElement: + case QPainterPath::LineToElement: + { + pos.setX( el.x ); + pos.setY( el.y ); + break; + } + case QPainterPath::CurveToElement: + { + QRectF r( pos, QPointF( el.x, el.y ) ); + clipRects += r.normalized(); + + pos.setX( el.x ); + pos.setY( el.y ); + + break; + } + case QPainterPath::CurveToDataElement: + { + if ( clipRects.size() > 0 ) + { + QRectF r = clipRects.last(); + r.setCoords( + qMin( r.left(), el.x ), + qMin( r.top(), el.y ), + qMax( r.right(), el.x ), + qMax( r.bottom(), el.y ) + ); + clipRects.last() = r.normalized(); + } + break; + } + } + } + } + +private: + void alignCornerRects( const QRectF &rect ) + { + for ( int i = 0; i < clipRects.size(); i++ ) + { + QRectF &r = clipRects[i]; + if ( r.center().x() < rect.center().x() ) + r.setLeft( rect.left() ); + else + r.setRight( rect.right() ); + + if ( r.center().y() < rect.center().y() ) + r.setTop( rect.top() ); + else + r.setBottom( rect.bottom() ); + } + } + + +public: + QVector clipRects; + + struct Border + { + QList pathList; + QList rectList; + QRegion clipRegion; + } border; + + struct Background + { + QPainterPath path; + QBrush brush; + QPointF origin; + } background; + +private: + QPen d_pen; + QBrush d_brush; + QPointF d_origin; +}; + +static void qwtDrawBackground( QPainter *painter, QWidget *widget ) +{ + const QBrush &brush = + widget->palette().brush( widget->backgroundRole() ); + + if ( brush.style() == Qt::TexturePattern ) + { + QPixmap pm( widget->size() ); + pm.fill( widget, 0, 0 ); + painter->drawPixmap( 0, 0, pm ); + } + else if ( brush.gradient() ) + { + QVector rects; + + if ( brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode ) + { + rects += widget->rect(); + } + else + { + rects = painter->clipRegion().rects(); + } + +#if 1 + bool useRaster = false; + + if ( painter->paintEngine()->type() == QPaintEngine::X11 ) + { + // Qt 4.7.1: gradients on X11 are broken ( subrects + + // QGradient::StretchToDeviceMode ) and horrible slow. + // As workaround we have to use the raster paintengine. + // Even if the QImage -> QPixmap translation is slow + // it is three times faster, than using X11 directly + + useRaster = true; + } #endif -#include -#include "qwt_painter.h" -#include "qwt_math.h" -#include "qwt_plot.h" -#include "qwt_paint_buffer.h" -#include "qwt_plot_canvas.h" + if ( useRaster ) + { + QImage::Format format = QImage::Format_RGB32; + + const QGradientStops stops = brush.gradient()->stops(); + for ( int i = 0; i < stops.size(); i++ ) + { + if ( stops[i].second.alpha() != 255 ) + { + // don't use Format_ARGB32_Premultiplied. It's + // recommended by the Qt docs, but QPainter::drawImage() + // is horrible slow on X11. + + format = QImage::Format_ARGB32; + break; + } + } + + QImage image( widget->size(), format ); + + QPainter p( &image ); + p.setPen( Qt::NoPen ); + p.setBrush( brush ); + + p.drawRects( rects ); + + p.end(); + + painter->drawImage( 0, 0, image ); + } + else + { + painter->save(); + + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); + + painter->drawRects( rects ); + + painter->restore(); + } + } + else + { + painter->save(); + + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); + + painter->drawRects( painter->clipRegion().rects() ); + + painter->restore(); + } +} + +static inline void qwtRevertPath( QPainterPath &path ) +{ + if ( path.elementCount() == 4 ) + { + QPainterPath::Element &el0 = + const_cast( path.elementAt(0) ); + QPainterPath::Element &el2 = + const_cast( path.elementAt(3) ); + + qSwap( el0.x, el2.x ); + qSwap( el0.y, el2.y ); + } +} + +static QPainterPath qwtCombinePathList( const QRectF &rect, + const QList &pathList ) +{ + if ( pathList.isEmpty() ) + return QPainterPath(); + + QPainterPath ordered[8]; // starting top left + + for ( int i = 0; i < pathList.size(); i++ ) + { + int index = -1; + QPainterPath subPath = pathList[i]; + + const QRectF br = pathList[i].controlPointRect(); + if ( br.center().x() < rect.center().x() ) + { + if ( br.center().y() < rect.center().y() ) + { + if ( qAbs( br.top() - rect.top() ) < + qAbs( br.left() - rect.left() ) ) + { + index = 1; + } + else + { + index = 0; + } + } + else + { + if ( qAbs( br.bottom() - rect.bottom() ) < + qAbs( br.left() - rect.left() ) ) + { + index = 6; + } + else + { + index = 7; + } + } + + if ( subPath.currentPosition().y() > br.center().y() ) + qwtRevertPath( subPath ); + } + else + { + if ( br.center().y() < rect.center().y() ) + { + if ( qAbs( br.top() - rect.top() ) < + qAbs( br.right() - rect.right() ) ) + { + index = 2; + } + else + { + index = 3; + } + } + else + { + if ( qAbs( br.bottom() - rect.bottom() ) < + qAbs( br.right() - rect.right() ) ) + { + index = 5; + } + else + { + index = 4; + } + } + if ( subPath.currentPosition().y() < br.center().y() ) + qwtRevertPath( subPath ); + } + ordered[index] = subPath; + } + + for ( int i = 0; i < 4; i++ ) + { + if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() ) + { + // we don't accept incomplete rounded borders + return QPainterPath(); + } + } + + + const QPolygonF corners( rect ); + + QPainterPath path; + //path.moveTo( rect.topLeft() ); + + for ( int i = 0; i < 4; i++ ) + { + if ( ordered[2 * i].isEmpty() ) + { + path.lineTo( corners[i] ); + } + else + { + path.connectPath( ordered[2 * i] ); + path.connectPath( ordered[2 * i + 1] ); + } + } + + path.closeSubpath(); + +#if 0 + return path.simplified(); +#else + return path; +#endif +} + +static inline void qwtDrawStyledBackground( + QWidget *w, QPainter *painter ) +{ + QStyleOption opt; + opt.initFrom(w); + w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w); +} + +static QWidget *qwtBackgroundWidget( QWidget *w ) +{ + if ( w->parentWidget() == NULL ) + return w; + + if ( w->autoFillBackground() ) + { + const QBrush brush = w->palette().brush( w->backgroundRole() ); + if ( brush.color().alpha() > 0 ) + return w; + } + + if ( w->testAttribute( Qt::WA_StyledBackground ) ) + { + QImage image( 1, 1, QImage::Format_ARGB32 ); + image.fill( Qt::transparent ); + + QPainter painter( &image ); + painter.translate( -w->rect().center() ); + qwtDrawStyledBackground( w, &painter ); + painter.end(); + + if ( qAlpha( image.pixel( 0, 0 ) ) != 0 ) + return w; + } + + return qwtBackgroundWidget( w->parentWidget() ); +} + +static void qwtFillBackground( QPainter *painter, + QWidget *widget, const QVector &fillRects ) +{ + if ( fillRects.isEmpty() ) + return; + + QRegion clipRegion; + if ( painter->hasClipping() ) + clipRegion = painter->transform().map( painter->clipRegion() ); + else + clipRegion = widget->contentsRect(); + + // Try to find out which widget fills + // the unfilled areas of the styled background + + QWidget *bgWidget = qwtBackgroundWidget( widget->parentWidget() ); + + for ( int i = 0; i < fillRects.size(); i++ ) + { + const QRect rect = fillRects[i].toAlignedRect(); + if ( clipRegion.intersects( rect ) ) + { + QPixmap pm( rect.size() ); + pm.fill( bgWidget, widget->mapTo( bgWidget, rect.topLeft() ) ); + painter->drawPixmap( rect, pm ); + } + } +} + +static void qwtFillBackground( QPainter *painter, QwtPlotCanvas *canvas ) +{ + QVector rects; + + if ( canvas->testAttribute( Qt::WA_StyledBackground ) ) + { + QwtStyleSheetRecorder recorder( canvas->size() ); + + QPainter p( &recorder ); + qwtDrawStyledBackground( canvas, &p ); + p.end(); + + if ( recorder.background.brush.isOpaque() ) + rects = recorder.clipRects; + else + rects += canvas->rect(); + } + else + { + const QRectF r = canvas->rect(); + const double radius = canvas->borderRadius(); + if ( radius > 0.0 ) + { + QSize sz( radius, radius ); + + rects += QRectF( r.topLeft(), sz ); + rects += QRectF( r.topRight() - QPointF( radius, 0 ), sz ); + rects += QRectF( r.bottomRight() - QPointF( radius, radius ), sz ); + rects += QRectF( r.bottomLeft() - QPointF( 0, radius ), sz ); + } + } + + qwtFillBackground( painter, canvas, rects); +} + class QwtPlotCanvas::PrivateData { public: PrivateData(): - focusIndicator(NoFocusIndicator), - paintAttributes(0), - cache(NULL) + focusIndicator( NoFocusIndicator ), + borderRadius( 0 ), + paintAttributes( 0 ), + backingStore( NULL ) { + styleSheet.hasBorder = false; } ~PrivateData() { - delete cache; + delete backingStore; } FocusIndicator focusIndicator; - int paintAttributes; - QPixmap *cache; + double borderRadius; + QwtPlotCanvas::PaintAttributes paintAttributes; + QPixmap *backingStore; + + struct StyleSheet + { + bool hasBorder; + QPainterPath borderPath; + QVector cornerRects; + + struct StyleSheetBackground + { + QBrush brush; + QPointF origin; + } background; + + } styleSheet; + }; -//! Sets a cross cursor, enables QwtPlotCanvas::PaintCached +//! Sets a cross cursor, enables QwtPlotCanvas::BackingStore -QwtPlotCanvas::QwtPlotCanvas(QwtPlot *plot): - QFrame(plot) +QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ): + QFrame( plot ) { d_data = new PrivateData; -#if QT_VERSION >= 0x040100 - setAutoFillBackground(true); +#ifndef QT_NO_CURSOR + setCursor( Qt::CrossCursor ); #endif -#if QT_VERSION < 0x040000 - setWFlags(Qt::WNoAutoErase); -#ifndef QT_NO_CURSOR - setCursor(Qt::crossCursor); -#endif -#else -#ifndef QT_NO_CURSOR - setCursor(Qt::CrossCursor); -#endif -#endif // >= 0x040000 - - setPaintAttribute(PaintCached, true); - setPaintAttribute(PaintPacked, true); + setAutoFillBackground( true ); + setPaintAttribute( QwtPlotCanvas::BackingStore, true ); + setPaintAttribute( QwtPlotCanvas::Opaque, true ); + setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true ); } //! Destructor @@ -80,21 +544,13 @@ QwtPlotCanvas::~QwtPlotCanvas() //! Return parent plot widget QwtPlot *QwtPlotCanvas::plot() { - QWidget *w = parentWidget(); - if ( w && w->inherits("QwtPlot") ) - return (QwtPlot *)w; - - return NULL; + return qobject_cast( parentWidget() ); } //! Return parent plot widget const QwtPlot *QwtPlotCanvas::plot() const { - const QWidget *w = parentWidget(); - if ( w && w->inherits("QwtPlot") ) - return (QwtPlot *)w; - - return NULL; + return qobject_cast( parentWidget() ); } /*! @@ -103,13 +559,11 @@ const QwtPlot *QwtPlotCanvas::plot() const \param attribute Paint attribute \param on On/Off - The default setting enables PaintCached and PaintPacked - - \sa testPaintAttribute(), drawCanvas(), drawContents(), paintCache() + \sa testPaintAttribute(), backingStore() */ -void QwtPlotCanvas::setPaintAttribute(PaintAttribute attribute, bool on) +void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on ) { - if ( bool(d_data->paintAttributes & attribute) == on ) + if ( bool( d_data->paintAttributes & attribute ) == on ) return; if ( on ) @@ -117,43 +571,40 @@ void QwtPlotCanvas::setPaintAttribute(PaintAttribute attribute, bool on) else d_data->paintAttributes &= ~attribute; - switch(attribute) + switch ( attribute ) { - case PaintCached: + case BackingStore: { if ( on ) { - if ( d_data->cache == NULL ) - d_data->cache = new QPixmap(); + if ( d_data->backingStore == NULL ) + d_data->backingStore = new QPixmap(); if ( isVisible() ) { - const QRect cr = contentsRect(); - *d_data->cache = QPixmap::grabWidget(this, - cr.x(), cr.y(), cr.width(), cr.height() ); + *d_data->backingStore = + QPixmap::grabWidget( this, rect() ); } } else { - delete d_data->cache; - d_data->cache = NULL; + delete d_data->backingStore; + d_data->backingStore = NULL; } break; } - case PaintPacked: + case Opaque: { - /* - If not visible, changing of the background mode - is delayed until it becomes visible. This tries to avoid - looking through the canvas when the canvas is shown the first - time. - */ - - if ( on == false || isVisible() ) - QwtPlotCanvas::setSystemBackground(!on); + if ( on ) + setAttribute( Qt::WA_OpaquePaintEvent, true ); break; } + case HackStyledBackground: + case ImmediatePaint: + { + break; + } } } @@ -164,28 +615,22 @@ void QwtPlotCanvas::setPaintAttribute(PaintAttribute attribute, bool on) \return true if the attribute is enabled \sa setPaintAttribute() */ -bool QwtPlotCanvas::testPaintAttribute(PaintAttribute attribute) const +bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const { - return (d_data->paintAttributes & attribute) != 0; + return d_data->paintAttributes & attribute; } -//! Return the paint cache, might be null -QPixmap *QwtPlotCanvas::paintCache() +//! \return Backing store, might be null +const QPixmap *QwtPlotCanvas::backingStore() const { - return d_data->cache; + return d_data->backingStore; } -//! Return the paint cache, might be null -const QPixmap *QwtPlotCanvas::paintCache() const +//! Invalidate the internal backing store +void QwtPlotCanvas::invalidateBackingStore() { - return d_data->cache; -} - -//! Invalidate the internal paint cache -void QwtPlotCanvas::invalidatePaintCache() -{ - if ( d_data->cache ) - *d_data->cache = QPixmap(); + if ( d_data->backingStore ) + *d_data->backingStore = QPixmap(); } /*! @@ -193,14 +638,14 @@ void QwtPlotCanvas::invalidatePaintCache() \sa FocusIndicator, focusIndicator() */ -void QwtPlotCanvas::setFocusIndicator(FocusIndicator focusIndicator) +void QwtPlotCanvas::setFocusIndicator( FocusIndicator focusIndicator ) { d_data->focusIndicator = focusIndicator; } /*! \return Focus indicator - + \sa FocusIndicator, setFocusIndicator() */ QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const @@ -209,186 +654,285 @@ QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const } /*! - Hide event - \param event Hide event + Set the radius for the corners of the border frame + + \param radius Radius of a rounded corner + \sa borderRadius() */ -void QwtPlotCanvas::hideEvent(QHideEvent *event) +void QwtPlotCanvas::setBorderRadius( double radius ) { - QFrame::hideEvent(event); + d_data->borderRadius = qMax( 0.0, radius ); +} - if ( d_data->paintAttributes & PaintPacked ) +/*! + \return Radius for the corners of the border frame + \sa setBorderRadius() +*/ +double QwtPlotCanvas::borderRadius() const +{ + return d_data->borderRadius; +} + +/*! + Qt event handler for QEvent::PolishRequest and QEvent::StyleChange + \param event Qt Event +*/ +bool QwtPlotCanvas::event( QEvent *event ) +{ + if ( event->type() == QEvent::PolishRequest ) { - // enable system background to avoid the "looking through - // the canvas" effect, for the next show + if ( testPaintAttribute( QwtPlotCanvas::Opaque ) ) + { + // Setting a style sheet changes the + // Qt::WA_OpaquePaintEvent attribute, but we insist + // on painting the background. - setSystemBackground(true); + setAttribute( Qt::WA_OpaquePaintEvent, true ); + } } + + if ( event->type() == QEvent::PolishRequest || + event->type() == QEvent::StyleChange ) + { + updateStyleSheetInfo(); + } + + return QFrame::event( event ); } /*! Paint event \param event Paint event */ -void QwtPlotCanvas::paintEvent(QPaintEvent *event) +void QwtPlotCanvas::paintEvent( QPaintEvent *event ) { -#if QT_VERSION >= 0x040000 - QPainter painter(this); - - if ( !contentsRect().contains( event->rect() ) ) + QPainter painter( this ); + painter.setClipRegion( event->region() ); + + if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) && + d_data->backingStore != NULL ) { - painter.save(); - painter.setClipRegion( event->region() & frameRect() ); - drawFrame( &painter ); - painter.restore(); - } + QPixmap &bs = *d_data->backingStore; + if ( bs.size() != size() ) + { + bs = QPixmap( size() ); - painter.setClipRegion(event->region() & contentsRect()); - - drawContents( &painter ); -#else // QT_VERSION < 0x040000 - QFrame::paintEvent(event); +#ifdef Q_WS_X11 + if ( bs.x11Info().screen() != x11Info().screen() ) + bs.x11SetScreen( x11Info().screen() ); #endif - if ( d_data->paintAttributes & PaintPacked ) - setSystemBackground(false); -} + if ( testAttribute(Qt::WA_StyledBackground) ) + { + QPainter p( &bs ); + qwtFillBackground( &p, this ); + drawCanvas( &p, true ); + } + else + { + QPainter p; + if ( d_data->borderRadius <= 0.0 ) + { + bs.fill( this, 0, 0 ); + p.begin( &bs ); + drawCanvas( &p, false ); + } + else + { + p.begin( &bs ); + qwtFillBackground( &p, this ); + drawCanvas( &p, true ); + } -/*! - Redraw the canvas, and focus rect - \param painter Painter -*/ -void QwtPlotCanvas::drawContents(QPainter *painter) -{ - if ( d_data->paintAttributes & PaintCached && d_data->cache - && d_data->cache->size() == contentsRect().size() ) - { - painter->drawPixmap(contentsRect().topLeft(), *d_data->cache); + if ( frameWidth() > 0 ) + drawBorder( &p ); + } + } + + painter.drawPixmap( 0, 0, *d_data->backingStore ); } else { - QwtPlot *plot = ((QwtPlot *)parent()); - const bool doAutoReplot = plot->autoReplot(); - plot->setAutoReplot(false); + if ( testAttribute(Qt::WA_StyledBackground ) ) + { + if ( testAttribute( Qt::WA_OpaquePaintEvent ) ) + { + qwtFillBackground( &painter, this ); + drawCanvas( &painter, true ); + } + else + { + drawCanvas( &painter, false ); + } + } + else + { + if ( testAttribute( Qt::WA_OpaquePaintEvent ) ) + { + if ( autoFillBackground() ) + qwtDrawBackground( &painter, this ); + } - drawCanvas(painter); + drawCanvas( &painter, false ); - plot->setAutoReplot(doAutoReplot); + if ( frameWidth() > 0 ) + drawBorder( &painter ); + } } if ( hasFocus() && focusIndicator() == CanvasFocusIndicator ) - drawFocusIndicator(painter); + drawFocusIndicator( &painter ); } -/*! - Draw the the canvas - - Paints all plot items to the contentsRect(), using QwtPlot::drawCanvas - and updates the paint cache. - - \param painter Painter - - \sa QwtPlot::drawCanvas(), setPaintAttributes(), testPaintAttributes() -*/ -void QwtPlotCanvas::drawCanvas(QPainter *painter) +void QwtPlotCanvas::drawCanvas( QPainter *painter, bool withBackground ) { - if ( !contentsRect().isValid() ) - return; + bool hackStyledBackground = false; - QBrush bgBrush; -#if QT_VERSION >= 0x040000 - bgBrush = palette().brush(backgroundRole()); -#else - QColorGroup::ColorRole role = - QPalette::backgroundRoleFromMode( backgroundMode() ); - bgBrush = colorGroup().brush( role ); -#endif - - if ( d_data->paintAttributes & PaintCached && d_data->cache ) + if ( withBackground && testAttribute( Qt::WA_StyledBackground ) + && testPaintAttribute( HackStyledBackground ) ) { - *d_data->cache = QPixmap(contentsRect().size()); + // Antialiasing rounded borders is done by + // inserting pixels with colors between the + // border color and the color on the canvas, + // When the border is painted before the plot items + // these colors are interpolated for the canvas + // and the plot items need to be clipped excluding + // the anialiased pixels. In situations, where + // the plot items fill the area at the rounded + // borders this is noticeable. + // The only way to avoid these annoying "artefacts" + // is to paint the border on top of the plot items. -#ifdef Q_WS_X11 -#if QT_VERSION >= 0x040000 - if ( d_data->cache->x11Info().screen() != x11Info().screen() ) - d_data->cache->x11SetScreen(x11Info().screen()); -#else - if ( d_data->cache->x11Screen() != x11Screen() ) - d_data->cache->x11SetScreen(x11Screen()); -#endif -#endif - - if ( d_data->paintAttributes & PaintPacked ) + if ( d_data->styleSheet.hasBorder && + !d_data->styleSheet.borderPath.isEmpty() ) { - QPainter bgPainter(d_data->cache); - bgPainter.setPen(Qt::NoPen); - - bgPainter.setBrush(bgBrush); - bgPainter.drawRect(d_data->cache->rect()); + // We have a border with at least one rounded corner + hackStyledBackground = true; } - else - d_data->cache->fill(this, d_data->cache->rect().topLeft()); + } - QPainter cachePainter(d_data->cache); - cachePainter.translate(-contentsRect().x(), - -contentsRect().y()); + if ( withBackground ) + { + painter->save(); - ((QwtPlot *)parent())->drawCanvas(&cachePainter); + if ( testAttribute( Qt::WA_StyledBackground ) ) + { + if ( hackStyledBackground ) + { + // paint background without border - cachePainter.end(); + painter->setPen( Qt::NoPen ); + painter->setBrush( d_data->styleSheet.background.brush ); + painter->setBrushOrigin( d_data->styleSheet.background.origin ); + painter->setClipPath( d_data->styleSheet.borderPath ); + painter->drawRect( contentsRect() ); + } + else + { + qwtDrawStyledBackground( this, painter ); + } + } + else if ( autoFillBackground() ) + { + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().brush( backgroundRole() ) ); - painter->drawPixmap(contentsRect(), *d_data->cache); + if ( d_data->borderRadius > 0.0 ) + { + if ( frameWidth() > 0 ) + { + painter->setClipPath( borderPath( rect() ) ); + painter->drawRect( rect() ); + } + else + { + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->drawPath( borderPath( rect() ) ); + } + } + else + { + painter->drawRect( contentsRect() ); + } + } + + painter->restore(); + } + + painter->save(); + + if ( !d_data->styleSheet.borderPath.isEmpty() ) + { + painter->setClipPath( + d_data->styleSheet.borderPath, Qt::IntersectClip ); } else { -#if QT_VERSION >= 0x040000 - if ( d_data->paintAttributes & PaintPacked ) -#endif - { - painter->save(); + if ( d_data->borderRadius > 0.0 ) + painter->setClipPath( borderPath( rect() ), Qt::IntersectClip ); + else + painter->setClipRect( contentsRect(), Qt::IntersectClip ); + } - painter->setPen(Qt::NoPen); - painter->setBrush(bgBrush); - painter->drawRect(contentsRect()); + plot()->drawCanvas( painter ); - painter->restore(); - } + painter->restore(); - ((QwtPlot *)parent())->drawCanvas(painter); + if ( withBackground && hackStyledBackground ) + { + // Now paint the border on top + QStyleOptionFrame opt; + opt.initFrom(this); + style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, this); } } -/*! +/*! + Draw the border of the plot canvas + + \param painter Painter + \sa setBorderRadius(), QFrame::drawFrame() +*/ +void QwtPlotCanvas::drawBorder( QPainter *painter ) +{ + if ( d_data->borderRadius > 0 ) + { + if ( frameWidth() > 0 ) + { + QwtPainter::drawRoundedFrame( painter, QRectF( rect() ), + d_data->borderRadius, d_data->borderRadius, + palette(), frameWidth(), frameStyle() ); + } + } + else + { + drawFrame( painter ); + } +} + +/*! + Resize event + \param event Resize event +*/ +void QwtPlotCanvas::resizeEvent( QResizeEvent *event ) +{ + QFrame::resizeEvent( event ); + updateStyleSheetInfo(); +} + +/*! Draw the focus indication \param painter Painter */ -void QwtPlotCanvas::drawFocusIndicator(QPainter *painter) +void QwtPlotCanvas::drawFocusIndicator( QPainter *painter ) { const int margin = 1; QRect focusRect = contentsRect(); - focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin, - focusRect.width() - 2 * margin, focusRect.height() - 2 * margin); + focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin, + focusRect.width() - 2 * margin, focusRect.height() - 2 * margin ); - QwtPainter::drawFocusRect(painter, this, focusRect); -} - -void QwtPlotCanvas::setSystemBackground(bool on) -{ -#if QT_VERSION < 0x040000 - if ( backgroundMode() == Qt::NoBackground ) - { - if ( on ) - setBackgroundMode(Qt::PaletteBackground); - } - else - { - if ( !on ) - setBackgroundMode(Qt::NoBackground); - } -#else - if ( testAttribute(Qt::WA_NoSystemBackground) == on ) - setAttribute(Qt::WA_NoSystemBackground, !on); -#endif + QwtPainter::drawFocusRect( painter, this, focusRect ); } /*! @@ -397,26 +941,139 @@ void QwtPlotCanvas::setSystemBackground(bool on) */ void QwtPlotCanvas::replot() { - invalidatePaintCache(); + invalidateBackingStore(); - /* - In case of cached or packed painting the canvas - is repainted completely and doesn't need to be erased. - */ - const bool erase = - !testPaintAttribute(QwtPlotCanvas::PaintPacked) - && !testPaintAttribute(QwtPlotCanvas::PaintCached); - -#if QT_VERSION >= 0x040000 - const bool noBackgroundMode = testAttribute(Qt::WA_NoBackground); - if ( !erase && !noBackgroundMode ) - setAttribute(Qt::WA_NoBackground, true); - - repaint(contentsRect()); - - if ( !erase && !noBackgroundMode ) - setAttribute(Qt::WA_NoBackground, false); -#else - repaint(contentsRect(), erase); -#endif + if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) ) + repaint( contentsRect() ); + else + update( contentsRect() ); +} + +//! Update the cached informations about the current style sheet +void QwtPlotCanvas::updateStyleSheetInfo() +{ + if ( !testAttribute(Qt::WA_StyledBackground ) ) + return; + + QwtStyleSheetRecorder recorder( size() ); + + QPainter painter( &recorder ); + + QStyleOption opt; + opt.initFrom(this); + style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this); + + painter.end(); + + d_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty(); + d_data->styleSheet.cornerRects = recorder.clipRects; + + if ( recorder.background.path.isEmpty() ) + { + if ( !recorder.border.rectList.isEmpty() ) + { + d_data->styleSheet.borderPath = + qwtCombinePathList( rect(), recorder.border.pathList ); + } + } + else + { + d_data->styleSheet.borderPath = recorder.background.path; + d_data->styleSheet.background.brush = recorder.background.brush; + d_data->styleSheet.background.origin = recorder.background.origin; + } +} + +/*! + Calculate the painter path for a styled or rounded border + + When the canvas has no styled background or rounded borders + the painter path is empty. + + \param rect Bounding rectangle of the canvas + \return Painter path, that can be used for clipping +*/ +QPainterPath QwtPlotCanvas::borderPath( const QRect &rect ) const +{ + if ( testAttribute(Qt::WA_StyledBackground ) ) + { + QwtStyleSheetRecorder recorder( rect.size() ); + + QPainter painter( &recorder ); + + QStyleOption opt; + opt.initFrom(this); + opt.rect = rect; + style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this); + + painter.end(); + + if ( !recorder.background.path.isEmpty() ) + return recorder.background.path; + + if ( !recorder.border.rectList.isEmpty() ) + return qwtCombinePathList( rect, recorder.border.pathList ); + } + else if ( d_data->borderRadius > 0.0 ) + { + double fw2 = frameWidth() * 0.5; + QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 ); + + QPainterPath path; + path.addRoundedRect( r, d_data->borderRadius, d_data->borderRadius ); + return path; + } + + return QPainterPath(); +} + +/*! + Calculate a mask, that can be used to clip away the border frame + + \param size Size including the frame +*/ +QBitmap QwtPlotCanvas::borderMask( const QSize &size ) const +{ + const QRect r( 0, 0, size.width(), size.height() ); + + const QPainterPath path = borderPath( r ); + if ( path.isEmpty() ) + return QBitmap(); + + QImage image( size, QImage::Format_ARGB32_Premultiplied ); + image.fill( Qt::color0 ); + + QPainter painter( &image ); + painter.setClipPath( path ); + painter.fillRect( r, Qt::color1 ); + + // now erase the frame + + painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); + + if ( testAttribute(Qt::WA_StyledBackground ) ) + { + QStyleOptionFrame opt; + opt.initFrom(this); + opt.rect = r; + style()->drawPrimitive( QStyle::PE_Frame, &opt, &painter, this ); + } + else + { + if ( d_data->borderRadius > 0 && frameWidth() > 0 ) + { + painter.setPen( QPen( Qt::color1, frameWidth() ) ); + painter.setBrush( Qt::NoBrush ); + painter.setRenderHint( QPainter::Antialiasing, true ); + + painter.drawPath( path ); + } + } + + painter.end(); + + const QImage mask = image.createMaskFromColor( + QColor( Qt::color1 ).rgb(), Qt::MaskOutColor ); + + return QBitmap::fromImage( mask ); } diff --git a/qwt/src/qwt_plot_canvas.h b/qwt/src/qwt_plot_canvas.h index 71aa7b6db..c6ff758be 100644 --- a/qwt/src/qwt_plot_canvas.h +++ b/qwt/src/qwt_plot_canvas.h @@ -2,26 +2,26 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #ifndef QWT_PLOT_CANVAS_H #define QWT_PLOT_CANVAS_H +#include "qwt_global.h" #include #include -#include "qwt_global.h" +#include +#include class QwtPlot; class QPixmap; /*! - \brief Canvas of a QwtPlot. - \sa QwtPlot + \brief Canvas of a QwtPlot. + \sa QwtPlot */ class QWT_EXPORT QwtPlotCanvas : public QFrame { @@ -31,31 +31,72 @@ public: /*! \brief Paint attributes - - - PaintCached\n - Paint double buffered and reuse the content of the pixmap buffer - for some spontaneous repaints that happen when a plot gets unhidden, - deiconified or changes the focus. - Disabling the cache will improve the performance for - incremental paints (using QwtPlotCurve::draw). - - PaintPacked\n - Suppress system background repaints and paint it together with - the canvas contents. - Painting packed might avoid flickering for expensive repaints, - when there is a notable gap between painting the background - and the plot contents. + The default setting enables BackingStore and Opaque. - The default setting enables PaintCached and PaintPacked - - \sa setPaintAttribute(), testPaintAttribute(), paintCache() + \sa setPaintAttribute(), testPaintAttribute() */ enum PaintAttribute { - PaintCached = 1, - PaintPacked = 2 + /*! + \brief Paint double buffered reusing the content + of the pixmap buffer when possible. + + Using a backing store might improve the performance + significantly, when workin with widget overlays ( like rubberbands ). + Disabling the cache might improve the performance for + incremental paints (using QwtPlotDirectPainter ). + + \sa backingStore(), invalidateBackingStore() + */ + BackingStore = 1, + + /*! + \brief Try to fill the complete contents rectangle + of the plot canvas + + When using styled backgrounds Qt assumes, that the + canvas doesn't fill its area completely + ( f.e because of rounded borders ) and fills the area + below the canvas. When this is done with gradients it might + result in a serious performance bottleneck - depending on the size. + + When the Opaque attribute is enabled the canvas tries to + identify the gaps with some heuristics and to fill those only. + + \warning Will not work for semitransparent backgrounds + */ + Opaque = 2, + + /*! + \brief Try to improve painting of styled backgrounds + + QwtPlotCanvas supports the box model attributes for + customizing the layout with style sheets. Unfortunately + the design of Qt style sheets has no concept how to + handle backgrounds with rounded corners - beside of padding. + + When HackStyledBackground is enabled the plot canvas tries + to seperate the background from the background border + by reverse engeneering to paint the background before and + the border after the plot items. In this order the border + gets prefectly antialiased and you can avoid some pixel + artifacts in the corners. + */ + HackStyledBackground = 4, + + /*! + When ImmediatePaint is set replot() calls repaint() + instead of update(). + + \sa replot(), QWidget::repaint(), QWidget::update() + */ + ImmediatePaint = 8 }; + //! Paint attributes + typedef QFlags PaintAttributes; + /*! \brief Focus indicator @@ -81,39 +122,47 @@ public: ItemFocusIndicator }; - explicit QwtPlotCanvas(QwtPlot *); + explicit QwtPlotCanvas( QwtPlot * ); virtual ~QwtPlotCanvas(); QwtPlot *plot(); const QwtPlot *plot() const; - void setFocusIndicator(FocusIndicator); + void setFocusIndicator( FocusIndicator ); FocusIndicator focusIndicator() const; - void setPaintAttribute(PaintAttribute, bool on = true); - bool testPaintAttribute(PaintAttribute) const; + void setBorderRadius( double ); + double borderRadius() const; - QPixmap *paintCache(); - const QPixmap *paintCache() const; - void invalidatePaintCache(); + QPainterPath borderPath( const QRect &rect ) const; + QBitmap borderMask( const QSize & ) const; + + void setPaintAttribute( PaintAttribute, bool on = true ); + bool testPaintAttribute( PaintAttribute ) const; + + const QPixmap *backingStore() const; + void invalidateBackingStore(); void replot(); + virtual bool event( QEvent * ); + protected: - virtual void hideEvent(QHideEvent *); + virtual void paintEvent( QPaintEvent * ); + virtual void resizeEvent( QResizeEvent * ); - virtual void paintEvent(QPaintEvent *); + virtual void drawFocusIndicator( QPainter * ); + virtual void drawBorder( QPainter * ); - virtual void drawContents(QPainter *); - virtual void drawFocusIndicator(QPainter *); + void updateStyleSheetInfo(); - void drawCanvas(QPainter *painter = NULL); - -private: - void setSystemBackground(bool); +private: + void drawCanvas( QPainter *, bool withBackground ); class PrivateData; PrivateData *d_data; }; +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCanvas::PaintAttributes ) + #endif diff --git a/qwt/src/qwt_plot_curve.cpp b/qwt/src/qwt_plot_curve.cpp index 35f06a21e..cb786c7c6 100644 --- a/qwt/src/qwt_plot_curve.cpp +++ b/qwt/src/qwt_plot_curve.cpp @@ -7,195 +7,48 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -#include -#include -#include -#include "qwt_global.h" -#include "qwt_legend.h" -#include "qwt_legend_item.h" -#include "qwt_data.h" -#include "qwt_scale_map.h" -#include "qwt_double_rect.h" +#include "qwt_plot_curve.h" #include "qwt_math.h" #include "qwt_clipper.h" #include "qwt_painter.h" +#include "qwt_legend.h" +#include "qwt_legend_item.h" +#include "qwt_scale_map.h" #include "qwt_plot.h" #include "qwt_plot_canvas.h" #include "qwt_curve_fitter.h" #include "qwt_symbol.h" -#include "qwt_plot_curve.h" +#include +#include +#include +#include -#if QT_VERSION < 0x040000 -#include -#else -#include -#endif - -#if QT_VERSION >= 0x040000 - -#include -#include - -class QwtPlotCurvePaintHelper: public QObject +static int verifyRange( int size, int &i1, int &i2 ) { -public: - QwtPlotCurvePaintHelper(const QwtPlotCurve *curve, int from, int to): - _curve(curve), - _from(from), - _to(to) - { - } - - virtual bool eventFilter(QObject *, QEvent *event) - { - if ( event->type() == QEvent::Paint ) - { - _curve->draw(_from, _to); - return true; - } - return false; - } -private: - const QwtPlotCurve *_curve; - int _from; - int _to; -}; - -#endif // QT_VERSION >= 0x040000 - -// Creating and initializing a QPainter is an -// expensive operation. So we keep an painter -// open for situations, where we paint outside -// of paint events. This improves the performance -// of incremental painting like in the realtime -// example a lot. -// But it is not possible to have more than -// one QPainter open at the same time. So we -// need to close it before regular paint events -// are processed. - -class QwtGuardedPainter: public QObject -{ -public: - ~QwtGuardedPainter() - { - end(); - } - - QPainter *begin(QwtPlotCanvas *canvas) - { - _canvas = canvas; - - QMap::iterator it = _map.find(_canvas); - if ( it == _map.end() ) - { - QPainter *painter = new QPainter(_canvas); - painter->setClipping(true); - painter->setClipRect(_canvas->contentsRect()); - - it = _map.insert(_canvas, painter); - _canvas->installEventFilter(this); - } -#if QT_VERSION < 0x040000 - return it.data(); -#else - return it.value(); -#endif - } - - void end() - { - if ( _canvas ) - { - QMap::iterator it = _map.find(_canvas); - if ( it != _map.end() ) - { - _canvas->removeEventFilter(this); - -#if QT_VERSION < 0x040000 - delete it.data(); -#else - delete it.value(); -#endif - _map.erase(it); - } - } - } - - virtual bool eventFilter(QObject *, QEvent *event) - { - if ( event->type() == QEvent::Paint ) - end(); - - return false; - } - -private: -#if QT_VERSION < 0x040000 - QGuardedPtr _canvas; -#else - QPointer _canvas; -#endif - static QMap _map; -}; - -QMap QwtGuardedPainter::_map; - -static int verifyRange(int size, int &i1, int &i2) -{ - if (size < 1) + if ( size < 1 ) return 0; - i1 = qwtLim(i1, 0, size-1); - i2 = qwtLim(i2, 0, size-1); + i1 = qBound( 0, i1, size - 1 ); + i2 = qBound( 0, i2, size - 1 ); if ( i1 > i2 ) - qSwap(i1, i2); + qSwap( i1, i2 ); - return (i2 - i1 + 1); + return ( i2 - i1 + 1 ); } class QwtPlotCurve::PrivateData { public: - class PixelMatrix: private QBitArray - { - public: - PixelMatrix(const QRect& rect): - QBitArray(rect.width() * rect.height()), - _rect(rect) - { - fill(false); - } - - inline bool testPixel(const QPoint& pos) - { - if ( !_rect.contains(pos) ) - return false; - - const int idx = _rect.width() * (pos.y() - _rect.y()) + - (pos.x() - _rect.x()); - - const bool marked = testBit(idx); - if ( !marked ) - setBit(idx, true); - - return !marked; - } - - private: - QRect _rect; - }; - PrivateData(): - curveType(Yfx), - style(QwtPlotCurve::Lines), - reference(0.0), - attributes(0), - paintAttributes(0) + style( QwtPlotCurve::Lines ), + baseline( 0.0 ), + symbol( NULL ), + attributes( 0 ), + paintAttributes( QwtPlotCurve::ClipPolygons ), + legendAttributes( 0 ) { - symbol = new QwtSymbol(); - pen = QPen(Qt::black); + pen = QPen( Qt::black ); curveFitter = new QwtSplineCurveFitter; } @@ -205,45 +58,37 @@ public: delete curveFitter; } - QwtPlotCurve::CurveType curveType; QwtPlotCurve::CurveStyle style; - double reference; + double baseline; - QwtSymbol *symbol; + const QwtSymbol *symbol; QwtCurveFitter *curveFitter; QPen pen; QBrush brush; - int attributes; - int paintAttributes; + QwtPlotCurve::CurveAttributes attributes; + QwtPlotCurve::PaintAttributes paintAttributes; - QwtGuardedPainter guardedPainter; + QwtPlotCurve::LegendAttributes legendAttributes; }; -//! Constructor -QwtPlotCurve::QwtPlotCurve(): - QwtPlotItem(QwtText()) +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotCurve::QwtPlotCurve( const QwtText &title ): + QwtPlotSeriesItem( title ) { init(); } /*! Constructor - \param title Title of the curve + \param title Title of the curve */ -QwtPlotCurve::QwtPlotCurve(const QwtText &title): - QwtPlotItem(title) -{ - init(); -} - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotCurve::QwtPlotCurve(const QString &title): - QwtPlotItem(QwtText(title)) +QwtPlotCurve::QwtPlotCurve( const QString &title ): + QwtPlotSeriesItem( QwtText( title ) ) { init(); } @@ -251,22 +96,19 @@ QwtPlotCurve::QwtPlotCurve(const QString &title): //! Destructor QwtPlotCurve::~QwtPlotCurve() { - delete d_xy; delete d_data; } -/*! - \brief Initialize data members -*/ +//! Initialize internal members void QwtPlotCurve::init() { - setItemAttribute(QwtPlotItem::Legend); - setItemAttribute(QwtPlotItem::AutoScale); + setItemAttribute( QwtPlotItem::Legend ); + setItemAttribute( QwtPlotItem::AutoScale ); d_data = new PrivateData; - d_xy = new QwtPolygonFData(QwtArray()); + d_series = new QwtPointSeriesData(); - setZ(20.0); + setZ( 20.0 ); } //! \return QwtPlotItem::Rtti_PlotCurve @@ -280,9 +122,9 @@ int QwtPlotCurve::rtti() const \param attribute Paint attribute \param on On/Off - /sa PaintAttribute, testPaintAttribute() + \sa testPaintAttribute() */ -void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on) +void QwtPlotCurve::setPaintAttribute( PaintAttribute attribute, bool on ) { if ( on ) d_data->paintAttributes |= attribute; @@ -292,20 +134,44 @@ void QwtPlotCurve::setPaintAttribute(PaintAttribute attribute, bool on) /*! \brief Return the current paint attributes - \sa PaintAttribute, setPaintAttribute() + \sa setPaintAttribute() */ -bool QwtPlotCurve::testPaintAttribute(PaintAttribute attribute) const +bool QwtPlotCurve::testPaintAttribute( PaintAttribute attribute ) const { - return (d_data->paintAttributes & attribute); + return ( d_data->paintAttributes & attribute ); +} + +/*! + Specify an attribute how to draw the legend identifier + + \param attribute Attribute + \param on On/Off + /sa testLegendAttribute() +*/ +void QwtPlotCurve::setLegendAttribute( LegendAttribute attribute, bool on ) +{ + if ( on ) + d_data->legendAttributes |= attribute; + else + d_data->legendAttributes &= ~attribute; +} + +/*! + \brief Return the current paint attributes + \sa setLegendAttribute() +*/ +bool QwtPlotCurve::testLegendAttribute( LegendAttribute attribute ) const +{ + return ( d_data->legendAttributes & attribute ); } /*! Set the curve's drawing style \param style Curve style - \sa CurveStyle, style() + \sa style() */ -void QwtPlotCurve::setStyle(CurveStyle style) +void QwtPlotCurve::setStyle( CurveStyle style ) { if ( style != d_data->style ) { @@ -316,44 +182,45 @@ void QwtPlotCurve::setStyle(CurveStyle style) /*! Return the current style - \sa CurveStyle, setStyle() + \sa setStyle() */ -QwtPlotCurve::CurveStyle QwtPlotCurve::style() const -{ - return d_data->style; +QwtPlotCurve::CurveStyle QwtPlotCurve::style() const +{ + return d_data->style; } /*! - \brief Assign a symbol + Assign a symbol + \param symbol Symbol \sa symbol() */ -void QwtPlotCurve::setSymbol(const QwtSymbol &symbol ) +void QwtPlotCurve::setSymbol( const QwtSymbol *symbol ) { - delete d_data->symbol; - d_data->symbol = symbol.clone(); - itemChanged(); + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + itemChanged(); + } } /*! - \brief Return the current symbol - \sa setSymbol() + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() */ -const QwtSymbol &QwtPlotCurve::symbol() const -{ - return *d_data->symbol; +const QwtSymbol *QwtPlotCurve::symbol() const +{ + return d_data->symbol; } /*! Assign a pen - The width of non cosmetic pens is scaled according to the resolution - of the paint device. - \param pen New pen - \sa pen(), brush(), QwtPainter::scaledPen() + \sa pen(), brush() */ -void QwtPlotCurve::setPen(const QPen &pen) +void QwtPlotCurve::setPen( const QPen &pen ) { if ( pen != d_data->pen ) { @@ -363,30 +230,30 @@ void QwtPlotCurve::setPen(const QPen &pen) } /*! - \brief Return the pen used to draw the lines - \sa setPen(), brush() + \return Pen used to draw the lines + \sa setPen(), brush() */ -const QPen& QwtPlotCurve::pen() const -{ - return d_data->pen; +const QPen& QwtPlotCurve::pen() const +{ + return d_data->pen; } /*! - \brief Assign a brush. + \brief Assign a brush. - In case of brush.style() != QBrush::NoBrush + In case of brush.style() != QBrush::NoBrush and style() != QwtPlotCurve::Sticks the area between the curve and the baseline will be filled. In case !brush.color().isValid() the area will be filled by pen.color(). The fill algorithm simply connects the first and the - last curve point to the baseline. So the curve data has to be sorted - (ascending or descending). + last curve point to the baseline. So the curve data has to be sorted + (ascending or descending). \param brush New brush \sa brush(), setBaseline(), baseline() */ -void QwtPlotCurve::setBrush(const QBrush &brush) +void QwtPlotCurve::setBrush( const QBrush &brush ) { if ( brush != d_data->brush ) { @@ -396,301 +263,97 @@ void QwtPlotCurve::setBrush(const QBrush &brush) } /*! - \brief Return the brush used to fill the area between lines and the baseline + \return Brush used to fill the area between lines and the baseline \sa setBrush(), setBaseline(), baseline() */ -const QBrush& QwtPlotCurve::brush() const +const QBrush& QwtPlotCurve::brush() const { return d_data->brush; } - /*! - Set data by copying x- and y-values from specified memory blocks. - Contrary to setCurveRawData(), this function makes a 'deep copy' of - the data. - - \param xData Pointer to x values - \param yData Pointer to y values - \param size Size of xData and yData - - \note Internally the data is stored in a QwtArrayData object -*/ -void QwtPlotCurve::setData(const double *xData, const double *yData, int size) -{ - delete d_xy; - d_xy = new QwtArrayData(xData, yData, size); - itemChanged(); -} - -/*! - Initialize data with x- and y-arrays (explicitly shared) - ( Builds an QwtArrayData object internally ) - - \param xData x data - \param yData y data - - \note Internally the data is stored in a QwtArrayData object -*/ -void QwtPlotCurve::setData(const QwtArray &xData, - const QwtArray &yData) -{ - delete d_xy; - d_xy = new QwtArrayData(xData, yData); - itemChanged(); -} - -/*! - Initialize data with an array of points (explicitly shared). - - \param data Data - \note Internally the data is stored in a QwtPolygonFData object -*/ -#if QT_VERSION < 0x040000 -void QwtPlotCurve::setData(const QwtArray &data) -#else -void QwtPlotCurve::setData(const QPolygonF &data) -#endif -{ - delete d_xy; - d_xy = new QwtPolygonFData(data); - itemChanged(); -} - -/*! - Initialize data with a pointer to QwtData. - - \param data Data - \sa QwtData::copy() -*/ -void QwtPlotCurve::setData(const QwtData &data) -{ - delete d_xy; - d_xy = data.copy(); - itemChanged(); -} - -/*! - \brief Initialize the data by pointing to memory blocks which are not managed - by QwtPlotCurve. - - setRawData is provided for efficiency. It is important to keep the pointers - during the lifetime of the underlying QwtCPointerData class. - - \param xData pointer to x data - \param yData pointer to y data - \param size size of x and y - - \note Internally the data is stored in a QwtCPointerData object -*/ -void QwtPlotCurve::setRawData(const double *xData, const double *yData, int size) -{ - delete d_xy; - d_xy = new QwtCPointerData(xData, yData, size); - itemChanged(); -} - -/*! - Returns the bounding rectangle of the curve data. If there is - no bounding rect, like for empty data the rectangle is invalid. - \sa QwtData::boundingRect(), QwtDoubleRect::isValid() -*/ - -QwtDoubleRect QwtPlotCurve::boundingRect() const -{ - if ( d_xy == NULL ) - return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid - - return d_xy->boundingRect(); -} - -/*! - \brief Draw the complete curve + Draw an interval of the curve \param painter Painter \param xMap Maps x-values into pixel coordinates. \param yMap Maps y-values into pixel coordinates. - - \sa drawCurve(), drawSymbols() -*/ -void QwtPlotCurve::draw(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &) const -{ - draw(painter, xMap, yMap, 0, -1); -} - -/*! - \brief Draw a set of points of a curve. - - When observing an measurement while it is running, new points have to be - added to an existing curve. drawCurve can be used to display them avoiding - a complete redraw of the canvas. - - Setting plot()->canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); - will result in faster painting, if the paint engine of the canvas widget - supports this feature. - + \param canvasRect Contents rect of the canvas \param from Index of the first point to be painted \param to Index of the last point to be painted. If to < 0 the curve will be painted to its last point. - \sa drawCurve(), drawSymbols() -*/ -void QwtPlotCurve::draw(int from, int to) const -{ - if ( !plot() ) - return; - - QwtPlotCanvas *canvas = plot()->canvas(); - -#if QT_VERSION >= 0x040000 -#if 0 - if ( canvas->paintEngine()->type() == QPaintEngine::OpenGL ) - { - /* - OpenGL alway repaint the complete widget. - So for this operation OpenGL is one of the slowest - environments. - */ - canvas->repaint(); - return; - } -#endif - - if ( !canvas->testAttribute(Qt::WA_WState_InPaintEvent) && - !canvas->testAttribute(Qt::WA_PaintOutsidePaintEvent) ) - { - /* - We save curve and range in helper and call repaint. - The helper filters the Paint event, to repeat - the QwtPlotCurve::draw, but now from inside the paint - event. - */ - - QwtPlotCurvePaintHelper helper(this, from, to); - canvas->installEventFilter(&helper); - - const bool noSystemBackground = - canvas->testAttribute(Qt::WA_NoSystemBackground); - canvas->setAttribute(Qt::WA_NoSystemBackground, true); - canvas->repaint(); - canvas->setAttribute(Qt::WA_NoSystemBackground, noSystemBackground); - - return; - } -#endif - - const QwtScaleMap xMap = plot()->canvasMap(xAxis()); - const QwtScaleMap yMap = plot()->canvasMap(yAxis()); - - if ( canvas->testPaintAttribute(QwtPlotCanvas::PaintCached) && - canvas->paintCache() && !canvas->paintCache()->isNull() ) - { - QPainter cachePainter((QPixmap *)canvas->paintCache()); - cachePainter.translate(-canvas->contentsRect().x(), - -canvas->contentsRect().y()); - - draw(&cachePainter, xMap, yMap, from, to); - } - -#if QT_VERSION >= 0x040000 - if ( canvas->testAttribute(Qt::WA_WState_InPaintEvent) ) - { - QPainter painter(canvas); - - painter.setClipping(true); - painter.setClipRect(canvas->contentsRect()); - - draw(&painter, xMap, yMap, from, to); - } - else -#endif - { - QPainter *painter = d_data->guardedPainter.begin(canvas); - draw(painter, xMap, yMap, from, to); - } -} - -/*! - \brief Draw an interval of the curve - \param painter Painter - \param xMap maps x-values into pixel coordinates. - \param yMap maps y-values into pixel coordinates. - \param from index of the first point to be painted - \param to index of the last point to be painted. If to < 0 the - curve will be painted to its last point. - \sa drawCurve(), drawSymbols(), */ -void QwtPlotCurve::draw(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const { if ( !painter || dataSize() <= 0 ) return; - if (to < 0) + if ( to < 0 ) to = dataSize() - 1; - if ( verifyRange(dataSize(), from, to) > 0 ) + if ( verifyRange( dataSize(), from, to ) > 0 ) { painter->save(); - painter->setPen(QwtPainter::scaledPen(d_data->pen)); + painter->setPen( d_data->pen ); /* - Qt 4.0.0 is slow when drawing lines, but it's even + Qt 4.0.0 is slow when drawing lines, but it's even slower when the painter has a brush. So we don't set the brush before we really need it. */ - drawCurve(painter, d_data->style, xMap, yMap, from, to); + drawCurve( painter, d_data->style, xMap, yMap, canvasRect, from, to ); painter->restore(); - if (d_data->symbol->style() != QwtSymbol::NoSymbol) + if ( d_data->symbol && + ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) { painter->save(); - drawSymbols(painter, *d_data->symbol, xMap, yMap, from, to); + drawSymbols( painter, *d_data->symbol, + xMap, yMap, canvasRect, from, to ); painter->restore(); } } } /*! - \brief Draw the line part (without symbols) of a curve interval. + \brief Draw the line part (without symbols) of a curve interval. \param painter Painter \param style curve style, see QwtPlotCurve::CurveStyle \param xMap x map \param yMap y map + \param canvasRect Contents rect of the canvas \param from index of the first point to be painted \param to index of the last point to be painted \sa draw(), drawDots(), drawLines(), drawSteps(), drawSticks() */ - -void QwtPlotCurve::drawCurve(QPainter *painter, int style, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawCurve( QPainter *painter, int style, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const { - switch (style) + switch ( style ) { case Lines: - if ( testCurveAttribute(Fitted) ) + if ( testCurveAttribute( Fitted ) ) { - // we always need the complete + // we always need the complete // curve for fitting from = 0; to = dataSize() - 1; } - drawLines(painter, xMap, yMap, from, to); + drawLines( painter, xMap, yMap, canvasRect, from, to ); break; case Sticks: - drawSticks(painter, xMap, yMap, from, to); + drawSticks( painter, xMap, yMap, canvasRect, from, to ); break; case Steps: - drawSteps(painter, xMap, yMap, from, to); + drawSteps( painter, xMap, yMap, canvasRect, from, to ); break; case Dots: - drawDots(painter, xMap, yMap, from, to); + drawDots( painter, xMap, yMap, canvasRect, from, to ); break; case NoCurve: default: @@ -707,125 +370,60 @@ void QwtPlotCurve::drawCurve(QPainter *painter, int style, \param painter Painter \param xMap x map \param yMap y map + \param canvasRect Contents rect of the canvas \param from index of the first point to be painted \param to index of the last point to be painted - \sa setCurveAttribute(), setCurveFitter(), draw(), + \sa setCurveAttribute(), setCurveFitter(), draw(), drawLines(), drawDots(), drawSteps(), drawSticks() */ -void QwtPlotCurve::drawLines(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawLines( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const { int size = to - from + 1; if ( size <= 0 ) return; - QwtPolygon polyline; - if ( ( d_data->attributes & Fitted ) && d_data->curveFitter ) + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + QPolygonF polyline( size ); + + QPointF *points = polyline.data(); + for ( int i = from; i <= to; i++ ) { - // Transform x and y values to window coordinates - // to avoid a distinction between linear and - // logarithmic scales. + const QPointF sample = d_series->sample( i ); -#if QT_VERSION < 0x040000 - QwtArray points(size); -#else - QPolygonF points(size); -#endif - for (int i = from; i <= to; i++) + double x = xMap.transform( sample.x() ); + double y = yMap.transform( sample.y() ); + if ( doAlign ) { - QwtDoublePoint &p = points[i]; - p.setX( xMap.xTransform(x(i)) ); - p.setY( yMap.xTransform(y(i)) ); + x = qRound( x ); + y = qRound( y ); } - points = d_data->curveFitter->fitCurve(points); - size = points.size(); + points[i - from].rx() = x; + points[i - from].ry() = y; + } - if ( size == 0 ) - return; + if ( ( d_data->attributes & Fitted ) && d_data->curveFitter ) + polyline = d_data->curveFitter->fitCurve( polyline ); - // Round QwtDoublePoints to QPoints - // When Qwt support for Qt3 has been dropped (Qwt 6.x) - // we will use a doubles for painting and the following - // step will be obsolete. + if ( d_data->paintAttributes & ClipPolygons ) + { + qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF()); + const QPolygonF clipped = QwtClipper::clipPolygonF( + canvasRect.adjusted(-pw, -pw, pw, pw), polyline, false ); - polyline.resize(size); - - const QwtDoublePoint *p = points.data(); - QPoint *pl = polyline.data(); - if ( d_data->paintAttributes & PaintFiltered ) - { - - QPoint pp(qRound(p[0].x()), qRound(p[0].y())); - pl[0] = pp; - - int count = 1; - for (int i = 1; i < size; i++) - { - const QPoint pi(qRound(p[i].x()), qRound(p[i].y())); - if ( pi != pp ) - { - pl[count++] = pi; - pp = pi; - } - } - if ( count != size ) - polyline.resize(count); - } - else - { - for ( int i = 0; i < size; i++ ) - { - pl[i].setX( qRound(p[i].x()) ); - pl[i].setY( qRound(p[i].y()) ); - } - } + QwtPainter::drawPolyline( painter, clipped ); } else { - polyline.resize(size); - - if ( d_data->paintAttributes & PaintFiltered ) - { - QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) ); - polyline.setPoint(0, pp); - - int count = 1; - for (int i = from + 1; i <= to; i++) - { - const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i))); - if ( pi != pp ) - { - polyline.setPoint(count, pi); - count++; - - pp = pi; - } - } - if ( count != size ) - polyline.resize(count); - } - else - { - for (int i = from; i <= to; i++) - { - int xi = xMap.transform(x(i)); - int yi = yMap.transform(y(i)); - - polyline.setPoint(i - from, xi, yi); - } - } + QwtPainter::drawPolyline( painter, polyline ); } - if ( d_data->paintAttributes & ClipPolygons ) - polyline = QwtClipper::clipPolygon(painter->window(), polyline); - - QwtPainter::drawPolyline(painter, polyline); - if ( d_data->brush.style() != Qt::NoBrush ) - fillCurve(painter, xMap, yMap, polyline); + fillCurve( painter, xMap, yMap, canvasRect, polyline ); } /*! @@ -834,28 +432,49 @@ void QwtPlotCurve::drawLines(QPainter *painter, \param painter Painter \param xMap x map \param yMap y map + \param canvasRect Contents rect of the canvas \param from index of the first point to be painted \param to index of the last point to be painted \sa draw(), drawCurve(), drawDots(), drawLines(), drawSteps() */ -void QwtPlotCurve::drawSticks(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawSticks( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &, int from, int to ) const { - int x0 = xMap.transform(d_data->reference); - int y0 = yMap.transform(d_data->reference); + painter->save(); + painter->setRenderHint( QPainter::Antialiasing, false ); - for (int i = from; i <= to; i++) + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + double x0 = xMap.transform( d_data->baseline ); + double y0 = yMap.transform( d_data->baseline ); + if ( doAlign ) { - const int xi = xMap.transform(x(i)); - const int yi = yMap.transform(y(i)); - - if (d_data->curveType == Xfy) - QwtPainter::drawLine(painter, x0, yi, xi, yi); - else - QwtPainter::drawLine(painter, xi, y0, xi, yi); + x0 = qRound( x0 ); + y0 = qRound( y0 ); } + + const Qt::Orientation o = orientation(); + + for ( int i = from; i <= to; i++ ) + { + const QPointF sample = d_series->sample( i ); + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + if ( doAlign ) + { + xi = qRound( xi ); + yi = qRound( yi ); + } + + if ( o == Qt::Horizontal ) + QwtPainter::drawLine( painter, x0, yi, xi, yi ); + else + QwtPainter::drawLine( painter, xi, y0, xi, yi ); + } + + painter->restore(); } /*! @@ -864,138 +483,124 @@ void QwtPlotCurve::drawSticks(QPainter *painter, \param painter Painter \param xMap x map \param yMap y map + \param canvasRect Contents rect of the canvas \param from index of the first point to be painted \param to index of the last point to be painted \sa draw(), drawCurve(), drawSticks(), drawLines(), drawSteps() */ -void QwtPlotCurve::drawDots(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawDots( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const { - const QRect window = painter->window(); - if ( window.isEmpty() ) - return; - const bool doFill = d_data->brush.style() != Qt::NoBrush; + const bool doAlign = QwtPainter::roundingAlignment( painter ); - QwtPolygon polyline; + QPolygonF polyline; if ( doFill ) - polyline.resize(to - from + 1); + polyline.resize( to - from + 1 ); - if ( to > from && d_data->paintAttributes & PaintFiltered ) + QPointF *points = polyline.data(); + + for ( int i = from; i <= to; i++ ) { - if ( doFill ) + const QPointF sample = d_series->sample( i ); + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + if ( doAlign ) { - QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) ); - - QwtPainter::drawPoint(painter, pp.x(), pp.y()); - polyline.setPoint(0, pp); - - int count = 1; - for (int i = from + 1; i <= to; i++) - { - const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i))); - if ( pi != pp ) - { - QwtPainter::drawPoint(painter, pi.x(), pi.y()); - - polyline.setPoint(count, pi); - count++; - - pp = pi; - } - } - if ( int(polyline.size()) != count ) - polyline.resize(count); + xi = qRound( xi ); + yi = qRound( yi ); } - else + + QwtPainter::drawPoint( painter, QPointF( xi, yi ) ); + + if ( doFill ) { - // if we don't need to fill, we can sort out - // duplicates independent from the order - - PrivateData::PixelMatrix pixelMatrix(window); - - for (int i = from; i <= to; i++) - { - const QPoint p( xMap.transform(x(i)), - yMap.transform(y(i)) ); - - if ( pixelMatrix.testPixel(p) ) - QwtPainter::drawPoint(painter, p.x(), p.y()); - } - } - } - else - { - for (int i = from; i <= to; i++) - { - const int xi = xMap.transform(x(i)); - const int yi = yMap.transform(y(i)); - QwtPainter::drawPoint(painter, xi, yi); - - if ( doFill ) - polyline.setPoint(i - from, xi, yi); + points[i - from].rx() = xi; + points[i - from].ry() = yi; } } if ( doFill ) - { - if ( d_data->paintAttributes & ClipPolygons ) - polyline = QwtClipper::clipPolygon(painter->window(), polyline); - - fillCurve(painter, xMap, yMap, polyline); - } + fillCurve( painter, xMap, yMap, canvasRect, polyline ); } /*! Draw step function - The direction of the steps depends on Inverted attribute. + The direction of the steps depends on Inverted attribute. \param painter Painter \param xMap x map \param yMap y map + \param canvasRect Contents rect of the canvas \param from index of the first point to be painted \param to index of the last point to be painted \sa CurveAttribute, setCurveAttribute(), draw(), drawCurve(), drawDots(), drawLines(), drawSticks() */ -void QwtPlotCurve::drawSteps(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawSteps( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const { - QwtPolygon polyline(2 * (to - from) + 1); + const bool doAlign = QwtPainter::roundingAlignment( painter ); - bool inverted = d_data->curveType == Yfx; + QPolygonF polygon( 2 * ( to - from ) + 1 ); + QPointF *points = polygon.data(); + + bool inverted = orientation() == Qt::Vertical; if ( d_data->attributes & Inverted ) inverted = !inverted; - int i,ip; - for (i = from, ip = 0; i <= to; i++, ip += 2) + int i, ip; + for ( i = from, ip = 0; i <= to; i++, ip += 2 ) { - const int xi = xMap.transform(x(i)); - const int yi = yMap.transform(y(i)); + const QPointF sample = d_series->sample( i ); + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + if ( doAlign ) + { + xi = qRound( xi ); + yi = qRound( yi ); + } if ( ip > 0 ) { - if (inverted) - polyline.setPoint(ip - 1, polyline[ip-2].x(), yi); + const QPointF &p0 = points[ip - 2]; + QPointF &p = points[ip - 1]; + + if ( inverted ) + { + p.rx() = p0.x(); + p.ry() = yi; + } else - polyline.setPoint(ip - 1, xi, polyline[ip-2].y()); + { + p.rx() = xi; + p.ry() = p0.y(); + } } - polyline.setPoint(ip, xi, yi); + points[ip].rx() = xi; + points[ip].ry() = yi; } if ( d_data->paintAttributes & ClipPolygons ) - polyline = QwtClipper::clipPolygon(painter->window(), polyline); + { + const QPolygonF clipped = QwtClipper::clipPolygonF( + canvasRect, polygon, false ); - QwtPainter::drawPolyline(painter, polyline); + QwtPainter::drawPolyline( painter, clipped ); + } + else + { + QwtPainter::drawPolyline( painter, polygon ); + } if ( d_data->brush.style() != Qt::NoBrush ) - fillCurve(painter, xMap, yMap, polyline); + fillCurve( painter, xMap, yMap, canvasRect, polygon ); } @@ -1005,11 +610,11 @@ void QwtPlotCurve::drawSteps(QPainter *painter, \param attribute Curve attribute \param on On/Off - /sa CurveAttribute, testCurveAttribute(), setCurveFitter() + /sa testCurveAttribute(), setCurveFitter() */ -void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on) +void QwtPlotCurve::setCurveAttribute( CurveAttribute attribute, bool on ) { - if ( bool(d_data->attributes & attribute) == on ) + if ( bool( d_data->attributes & attribute ) == on ) return; if ( on ) @@ -1022,44 +627,31 @@ void QwtPlotCurve::setCurveAttribute(CurveAttribute attribute, bool on) /*! \return true, if attribute is enabled - \sa CurveAttribute, setCurveAttribute() + \sa setCurveAttribute() */ -bool QwtPlotCurve::testCurveAttribute(CurveAttribute attribute) const -{ +bool QwtPlotCurve::testCurveAttribute( CurveAttribute attribute ) const +{ return d_data->attributes & attribute; } -/*! - Assign the curve type - - \param curveType Yfx or Xfy - \sa CurveType, curveType() -*/ -void QwtPlotCurve::setCurveType(CurveType curveType) -{ - if ( d_data->curveType != curveType ) - { - d_data->curveType = curveType; - itemChanged(); - } -} - -/*! - Return the curve type - \sa CurveType, setCurveType() -*/ -QwtPlotCurve::CurveType QwtPlotCurve::curveType() const -{ - return d_data->curveType; -} - /*! Assign a curve fitter - setCurveFitter(NULL) disables curve fitting. - \param curveFitter Curve fitter + The curve fitter "smooths" the curve points, when the Fitted + CurveAttribute is set. setCurveFitter(NULL) also disables curve fitting. + + The curve fitter operates on the translated points ( = widget coordinates) + to be functional for logarithmic scales. Obviously this is less performant + for fitting algorithms, that reduce the number of points. + + For situations, where curve fitting is used to improve the performance + of painting huge series of points it might be better to execute the fitter + on the curve points once and to cache the result in the QwtSeriesData object. + + \param curveFitter() Curve fitter + \sa Fitted */ -void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter) +void QwtPlotCurve::setCurveFitter( QwtCurveFitter *curveFitter ) { delete d_data->curveFitter; d_data->curveFitter = curveFitter; @@ -1069,135 +661,191 @@ void QwtPlotCurve::setCurveFitter(QwtCurveFitter *curveFitter) /*! Get the curve fitter. If curve fitting is disabled NULL is returned. + \return Curve fitter + \sa setCurveFitter(), Fitted */ QwtCurveFitter *QwtPlotCurve::curveFitter() const { return d_data->curveFitter; } -/*! - Fill the area between the curve and the baseline with +/*! + Fill the area between the curve and the baseline with the curve brush \param painter Painter \param xMap x map \param yMap y map - \param pa Polygon + \param canvasRect Contents rect of the canvas + \param polygon Polygon - will be modified ! - \sa setBrush(), setBaseline(), setCurveType() + \sa setBrush(), setBaseline(), setStyle() */ -void QwtPlotCurve::fillCurve(QPainter *painter, +void QwtPlotCurve::fillCurve( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - QwtPolygon &pa) const + const QRectF &canvasRect, QPolygonF &polygon ) const { if ( d_data->brush.style() == Qt::NoBrush ) return; - closePolyline(xMap, yMap, pa); - if ( pa.count() <= 2 ) // a line can't be filled + closePolyline( painter, xMap, yMap, polygon ); + if ( polygon.count() <= 2 ) // a line can't be filled return; - QBrush b = d_data->brush; - if ( !b.color().isValid() ) - b.setColor(d_data->pen.color()); + QBrush brush = d_data->brush; + if ( !brush.color().isValid() ) + brush.setColor( d_data->pen.color() ); + + if ( d_data->paintAttributes & ClipPolygons ) + polygon = QwtClipper::clipPolygonF( canvasRect, polygon, true ); painter->save(); - painter->setPen(QPen(Qt::NoPen)); - painter->setBrush(b); + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); - QwtPainter::drawPolygon(painter, pa); + QwtPainter::drawPolygon( painter, polygon ); painter->restore(); } /*! - \brief Complete a polygon to be a closed polygon - including the area between the original polygon - and the baseline. + \brief Complete a polygon to be a closed polygon including the + area between the original polygon and the baseline. + + \param painter Painter \param xMap X map \param yMap Y map - \param pa Polygon to be completed + \param polygon Polygon to be completed */ -void QwtPlotCurve::closePolyline( +void QwtPlotCurve::closePolyline( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - QwtPolygon &pa) const + QPolygonF &polygon ) const { - const int sz = pa.size(); - if ( sz < 2 ) + if ( polygon.size() < 2 ) return; - pa.resize(sz + 2); + const bool doAlign = QwtPainter::roundingAlignment( painter ); - if ( d_data->curveType == QwtPlotCurve::Xfy ) + double baseline = d_data->baseline; + + if ( orientation() == Qt::Vertical ) { - pa.setPoint(sz, - xMap.transform(d_data->reference), pa.point(sz - 1).y()); - pa.setPoint(sz + 1, - xMap.transform(d_data->reference), pa.point(0).y()); + if ( yMap.transformation()->type() == QwtScaleTransformation::Log10 ) + { + if ( baseline < QwtScaleMap::LogMin ) + baseline = QwtScaleMap::LogMin; + } + + double refY = yMap.transform( baseline ); + if ( doAlign ) + refY = qRound( refY ); + + polygon += QPointF( polygon.last().x(), refY ); + polygon += QPointF( polygon.first().x(), refY ); } else { - pa.setPoint(sz, - pa.point(sz - 1).x(), yMap.transform(d_data->reference)); - pa.setPoint(pa.size() - 1, - pa.point(0).x(), yMap.transform(d_data->reference)); + if ( xMap.transformation()->type() == QwtScaleTransformation::Log10 ) + { + if ( baseline < QwtScaleMap::LogMin ) + baseline = QwtScaleMap::LogMin; + } + + double refX = xMap.transform( baseline ); + if ( doAlign ) + refX = qRound( refX ); + + polygon += QPointF( refX, polygon.last().y() ); + polygon += QPointF( refX, polygon.first().y() ); } } /*! - \brief Draw symbols + Draw symbols + \param painter Painter \param symbol Curve symbol \param xMap x map \param yMap y map - \param from index of the first point to be painted - \param to index of the last point to be painted + \param canvasRect Contents rect of the canvas + \param from Index of the first point to be painted + \param to Index of the last point to be painted - \sa setSymbol(), draw(), drawCurve() + \sa setSymbol(), drawSeries(), drawCurve() */ -void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const +void QwtPlotCurve::drawSymbols( QPainter *painter, const QwtSymbol &symbol, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const { - painter->setBrush(symbol.brush()); - painter->setPen(QwtPainter::scaledPen(symbol.pen())); + const bool doAlign = QwtPainter::roundingAlignment( painter ); - const QwtMetricsMap &metricsMap = QwtPainter::metricsMap(); - - QRect rect; - rect.setSize(metricsMap.screenToLayout(symbol.size())); - - if ( to > from && d_data->paintAttributes & PaintFiltered ) + bool usePixmap = testPaintAttribute( CacheSymbols ); + if ( usePixmap && !doAlign ) { - const QRect window = painter->window(); - if ( window.isEmpty() ) - return; + // Don't use the pixmap, when the paint device + // could generate scalable vectors - PrivateData::PixelMatrix pixelMatrix(window); + usePixmap = false; + } - for (int i = from; i <= to; i++) + if ( usePixmap ) + { + QPixmap pm( symbol.boundingSize() ); + pm.fill( Qt::transparent ); + + const double pw2 = 0.5 * pm.width(); + const double ph2 = 0.5 * pm.height(); + + QPainter p( &pm ); + p.setRenderHints( painter->renderHints() ); + symbol.drawSymbol( &p, QPointF( pw2, ph2 ) ); + p.end(); + + for ( int i = from; i <= to; i++ ) { - const QPoint pi( xMap.transform(x(i)), - yMap.transform(y(i)) ); + const QPointF sample = d_series->sample( i ); - if ( pixelMatrix.testPixel(pi) ) + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + if ( doAlign ) { - rect.moveCenter(pi); - symbol.draw(painter, rect); + xi = qRound( xi ); + yi = qRound( yi ); + } + + if ( canvasRect.contains( xi, yi ) ) + { + const int left = qCeil( xi ) - pw2; + const int top = qCeil( yi ) - ph2; + + painter->drawPixmap( left, top, pm ); } } } else { - for (int i = from; i <= to; i++) - { - const int xi = xMap.transform(x(i)); - const int yi = yMap.transform(y(i)); + const int chunkSize = 500; - rect.moveCenter(QPoint(xi, yi)); - symbol.draw(painter, rect); + for ( int i = from; i <= to; i += chunkSize ) + { + const int n = qMin( chunkSize, to - i + 1 ); + + QPolygonF points; + for ( int j = 0; j < n; j++ ) + { + const QPointF sample = d_series->sample( i + j ); + + const double xi = xMap.transform( sample.x() ); + const double yi = yMap.transform( sample.y() ); + + if ( canvasRect.contains( xi, yi ) ) + points += QPointF( xi, yi ); + } + + if ( points.size() > 0 ) + symbol.drawSymbols( painter, points ); } } } @@ -1206,40 +854,33 @@ void QwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol, \brief Set the value of the baseline The baseline is needed for filling the curve with a brush or - the Sticks drawing style. - The default value is 0.0. The interpretation - of the baseline depends on the CurveType. With QwtPlotCurve::Yfx, - the baseline is interpreted as a horizontal line at y = baseline(), - with QwtPlotCurve::Yfy, it is interpreted as a vertical line at - x = baseline(). - \param reference baseline - \sa baseline(), setBrush(), setStyle(), setCurveType() + the Sticks drawing style. + The interpretation of the baseline depends on the CurveType. + With QwtPlotCurve::Yfx, the baseline is interpreted as a horizontal line + at y = baseline(), with QwtPlotCurve::Yfy, it is interpreted as a vertical + line at x = baseline(). + + The default value is 0.0. + + \param value Value of the baseline + \sa baseline(), setBrush(), setStyle(), setStyle() */ -void QwtPlotCurve::setBaseline(double reference) +void QwtPlotCurve::setBaseline( double value ) { - if ( d_data->reference != reference ) + if ( d_data->baseline != value ) { - d_data->reference = reference; + d_data->baseline = value; itemChanged(); } } /*! - Return the value of the baseline - \sa setBaseline() + \return Value of the baseline + \sa setBaseline() */ -double QwtPlotCurve::baseline() const -{ - return d_data->reference; -} - -/*! - Return the size of the data arrays - \sa setData() -*/ -int QwtPlotCurve::dataSize() const +double QwtPlotCurve::baseline() const { - return d_xy->size(); + return d_data->baseline; } /*! @@ -1248,106 +889,235 @@ int QwtPlotCurve::dataSize() const \param pos Position, where to look for the closest curve point \param dist If dist != NULL, closestPoint() returns the distance between the position and the clostest curve point - \return Index of the closest curve point, or -1 if none can be found + \return Index of the closest curve point, or -1 if none can be found ( f.e when the curve has no points ) - \note closestPoint() implements a dumb algorithm, that iterates + \note closestPoint() implements a dumb algorithm, that iterates over all points */ -int QwtPlotCurve::closestPoint(const QPoint &pos, double *dist) const +int QwtPlotCurve::closestPoint( const QPoint &pos, double *dist ) const { if ( plot() == NULL || dataSize() <= 0 ) return -1; - const QwtScaleMap xMap = plot()->canvasMap(xAxis()); - const QwtScaleMap yMap = plot()->canvasMap(yAxis()); + const QwtScaleMap xMap = plot()->canvasMap( xAxis() ); + const QwtScaleMap yMap = plot()->canvasMap( yAxis() ); int index = -1; double dmin = 1.0e10; - for (int i=0; i < dataSize(); i++) + for ( uint i = 0; i < dataSize(); i++ ) { - const double cx = xMap.xTransform(x(i)) - pos.x(); - const double cy = yMap.xTransform(y(i)) - pos.y(); + const QPointF sample = d_series->sample( i ); - const double f = qwtSqr(cx) + qwtSqr(cy); - if (f < dmin) + const double cx = xMap.transform( sample.x() ) - pos.x(); + const double cy = yMap.transform( sample.y() ) - pos.y(); + + const double f = qwtSqr( cx ) + qwtSqr( cy ); + if ( f < dmin ) { index = i; dmin = f; } } if ( dist ) - *dist = sqrt(dmin); + *dist = qSqrt( dmin ); return index; } -//! Update the widget that represents the curve on the legend -void QwtPlotCurve::updateLegend(QwtLegend *legend) const +/*! + \brief Update the widget that represents the item on the legend + + \param legend Legend + \sa drawLegendIdentifier(), legendItem(), QwtPlotItem::Legend +*/ +void QwtPlotCurve::updateLegend( QwtLegend *legend ) const { - if ( !legend ) - return; - - QwtPlotItem::updateLegend(legend); - - QWidget *widget = legend->find(this); - if ( !widget || !widget->inherits("QwtLegendItem") ) - return; - - QwtLegendItem *legendItem = (QwtLegendItem *)widget; - -#if QT_VERSION < 0x040000 - const bool doUpdate = legendItem->isUpdatesEnabled(); -#else - const bool doUpdate = legendItem->updatesEnabled(); -#endif - legendItem->setUpdatesEnabled(false); - - const int policy = legend->displayPolicy(); - - if (policy == QwtLegend::FixedIdentifier) + if ( legend && testItemAttribute( QwtPlotItem::Legend ) + && ( d_data->legendAttributes & QwtPlotCurve::LegendShowSymbol ) + && d_data->symbol + && d_data->symbol->style() != QwtSymbol::NoSymbol ) { - int mode = legend->identifierMode(); - - if (mode & QwtLegendItem::ShowLine) - legendItem->setCurvePen(pen()); - - if (mode & QwtLegendItem::ShowSymbol) - legendItem->setSymbol(symbol()); - - if (mode & QwtLegendItem::ShowText) - legendItem->setText(title()); - else - legendItem->setText(QwtText()); - - legendItem->setIdentifierMode(mode); - } - else if (policy == QwtLegend::AutoIdentifier) - { - int mode = 0; - - if (QwtPlotCurve::NoCurve != style()) + QWidget *lgdItem = legend->find( this ); + if ( lgdItem == NULL ) { - legendItem->setCurvePen(pen()); - mode |= QwtLegendItem::ShowLine; + lgdItem = legendItem(); + if ( lgdItem ) + legend->insert( this, lgdItem ); } - if (QwtSymbol::NoSymbol != symbol().style()) + + QwtLegendItem *l = qobject_cast( lgdItem ); + if ( l ) { - legendItem->setSymbol(symbol()); - mode |= QwtLegendItem::ShowSymbol; + QSize sz = d_data->symbol->boundingSize(); + sz += QSize( 2, 2 ); // margin + + if ( d_data->legendAttributes & QwtPlotCurve::LegendShowLine ) + { + // Avoid, that the line is completely covered by the symbol + + int w = qCeil( 1.5 * sz.width() ); + if ( w % 2 ) + w++; + + sz.setWidth( qMax( 8, w ) ); + } + + l->setIdentifierSize( sz ); } - if ( !title().isEmpty() ) - { - legendItem->setText(title()); - mode |= QwtLegendItem::ShowText; - } - else - { - legendItem->setText(QwtText()); - } - legendItem->setIdentifierMode(mode); } - legendItem->setUpdatesEnabled(doUpdate); - legendItem->update(); + QwtPlotItem::updateLegend( legend ); } + +/*! + \brief Draw the identifier representing the curve on the legend + + \param painter Painter + \param rect Bounding rectangle for the identifier + + \sa setLegendAttribute(), QwtPlotItem::Legend +*/ +void QwtPlotCurve::drawLegendIdentifier( + QPainter *painter, const QRectF &rect ) const +{ + if ( rect.isEmpty() ) + return; + + const int dim = qMin( rect.width(), rect.height() ); + + QSize size( dim, dim ); + + QRectF r( 0, 0, size.width(), size.height() ); + r.moveCenter( rect.center() ); + + if ( d_data->legendAttributes == 0 ) + { + QBrush brush = d_data->brush; + if ( brush.style() == Qt::NoBrush ) + { + if ( style() != QwtPlotCurve::NoCurve ) + brush = QBrush( pen().color() ); + else if ( d_data->symbol && + ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) + { + brush = QBrush( d_data->symbol->pen().color() ); + } + } + if ( brush.style() != Qt::NoBrush ) + painter->fillRect( r, brush ); + } + if ( d_data->legendAttributes & QwtPlotCurve::LegendShowBrush ) + { + if ( d_data->brush.style() != Qt::NoBrush ) + painter->fillRect( r, d_data->brush ); + } + if ( d_data->legendAttributes & QwtPlotCurve::LegendShowLine ) + { + if ( pen() != Qt::NoPen ) + { + painter->setPen( pen() ); + QwtPainter::drawLine( painter, rect.left(), rect.center().y(), + rect.right() - 1.0, rect.center().y() ); + } + } + if ( d_data->legendAttributes & QwtPlotCurve::LegendShowSymbol ) + { + if ( d_data->symbol && + ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) + { + QSize symbolSize = d_data->symbol->boundingSize(); + symbolSize -= QSize( 2, 2 ); + + // scale the symbol size down if it doesn't fit into rect. + + double xRatio = 1.0; + if ( rect.width() < symbolSize.width() ) + xRatio = rect.width() / symbolSize.width(); + double yRatio = 1.0; + if ( rect.height() < symbolSize.height() ) + yRatio = rect.height() / symbolSize.height(); + + const double ratio = qMin( xRatio, yRatio ); + + painter->save(); + painter->scale( ratio, ratio ); + + d_data->symbol->drawSymbol( painter, rect.center() / ratio ); + + painter->restore(); + } + } +} + +/*! + Initialize data with an array of points (explicitly shared). + + \param samples Vector of points +*/ +void QwtPlotCurve::setSamples( const QVector &samples ) +{ + delete d_series; + d_series = new QwtPointSeriesData( samples ); + itemChanged(); +} + +#ifndef QWT_NO_COMPAT + +/*! + \brief Initialize the data by pointing to memory blocks which + are not managed by QwtPlotCurve. + + setRawSamples is provided for efficiency. + It is important to keep the pointers + during the lifetime of the underlying QwtCPointerData class. + + \param xData pointer to x data + \param yData pointer to y data + \param size size of x and y + + \sa QwtCPointerData +*/ +void QwtPlotCurve::setRawSamples( + const double *xData, const double *yData, int size ) +{ + delete d_series; + d_series = new QwtCPointerData( xData, yData, size ); + itemChanged(); +} + +/*! + Set data by copying x- and y-values from specified memory blocks. + Contrary to setRawSamples(), this function makes a 'deep copy' of + the data. + + \param xData pointer to x values + \param yData pointer to y values + \param size size of xData and yData + + \sa QwtPointArrayData +*/ +void QwtPlotCurve::setSamples( + const double *xData, const double *yData, int size ) +{ + delete d_series; + d_series = new QwtPointArrayData( xData, yData, size ); + itemChanged(); +} + +/*! + \brief Initialize data with x- and y-arrays (explicitly shared) + + \param xData x data + \param yData y data + + \sa QwtPointArrayData +*/ +void QwtPlotCurve::setSamples( const QVector &xData, + const QVector &yData ) +{ + delete d_series; + d_series = new QwtPointArrayData( xData, yData ); + itemChanged(); +} +#endif // !QWT_NO_COMPAT diff --git a/qwt/src/qwt_plot_curve.h b/qwt/src/qwt_plot_curve.h index 08d3a85d6..e42a4c38c 100644 --- a/qwt/src/qwt_plot_curve.h +++ b/qwt/src/qwt_plot_curve.h @@ -10,15 +10,15 @@ #ifndef QWT_PLOT_CURVE_H #define QWT_PLOT_CURVE_H +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_series_data.h" +#include "qwt_text.h" #include #include -#include "qwt_global.h" -#include "qwt_plot_item.h" -#include "qwt_text.h" -#include "qwt_polygon.h" -#include "qwt_data.h" class QPainter; +class QPolygonF; class QwtScaleMap; class QwtSymbol; class QwtCurveFitter; @@ -27,20 +27,21 @@ class QwtCurveFitter; \brief A plot item, that represents a series of points A curve is the representation of a series of points in the x-y plane. - It supports different display styles, interpolation ( f.e. spline ) + It supports different display styles, interpolation ( f.e. spline ) and symbols. \par Usage
a) Assign curve properties
When a curve is created, it is configured to draw black solid lines - with in Lines style and no symbols. You can change this by calling + with in QwtPlotCurve::Lines style and no symbols. + You can change this by calling setPen(), setStyle() and setSymbol().
b) Connect/Assign data.
-
QwtPlotCurve gets its points using a QwtData object offering +
QwtPlotCurve gets its points using a QwtSeriesData object offering a bridge to the real storage of the points ( like QAbstractItemModel ). - There are several convenience classes derived from QwtData, that also store + There are several convenience classes derived from QwtSeriesData, that also store the points inside ( like QStandardItemModel ). QwtPlotCurve also offers - a couple of variations of setData(), that build QwtData objects from + a couple of variations of setSamples(), that build QwtSeriesData objects from arrays internally.
c) Attach the curve to a plot
See QwtPlotItem::attach() @@ -49,281 +50,270 @@ class QwtCurveFitter; \par Example: see examples/bode - \sa QwtPlot, QwtData, QwtSymbol, QwtScaleMap + \sa QwtPointSeriesData, QwtSymbol, QwtScaleMap */ -class QWT_EXPORT QwtPlotCurve: public QwtPlotItem +class QWT_EXPORT QwtPlotCurve: public QwtPlotSeriesItem { public: /*! - Curve type. - - - Yfx\n - Draws y as a function of x (the default). The - baseline is interpreted as a horizontal line - with y = baseline(). - - Xfy\n - Draws x as a function of y. The baseline is - interpreted as a vertical line with x = baseline(). - - The baseline is used for aligning the sticks, or - filling the curve with a brush. - - \sa setCurveType(), curveType(), baseline() brush() - */ - enum CurveType - { - Yfx, - Xfy - }; - - /*! - Curve styles. - - - NoCurve\n - Don't draw a curve. Note: This doesn't affect the symbols. - - Lines\n - Connect the points with straight lines. The lines might - be interpolated depending on the 'Fitted' attribute. Curve - fitting can be configured using setCurveFitter(). - - Sticks\n - Draw vertical(Yfx) or horizontal(Xfy) sticks from a baseline - which is defined by setBaseline(). - - Steps\n - Connect the points with a step function. The step function - is drawn from the left to the right or vice versa, - depending on the 'Inverted' attribute. - - Dots\n - Draw dots at the locations of the data points. Note: - This is different from a dotted line (see setPen()), and faster - as a curve in NoStyle style and a symbol painting a point. - - UserCurve\n - Styles >= UserCurve are reserved for derived - classes of QwtPlotCurve that overload drawCurve() with - additional application specific curve types. - + Curve styles. \sa setStyle(), style() */ enum CurveStyle { - NoCurve, + /*! + Don't draw a curve. Note: This doesn't affect the symbols. + */ + NoCurve = -1, + /*! + Connect the points with straight lines. The lines might + be interpolated depending on the 'Fitted' attribute. Curve + fitting can be configured using setCurveFitter(). + */ Lines, + + /*! + Draw vertical or horizontal sticks ( depending on the + orientation() ) from a baseline which is defined by setBaseline(). + */ Sticks, + + /*! + Connect the points with a step function. The step function + is drawn from the left to the right or vice versa, + depending on the QwtPlotCurve::Inverted attribute. + */ Steps, + + /*! + Draw dots at the locations of the data points. Note: + This is different from a dotted line (see setPen()), and faster + as a curve in QwtPlotCurve::NoStyle style and a symbol + painting a point. + */ Dots, + /*! + Styles >= QwtPlotCurve::UserCurve are reserved for derived + classes of QwtPlotCurve that overload drawCurve() with + additional application specific curve types. + */ UserCurve = 100 }; - /*! + /*! Attribute for drawing the curve - - - Fitted ( in combination with the Lines QwtPlotCurve::CurveStyle only )\n - A QwtCurveFitter tries to - interpolate/smooth the curve, before it is painted. - Note that curve fitting requires temorary memory - for calculating coefficients and additional points. - If painting in Fitted mode is slow it might be better - to fit the points, before they are passed to QwtPlotCurve. - - Inverted\n - For Steps only. Draws a step function - from the right to the left. - - \sa setCurveAttribute(), testCurveAttribute(), curveFitter() + \sa setCurveAttribute(), testCurveAttribute(), curveFitter() */ enum CurveAttribute { - Inverted = 1, - Fitted = 2 + /*! + For QwtPlotCurve::Steps only. + Draws a step function from the right to the left. + */ + Inverted = 0x01, + + /*! + Only in combination with QwtPlotCurve::Lines + A QwtCurveFitter tries to + interpolate/smooth the curve, before it is painted. + + \note Curve fitting requires temorary memory + for calculating coefficients and additional points. + If painting in QwtPlotCurve::Fitted mode is slow it might be better + to fit the points, before they are passed to QwtPlotCurve. + */ + Fitted = 0x02 }; - /*! + //! Curve attributes + typedef QFlags CurveAttributes; + + /*! + Attributes how to represent the curve on the legend + + \sa setLegendAttribute(), testLegendAttribute(), + drawLegendIdentifier() + */ + + enum LegendAttribute + { + /*! + QwtPlotCurve tries to find a color representing the curve + and paints a rectangle with it. + */ + LegendNoAttribute = 0x00, + + /*! + If the style() is not QwtPlotCurve::NoCurve a line + is painted with the curve pen(). + */ + LegendShowLine = 0x01, + + /*! + If the curve has a valid symbol it is painted. + */ + LegendShowSymbol = 0x02, + + /*! + If the curve has a brush a rectangle filled with the + curve brush() is painted. + */ + LegendShowBrush = 0x04 + }; + + //! Legend attributes + typedef QFlags LegendAttributes; + + /*! Attributes to modify the drawing algorithm. - - - PaintFiltered\n - Tries to reduce the data that has to be painted, by sorting out - duplicates, or paintings outside the visible area. Might have a - notable impact on curves with many close points. - Only a couple of very basic filtering algos are implemented. - - ClipPolygons\n - Clip polygons before painting them. In situations, where points - are far outside the visible area (f.e when zooming deep) this - might be a substantial improvement for the painting performance - ( especially on Windows ). - - The default is, that no paint attributes are enabled. + The default setting enables ClipPolygons \sa setPaintAttribute(), testPaintAttribute() */ enum PaintAttribute { - PaintFiltered = 1, - ClipPolygons = 2 + /*! + Clip polygons before painting them. In situations, where points + are far outside the visible area (f.e when zooming deep) this + might be a substantial improvement for the painting performance + */ + ClipPolygons = 0x01, + + /*! + Paint the symbol to a QPixmap and paint the pixmap + instead rendering the symbol for each point. The flag has + no effect, when the curve is not painted to the canvas + ( f.e when exporting the plot to a PDF document ). + */ + CacheSymbols = 0x02 }; - explicit QwtPlotCurve(); - explicit QwtPlotCurve(const QwtText &title); - explicit QwtPlotCurve(const QString &title); + //! Paint attributes + typedef QFlags PaintAttributes; + + explicit QwtPlotCurve( const QString &title = QString::null ); + explicit QwtPlotCurve( const QwtText &title ); virtual ~QwtPlotCurve(); virtual int rtti() const; - void setCurveType(CurveType); - CurveType curveType() const; + void setPaintAttribute( PaintAttribute, bool on = true ); + bool testPaintAttribute( PaintAttribute ) const; - void setPaintAttribute(PaintAttribute, bool on = true); - bool testPaintAttribute(PaintAttribute) const; + void setLegendAttribute( LegendAttribute, bool on = true ); + bool testLegendAttribute( LegendAttribute ) const; - void setRawData(const double *x, const double *y, int size); - void setData(const double *xData, const double *yData, int size); - void setData(const QwtArray &xData, const QwtArray &yData); -#if QT_VERSION < 0x040000 - void setData(const QwtArray &data); -#else - void setData(const QPolygonF &data); +#ifndef QWT_NO_COMPAT + void setRawSamples( const double *xData, const double *yData, int size ); + void setSamples( const double *xData, const double *yData, int size ); + void setSamples( const QVector &xData, const QVector &yData ); #endif - void setData(const QwtData &data); - - int closestPoint(const QPoint &pos, double *dist = NULL) const; + void setSamples( const QVector & ); - QwtData &data(); - const QwtData &data() const; - - int dataSize() const; - double x(int i) const; - double y(int i) const; - - virtual QwtDoubleRect boundingRect() const; + int closestPoint( const QPoint &pos, double *dist = NULL ) const; double minXValue() const; double maxXValue() const; double minYValue() const; double maxYValue() const; - void setCurveAttribute(CurveAttribute, bool on = true); - bool testCurveAttribute(CurveAttribute) const; + void setCurveAttribute( CurveAttribute, bool on = true ); + bool testCurveAttribute( CurveAttribute ) const; - void setPen(const QPen &); + void setPen( const QPen & ); const QPen &pen() const; - void setBrush(const QBrush &); + void setBrush( const QBrush & ); const QBrush &brush() const; - void setBaseline(double ref); + void setBaseline( double ref ); double baseline() const; - void setStyle(CurveStyle style); + void setStyle( CurveStyle style ); CurveStyle style() const; - void setSymbol(const QwtSymbol &s); - const QwtSymbol& symbol() const; + void setSymbol( const QwtSymbol *s ); + const QwtSymbol *symbol() const; - void setCurveFitter(QwtCurveFitter *); + void setCurveFitter( QwtCurveFitter * ); QwtCurveFitter *curveFitter() const; - virtual void draw(QPainter *p, + virtual void drawSeries( QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &) const; + const QRectF &canvasRect, int from, int to ) const; - virtual void draw(QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; - - void draw(int from, int to) const; - - virtual void updateLegend(QwtLegend *) const; + virtual void updateLegend( QwtLegend * ) const; + virtual void drawLegendIdentifier( QPainter *, const QRectF & ) const; protected: void init(); - virtual void drawCurve(QPainter *p, int style, + virtual void drawCurve( QPainter *p, int style, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; + const QRectF &canvasRect, int from, int to ) const; - virtual void drawSymbols(QPainter *p, const QwtSymbol &, + virtual void drawSymbols( QPainter *p, const QwtSymbol &, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; + const QRectF &canvasRect, int from, int to ) const; - void drawLines(QPainter *p, + void drawLines( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; - void drawSticks(QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; - void drawDots(QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; - void drawSteps(QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - int from, int to) const; + const QRectF &canvasRect, int from, int to ) const; - void fillCurve(QPainter *, + void drawSticks( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + void drawDots( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + void drawSteps( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void fillCurve( QPainter *, const QwtScaleMap &, const QwtScaleMap &, - QwtPolygon &) const; - void closePolyline(const QwtScaleMap &, const QwtScaleMap &, - QwtPolygon &) const; + const QRectF &canvasRect, QPolygonF & ) const; + + void closePolyline( QPainter *, + const QwtScaleMap &, const QwtScaleMap &, QPolygonF & ) const; private: - QwtData *d_xy; - class PrivateData; PrivateData *d_data; }; -//! \return the the curve data -inline QwtData &QwtPlotCurve::data() -{ - return *d_xy; -} - -//! \return the the curve data -inline const QwtData &QwtPlotCurve::data() const -{ - return *d_xy; -} - -/*! - \param i index - \return x-value at position i -*/ -inline double QwtPlotCurve::x(int i) const -{ - return d_xy->x(i); -} - -/*! - \param i index - \return y-value at position i -*/ -inline double QwtPlotCurve::y(int i) const -{ - return d_xy->y(i); -} - //! boundingRect().left() -inline double QwtPlotCurve::minXValue() const -{ - return boundingRect().left(); +inline double QwtPlotCurve::minXValue() const +{ + return boundingRect().left(); } //! boundingRect().right() -inline double QwtPlotCurve::maxXValue() const -{ - return boundingRect().right(); +inline double QwtPlotCurve::maxXValue() const +{ + return boundingRect().right(); } //! boundingRect().top() -inline double QwtPlotCurve::minYValue() const -{ - return boundingRect().top(); +inline double QwtPlotCurve::minYValue() const +{ + return boundingRect().top(); } //! boundingRect().bottom() -inline double QwtPlotCurve::maxYValue() const -{ - return boundingRect().bottom(); +inline double QwtPlotCurve::maxYValue() const +{ + return boundingRect().bottom(); } +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCurve::PaintAttributes ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCurve::LegendAttributes ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCurve::CurveAttributes ) + #endif diff --git a/qwt/src/qwt_plot_dict.cpp b/qwt/src/qwt_plot_dict.cpp index 808880e0d..4125137e8 100644 --- a/qwt/src/qwt_plot_dict.cpp +++ b/qwt/src/qwt_plot_dict.cpp @@ -7,87 +7,60 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - #include "qwt_plot_dict.h" class QwtPlotDict::PrivateData { public: -#if QT_VERSION < 0x040000 - class ItemList: public QValueList -#else class ItemList: public QList -#endif { public: - void insertItem(QwtPlotItem *item) + void insertItem( QwtPlotItem *item ) { if ( item == NULL ) return; - // Unfortunately there is no inSort operation - // for lists in Qt4. The implementation below - // is slow, but there shouldn't be many plot items. - -#ifdef __GNUC__ -#warning binary search missing -#endif - -#if QT_VERSION < 0x040000 - QValueListIterator it; -#else - QList::Iterator it; -#endif - for ( it = begin(); it != end(); ++it ) - { - if ( *it == item ) - return; - - if ( (*it)->z() > item->z() ) - { - insert(it, item); - return; - } - } - append(item); + QList::iterator it = + qUpperBound( begin(), end(), item, LessZThan() ); + insert( it, item ); } - void removeItem(QwtPlotItem *item) + void removeItem( QwtPlotItem *item ) { if ( item == NULL ) return; - int i = 0; + QList::iterator it = + qLowerBound( begin(), end(), item, LessZThan() ); -#if QT_VERSION < 0x040000 - QValueListIterator it; -#else - QList::Iterator it; -#endif - for ( it = begin(); it != end(); ++it ) + for ( ; it != end(); ++it ) { if ( item == *it ) { -#if QT_VERSION < 0x040000 - remove(it); -#else - removeAt(i); -#endif - return; + erase( it ); + break; } - i++; } } + private: + class LessZThan + { + public: + inline bool operator()( const QwtPlotItem *item1, + const QwtPlotItem *item2 ) const + { + return item1->z() < item2->z(); + } + }; }; ItemList itemList; bool autoDelete; }; -/*! - Constructor +/*! + Constructor Auto deletion is enabled. \sa setAutoDelete(), attachItem() @@ -98,7 +71,7 @@ QwtPlotDict::QwtPlotDict() d_data->autoDelete = true; } -/*! +/*! Destructor If autoDelete is on, all attached items will be deleted @@ -106,7 +79,7 @@ QwtPlotDict::QwtPlotDict() */ QwtPlotDict::~QwtPlotDict() { - detachItems(QwtPlotItem::Rtti_PlotItem, d_data->autoDelete); + detachItems( QwtPlotItem::Rtti_PlotItem, d_data->autoDelete ); delete d_data; } @@ -118,7 +91,7 @@ QwtPlotDict::~QwtPlotDict() \sa autoDelete(), attachItem() */ -void QwtPlotDict::setAutoDelete(bool autoDelete) +void QwtPlotDict::setAutoDelete( bool autoDelete ) { d_data->autoDelete = autoDelete; } @@ -144,22 +117,22 @@ bool QwtPlotDict::autoDelete() const \sa setAutoDelete(), ~QwtPlotDict() */ -void QwtPlotDict::attachItem(QwtPlotItem *item, bool on) +void QwtPlotDict::attachItem( QwtPlotItem *item, bool on ) { if ( on ) - d_data->itemList.insertItem(item); + d_data->itemList.insertItem( item ); else - d_data->itemList.removeItem(item); + d_data->itemList.removeItem( item ); } /*! Detach items from the dictionary - \param rtti In case of QwtPlotItem::Rtti_PlotItem detach all items + \param rtti In case of QwtPlotItem::Rtti_PlotItem detach all items otherwise only those items of the type rtti. \param autoDelete If true, delete all detached items */ -void QwtPlotDict::detachItems(int rtti, bool autoDelete) +void QwtPlotDict::detachItems( int rtti, bool autoDelete ) { PrivateData::ItemList list = d_data->itemList; QwtPlotItemIterator it = list.begin(); @@ -171,20 +144,45 @@ void QwtPlotDict::detachItems(int rtti, bool autoDelete) if ( rtti == QwtPlotItem::Rtti_PlotItem || item->rtti() == rtti ) { - item->attach(NULL); + item->attach( NULL ); if ( autoDelete ) delete item; } } } -//! \brief A QwtPlotItemList of all attached plot items. -/// -/// Use caution when iterating these lists, as removing/detaching an item will -/// invalidate the iterator. Instead you can place pointers to objects to be -/// removed in a removal list, and traverse that list later. -//! \return List of all attached plot items. +/*! + \brief A QwtPlotItemList of all attached plot items. + + Use caution when iterating these lists, as removing/detaching an item will + invalidate the iterator. Instead you can place pointers to objects to be + removed in a removal list, and traverse that list later. + + \return List of all attached plot items. +*/ const QwtPlotItemList &QwtPlotDict::itemList() const { return d_data->itemList; } + +/*! + \return List of all attached plot items of a specific type. + \sa QwtPlotItem::rtti() +*/ +QwtPlotItemList QwtPlotDict::itemList( int rtti ) const +{ + if ( rtti == QwtPlotItem::Rtti_PlotItem ) + return d_data->itemList; + + QwtPlotItemList items; + + PrivateData::ItemList list = d_data->itemList; + for ( QwtPlotItemIterator it = list.begin(); it != list.end(); ++it ) + { + QwtPlotItem *item = *it; + if ( item->rtti() == rtti ) + items += item; + } + + return items; +} diff --git a/qwt/src/qwt_plot_dict.h b/qwt/src/qwt_plot_dict.h index bc369ae50..f68c80b10 100644 --- a/qwt/src/qwt_plot_dict.h +++ b/qwt/src/qwt_plot_dict.h @@ -7,28 +7,18 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - /*! \file !*/ #ifndef QWT_PLOT_DICT #define QWT_PLOT_DICT #include "qwt_global.h" #include "qwt_plot_item.h" - -#if QT_VERSION < 0x040000 -#include -typedef QValueListConstIterator QwtPlotItemIterator; -/// \var typedef QValueList< QwtPlotItem *> QwtPlotItemList -/// \brief See QT 3.x assistant documentation for QValueList -typedef QValueList QwtPlotItemList; -#else #include -typedef QList::ConstIterator QwtPlotItemIterator; + /// \var typedef QList< QwtPlotItem *> QwtPlotItemList /// \brief See QT 4.x assistant documentation for QList typedef QList QwtPlotItemList; -#endif +typedef QList::ConstIterator QwtPlotItemIterator; /*! \brief A dictionary for plot items @@ -43,20 +33,21 @@ class QWT_EXPORT QwtPlotDict { public: explicit QwtPlotDict(); - ~QwtPlotDict(); + virtual ~QwtPlotDict(); - void setAutoDelete(bool); + void setAutoDelete( bool ); bool autoDelete() const; const QwtPlotItemList& itemList() const; + QwtPlotItemList itemList( int rtti ) const; - void detachItems(int rtti = QwtPlotItem::Rtti_PlotItem, - bool autoDelete = true); + void detachItems( int rtti = QwtPlotItem::Rtti_PlotItem, + bool autoDelete = true ); private: friend class QwtPlotItem; - void attachItem(QwtPlotItem *, bool); + void attachItem( QwtPlotItem *, bool ); class PrivateData; PrivateData *d_data; diff --git a/qwt/src/qwt_plot_directpainter.cpp b/qwt/src/qwt_plot_directpainter.cpp new file mode 100644 index 000000000..8ae82324a --- /dev/null +++ b/qwt/src/qwt_plot_directpainter.cpp @@ -0,0 +1,313 @@ +/* -*- 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_plot_directpainter.h" +#include "qwt_scale_map.h" +#include "qwt_plot.h" +#include "qwt_plot_canvas.h" +#include "qwt_plot_seriesitem.h" +#include +#include +#include +#include + +static inline void renderItem( + QPainter *painter, const QRect &canvasRect, + QwtPlotAbstractSeriesItem *seriesItem, int from, int to ) +{ + // A minor performance improvement is possible + // with caching the maps. TODO ... + + QwtPlot *plot = seriesItem->plot(); + const QwtScaleMap xMap = plot->canvasMap( seriesItem->xAxis() ); + const QwtScaleMap yMap = plot->canvasMap( seriesItem->yAxis() ); + + painter->setRenderHint( QPainter::Antialiasing, + seriesItem->testRenderHint( QwtPlotItem::RenderAntialiased ) ); + seriesItem->drawSeries( painter, xMap, yMap, canvasRect, from, to ); +} + +class QwtPlotDirectPainter::PrivateData +{ +public: + PrivateData(): + attributes( 0 ), + hasClipping(false), + seriesItem( NULL ) + { + } + + QwtPlotDirectPainter::Attributes attributes; + + bool hasClipping; + QRegion clipRegion; + + QPainter painter; + + QwtPlotAbstractSeriesItem *seriesItem; + int from; + int to; +}; + +//! Constructor +QwtPlotDirectPainter::QwtPlotDirectPainter( QObject *parent ): + QObject( parent ) +{ + d_data = new PrivateData; +} + +//! Destructor +QwtPlotDirectPainter::~QwtPlotDirectPainter() +{ + delete d_data; +} + +/*! + Change an attribute + + \param attribute Attribute to change + \param on On/Off + + \sa Attribute, testAttribute() +*/ +void QwtPlotDirectPainter::setAttribute( Attribute attribute, bool on ) +{ + if ( bool( d_data->attributes & attribute ) != on ) + { + if ( on ) + d_data->attributes |= attribute; + else + d_data->attributes &= ~attribute; + + if ( ( attribute == AtomicPainter ) && on ) + reset(); + } +} + +/*! + Check if a attribute is set. + + \param attribute Attribute to be tested + \sa Attribute, setAttribute() +*/ +bool QwtPlotDirectPainter::testAttribute( Attribute attribute ) const +{ + return d_data->attributes & attribute; +} + +/*! + En/Disables clipping + + \param enable Enables clipping is true, disable it otherwise + \sa hasClipping(), clipRegion(), setClipRegion() +*/ +void QwtPlotDirectPainter::setClipping( bool enable ) +{ + d_data->hasClipping = enable; +} + +/*! + \return true, when clipping is enabled + \sa setClipping(), clipRegion(), setClipRegion() +*/ +bool QwtPlotDirectPainter::hasClipping() const +{ + return d_data->hasClipping; +} + +/*! + \brief Assign a clip region and enable clipping + + Depending on the environment setting a proper clip region might improve + the performance heavily. F.e. on Qt embedded only the clipped part of + the backing store will be copied to a ( maybe unaccelerated ) frame buffer + device. + + \param region Clip region + \sa clipRegion(), hasClipping(), setClipping() +*/ +void QwtPlotDirectPainter::setClipRegion( const QRegion ®ion ) +{ + d_data->clipRegion = region; + d_data->hasClipping = true; +} + +/*! + \return Currently set clip region. + \sa setClipRegion(), setClipping(), hasClipping() +*/ +QRegion QwtPlotDirectPainter::clipRegion() const +{ + return d_data->clipRegion; +} + +/*! + \brief Draw a set of points of a seriesItem. + + When observing an measurement while it is running, new points have to be + added to an existing seriesItem. drawSeries can be used to display them avoiding + a complete redraw of the canvas. + + Setting plot()->canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); + will result in faster painting, if the paint engine of the canvas widget + supports this feature. + + \param seriesItem Item to be painted + \param from Index of the first point to be painted + \param to Index of the last point to be painted. If to < 0 the + series will be painted to its last point. +*/ +void QwtPlotDirectPainter::drawSeries( + QwtPlotAbstractSeriesItem *seriesItem, int from, int to ) +{ + if ( seriesItem == NULL || seriesItem->plot() == NULL ) + return; + + QwtPlotCanvas *canvas = seriesItem->plot()->canvas(); + const QRect canvasRect = canvas->contentsRect(); + + const bool hasBackingStore = + canvas->testPaintAttribute( QwtPlotCanvas::BackingStore ) + && canvas->backingStore() && !canvas->backingStore()->isNull(); + + if ( hasBackingStore ) + { + QPainter painter( const_cast( canvas->backingStore() ) ); + painter.translate( -canvasRect.x(), -canvasRect.y() ); + + if ( d_data->hasClipping ) + painter.setClipRegion( d_data->clipRegion ); + + renderItem( &painter, canvasRect, seriesItem, from, to ); + + if ( testAttribute( QwtPlotDirectPainter::FullRepaint ) ) + { + canvas->repaint(); + return; + } + } + + bool immediatePaint = true; + if ( !canvas->testAttribute( Qt::WA_WState_InPaintEvent ) && + !canvas->testAttribute( Qt::WA_PaintOutsidePaintEvent ) ) + { + immediatePaint = false; + } + + if ( immediatePaint ) + { + QwtPlotCanvas *canvas = seriesItem->plot()->canvas(); + if ( !d_data->painter.isActive() ) + { + reset(); + + d_data->painter.begin( canvas ); + canvas->installEventFilter( this ); + } + + if ( d_data->hasClipping ) + { + d_data->painter.setClipRegion( + QRegion( canvasRect ) & d_data->clipRegion ); + } + else + { + if ( !d_data->painter.hasClipping() ) + d_data->painter.setClipRect( canvasRect ); + } + + renderItem( &d_data->painter, canvasRect, seriesItem, from, to ); + + if ( d_data->attributes & QwtPlotDirectPainter::AtomicPainter ) + { + reset(); + } + else + { + if ( d_data->hasClipping ) + d_data->painter.setClipping( false ); + } + } + else + { + reset(); + + d_data->seriesItem = seriesItem; + d_data->from = from; + d_data->to = to; + + QRegion clipRegion = canvasRect; + if ( d_data->hasClipping ) + clipRegion &= d_data->clipRegion; + + canvas->installEventFilter( this ); + canvas->repaint(clipRegion); + canvas->removeEventFilter( this ); + + d_data->seriesItem = NULL; + } +} + +//! Close the internal QPainter +void QwtPlotDirectPainter::reset() +{ + if ( d_data->painter.isActive() ) + { + QWidget *w = ( QWidget * )d_data->painter.device(); + if ( w ) + w->removeEventFilter( this ); + + d_data->painter.end(); + } +} + +//! Event filter +bool QwtPlotDirectPainter::eventFilter( QObject *, QEvent *event ) +{ + if ( event->type() == QEvent::Paint ) + { + reset(); + + if ( d_data->seriesItem ) + { + const QPaintEvent *pe = static_cast< QPaintEvent *>( event ); + + QwtPlotCanvas *canvas = d_data->seriesItem->plot()->canvas(); + + QPainter painter( canvas ); + painter.setClipRegion( pe->region() ); + + bool copyCache = testAttribute( CopyBackingStore ) + && canvas->testPaintAttribute( QwtPlotCanvas::BackingStore ); + + if ( copyCache ) + { + // is something valid in the cache ? + copyCache = ( canvas->backingStore() != NULL ) + && !canvas->backingStore()->isNull(); + } + + if ( copyCache ) + { + painter.drawPixmap( + canvas->contentsRect().topLeft(), + *canvas->backingStore() ); + } + else + { + renderItem( &painter, canvas->contentsRect(), + d_data->seriesItem, d_data->from, d_data->to ); + } + + return true; // don't call QwtPlotCanvas::paintEvent() + } + } + + return false; +} diff --git a/qwt/src/qwt_plot_directpainter.h b/qwt/src/qwt_plot_directpainter.h new file mode 100644 index 000000000..293278de3 --- /dev/null +++ b/qwt/src/qwt_plot_directpainter.h @@ -0,0 +1,100 @@ +/* -*- 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_PLOT_DIRECT_PAINTER_H +#define QWT_PLOT_DIRECT_PAINTER_H + +#include "qwt_global.h" +#include + +class QRegion; +class QwtPlotAbstractSeriesItem; + +/*! + \brief Painter object trying to paint incrementally + + Often applications want to display samples while they are + collected. When there are too many samples complete replots + will be expensive to be processed in a collection cycle. + + QwtPlotDirectPainter offers an API to paint + subsets ( f.e all additions points ) without erasing/repainting + the plot canvas. + + On certain environments it might be important to calculate a proper + clip region before painting. F.e. for Qt Embedded only the clipped part + of the backing store will be copied to a ( maybe unaccelerated ) + frame buffer. + + \warning Incremental painting will only help when no replot is triggered + by another operation ( like changing scales ) and nothing needs + to be erased. +*/ +class QWT_EXPORT QwtPlotDirectPainter: public QObject +{ +public: + /*! + \brief Paint attributes + \sa setAttribute(), testAttribute(), drawSeries() + */ + enum Attribute + { + /*! + Initializing a QPainter is an expensive operation. + When AtomicPainter is set each call of drawSeries() opens/closes + a temporary QPainter. Otherwise QwtPlotDirectPainter tries to + use the same QPainter as long as possible. + */ + AtomicPainter = 0x01, + + /*! + When FullRepaint is set the plot canvas is explicitely repainted + after the samples have been rendered. + */ + FullRepaint = 0x02, + + /*! + When QwtPlotCanvas::BackingStore is enabled the painter + has to paint to the backing store and the widget. In certain + situations/environments it might be faster to paint to + the backing store only and then copy the backingstore to the canvas. + This flag can also be useful for settings, where Qt fills the + the clip region with the widget background. + */ + CopyBackingStore = 0x04 + }; + + //! Paint attributes + typedef QFlags Attributes; + + QwtPlotDirectPainter( QObject *parent = NULL ); + virtual ~QwtPlotDirectPainter(); + + void setAttribute( Attribute, bool on ); + bool testAttribute( Attribute ) const; + + void setClipping( bool ); + bool hasClipping() const; + + void setClipRegion( const QRegion & ); + QRegion clipRegion() const; + + void drawSeries( QwtPlotAbstractSeriesItem *, int from, int to ); + void reset(); + + virtual bool eventFilter( QObject *, QEvent * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotDirectPainter::Attributes ) + +#endif diff --git a/qwt/src/qwt_plot_grid.cpp b/qwt/src/qwt_plot_grid.cpp index 2e6e0051b..8e25aebaa 100644 --- a/qwt/src/qwt_plot_grid.cpp +++ b/qwt/src/qwt_plot_grid.cpp @@ -2,27 +2,28 @@ * 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 -#include +#include "qwt_plot_grid.h" #include "qwt_painter.h" #include "qwt_text.h" #include "qwt_scale_map.h" #include "qwt_scale_div.h" -#include "qwt_plot_grid.h" +#include "qwt_math.h" +#include +#include class QwtPlotGrid::PrivateData { public: PrivateData(): - xEnabled(true), - yEnabled(true), - xMinEnabled(false), - yMinEnabled(false) + xEnabled( true ), + yEnabled( true ), + xMinEnabled( false ), + yMinEnabled( false ) { } @@ -40,10 +41,10 @@ public: //! Enables major grid, disables minor grid QwtPlotGrid::QwtPlotGrid(): - QwtPlotItem(QwtText("Grid")) + QwtPlotItem( QwtText( "Grid" ) ) { d_data = new PrivateData; - setZ(10.0); + setZ( 10.0 ); } //! Destructor @@ -65,7 +66,7 @@ int QwtPlotGrid::rtti() const \sa Minor gridlines can be enabled or disabled with enableXMin() */ -void QwtPlotGrid::enableX(bool tf) +void QwtPlotGrid::enableX( bool tf ) { if ( d_data->xEnabled != tf ) { @@ -79,11 +80,11 @@ void QwtPlotGrid::enableX(bool tf) \param tf Enable (true) or disable \sa Minor gridlines can be enabled or disabled with enableYMin() */ -void QwtPlotGrid::enableY(bool tf) +void QwtPlotGrid::enableY( bool tf ) { if ( d_data->yEnabled != tf ) { - d_data->yEnabled = tf; + d_data->yEnabled = tf; itemChanged(); } } @@ -93,7 +94,7 @@ void QwtPlotGrid::enableY(bool tf) \param tf Enable (true) or disable \sa enableX() */ -void QwtPlotGrid::enableXMin(bool tf) +void QwtPlotGrid::enableXMin( bool tf ) { if ( d_data->xMinEnabled != tf ) { @@ -107,7 +108,7 @@ void QwtPlotGrid::enableXMin(bool tf) \param tf Enable (true) or disable \sa enableY() */ -void QwtPlotGrid::enableYMin(bool tf) +void QwtPlotGrid::enableYMin( bool tf ) { if ( d_data->yMinEnabled != tf ) { @@ -121,7 +122,7 @@ void QwtPlotGrid::enableYMin(bool tf) \param scaleDiv Scale division */ -void QwtPlotGrid::setXDiv(const QwtScaleDiv &scaleDiv) +void QwtPlotGrid::setXDiv( const QwtScaleDiv &scaleDiv ) { if ( d_data->xScaleDiv != scaleDiv ) { @@ -135,11 +136,11 @@ void QwtPlotGrid::setXDiv(const QwtScaleDiv &scaleDiv) \param scaleDiv Scale division */ -void QwtPlotGrid::setYDiv(const QwtScaleDiv &scaleDiv) +void QwtPlotGrid::setYDiv( const QwtScaleDiv &scaleDiv ) { if ( d_data->yScaleDiv != scaleDiv ) { - d_data->yScaleDiv = scaleDiv; + d_data->yScaleDiv = scaleDiv; itemChanged(); } } @@ -147,13 +148,10 @@ void QwtPlotGrid::setYDiv(const QwtScaleDiv &scaleDiv) /*! Assign a pen for both major and minor gridlines - The width of non cosmetic pens is scaled according to the resolution - of the paint device. - \param pen Pen - \sa setMajPen(), setMinPen(), QwtPainter::scaledPen() + \sa setMajPen(), setMinPen() */ -void QwtPlotGrid::setPen(const QPen &pen) +void QwtPlotGrid::setPen( const QPen &pen ) { if ( d_data->majPen != pen || d_data->minPen != pen ) { @@ -166,13 +164,10 @@ void QwtPlotGrid::setPen(const QPen &pen) /*! Assign a pen for the major gridlines - The width of non cosmetic pens is scaled according to the resolution - of the paint device. - \param pen Pen - \sa majPen(), setMinPen(), setPen(), QwtPainter::scaledPen() + \sa majPen(), setMinPen(), setPen() */ -void QwtPlotGrid::setMajPen(const QPen &pen) +void QwtPlotGrid::setMajPen( const QPen &pen ) { if ( d_data->majPen != pen ) { @@ -184,93 +179,107 @@ void QwtPlotGrid::setMajPen(const QPen &pen) /*! Assign a pen for the minor gridlines - The width of non cosmetic pens is scaled according to the resolution - of the paint device. - \param pen Pen - \sa minPen(), setMajPen(), setPen(), QwtPainter::scaledPen() + \sa minPen(), setMajPen(), setPen() */ -void QwtPlotGrid::setMinPen(const QPen &pen) +void QwtPlotGrid::setMinPen( const QPen &pen ) { if ( d_data->minPen != pen ) { - d_data->minPen = pen; + d_data->minPen = pen; itemChanged(); } } /*! \brief Draw the grid - - The grid is drawn into the bounding rectangle such that + + The grid is drawn into the bounding rectangle such that gridlines begin and end at the rectangle's borders. The X and Y maps are used to map the scale divisions into the drawing region screen. \param painter Painter \param xMap X axis map - \param yMap Y axis + \param yMap Y axis \param canvasRect Contents rect of the plot canvas */ -void QwtPlotGrid::draw(QPainter *painter, +void QwtPlotGrid::draw( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &canvasRect) const + const QRectF &canvasRect ) const { // draw minor gridlines - painter->setPen(QwtPainter::scaledPen(d_data->minPen)); - - if (d_data->xEnabled && d_data->xMinEnabled) + QPen minPen = d_data->minPen; + minPen.setCapStyle( Qt::FlatCap ); + + painter->setPen( minPen ); + + if ( d_data->xEnabled && d_data->xMinEnabled ) { - drawLines(painter, canvasRect, Qt::Vertical, xMap, - d_data->xScaleDiv.ticks(QwtScaleDiv::MinorTick)); - drawLines(painter, canvasRect, Qt::Vertical, xMap, - d_data->xScaleDiv.ticks(QwtScaleDiv::MediumTick)); + drawLines( painter, canvasRect, Qt::Vertical, xMap, + d_data->xScaleDiv.ticks( QwtScaleDiv::MinorTick ) ); + drawLines( painter, canvasRect, Qt::Vertical, xMap, + d_data->xScaleDiv.ticks( QwtScaleDiv::MediumTick ) ); } - if (d_data->yEnabled && d_data->yMinEnabled) + if ( d_data->yEnabled && d_data->yMinEnabled ) { - drawLines(painter, canvasRect, Qt::Horizontal, yMap, - d_data->yScaleDiv.ticks(QwtScaleDiv::MinorTick)); - drawLines(painter, canvasRect, Qt::Horizontal, yMap, - d_data->yScaleDiv.ticks(QwtScaleDiv::MediumTick)); + drawLines( painter, canvasRect, Qt::Horizontal, yMap, + d_data->yScaleDiv.ticks( QwtScaleDiv::MinorTick ) ); + drawLines( painter, canvasRect, Qt::Horizontal, yMap, + d_data->yScaleDiv.ticks( QwtScaleDiv::MediumTick ) ); } // draw major gridlines - painter->setPen(QwtPainter::scaledPen(d_data->majPen)); - - if (d_data->xEnabled) + QPen majPen = d_data->majPen; + majPen.setCapStyle( Qt::FlatCap ); + + painter->setPen( majPen ); + + if ( d_data->xEnabled ) { - drawLines(painter, canvasRect, Qt::Vertical, xMap, - d_data->xScaleDiv.ticks(QwtScaleDiv::MajorTick)); + drawLines( painter, canvasRect, Qt::Vertical, xMap, + d_data->xScaleDiv.ticks( QwtScaleDiv::MajorTick ) ); } - if (d_data->yEnabled) + if ( d_data->yEnabled ) { - drawLines(painter, canvasRect, Qt::Horizontal, yMap, - d_data->yScaleDiv.ticks(QwtScaleDiv::MajorTick)); + drawLines( painter, canvasRect, Qt::Horizontal, yMap, + d_data->yScaleDiv.ticks( QwtScaleDiv::MajorTick ) ); } } -void QwtPlotGrid::drawLines(QPainter *painter, const QRect &canvasRect, - Qt::Orientation orientation, const QwtScaleMap &scaleMap, - const QwtValueList &values) const +void QwtPlotGrid::drawLines( QPainter *painter, const QRectF &canvasRect, + Qt::Orientation orientation, const QwtScaleMap &scaleMap, + const QList &values ) const { - const int x1 = canvasRect.left(); - const int x2 = canvasRect.right(); - const int y1 = canvasRect.top(); - const int y2 = canvasRect.bottom(); + const double x1 = canvasRect.left(); + const double x2 = canvasRect.right() - 1.0; + const double y1 = canvasRect.top(); + const double y2 = canvasRect.bottom() - 1.0; - for (uint i = 0; i < (uint)values.count(); i++) + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + for ( int i = 0; i < values.count(); i++ ) { - const int value = scaleMap.transform(values[i]); + double value = scaleMap.transform( values[i] ); + if ( doAlign ) + value = qRound( value ); + if ( orientation == Qt::Horizontal ) { - if ((value >= y1) && (value <= y2)) - QwtPainter::drawLine(painter, x1, value, x2, value); + if ( qwtFuzzyGreaterOrEqual( value, y1 ) && + qwtFuzzyLessOrEqual( value, y2 ) ) + { + QwtPainter::drawLine( painter, x1, value, x2, value ); + } } else { - if ((value >= x1) && (value <= x2)) - QwtPainter::drawLine(painter, value, y1, value, y2); + if ( qwtFuzzyGreaterOrEqual( value, x1 ) && + qwtFuzzyLessOrEqual( value, x2 ) ) + { + QwtPainter::drawLine( painter, value, y1, value, y2 ); + } } } } @@ -279,69 +288,69 @@ void QwtPlotGrid::drawLines(QPainter *painter, const QRect &canvasRect, \return the pen for the major gridlines \sa setMajPen(), setMinPen(), setPen() */ -const QPen &QwtPlotGrid::majPen() const -{ - return d_data->majPen; +const QPen &QwtPlotGrid::majPen() const +{ + return d_data->majPen; } /*! \return the pen for the minor gridlines \sa setMinPen(), setMajPen(), setPen() */ -const QPen &QwtPlotGrid::minPen() const -{ - return d_data->minPen; +const QPen &QwtPlotGrid::minPen() const +{ + return d_data->minPen; } - + /*! \return true if vertical gridlines are enabled \sa enableX() */ bool QwtPlotGrid::xEnabled() const -{ - return d_data->xEnabled; +{ + return d_data->xEnabled; } /*! \return true if minor vertical gridlines are enabled \sa enableXMin() */ -bool QwtPlotGrid::xMinEnabled() const -{ - return d_data->xMinEnabled; +bool QwtPlotGrid::xMinEnabled() const +{ + return d_data->xMinEnabled; } /*! \return true if horizontal gridlines are enabled \sa enableY() */ -bool QwtPlotGrid::yEnabled() const -{ - return d_data->yEnabled; +bool QwtPlotGrid::yEnabled() const +{ + return d_data->yEnabled; } /*! \return true if minor horizontal gridlines are enabled \sa enableYMin() */ -bool QwtPlotGrid::yMinEnabled() const +bool QwtPlotGrid::yMinEnabled() const { - return d_data->yMinEnabled; + return d_data->yMinEnabled; } - + /*! \return the scale division of the x axis */ -const QwtScaleDiv &QwtPlotGrid::xScaleDiv() const -{ - return d_data->xScaleDiv; +const QwtScaleDiv &QwtPlotGrid::xScaleDiv() const +{ + return d_data->xScaleDiv; } /*! \return the scale division of the y axis */ -const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const -{ - return d_data->yScaleDiv; +const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const +{ + return d_data->yScaleDiv; } - + /*! Update the grid to changes of the axes scale division @@ -350,9 +359,9 @@ const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const \sa QwtPlot::updateAxes() */ -void QwtPlotGrid::updateScaleDiv(const QwtScaleDiv& xScaleDiv, - const QwtScaleDiv& yScaleDiv) +void QwtPlotGrid::updateScaleDiv( const QwtScaleDiv& xScaleDiv, + const QwtScaleDiv& yScaleDiv ) { - setXDiv(xScaleDiv); - setYDiv(yScaleDiv); + setXDiv( xScaleDiv ); + setYDiv( yScaleDiv ); } diff --git a/qwt/src/qwt_plot_grid.h b/qwt/src/qwt_plot_grid.h index ef64ddd0f..c8278abc9 100644 --- a/qwt/src/qwt_plot_grid.h +++ b/qwt/src/qwt_plot_grid.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -39,43 +39,43 @@ public: virtual int rtti() const; - void enableX(bool tf); + void enableX( bool tf ); bool xEnabled() const; - void enableY(bool tf); + void enableY( bool tf ); bool yEnabled() const; - void enableXMin(bool tf); + void enableXMin( bool tf ); bool xMinEnabled() const; - void enableYMin(bool tf); + void enableYMin( bool tf ); bool yMinEnabled() const; - void setXDiv(const QwtScaleDiv &sx); + void setXDiv( const QwtScaleDiv &sx ); const QwtScaleDiv &xScaleDiv() const; - void setYDiv(const QwtScaleDiv &sy); + void setYDiv( const QwtScaleDiv &sy ); const QwtScaleDiv &yScaleDiv() const; - void setPen(const QPen &p); + void setPen( const QPen &p ); - void setMajPen(const QPen &p); + void setMajPen( const QPen &p ); const QPen& majPen() const; - void setMinPen(const QPen &p); + void setMinPen( const QPen &p ); const QPen& minPen() const; - virtual void draw(QPainter *p, + virtual void draw( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &rect) const; + const QRectF &rect ) const; - virtual void updateScaleDiv(const QwtScaleDiv &xMap, - const QwtScaleDiv &yMap); + virtual void updateScaleDiv( + const QwtScaleDiv &xMap, const QwtScaleDiv &yMap ); private: - void drawLines(QPainter *painter, const QRect &, - Qt::Orientation orientation, const QwtScaleMap &, - const QwtValueList &) const; + void drawLines( QPainter *painter, const QRectF &, + Qt::Orientation orientation, const QwtScaleMap &, + const QList & ) const; class PrivateData; PrivateData *d_data; diff --git a/qwt/src/qwt_plot_histogram.cpp b/qwt/src/qwt_plot_histogram.cpp new file mode 100644 index 000000000..1fcf87109 --- /dev/null +++ b/qwt/src/qwt_plot_histogram.cpp @@ -0,0 +1,648 @@ +/* -*- 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_plot_histogram.h" +#include "qwt_plot.h" +#include "qwt_legend.h" +#include "qwt_legend_item.h" +#include "qwt_painter.h" +#include "qwt_column_symbol.h" +#include "qwt_scale_map.h" +#include +#include + +static inline bool isCombinable( const QwtInterval &d1, + const QwtInterval &d2 ) +{ + if ( d1.isValid() && d2.isValid() ) + { + if ( d1.maxValue() == d2.minValue() ) + { + if ( !( d1.borderFlags() & QwtInterval::ExcludeMaximum + && d2.borderFlags() & QwtInterval::ExcludeMinimum ) ) + { + return true; + } + } + } + + return false; +} + +class QwtPlotHistogram::PrivateData +{ +public: + PrivateData(): + baseline( 0.0 ), + style( Columns ), + symbol( NULL ) + { + } + + ~PrivateData() + { + delete symbol; + } + + double baseline; + + QPen pen; + QBrush brush; + QwtPlotHistogram::HistogramStyle style; + const QwtColumnSymbol *symbol; +}; + +/*! + Constructor + \param title Title of the histogram. +*/ + +QwtPlotHistogram::QwtPlotHistogram( const QwtText &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +/*! + Constructor + \param title Title of the histogram. +*/ +QwtPlotHistogram::QwtPlotHistogram( const QString &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +//! Destructor +QwtPlotHistogram::~QwtPlotHistogram() +{ + delete d_data; +} + +//! Initialize data members +void QwtPlotHistogram::init() +{ + d_data = new PrivateData(); + d_series = new QwtIntervalSeriesData(); + + setItemAttribute( QwtPlotItem::AutoScale, true ); + setItemAttribute( QwtPlotItem::Legend, true ); + + setZ( 20.0 ); +} + +/*! + Set the histogram's drawing style + + \param style Histogram style + \sa HistogramStyle, style() +*/ +void QwtPlotHistogram::setStyle( HistogramStyle style ) +{ + if ( style != d_data->style ) + { + d_data->style = style; + itemChanged(); + } +} + +/*! + Return the current style + \sa HistogramStyle, setStyle() +*/ +QwtPlotHistogram::HistogramStyle QwtPlotHistogram::style() const +{ + return d_data->style; +} + +/*! + Assign a pen, that is used in a style() depending way. + + \param pen New pen + \sa pen(), brush() +*/ +void QwtPlotHistogram::setPen( const QPen &pen ) +{ + if ( pen != d_data->pen ) + { + d_data->pen = pen; + itemChanged(); + } +} + +/*! + \return Pen used in a style() depending way. + \sa setPen(), brush() +*/ +const QPen &QwtPlotHistogram::pen() const +{ + return d_data->pen; +} + +/*! + Assign a brush, that is used in a style() depending way. + + \param brush New brush + \sa pen(), brush() +*/ +void QwtPlotHistogram::setBrush( const QBrush &brush ) +{ + if ( brush != d_data->brush ) + { + d_data->brush = brush; + itemChanged(); + } +} + +/*! + \return Brush used in a style() depending way. + \sa setPen(), brush() +*/ +const QBrush &QwtPlotHistogram::brush() const +{ + return d_data->brush; +} + +/*! + \brief Assign a symbol + + In Column style an optional symbol can be assigned, that is responsible + for displaying the rectangle that is defined by the interval and + the distance between baseline() and value. When no symbol has been + defined the area is displayed as plain rectangle using pen() and brush(). + + \sa style(), symbol(), drawColumn(), pen(), brush() + + \note In applications, where different intervals need to be displayed + in a different way ( f.e different colors or even using differnt symbols) + it is recommended to overload drawColumn(). +*/ +void QwtPlotHistogram::setSymbol( const QwtColumnSymbol *symbol ) +{ + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + itemChanged(); + } +} + +/*! + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() +*/ +const QwtColumnSymbol *QwtPlotHistogram::symbol() const +{ + return d_data->symbol; +} + +/*! + \brief Set the value of the baseline + + Each column representing an QwtIntervalSample is defined by its + interval and the interval between baseline and the value of the sample. + + The default value of the baseline is 0.0. + + \param value Value of the baseline + \sa baseline() +*/ +void QwtPlotHistogram::setBaseline( double value ) +{ + if ( d_data->baseline != value ) + { + d_data->baseline = value; + itemChanged(); + } +} + +/*! + \return Value of the baseline + \sa setBaseline() +*/ +double QwtPlotHistogram::baseline() const +{ + return d_data->baseline; +} + +/*! + \return Bounding rectangle of all samples. + For an empty series the rectangle is invalid. +*/ +QRectF QwtPlotHistogram::boundingRect() const +{ + QRectF rect = d_series->boundingRect(); + if ( !rect.isValid() ) + return rect; + + if ( orientation() == Qt::Horizontal ) + { + rect = QRectF( rect.y(), rect.x(), + rect.height(), rect.width() ); + + if ( rect.left() > d_data->baseline ) + rect.setLeft( d_data->baseline ); + else if ( rect.right() < d_data->baseline ) + rect.setRight( d_data->baseline ); + } + else + { + if ( rect.bottom() < d_data->baseline ) + rect.setBottom( d_data->baseline ); + else if ( rect.top() > d_data->baseline ) + rect.setTop( d_data->baseline ); + } + + return rect; +} + +//! \return QwtPlotItem::Rtti_PlotHistogram +int QwtPlotHistogram::rtti() const +{ + return QwtPlotItem::Rtti_PlotHistogram; +} + +/*! + Initialize data with an array of samples. + \param samples Vector of points +*/ +void QwtPlotHistogram::setSamples( + const QVector &samples ) +{ + delete d_series; + d_series = new QwtIntervalSeriesData( samples ); + itemChanged(); +} + +/*! + Draw a subset of the histogram samples + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rect of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + series will be painted to its last sample. + + \sa drawOutline(), drawLines(), drawColumns +*/ +void QwtPlotHistogram::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &, int from, int to ) const +{ + if ( !painter || dataSize() <= 0 ) + return; + + if ( to < 0 ) + to = dataSize() - 1; + + switch ( d_data->style ) + { + case Outline: + drawOutline( painter, xMap, yMap, from, to ); + break; + case Lines: + drawLines( painter, xMap, yMap, from, to ); + break; + case Columns: + drawColumns( painter, xMap, yMap, from, to ); + break; + default: + break; + } +} + +/*! + Draw a histogram in Outline style() + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + histogram will be painted to its last point. + + \sa setStyle(), style() + \warning The outline style requires, that the intervals are in increasing + order and not overlapping. +*/ +void QwtPlotHistogram::drawOutline( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + double v0 = ( orientation() == Qt::Horizontal ) ? + xMap.transform( baseline() ) : yMap.transform( baseline() ); + if ( doAlign ) + v0 = qRound( v0 ); + + QwtIntervalSample previous; + + QPolygonF polygon; + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample sample = d_series->sample( i ); + + if ( !sample.interval.isValid() ) + { + flushPolygon( painter, v0, polygon ); + previous = sample; + continue; + } + + if ( previous.interval.isValid() ) + { + if ( !isCombinable( previous.interval, sample.interval ) ) + flushPolygon( painter, v0, polygon ); + } + + if ( orientation() == Qt::Vertical ) + { + double x1 = xMap.transform( sample.interval.minValue() ); + double x2 = xMap.transform( sample.interval.maxValue() ); + double y = yMap.transform( sample.value ); + if ( doAlign ) + { + x1 = qRound( x1 ); + x2 = qRound( x2 ); + y = qRound( y ); + } + + if ( polygon.size() == 0 ) + polygon += QPointF( x1, v0 ); + + polygon += QPointF( x1, y ); + polygon += QPointF( x2, y ); + } + else + { + double y1 = yMap.transform( sample.interval.minValue() ); + double y2 = yMap.transform( sample.interval.maxValue() ); + double x = xMap.transform( sample.value ); + if ( doAlign ) + { + y1 = qRound( y1 ); + y2 = qRound( y2 ); + x = qRound( x ); + } + + if ( polygon.size() == 0 ) + polygon += QPointF( v0, y1 ); + + polygon += QPointF( x, y1 ); + polygon += QPointF( x, y2 ); + } + previous = sample; + } + + flushPolygon( painter, v0, polygon ); +} + +/*! + Draw a histogram in Columns style() + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + histogram will be painted to its last point. + + \sa setStyle(), style(), setSymbol(), drawColumn() +*/ +void QwtPlotHistogram::drawColumns( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const +{ + painter->setPen( d_data->pen ); + painter->setBrush( d_data->brush ); + + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample sample = d_series->sample( i ); + if ( !sample.interval.isNull() ) + { + const QwtColumnRect rect = columnRect( sample, xMap, yMap ); + drawColumn( painter, rect, sample ); + } + } +} + +/*! + Draw a histogram in Lines style() + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + histogram will be painted to its last point. + + \sa setStyle(), style(), setPen() +*/ +void QwtPlotHistogram::drawLines( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + painter->setPen( d_data->pen ); + painter->setBrush( Qt::NoBrush ); + + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample sample = d_series->sample( i ); + if ( !sample.interval.isNull() ) + { + const QwtColumnRect rect = columnRect( sample, xMap, yMap ); + + QRectF r = rect.toRect(); + if ( doAlign ) + { + r.setLeft( qRound( r.left() ) ); + r.setRight( qRound( r.right() ) ); + r.setTop( qRound( r.top() ) ); + r.setBottom( qRound( r.bottom() ) ); + } + + switch ( rect.direction ) + { + case QwtColumnRect::LeftToRight: + { + QwtPainter::drawLine( painter, + r.topRight(), r.bottomRight() ); + break; + } + case QwtColumnRect::RightToLeft: + { + QwtPainter::drawLine( painter, + r.topLeft(), r.bottomLeft() ); + break; + } + case QwtColumnRect::TopToBottom: + { + QwtPainter::drawLine( painter, + r.bottomRight(), r.bottomLeft() ); + break; + } + case QwtColumnRect::BottomToTop: + { + QwtPainter::drawLine( painter, + r.topRight(), r.topLeft() ); + break; + } + } + } + } +} + +//! Internal, used by the Outline style. +void QwtPlotHistogram::flushPolygon( QPainter *painter, + double baseLine, QPolygonF &polygon ) const +{ + if ( polygon.size() == 0 ) + return; + + if ( orientation() == Qt::Horizontal ) + polygon += QPointF( baseLine, polygon.last().y() ); + else + polygon += QPointF( polygon.last().x(), baseLine ); + + if ( d_data->brush.style() != Qt::NoBrush ) + { + painter->setPen( Qt::NoPen ); + painter->setBrush( d_data->brush ); + + if ( orientation() == Qt::Horizontal ) + { + polygon += QPointF( polygon.last().x(), baseLine ); + polygon += QPointF( polygon.first().x(), baseLine ); + } + else + { + polygon += QPointF( baseLine, polygon.last().y() ); + polygon += QPointF( baseLine, polygon.first().y() ); + } + QwtPainter::drawPolygon( painter, polygon ); + polygon.resize( polygon.size() - 2 ); + } + if ( d_data->pen.style() != Qt::NoPen ) + { + painter->setBrush( Qt::NoBrush ); + painter->setPen( d_data->pen ); + QwtPainter::drawPolyline( painter, polygon ); + } + polygon.clear(); +} + +/*! + Calculate the area that is covered by a sample + + \param sample Sample + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + + \return Rectangle, that is covered by a sample +*/ +QwtColumnRect QwtPlotHistogram::columnRect( const QwtIntervalSample &sample, + const QwtScaleMap &xMap, const QwtScaleMap &yMap ) const +{ + QwtColumnRect rect; + + const QwtInterval &iv = sample.interval; + if ( !iv.isValid() ) + return rect; + + if ( orientation() == Qt::Horizontal ) + { + const double x0 = xMap.transform( baseline() ); + const double x = xMap.transform( sample.value ); + const double y1 = yMap.transform( iv.minValue() ); + const double y2 = yMap.transform( iv.maxValue() ); + + rect.hInterval.setInterval( x0, x ); + rect.vInterval.setInterval( y1, y2, iv.borderFlags() ); + rect.direction = ( x < x0 ) ? QwtColumnRect::RightToLeft : + QwtColumnRect::LeftToRight; + } + else + { + const double x1 = xMap.transform( iv.minValue() ); + const double x2 = xMap.transform( iv.maxValue() ); + const double y0 = yMap.transform( baseline() ); + const double y = yMap.transform( sample.value ); + + rect.hInterval.setInterval( x1, x2, iv.borderFlags() ); + rect.vInterval.setInterval( y0, y ); + rect.direction = ( y < y0 ) ? QwtColumnRect::BottomToTop : + QwtColumnRect::TopToBottom; + } + + return rect; +} + +/*! + Draw a column for a sample in Columns style(). + + When a symbol() has been set the symbol is used otherwise the + column is displayed as plain rectangle using pen() and brush(). + + \param painter Painter + \param rect Rectangle where to paint the column in paint device coordinates + \param sample Sample to be displayed + + \note In applications, where different intervals need to be displayed + in a different way ( f.e different colors or even using differnt symbols) + it is recommended to overload drawColumn(). +*/ +void QwtPlotHistogram::drawColumn( QPainter *painter, + const QwtColumnRect &rect, const QwtIntervalSample &sample ) const +{ + Q_UNUSED( sample ); + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtColumnSymbol::NoStyle ) ) + { + d_data->symbol->draw( painter, rect ); + } + else + { + 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() ) ); + } + + QwtPainter::drawRect( painter, r ); + } +} + +/*! + Draw a plain rectangle without pen using the brush() as identifier + + \param painter Painter + \param rect Bounding rectangle for the identifier +*/ +void QwtPlotHistogram::drawLegendIdentifier( + QPainter *painter, const QRectF &rect ) const +{ + const double dim = qMin( rect.width(), rect.height() ); + + QSizeF size( dim, dim ); + + QRectF r( 0, 0, size.width(), size.height() ); + r.moveCenter( rect.center() ); + + painter->fillRect( r, d_data->brush ); +} diff --git a/qwt/src/qwt_plot_histogram.h b/qwt/src/qwt_plot_histogram.h new file mode 100644 index 000000000..cf6d98e5b --- /dev/null +++ b/qwt/src/qwt_plot_histogram.h @@ -0,0 +1,134 @@ +/* -*- 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_PLOT_HISTOGRAM_H +#define QWT_PLOT_HISTOGRAM_H + +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_column_symbol.h" +#include +#include + +class QwtIntervalData; +class QString; +class QPolygonF; + +/*! + \brief QwtPlotHistogram represents a series of samples, where an interval + is associated with a value ( \f$y = f([x1,x2])\f$ ). + + The representation depends on the style() and an optional symbol() + that is displayed for each interval. + + \note The term "histogram" is used in a different way in the areas of + digital image processing and statistics. Wikipedia introduces the + terms "image histogram" and "color histogram" to avoid confusions. + While "image histograms" can be displayed by a QwtPlotCurve there + is no applicable plot item for a "color histogram" yet. +*/ + +class QWT_EXPORT QwtPlotHistogram: public QwtPlotSeriesItem +{ +public: + /*! + Histogram styles. + The default style is QwtPlotHistogram::Columns. + + \sa setStyle(), style(), setSymbol(), symbol(), setBaseline() + */ + enum HistogramStyle + { + /*! + Draw an outline around the area, that is build by all intervals + using the pen() and fill it with the brush(). The outline style + requires, that the intervals are in increasing order and + not overlapping. + */ + Outline, + + /*! + Draw a column for each interval. When a symbol() has been set + the symbol is used otherwise the column is displayed as + plain rectangle using pen() and brush(). + */ + Columns, + + /*! + Draw a simple line using the pen() for each interval. + */ + Lines, + + /*! + Styles >= UserStyle are reserved for derived + classes that overload drawSeries() with + additional application specific ways to display a histogram. + */ + UserStyle = 100 + }; + + explicit QwtPlotHistogram( const QString &title = QString::null ); + explicit QwtPlotHistogram( const QwtText &title ); + virtual ~QwtPlotHistogram(); + + virtual int rtti() const; + + void setPen( const QPen & ); + const QPen &pen() const; + + void setBrush( const QBrush & ); + const QBrush &brush() const; + + void setSamples( const QVector & ); + + void setBaseline( double reference ); + double baseline() const; + + void setStyle( HistogramStyle style ); + HistogramStyle style() const; + + void setSymbol( const QwtColumnSymbol * ); + const QwtColumnSymbol *symbol() const; + + virtual void drawSeries( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual QRectF boundingRect() const; + + virtual void drawLegendIdentifier( QPainter *, const QRectF & ) const; + +protected: + virtual QwtColumnRect columnRect( const QwtIntervalSample &, + const QwtScaleMap &, const QwtScaleMap & ) const; + + virtual void drawColumn( QPainter *, const QwtColumnRect &, + const QwtIntervalSample & ) const; + + void drawColumns( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const; + + void drawOutline( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const; + + void drawLines( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const; + +private: + void init(); + void flushPolygon( QPainter *, double baseLine, QPolygonF & ) const; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/qwt/src/qwt_plot_intervalcurve.cpp b/qwt/src/qwt_plot_intervalcurve.cpp new file mode 100644 index 000000000..94e57acf8 --- /dev/null +++ b/qwt/src/qwt_plot_intervalcurve.cpp @@ -0,0 +1,547 @@ +/* -*- 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_plot_intervalcurve.h" +#include "qwt_interval_symbol.h" +#include "qwt_scale_map.h" +#include "qwt_clipper.h" +#include "qwt_painter.h" + +#include + +static inline bool qwtIsHSampleInside( const QwtIntervalSample &sample, + double xMin, double xMax, double yMin, double yMax ) +{ + const double y = sample.value; + const double x1 = sample.interval.minValue(); + const double x2 = sample.interval.maxValue(); + + const bool isOffScreen = ( y < yMin ) || ( y > yMax ) + || ( x1 < xMin && x2 < xMin ) || ( x1 > yMax && x2 > xMax ); + + return !isOffScreen; +} + +static inline bool qwtIsVSampleInside( const QwtIntervalSample &sample, + double xMin, double xMax, double yMin, double yMax ) +{ + const double x = sample.value; + const double y1 = sample.interval.minValue(); + const double y2 = sample.interval.maxValue(); + + const bool isOffScreen = ( x < xMin ) || ( x > xMax ) + || ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax ); + + return !isOffScreen; +} + +class QwtPlotIntervalCurve::PrivateData +{ +public: + PrivateData(): + style( Tube ), + symbol( NULL ), + pen( Qt::black ), + brush( Qt::white ) + { + paintAttributes = QwtPlotIntervalCurve::ClipPolygons; + paintAttributes |= QwtPlotIntervalCurve::ClipSymbol; + + pen.setCapStyle( Qt::FlatCap ); + } + + ~PrivateData() + { + delete symbol; + } + + CurveStyle style; + const QwtIntervalSymbol *symbol; + + QPen pen; + QBrush brush; + + QwtPlotIntervalCurve::PaintAttributes paintAttributes; +}; + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QwtText &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QString &title ): + QwtPlotSeriesItem( QwtText( title ) ) +{ + init(); +} + +//! Destructor +QwtPlotIntervalCurve::~QwtPlotIntervalCurve() +{ + delete d_data; +} + +//! Initialize internal members +void QwtPlotIntervalCurve::init() +{ + setItemAttribute( QwtPlotItem::Legend, true ); + setItemAttribute( QwtPlotItem::AutoScale, true ); + + d_data = new PrivateData; + d_series = new QwtIntervalSeriesData(); + + setZ( 19.0 ); +} + +//! \return QwtPlotItem::Rtti_PlotIntervalCurve +int QwtPlotIntervalCurve::rtti() const +{ + return QwtPlotIntervalCurve::Rtti_PlotIntervalCurve; +} + +/*! + Specify an attribute how to draw the curve + + \param attribute Paint attribute + \param on On/Off + \sa testPaintAttribute() +*/ +void QwtPlotIntervalCurve::setPaintAttribute( + PaintAttribute attribute, bool on ) +{ + if ( on ) + d_data->paintAttributes |= attribute; + else + d_data->paintAttributes &= ~attribute; +} + +/*! + \brief Return the current paint attributes + \sa PaintAttribute, setPaintAttribute() +*/ +bool QwtPlotIntervalCurve::testPaintAttribute( + PaintAttribute attribute ) const +{ + return ( d_data->paintAttributes & attribute ); +} + +/*! + Initialize data with an array of samples. + \param samples Vector of samples +*/ +void QwtPlotIntervalCurve::setSamples( + const QVector &samples ) +{ + delete d_series; + d_series = new QwtIntervalSeriesData( samples ); + itemChanged(); +} + +/*! + Set the curve's drawing style + + \param style Curve style + \sa CurveStyle, style() +*/ +void QwtPlotIntervalCurve::setStyle( CurveStyle style ) +{ + if ( style != d_data->style ) + { + d_data->style = style; + itemChanged(); + } +} + +/*! + \brief Return the current style + \sa setStyle() +*/ +QwtPlotIntervalCurve::CurveStyle QwtPlotIntervalCurve::style() const +{ + return d_data->style; +} + +/*! + Assign a symbol. + + \param symbol Symbol + \sa symbol() +*/ +void QwtPlotIntervalCurve::setSymbol( const QwtIntervalSymbol *symbol ) +{ + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + itemChanged(); + } +} + +/*! + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() +*/ +const QwtIntervalSymbol *QwtPlotIntervalCurve::symbol() const +{ + return d_data->symbol; +} + +/*! + \brief Assign a pen + \param pen New pen + \sa pen(), brush() +*/ +void QwtPlotIntervalCurve::setPen( const QPen &pen ) +{ + if ( pen != d_data->pen ) + { + d_data->pen = pen; + itemChanged(); + } +} + +/*! + \brief Return the pen used to draw the lines + \sa setPen(), brush() +*/ +const QPen& QwtPlotIntervalCurve::pen() const +{ + return d_data->pen; +} + +/*! + Assign a brush. + + The brush is used to fill the area in Tube style(). + + \param brush Brush + \sa brush(), pen(), setStyle(), CurveStyle +*/ +void QwtPlotIntervalCurve::setBrush( const QBrush &brush ) +{ + if ( brush != d_data->brush ) + { + d_data->brush = brush; + itemChanged(); + } +} + +/*! + \return Brush used to fill the area in Tube style() + \sa setBrush(), setStyle(), CurveStyle +*/ +const QBrush& QwtPlotIntervalCurve::brush() const +{ + return d_data->brush; +} + +/*! + \return Bounding rectangle of all samples. + For an empty series the rectangle is invalid. +*/ +QRectF QwtPlotIntervalCurve::boundingRect() const +{ + QRectF rect = QwtPlotSeriesItem::boundingRect(); + if ( rect.isValid() && orientation() == Qt::Vertical ) + rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() ); + + return rect; +} + +/*! + Draw a subset of the samples + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rect of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + series will be painted to its last sample. + + \sa drawTube(), drawSymbols() +*/ +void QwtPlotIntervalCurve::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + if ( to < 0 ) + to = dataSize() - 1; + + if ( from < 0 ) + from = 0; + + if ( from > to ) + return; + + switch ( d_data->style ) + { + case Tube: + drawTube( painter, xMap, yMap, canvasRect, from, to ); + break; + + case NoCurve: + default: + break; + } + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) ) + { + drawSymbols( painter, *d_data->symbol, + xMap, yMap, canvasRect, from, to ); + } +} + +/*! + Draw a tube + + Builds 2 curves from the upper and lower limits of the intervals + and draws them with the pen(). The area between the curves is + filled with the brush(). + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rect of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + series will be painted to its last sample. + + \sa drawSeries(), drawSymbols() +*/ +void QwtPlotIntervalCurve::drawTube( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + painter->save(); + + const size_t size = to - from + 1; + QPolygonF polygon( 2 * size ); + QPointF *points = polygon.data(); + + for ( uint i = 0; i < size; i++ ) + { + QPointF &minValue = points[i]; + QPointF &maxValue = points[2 * size - 1 - i]; + + const QwtIntervalSample intervalSample = sample( from + i ); + if ( orientation() == Qt::Vertical ) + { + double x = xMap.transform( intervalSample.value ); + double y1 = yMap.transform( intervalSample.interval.minValue() ); + double y2 = yMap.transform( intervalSample.interval.maxValue() ); + if ( doAlign ) + { + x = qRound( x ); + y1 = qRound( y1 ); + y2 = qRound( y2 ); + } + + minValue.rx() = x; + minValue.ry() = y1; + maxValue.rx() = x; + maxValue.ry() = y2; + } + else + { + double y = yMap.transform( intervalSample.value ); + double x1 = xMap.transform( intervalSample.interval.minValue() ); + double x2 = xMap.transform( intervalSample.interval.maxValue() ); + if ( doAlign ) + { + y = qRound( y ); + x1 = qRound( x1 ); + x2 = qRound( x2 ); + } + + minValue.rx() = x1; + minValue.ry() = y; + maxValue.rx() = x2; + maxValue.ry() = y; + } + } + + if ( d_data->brush.style() != Qt::NoBrush ) + { + painter->setPen( QPen( Qt::NoPen ) ); + painter->setBrush( d_data->brush ); + + if ( d_data->paintAttributes & ClipPolygons ) + { + const qreal m = 1.0; + const QPolygonF p = QwtClipper::clipPolygonF( + canvasRect.adjusted(-m, -m, m, m), polygon, true ); + + QwtPainter::drawPolygon( painter, p ); + } + else + { + QwtPainter::drawPolygon( painter, polygon ); + } + } + + if ( d_data->pen.style() != Qt::NoPen ) + { + painter->setPen( d_data->pen ); + painter->setBrush( Qt::NoBrush ); + + if ( d_data->paintAttributes & ClipPolygons ) + { + qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF()); + const QRectF clipRect = canvasRect.adjusted(-pw, -pw, pw, pw); + + QPolygonF p; + + p.resize( size ); + qMemCopy( p.data(), points, size * sizeof( QPointF ) ); + p = QwtClipper::clipPolygonF( canvasRect, p ); + QwtPainter::drawPolyline( painter, p ); + + p.resize( size ); + qMemCopy( p.data(), points + size, size * sizeof( QPointF ) ); + p = QwtClipper::clipPolygonF( canvasRect, p ); + QwtPainter::drawPolyline( painter, p ); + } + else + { + QwtPainter::drawPolyline( painter, points, size ); + QwtPainter::drawPolyline( painter, points + size, size ); + } + } + + painter->restore(); +} + +/*! + Draw symbols for a subset of the samples + + \param painter Painter + \param symbol Interval symbol + \param xMap x map + \param yMap y map + \param canvasRect Contents rect of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted + + \sa setSymbol(), drawSeries(), drawTube() +*/ +void QwtPlotIntervalCurve::drawSymbols( + QPainter *painter, const QwtIntervalSymbol &symbol, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + painter->save(); + + QPen pen = symbol.pen(); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + painter->setBrush( symbol.brush() ); + + const QRectF &tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect); + + const double xMin = tr.left(); + const double xMax = tr.right(); + const double yMin = tr.top(); + const double yMax = tr.bottom(); + + const bool doClip = d_data->paintAttributes & ClipPolygons; + + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample s = sample( i ); + + if ( orientation() == Qt::Vertical ) + { + if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) ) + { + const double x = xMap.transform( s.value ); + const double y1 = yMap.transform( s.interval.minValue() ); + const double y2 = yMap.transform( s.interval.maxValue() ); + + symbol.draw( painter, orientation(), + QPointF( x, y1 ), QPointF( x, y2 ) ); + } + } + else + { + if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) ) + { + const double y = yMap.transform( s.value ); + const double x1 = xMap.transform( s.interval.minValue() ); + const double x2 = xMap.transform( s.interval.maxValue() ); + + symbol.draw( painter, orientation(), + QPointF( x1, y ), QPointF( x2, y ) ); + } + } + } + + painter->restore(); +} + +/*! + In case of Tibe stale() a plain rectangle is painted without a pen filled + the brush(). If a symbol is assigned it is painted cebtered into rect. + + \param painter Painter + \param rect Bounding rectangle for the identifier +*/ + +void QwtPlotIntervalCurve::drawLegendIdentifier( + QPainter *painter, const QRectF &rect ) const +{ + const double dim = qMin( rect.width(), rect.height() ); + + QSizeF size( dim, dim ); + + QRectF r( 0, 0, size.width(), size.height() ); + r.moveCenter( rect.center() ); + + if ( d_data->style == Tube ) + { + painter->fillRect( r, d_data->brush ); + } + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) ) + { + QPen pen = d_data->symbol->pen(); + pen.setWidthF( pen.widthF() ); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + painter->setBrush( d_data->symbol->brush() ); + + if ( orientation() == Qt::Vertical ) + { + d_data->symbol->draw( painter, orientation(), + QPointF( r.center().x(), r.top() ), + QPointF( r.center().x(), r.bottom() - 1 ) ); + } + else + { + d_data->symbol->draw( painter, orientation(), + QPointF( r.left(), r.center().y() ), + QPointF( r.right() - 1, r.center().y() ) ); + } + } +} diff --git a/qwt/src/qwt_plot_intervalcurve.h b/qwt/src/qwt_plot_intervalcurve.h new file mode 100644 index 000000000..b26586e64 --- /dev/null +++ b/qwt/src/qwt_plot_intervalcurve.h @@ -0,0 +1,130 @@ +/* -*- 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_PLOT_INTERVAL_CURVE_H +#define QWT_PLOT_INTERVAL_CURVE_H + +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_series_data.h" + +class QwtIntervalSymbol; + +/*! + \brief QwtPlotIntervalCurve represents a series of samples, where each value + is associated with an interval ( \f$[y1,y2] = f(x)\f$ ). + + The representation depends on the style() and an optional symbol() + that is displayed for each interval. QwtPlotIntervalCurve might be used + to disply error bars or the area between 2 curves. +*/ + +class QWT_EXPORT QwtPlotIntervalCurve: public QwtPlotSeriesItem +{ +public: + /*! + \brief Curve styles. + The default setting is QwtPlotIntervalCurve::Tube. + + \sa setStyle(), style() + */ + + enum CurveStyle + { + /*! + Don't draw a curve. Note: This doesn't affect the symbols. + */ + NoCurve, + + /*! + Build 2 curves from the upper and lower limits of the intervals + and draw them with the pen(). The area between the curves is + filled with the brush(). + */ + Tube, + + /*! + Styles >= QwtPlotIntervalCurve::UserCurve are reserved for derived + classes that overload drawSeries() with + additional application specific curve types. + */ + UserCurve = 100 + }; + + /*! + Attributes to modify the drawing algorithm. + \sa setPaintAttribute(), testPaintAttribute() + */ + enum PaintAttribute + { + /*! + Clip polygons before painting them. In situations, where points + are far outside the visible area (f.e when zooming deep) this + might be a substantial improvement for the painting performance. + */ + ClipPolygons = 0x01, + + //! Check if a symbol is on the plot canvas before painting it. + ClipSymbol = 0x02 + }; + + //! Paint attributes + typedef QFlags PaintAttributes; + + explicit QwtPlotIntervalCurve( const QString &title = QString::null ); + explicit QwtPlotIntervalCurve( const QwtText &title ); + + virtual ~QwtPlotIntervalCurve(); + + virtual int rtti() const; + + void setPaintAttribute( PaintAttribute, bool on = true ); + bool testPaintAttribute( PaintAttribute ) const; + + void setSamples( const QVector & ); + + void setPen( const QPen & ); + const QPen &pen() const; + + void setBrush( const QBrush & ); + const QBrush &brush() const; + + void setStyle( CurveStyle style ); + CurveStyle style() const; + + void setSymbol( const QwtIntervalSymbol * ); + const QwtIntervalSymbol *symbol() const; + + virtual void drawSeries( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual QRectF boundingRect() const; + virtual void drawLegendIdentifier( QPainter *, const QRectF & ) const; + +protected: + + void init(); + + virtual void drawTube( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawSymbols( QPainter *, const QwtIntervalSymbol &, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotIntervalCurve::PaintAttributes ) + +#endif diff --git a/qwt/src/qwt_plot_item.cpp b/qwt/src/qwt_plot_item.cpp index 6587e4c49..7601f4400 100644 --- a/qwt/src/qwt_plot_item.cpp +++ b/qwt/src/qwt_plot_item.cpp @@ -2,40 +2,38 @@ * 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_plot_item.h" #include "qwt_text.h" #include "qwt_plot.h" #include "qwt_legend.h" #include "qwt_legend_item.h" -#include "qwt_plot_item.h" +#include "qwt_scale_div.h" +#include class QwtPlotItem::PrivateData { public: PrivateData(): - plot(NULL), - isVisible(true), - attributes(0), -#if QT_VERSION >= 0x040000 - renderHints(0), -#endif - z(0.0), - xAxis(QwtPlot::xBottom), - yAxis(QwtPlot::yLeft) + plot( NULL ), + isVisible( true ), + attributes( 0 ), + renderHints( 0 ), + z( 0.0 ), + xAxis( QwtPlot::xBottom ), + yAxis( QwtPlot::yLeft ) { } mutable QwtPlot *plot; bool isVisible; - int attributes; -#if QT_VERSION >= 0x040000 - int renderHints; -#endif + QwtPlotItem::ItemAttributes attributes; + QwtPlotItem::RenderHints renderHints; double z; int xAxis; @@ -44,11 +42,11 @@ public: QwtText title; }; -/*! +/*! Constructor \param title Title of the item */ -QwtPlotItem::QwtPlotItem(const QwtText &title) +QwtPlotItem::QwtPlotItem( const QwtText &title ) { d_data = new PrivateData; d_data->title = title; @@ -57,11 +55,11 @@ QwtPlotItem::QwtPlotItem(const QwtText &title) //! Destroy the QwtPlotItem QwtPlotItem::~QwtPlotItem() { - attach(NULL); + attach( NULL ); delete d_data; } -/*! +/*! \brief Attach the item to a plot. This method will attach a QwtPlotItem to the QwtPlot argument. It will first @@ -70,9 +68,9 @@ QwtPlotItem::~QwtPlotItem() was attached to. \param plot Plot widget - \sa QwtPlotItem::detach() + \sa detach() */ -void QwtPlotItem::attach(QwtPlot *plot) +void QwtPlotItem::attach( QwtPlot *plot ) { if ( plot == d_data->plot ) return; @@ -82,13 +80,9 @@ void QwtPlotItem::attach(QwtPlot *plot) if ( d_data->plot ) { if ( d_data->plot->legend() ) - { - QWidget *legendItem = d_data->plot->legend()->find(this); - if ( legendItem ) - delete legendItem; - } + d_data->plot->legend()->remove( this ); - d_data->plot->attachItem(this, false); + d_data->plot->attachItem( this, false ); if ( d_data->plot->autoReplot() ) d_data->plot->update(); @@ -100,20 +94,32 @@ void QwtPlotItem::attach(QwtPlot *plot) { // insert the item into the current plot - d_data->plot->attachItem(this, true); + d_data->plot->attachItem( this, true ); itemChanged(); } } -/*! +/*! + \brief This method detaches a QwtPlotItem from any + QwtPlot it has been associated with. + + detach() is equivalent to calling attach( NULL ) + \sa attach() +*/ +void QwtPlotItem::detach() +{ + attach( NULL ); +} + +/*! Return rtti for the specific class represented. QwtPlotItem is simply a virtual interface class, and base classes will implement this method with specific rtti values so a user can differentiate them. - The rtti value is useful for environments, where the + The rtti value is useful for environments, where the runtime type information is disabled and it is not possible to do a dynamic_cast<...>. - + \return rtti value \sa RttiValues */ @@ -123,9 +129,9 @@ int QwtPlotItem::rtti() const } //! Return attached plot -QwtPlot *QwtPlotItem::plot() const -{ - return d_data->plot; +QwtPlot *QwtPlotItem::plot() const +{ + return d_data->plot; } /*! @@ -133,9 +139,9 @@ QwtPlot *QwtPlotItem::plot() const \return setZ(), QwtPlotDict::itemList() */ -double QwtPlotItem::z() const -{ - return d_data->z; +double QwtPlotItem::z() const +{ + return d_data->z; } /*! @@ -146,43 +152,44 @@ double QwtPlotItem::z() const \param z Z-value \sa z(), QwtPlotDict::itemList() */ -void QwtPlotItem::setZ(double z) -{ +void QwtPlotItem::setZ( double z ) +{ if ( d_data->z != z ) { - d_data->z = z; + if ( d_data->plot ) // update the z order + d_data->plot->attachItem( this, false ); + + d_data->z = z; + if ( d_data->plot ) - { - // update the z order - d_data->plot->attachItem(this, false); - d_data->plot->attachItem(this, true); - } + d_data->plot->attachItem( this, true ); + itemChanged(); } } -/*! +/*! Set a new title \param title Title - \sa title() -*/ -void QwtPlotItem::setTitle(const QString &title) + \sa title() +*/ +void QwtPlotItem::setTitle( const QString &title ) { - setTitle(QwtText(title)); + setTitle( QwtText( title ) ); } -/*! +/*! Set a new title \param title Title - \sa title() -*/ -void QwtPlotItem::setTitle(const QwtText &title) + \sa title() +*/ +void QwtPlotItem::setTitle( const QwtText &title ) { if ( d_data->title != title ) { - d_data->title = title; + d_data->title = title; itemChanged(); } } @@ -198,15 +205,15 @@ const QwtText &QwtPlotItem::title() const /*! Toggle an item attribute - + \param attribute Attribute type \param on true/false \sa testItemAttribute(), ItemAttribute */ -void QwtPlotItem::setItemAttribute(ItemAttribute attribute, bool on) +void QwtPlotItem::setItemAttribute( ItemAttribute attribute, bool on ) { - if ( bool(d_data->attributes & attribute) != on ) + if ( bool( d_data->attributes & attribute ) != on ) { if ( on ) d_data->attributes |= attribute; @@ -224,24 +231,22 @@ void QwtPlotItem::setItemAttribute(ItemAttribute attribute, bool on) \return true/false \sa setItemAttribute(), ItemAttribute */ -bool QwtPlotItem::testItemAttribute(ItemAttribute attribute) const +bool QwtPlotItem::testItemAttribute( ItemAttribute attribute ) const { - return d_data->attributes & attribute; + return ( d_data->attributes & attribute ); } -#if QT_VERSION >= 0x040000 - /*! Toggle an render hint - + \param hint Render hint \param on true/false \sa testRenderHint(), RenderHint */ -void QwtPlotItem::setRenderHint(RenderHint hint, bool on) +void QwtPlotItem::setRenderHint( RenderHint hint, bool on ) { - if ( ((d_data->renderHints & hint) != 0) != on ) + if ( ( ( d_data->renderHints & hint ) != 0 ) != on ) { if ( on ) d_data->renderHints |= hint; @@ -259,51 +264,49 @@ void QwtPlotItem::setRenderHint(RenderHint hint, bool on) \return true/false \sa setRenderHint(), RenderHint */ -bool QwtPlotItem::testRenderHint(RenderHint hint) const +bool QwtPlotItem::testRenderHint( RenderHint hint ) const { - return (d_data->renderHints & hint); + return ( d_data->renderHints & hint ); } -#endif - //! Show the item void QwtPlotItem::show() { - setVisible(true); + setVisible( true ); } //! Hide the item void QwtPlotItem::hide() { - setVisible(false); + setVisible( false ); } -/*! +/*! Show/Hide the item \param on Show if true, otherwise hide \sa isVisible(), show(), hide() */ -void QwtPlotItem::setVisible(bool on) -{ +void QwtPlotItem::setVisible( bool on ) +{ if ( on != d_data->isVisible ) { - d_data->isVisible = on; - itemChanged(); + d_data->isVisible = on; + itemChanged(); } } -/*! +/*! \return true if visible \sa setVisible(), show(), hide() */ bool QwtPlotItem::isVisible() const -{ - return d_data->isVisible; +{ + return d_data->isVisible; } -/*! - Update the legend and call QwtPlot::autoRefresh for the +/*! + Update the legend and call QwtPlot::autoRefresh for the parent plot. \sa updateLegend() @@ -313,13 +316,13 @@ void QwtPlotItem::itemChanged() if ( d_data->plot ) { if ( d_data->plot->legend() ) - updateLegend(d_data->plot->legend()); + updateLegend( d_data->plot->legend() ); d_data->plot->autoRefresh(); } } -/*! +/*! Set X and Y axis The item will painted according to the coordinates its Axes. @@ -329,82 +332,82 @@ void QwtPlotItem::itemChanged() \sa setXAxis(), setYAxis(), xAxis(), yAxis() */ -void QwtPlotItem::setAxis(int xAxis, int yAxis) +void QwtPlotItem::setAxes( int xAxis, int yAxis ) { - if (xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop ) - d_data->xAxis = xAxis; + if ( xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop ) + d_data->xAxis = xAxis; if ( yAxis == QwtPlot::yLeft || yAxis == QwtPlot::yRight || yAxis == QwtPlot::yLeft1 || yAxis == QwtPlot::yRight1 || yAxis == QwtPlot::yLeft2 || yAxis == QwtPlot::yRight2 || yAxis == QwtPlot::yLeft3 || yAxis == QwtPlot::yRight3 ) - d_data->yAxis = yAxis; + d_data->yAxis = yAxis; - itemChanged(); + itemChanged(); } -/*! +/*! Set the X axis The item will painted according to the coordinates its Axes. \param axis X Axis - \sa setAxis(), setYAxis(), xAxis() + \sa setAxes(), setYAxis(), xAxis() */ -void QwtPlotItem::setXAxis(int axis) +void QwtPlotItem::setXAxis( int axis ) { - if (axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) + if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) { - d_data->xAxis = axis; - itemChanged(); + d_data->xAxis = axis; + itemChanged(); } } -/*! +/*! Set the Y axis The item will painted according to the coordinates its Axes. \param axis Y Axis - \sa setAxis(), setXAxis(), yAxis() + \sa setAxes(), setXAxis(), yAxis() */ -void QwtPlotItem::setYAxis(int axis) +void QwtPlotItem::setYAxis( int axis ) { - if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight || + if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight || axis == QwtPlot::yLeft1 || axis == QwtPlot::yRight1 || axis == QwtPlot::yLeft2 || axis == QwtPlot::yRight2 || axis == QwtPlot::yLeft3 || axis == QwtPlot::yRight3 ) { - d_data->yAxis = axis; - itemChanged(); + d_data->yAxis = axis; + itemChanged(); } } //! Return xAxis -int QwtPlotItem::xAxis() const -{ - return d_data->xAxis; +int QwtPlotItem::xAxis() const +{ + return d_data->xAxis; } //! Return yAxis -int QwtPlotItem::yAxis() const -{ - return d_data->yAxis; +int QwtPlotItem::yAxis() const +{ + return d_data->yAxis; } /*! - \return An invalid bounding rect: QwtDoubleRect(1.0, 1.0, -2.0, -2.0) + \return An invalid bounding rect: QRectF(1.0, 1.0, -2.0, -2.0) */ -QwtDoubleRect QwtPlotItem::boundingRect() const +QRectF QwtPlotItem::boundingRect() const { - return QwtDoubleRect(1.0, 1.0, -2.0, -2.0); // invalid + return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid } /*! \brief Allocate the widget that represents the item on the legend - The default implementation is made for QwtPlotCurve and returns a - QwtLegendItem(), but an item could be represented by any type of widget, + The default implementation returns a QwtLegendItem(), but an item + could be represented by any type of widget, by overloading legendItem() and updateLegend(). \return QwtLegendItem() @@ -412,7 +415,15 @@ QwtDoubleRect QwtPlotItem::boundingRect() const */ QWidget *QwtPlotItem::legendItem() const { - return new QwtLegendItem; + QwtLegendItem *item = new QwtLegendItem; + if ( d_data->plot ) + { + QObject::connect( item, SIGNAL( clicked() ), + d_data->plot, SLOT( legendItemClicked() ) ); + QObject::connect( item, SIGNAL( checked( bool ) ), + d_data->plot, SLOT( legendItemChecked( bool ) ) ); + } + return item; } /*! @@ -420,54 +431,67 @@ QWidget *QwtPlotItem::legendItem() const updateLegend() is called from itemChanged() to adopt the widget representing the item on the legend to its new configuration. - - The default implementation is made for QwtPlotCurve and updates a - QwtLegendItem(), but an item could be represented by any type of widget, + + The default implementation updates a QwtLegendItem(), + but an item could be represented by any type of widget, by overloading legendItem() and updateLegend(). \param legend Legend \sa legendItem(), itemChanged(), QwtLegend() */ -void QwtPlotItem::updateLegend(QwtLegend *legend) const +void QwtPlotItem::updateLegend( QwtLegend *legend ) const { - if ( !legend ) + if ( legend == NULL ) return; - QWidget *lgdItem = legend->find(this); - if ( testItemAttribute(QwtPlotItem::Legend) ) + QWidget *lgdItem = legend->find( this ); + if ( testItemAttribute( QwtPlotItem::Legend ) ) { if ( lgdItem == NULL ) { lgdItem = legendItem(); if ( lgdItem ) - { - if ( lgdItem->inherits("QwtLegendItem") ) - { - QwtLegendItem *label = (QwtLegendItem *)lgdItem; - label->setItemMode(legend->itemMode()); - - if ( d_data->plot ) - { - QObject::connect(label, SIGNAL(clicked()), - d_data->plot, SLOT(legendItemClicked())); - QObject::connect(label, SIGNAL(checked(bool)), - d_data->plot, SLOT(legendItemChecked(bool))); - } - } - legend->insert(this, lgdItem); - } + legend->insert( this, lgdItem ); } - if ( lgdItem && lgdItem->inherits("QwtLegendItem") ) + + QwtLegendItem *label = qobject_cast( lgdItem ); + if ( label ) { - QwtLegendItem* label = (QwtLegendItem*)lgdItem; - if ( label ) - label->setText(d_data->title); + // paint the identifier + const QSize sz = label->identifierSize(); + + QPixmap identifier( sz.width(), sz.height() ); + identifier.fill( Qt::transparent ); + + QPainter painter( &identifier ); + painter.setRenderHint( QPainter::Antialiasing, + testRenderHint( QwtPlotItem::RenderAntialiased ) ); + drawLegendIdentifier( &painter, + QRect( 0, 0, sz.width(), sz.height() ) ); + painter.end(); + + const bool doUpdate = label->updatesEnabled(); + if ( doUpdate ) + label->setUpdatesEnabled( false ); + + label->setText( title() ); + label->setIdentifier( identifier ); + label->setItemMode( legend->itemMode() ); + + if ( doUpdate ) + label->setUpdatesEnabled( true ); + + label->update(); } } else { - delete lgdItem; + if ( lgdItem ) + { + lgdItem->hide(); + lgdItem->deleteLater(); + } } } @@ -484,9 +508,11 @@ void QwtPlotItem::updateLegend(QwtLegend *legend) const \sa QwtPlot::updateAxes() */ -void QwtPlotItem::updateScaleDiv(const QwtScaleDiv &, - const QwtScaleDiv &) -{ +void QwtPlotItem::updateScaleDiv( const QwtScaleDiv &xScaleDiv, + const QwtScaleDiv &yScaleDiv ) +{ + Q_UNUSED( xScaleDiv ); + Q_UNUSED( yScaleDiv ); } /*! @@ -495,12 +521,12 @@ void QwtPlotItem::updateScaleDiv(const QwtScaleDiv &, \param xMap X map \param yMap X map - \return Bounding rect of the scale maps + \return Bounding scale rect of the scale maps, normalized */ -QwtDoubleRect QwtPlotItem::scaleRect(const QwtScaleMap &xMap, - const QwtScaleMap &yMap) const +QRectF QwtPlotItem::scaleRect( const QwtScaleMap &xMap, + const QwtScaleMap &yMap ) const { - return QwtDoubleRect(xMap.s1(), yMap.s1(), + return QRectF( xMap.s1(), yMap.s1(), xMap.sDist(), yMap.sDist() ); } @@ -510,61 +536,13 @@ QwtDoubleRect QwtPlotItem::scaleRect(const QwtScaleMap &xMap, \param xMap X map \param yMap X map - \return Bounding rect of the scale maps + \return Bounding paint rect of the scale maps, normalized */ -QRect QwtPlotItem::paintRect(const QwtScaleMap &xMap, - const QwtScaleMap &yMap) const +QRectF QwtPlotItem::paintRect( const QwtScaleMap &xMap, + const QwtScaleMap &yMap ) const { - const QRect rect( qRound(xMap.p1()), qRound(yMap.p1()), - qRound(xMap.pDist()), qRound(yMap.pDist()) ); + const QRectF rect( xMap.p1(), yMap.p1(), + xMap.pDist(), yMap.pDist() ); return rect; } - -/*! - Transform a rectangle - - \param xMap X map - \param yMap Y map - \param rect Rectangle in scale coordinates - \return Rectangle in paint coordinates - - \sa invTransform() -*/ -QRect QwtPlotItem::transform(const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QwtDoubleRect& rect) const -{ - int x1 = qRound(xMap.transform(rect.left())); - int x2 = qRound(xMap.transform(rect.right())); - int y1 = qRound(yMap.transform(rect.top())); - int y2 = qRound(yMap.transform(rect.bottom())); - - if ( x2 < x1 ) - qSwap(x1, x2); - if ( y2 < y1 ) - qSwap(y1, y2); - - return QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); -} - -/*! - Transform a rectangle from paint to scale coordinates - - \param xMap X map - \param yMap Y map - \param rect Rectangle in paint coordinates - \return Rectangle in scale coordinates - \sa transform() -*/ -QwtDoubleRect QwtPlotItem::invTransform(const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRect& rect) const -{ - const double x1 = xMap.invTransform(rect.left()); - const double x2 = xMap.invTransform(rect.right()); - const double y1 = yMap.invTransform(rect.top()); - const double y2 = yMap.invTransform(rect.bottom()); - - const QwtDoubleRect r(x1, y1, x2 - x1, y2 - y1); - - return r.normalized(); -} diff --git a/qwt/src/qwt_plot_item.h b/qwt/src/qwt_plot_item.h index a7ef37403..ca3b5f037 100644 --- a/qwt/src/qwt_plot_item.h +++ b/qwt/src/qwt_plot_item.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -13,10 +13,9 @@ #include "qwt_global.h" #include "qwt_legend_itemmanager.h" #include "qwt_text.h" -#include "qwt_double_rect.h" +#include class QString; -class QRect; class QPainter; class QWidget; class QwtPlot; @@ -54,10 +53,10 @@ class QwtScaleDiv; into autoscaling or has an entry on the legnd. Before misusing the existing item classes it might be better to - implement a new type of plot item + implement a new type of plot item ( don't implement a watermark as spectrogram ). - Deriving a new type of QwtPlotItem primarily means to implement - the YourPlotItem::draw() method. + Deriving a new type of QwtPlotItem primarily means to implement + the YourPlotItem::draw() method. \sa The cpuplot example shows the implementation of additional plot items. */ @@ -67,18 +66,20 @@ class QWT_EXPORT QwtPlotItem: public QwtLegendItemManager public: /*! \brief Runtime type information - + RttiValues is used to cast plot items, without having to enable runtime type information of the compiler. */ enum RttiValues - { + { Rtti_PlotItem = 0, Rtti_PlotGrid, Rtti_PlotScale, Rtti_PlotMarker, Rtti_PlotCurve, + Rtti_PlotSpectroCurve, + Rtti_PlotIntervalCurve, Rtti_PlotHistogram, Rtti_PlotSpectrogram, Rtti_PlotSVG, @@ -88,73 +89,67 @@ public: /*! Plot Item Attributes - - - Legend\n - The item is represented on the legend. - - AutoScale \n - The boundingRect() of the item is included in the - autoscaling calculation. - \sa setItemAttribute(), testItemAttribute() */ enum ItemAttribute { - Legend = 1, - AutoScale = 2 + //! The item is represented on the legend. + Legend = 0x01, + + /*! + The boundingRect() of the item is included in the + autoscaling calculation. + */ + AutoScale = 0x02 }; -#if QT_VERSION >= 0x040000 + //! Plot Item Attributes + typedef QFlags ItemAttributes; + //! Render hints enum RenderHint { + //! Enable antialiasing RenderAntialiased = 1 }; -#endif - explicit QwtPlotItem(const QwtText &title = QwtText()); + //! Render hints + typedef QFlags RenderHints; + + explicit QwtPlotItem( const QwtText &title = QwtText() ); virtual ~QwtPlotItem(); - void attach(QwtPlot *plot); - - /*! - \brief This method detaches a QwtPlotItem from any QwtPlot it has been - associated with. - - detach() is equivalent to calling attach( NULL ) - \sa attach( QwtPlot* plot ) - */ - void detach() { attach(NULL); } + void attach( QwtPlot *plot ); + void detach(); QwtPlot *plot() const; - - void setTitle(const QString &title); - void setTitle(const QwtText &title); + + void setTitle( const QString &title ); + void setTitle( const QwtText &title ); const QwtText &title() const; virtual int rtti() const; - void setItemAttribute(ItemAttribute, bool on = true); - bool testItemAttribute(ItemAttribute) const; + void setItemAttribute( ItemAttribute, bool on = true ); + bool testItemAttribute( ItemAttribute ) const; -#if QT_VERSION >= 0x040000 - void setRenderHint(RenderHint, bool on = true); - bool testRenderHint(RenderHint) const; -#endif + void setRenderHint( RenderHint, bool on = true ); + bool testRenderHint( RenderHint ) const; - double z() const; - void setZ(double z); + double z() const; + void setZ( double z ); void show(); void hide(); - virtual void setVisible(bool); + virtual void setVisible( bool ); bool isVisible () const; - void setAxis(int xAxis, int yAxis); + void setAxes( int xAxis, int yAxis ); - void setXAxis(int axis); + void setXAxis( int axis ); int xAxis() const; - void setYAxis(int axis); + void setYAxis( int axis ); int yAxis() const; virtual void itemChanged(); @@ -167,25 +162,20 @@ public: \param yMap Maps y-values into pixel coordinates. \param canvasRect Contents rect of the canvas in painter coordinates */ - virtual void draw(QPainter *painter, + virtual void draw( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &canvasRect) const = 0; + const QRectF &canvasRect ) const = 0; - virtual QwtDoubleRect boundingRect() const; + virtual QRectF boundingRect() const; - virtual void updateLegend(QwtLegend *) const; - virtual void updateScaleDiv(const QwtScaleDiv&, - const QwtScaleDiv&); + virtual void updateLegend( QwtLegend * ) const; + virtual void updateScaleDiv( + const QwtScaleDiv&, const QwtScaleDiv& ); virtual QWidget *legendItem() const; - QwtDoubleRect scaleRect(const QwtScaleMap &, const QwtScaleMap &) const; - QRect paintRect(const QwtScaleMap &, const QwtScaleMap &) const; - - QRect transform(const QwtScaleMap &, const QwtScaleMap &, - const QwtDoubleRect&) const; - QwtDoubleRect invTransform(const QwtScaleMap &, const QwtScaleMap &, - const QRect&) const; + QRectF scaleRect( const QwtScaleMap &, const QwtScaleMap & ) const; + QRectF paintRect( const QwtScaleMap &, const QwtScaleMap & ) const; private: // Disabled copy constructor and operator= @@ -195,5 +185,8 @@ private: class PrivateData; PrivateData *d_data; }; - + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::ItemAttributes ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::RenderHints ) + #endif diff --git a/qwt/src/qwt_plot_layout.cpp b/qwt/src/qwt_plot_layout.cpp index 8bbcb8863..9d319504d 100644 --- a/qwt/src/qwt_plot_layout.cpp +++ b/qwt/src/qwt_plot_layout.cpp @@ -7,20 +7,19 @@ * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - -#include +#include "qwt_plot_layout.h" #include "qwt_text.h" #include "qwt_text_label.h" #include "qwt_plot_canvas.h" #include "qwt_scale_widget.h" #include "qwt_legend.h" -#include "qwt_plot_layout.h" +#include +#include class QwtPlotLayout::LayoutData { public: - void init(const QwtPlot *, const QRect &rect); + void init( const QwtPlot *, const QRectF &rect ); struct t_legendData { @@ -29,7 +28,7 @@ public: int hScrollBarHeight; QSize hint; } legend; - + struct t_titleData { QwtText text; @@ -44,7 +43,7 @@ public: int start; int end; int baseLineOffset; - int tickOffset; + int tickOffset; int dimWithoutTitle; } scale[QwtPlot::axisCnt]; @@ -58,54 +57,54 @@ public: Extract all layout relevant data from the plot components */ -void QwtPlotLayout::LayoutData::init(const QwtPlot *plot, const QRect &rect) +void QwtPlotLayout::LayoutData::init( const QwtPlot *plot, const QRectF &rect ) { // legend - if ( plot->plotLayout()->legendPosition() != QwtPlot::ExternalLegend + if ( plot->plotLayout()->legendPosition() != QwtPlot::ExternalLegend && plot->legend() ) { legend.frameWidth = plot->legend()->frameWidth(); - legend.vScrollBarWidth = + legend.vScrollBarWidth = plot->legend()->verticalScrollBar()->sizeHint().width(); - legend.hScrollBarHeight = + legend.hScrollBarHeight = plot->legend()->horizontalScrollBar()->sizeHint().height(); const QSize hint = plot->legend()->sizeHint(); - int w = qwtMin(hint.width(), rect.width()); - int h = plot->legend()->heightForWidth(w); + int w = qMin( hint.width(), qFloor( rect.width() ) ); + int h = plot->legend()->heightForWidth( w ); if ( h == 0 ) h = hint.height(); if ( h > rect.height() ) w += legend.vScrollBarWidth; - legend.hint = QSize(w, h); + legend.hint = QSize( w, h ); } - // title + // title title.frameWidth = 0; title.text = QwtText(); - if (plot->titleLabel() ) + if ( plot->titleLabel() ) { const QwtTextLabel *label = plot->titleLabel(); - title.text = label->text(); - if ( !(title.text.testPaintAttribute(QwtText::PaintUsingTextFont)) ) - title.text.setFont(label->font()); - + title.text = label->text(); + if ( !( title.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) ) + title.text.setFont( label->font() ); + title.frameWidth = plot->titleLabel()->frameWidth(); } - // scales + // scales - for (int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { - if ( plot->axisEnabled(axis) ) + if ( plot->axisEnabled( axis ) ) { - const QwtScaleWidget *scaleWidget = plot->axisWidget(axis); + const QwtScaleWidget *scaleWidget = plot->axisWidget( axis ); scale[axis].isEnabled = true; @@ -119,19 +118,19 @@ void QwtPlotLayout::LayoutData::init(const QwtPlot *plot, const QRect &rect) scale[axis].baseLineOffset = scaleWidget->margin(); scale[axis].tickOffset = scaleWidget->margin(); if ( scaleWidget->scaleDraw()->hasComponent( - QwtAbstractScaleDraw::Ticks) ) + QwtAbstractScaleDraw::Ticks ) ) { - scale[axis].tickOffset += - (int)scaleWidget->scaleDraw()->majTickLength(); + scale[axis].tickOffset += + scaleWidget->scaleDraw()->maxTickLength(); } scale[axis].dimWithoutTitle = scaleWidget->dimForLength( - QWIDGETSIZE_MAX, scale[axis].scaleFont); + QWIDGETSIZE_MAX, scale[axis].scaleFont ); if ( !scaleWidget->title().isEmpty() ) { - scale[axis].dimWithoutTitle -= - scaleWidget->titleHeightForWidth(QWIDGETSIZE_MAX); + scale[axis].dimWithoutTitle -= + scaleWidget->titleHeightForWidth( QWIDGETSIZE_MAX ); } } else @@ -145,7 +144,7 @@ void QwtPlotLayout::LayoutData::init(const QwtPlot *plot, const QRect &rect) } } - // canvas + // canvas canvas.frameWidth = plot->canvas()->frameWidth(); } @@ -154,22 +153,20 @@ class QwtPlotLayout::PrivateData { public: PrivateData(): - margin(0), - spacing(5), - alignCanvasToScales(false) + spacing( 5 ), + alignCanvasToScales( false ) { } - QRect titleRect; - QRect legendRect; - QRect scaleRect[QwtPlot::axisCnt]; - QRect canvasRect; + QRectF titleRect; + QRectF legendRect; + QRectF scaleRect[QwtPlot::axisCnt]; + QRectF canvasRect; QwtPlotLayout::LayoutData layoutData; QwtPlot::LegendPosition legendPos; double legendRatio; - unsigned int margin; unsigned int spacing; unsigned int canvasMargin[QwtPlot::axisCnt]; bool alignCanvasToScales; @@ -183,8 +180,8 @@ QwtPlotLayout::QwtPlotLayout() { d_data = new PrivateData; - setLegendPosition(QwtPlot::BottomLegend); - setCanvasMargin(4); + setLegendPosition( QwtPlot::BottomLegend ); + setCanvasMargin( 4 ); invalidate(); } @@ -195,51 +192,27 @@ QwtPlotLayout::~QwtPlotLayout() delete d_data; } -/*! - Change the margin of the plot. The margin is the space - around all components. - - \param margin new margin - \sa margin(), setSpacing(), - QwtPlot::setMargin() -*/ -void QwtPlotLayout::setMargin(int margin) -{ - if ( margin < 0 ) - margin = 0; - d_data->margin = margin; -} - -/*! - \return margin - \sa setMargin(), spacing(), QwtPlot::margin() -*/ -int QwtPlotLayout::margin() const -{ - return d_data->margin; -} - /*! Change a margin of the canvas. The margin is the space above/below the scale ticks. A negative margin will be set to -1, excluding the borders of the scales. - + \param margin New margin - \param axis One of QwtPlot::Axis. Specifies where the position of the margin. + \param axis One of QwtPlot::Axis. Specifies where the position of the margin. -1 means margin at all borders. - \sa canvasMargin() + \sa canvasMargin() \warning The margin will have no effect when alignCanvasToScales is true */ -void QwtPlotLayout::setCanvasMargin(int margin, int axis) +void QwtPlotLayout::setCanvasMargin( int margin, int axis ) { if ( margin < -1 ) margin = -1; if ( axis == -1 ) { - for (axis = 0; axis < QwtPlot::axisCnt; axis++) + for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) d_data->canvasMargin[axis] = margin; } else if ( axis >= 0 && axis < QwtPlot::axisCnt ) @@ -250,7 +223,7 @@ void QwtPlotLayout::setCanvasMargin(int margin, int axis) \return Margin around the scale tick borders \sa setCanvasMargin() */ -int QwtPlotLayout::canvasMargin(int axis) const +int QwtPlotLayout::canvasMargin( int axis ) const { if ( axis < 0 || axis >= QwtPlot::axisCnt ) return 0; @@ -265,12 +238,12 @@ int QwtPlotLayout::canvasMargin(int axis) const \param alignCanvasToScales New align-canvas-to-axis-scales setting - \sa setCanvasMargin() + \sa setCanvasMargin() \note In this context the term 'scale' means the backbone of a scale. - \warning In case of alignCanvasToScales == true canvasMargin will have + \warning In case of alignCanvasToScales == true canvasMargin will have no effect */ -void QwtPlotLayout::setAlignCanvasToScales(bool alignCanvasToScales) +void QwtPlotLayout::setAlignCanvasToScales( bool alignCanvasToScales ) { d_data->alignCanvasToScales = alignCanvasToScales; } @@ -281,7 +254,7 @@ void QwtPlotLayout::setAlignCanvasToScales(bool alignCanvasToScales) - align with the axis scale ends to control its size. \return align-canvas-to-axis-scales setting - \sa setAlignCanvasToScales, setCanvasMargin() + \sa setAlignCanvasToScales, setCanvasMargin() \note In this context the term 'scale' means the backbone of a scale. */ bool QwtPlotLayout::alignCanvasToScales() const @@ -292,18 +265,18 @@ bool QwtPlotLayout::alignCanvasToScales() const /*! Change the spacing of the plot. The spacing is the distance between the plot components. - + \param spacing new spacing - \sa setMargin(), spacing() + \sa setMargin(), spacing() */ -void QwtPlotLayout::setSpacing(int spacing) +void QwtPlotLayout::setSpacing( int spacing ) { - d_data->spacing = qwtMax(0, spacing); + d_data->spacing = qMax( 0, spacing ); } /*! \return spacing - \sa margin(), setSpacing() + \sa margin(), setSpacing() */ int QwtPlotLayout::spacing() const { @@ -312,23 +285,23 @@ int QwtPlotLayout::spacing() const /*! \brief Specify the position of the legend - \param pos The legend's position. - \param ratio Ratio between legend and the bounding rect + \param pos The legend's position. + \param ratio Ratio between legend and the bounding rect of title, canvas and axes. The legend will be shrinked if it would need more space than the given ratio. The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0 it will be reset to the default ratio. - The default vertical/horizontal ratio is 0.33/0.5. - + The default vertical/horizontal ratio is 0.33/0.5. + \sa QwtPlot::setLegendPosition() */ -void QwtPlotLayout::setLegendPosition(QwtPlot::LegendPosition pos, double ratio) +void QwtPlotLayout::setLegendPosition( QwtPlot::LegendPosition pos, double ratio ) { if ( ratio > 1.0 ) ratio = 1.0; - switch(pos) + switch ( pos ) { case QwtPlot::TopLegend: case QwtPlot::BottomLegend: @@ -354,15 +327,15 @@ void QwtPlotLayout::setLegendPosition(QwtPlot::LegendPosition pos, double ratio) /*! \brief Specify the position of the legend - \param pos The legend's position. Valid values are - \c QwtPlot::LeftLegend, \c QwtPlot::RightLegend, + \param pos The legend's position. Valid values are + \c QwtPlot::LeftLegend, \c QwtPlot::RightLegend, \c QwtPlot::TopLegend, \c QwtPlot::BottomLegend. - + \sa QwtPlot::setLegendPosition() */ -void QwtPlotLayout::setLegendPosition(QwtPlot::LegendPosition pos) +void QwtPlotLayout::setLegendPosition( QwtPlot::LegendPosition pos ) { - setLegendPosition(pos, 0.0); + setLegendPosition( pos, 0.0 ); } /*! @@ -377,16 +350,16 @@ QwtPlot::LegendPosition QwtPlotLayout::legendPosition() const /*! Specify the relative size of the legend in the plot - \param ratio Ratio between legend and the bounding rect + \param ratio Ratio between legend and the bounding rect of title, canvas and axes. The legend will be shrinked if it would need more space than the given ratio. The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0 it will be reset to the default ratio. - The default vertical/horizontal ratio is 0.33/0.5. + The default vertical/horizontal ratio is 0.33/0.5. */ -void QwtPlotLayout::setLegendRatio(double ratio) +void QwtPlotLayout::setLegendRatio( double ratio ) { - setLegendPosition(legendPosition(), ratio); + setLegendPosition( legendPosition(), ratio ); } /*! @@ -403,7 +376,7 @@ double QwtPlotLayout::legendRatio() const \sa activate(), invalidate() */ -const QRect &QwtPlotLayout::titleRect() const +const QRectF &QwtPlotLayout::titleRect() const { return d_data->titleRect; } @@ -413,7 +386,7 @@ const QRect &QwtPlotLayout::titleRect() const \sa activate(), invalidate() */ -const QRect &QwtPlotLayout::legendRect() const +const QRectF &QwtPlotLayout::legendRect() const { return d_data->legendRect; } @@ -424,11 +397,11 @@ const QRect &QwtPlotLayout::legendRect() const \sa activate(), invalidate() */ -const QRect &QwtPlotLayout::scaleRect(int axis) const +const QRectF &QwtPlotLayout::scaleRect( int axis ) const { if ( axis < 0 || axis >= QwtPlot::axisCnt ) { - static QRect dummyRect; + static QRectF dummyRect; return dummyRect; } return d_data->scaleRect[axis]; @@ -439,28 +412,28 @@ const QRect &QwtPlotLayout::scaleRect(int axis) const \sa activate(), invalidate() */ -const QRect &QwtPlotLayout::canvasRect() const +const QRectF &QwtPlotLayout::canvasRect() const { return d_data->canvasRect; } /*! - Invalidate the geometry of all components. + Invalidate the geometry of all components. \sa activate() */ void QwtPlotLayout::invalidate() { d_data->titleRect = d_data->legendRect = d_data->canvasRect = QRect(); - for (int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) d_data->scaleRect[axis] = QRect(); } -/*! +/*! \brief Return a minimum size hint \sa QwtPlot::minimumSizeHint() */ -QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const +QSize QwtPlotLayout::minimumSizeHint( const QwtPlot *plot ) const { class ScaleData { @@ -482,29 +455,30 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const int axis; for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) { - if ( plot->axisEnabled(axis) ) + if ( plot->axisEnabled( axis ) ) { - const QwtScaleWidget *scl = plot->axisWidget(axis); + const QwtScaleWidget *scl = plot->axisWidget( axis ); ScaleData &sd = scaleData[axis]; const QSize hint = scl->minimumSizeHint(); - sd.w = hint.width(); - sd.h = hint.height(); - scl->getBorderDistHint(sd.minLeft, sd.minRight); + sd.w = hint.width(); + sd.h = hint.height(); + scl->getBorderDistHint( sd.minLeft, sd.minRight ); sd.tickOffset = scl->margin(); - if ( scl->scaleDraw()->hasComponent(QwtAbstractScaleDraw::Ticks) ) - sd.tickOffset += scl->scaleDraw()->majTickLength(); + if ( scl->scaleDraw()->hasComponent( QwtAbstractScaleDraw::Ticks ) ) + sd.tickOffset += scl->scaleDraw()->maxTickLength(); } canvasBorder[axis] = plot->canvas()->frameWidth() + d_data->canvasMargin[axis] + 1; - + } + for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) { ScaleData &sd = scaleData[axis]; - if ( sd.w && (axis == QwtPlot::xBottom || axis == QwtPlot::xTop) ) + if ( sd.w && ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) ) { if ( (sd.minLeft > canvasBorder[QwtPlot::yLeft3]) && scaleData[QwtPlot::yLeft3].w ) @@ -585,6 +559,26 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const sd.w -= shiftRight; } + + + /*if ( ( sd.minLeft > canvasBorder[QwtPlot::yLeft] ) + && scaleData[QwtPlot::yLeft].w ) + { + int shiftLeft = sd.minLeft - canvasBorder[QwtPlot::yLeft]; + if ( shiftLeft > scaleData[QwtPlot::yLeft].w ) + shiftLeft = scaleData[QwtPlot::yLeft].w; + + sd.w -= shiftLeft; + } + if ( ( sd.minRight > canvasBorder[QwtPlot::yRight] ) + && scaleData[QwtPlot::yRight].w ) + { + int shiftRight = sd.minRight - canvasBorder[QwtPlot::yRight]; + if ( shiftRight > scaleData[QwtPlot::yRight].w ) + shiftRight = scaleData[QwtPlot::yRight].w; + + sd.w -= shiftRight; + }*/ } if ( sd.h && (axis == QwtPlot::yLeft || axis == QwtPlot::yRight || @@ -592,7 +586,7 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const axis == QwtPlot::yLeft2 || axis == QwtPlot::yRight2 || axis == QwtPlot::yLeft3 || axis == QwtPlot::yRight3)) { - if ( (sd.minLeft > canvasBorder[QwtPlot::xBottom]) && + if ( ( sd.minLeft > canvasBorder[QwtPlot::xBottom] ) && scaleData[QwtPlot::xBottom].h ) { int shiftBottom = sd.minLeft - canvasBorder[QwtPlot::xBottom]; @@ -601,7 +595,7 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const sd.h -= shiftBottom; } - if ( (sd.minLeft > canvasBorder[QwtPlot::xTop]) && + if ( ( sd.minLeft > canvasBorder[QwtPlot::xTop] ) && scaleData[QwtPlot::xTop].h ) { int shiftTop = sd.minRight - canvasBorder[QwtPlot::xTop]; @@ -616,35 +610,37 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const const QwtPlotCanvas *canvas = plot->canvas(); const QSize minCanvasSize = canvas->minimumSize(); + //int w = scaleData[QwtPlot::yLeft].w + scaleData[QwtPlot::yRight].w; int w = scaleData[QwtPlot::yLeft].w + scaleData[QwtPlot::yRight].w - + scaleData[QwtPlot::yLeft1].w + scaleData[QwtPlot::yRight1].w - + scaleData[QwtPlot::yLeft2].w + scaleData[QwtPlot::yRight2].w - + scaleData[QwtPlot::yLeft3].w + scaleData[QwtPlot::yRight3].w; - int cw = qwtMax(scaleData[QwtPlot::xBottom].w, scaleData[QwtPlot::xTop].w) - + 2 * (canvas->frameWidth() + 1); - w += qwtMax(cw, minCanvasSize.width()); + + scaleData[QwtPlot::yLeft1].w + scaleData[QwtPlot::yRight1].w + + scaleData[QwtPlot::yLeft2].w + scaleData[QwtPlot::yRight2].w + + scaleData[QwtPlot::yLeft3].w + scaleData[QwtPlot::yRight3].w; + + int cw = qMax( scaleData[QwtPlot::xBottom].w, scaleData[QwtPlot::xTop].w ) + + 2 * ( canvas->frameWidth() + 1 ); + w += qMax( cw, minCanvasSize.width() ); int h = scaleData[QwtPlot::xBottom].h + scaleData[QwtPlot::xTop].h; - int ch = qwtMax(scaleData[QwtPlot::yLeft].h, scaleData[QwtPlot::yRight].h) - + 2 * (canvas->frameWidth() + 1); - h += qwtMax(ch, minCanvasSize.height()); + int ch = qMax( scaleData[QwtPlot::yLeft].h, scaleData[QwtPlot::yRight].h ) + + 2 * ( canvas->frameWidth() + 1 ); + h += qMax( ch, minCanvasSize.height() ); const QwtTextLabel *title = plot->titleLabel(); - if (title && !title->text().isEmpty()) + if ( title && !title->text().isEmpty() ) { - // If only QwtPlot::yLeft or QwtPlot::yRight is showing, + // If only QwtPlot::yLeft or QwtPlot::yRight is showing, // we center on the plot canvas. - const bool centerOnCanvas = !(plot->axisEnabled(QwtPlot::yLeft) - && plot->axisEnabled(QwtPlot::yRight)); + const bool centerOnCanvas = !( plot->axisEnabled( QwtPlot::yLeft ) + && plot->axisEnabled( QwtPlot::yRight ) ); int titleW = w; if ( centerOnCanvas ) { - titleW -= scaleData[QwtPlot::yLeft].w + titleW -= scaleData[QwtPlot::yLeft].w + scaleData[QwtPlot::yRight].w; } - int titleH = title->heightForWidth(titleW); + int titleH = title->heightForWidth( titleW ); if ( titleH > titleW ) // Compensate for a long title { w = titleW = titleH; @@ -654,7 +650,7 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const + scaleData[QwtPlot::yRight].w; } - titleH = title->heightForWidth(titleW); + titleH = title->heightForWidth( titleW ); } h += titleH + d_data->spacing; } @@ -665,11 +661,11 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const if ( d_data->legendPos != QwtPlot::ExternalLegend && legend && !legend->isEmpty() ) { - if ( d_data->legendPos == QwtPlot::LeftLegend + if ( d_data->legendPos == QwtPlot::LeftLegend || d_data->legendPos == QwtPlot::RightLegend ) { int legendW = legend->sizeHint().width(); - int legendH = legend->heightForWidth(legendW); + int legendH = legend->heightForWidth( legendW ); if ( legend->frameWidth() > 0 ) w += d_data->spacing; @@ -678,28 +674,25 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const legendW += legend->verticalScrollBar()->sizeHint().height(); if ( d_data->legendRatio < 1.0 ) - legendW = qwtMin(legendW, int(w / (1.0 - d_data->legendRatio))); + legendW = qMin( legendW, int( w / ( 1.0 - d_data->legendRatio ) ) ); - w += legendW; + w += legendW + d_data->spacing; } else // QwtPlot::Top, QwtPlot::Bottom { - int legendW = qwtMin(legend->sizeHint().width(), w); - int legendH = legend->heightForWidth(legendW); + int legendW = qMin( legend->sizeHint().width(), w ); + int legendH = legend->heightForWidth( legendW ); if ( legend->frameWidth() > 0 ) h += d_data->spacing; if ( d_data->legendRatio < 1.0 ) - legendH = qwtMin(legendH, int(h / (1.0 - d_data->legendRatio))); - - h += legendH; + legendH = qMin( legendH, int( h / ( 1.0 - d_data->legendRatio ) ) ); + + h += legendH + d_data->spacing; } } - w += 2 * d_data->margin; - h += 2 * d_data->margin; - return QSize( w, h ); } @@ -711,26 +704,26 @@ QSize QwtPlotLayout::minimumSizeHint(const QwtPlot *plot) const \sa Options */ -QRect QwtPlotLayout::layoutLegend(int options, - const QRect &rect) const +QRectF QwtPlotLayout::layoutLegend( Options options, + const QRectF &rect ) const { - const QSize hint(d_data->layoutData.legend.hint); + const QSize hint( d_data->layoutData.legend.hint ); int dim; - if ( d_data->legendPos == QwtPlot::LeftLegend + if ( d_data->legendPos == QwtPlot::LeftLegend || d_data->legendPos == QwtPlot::RightLegend ) { // We don't allow vertical legends to take more than // half of the available space. - dim = qwtMin(hint.width(), int(rect.width() * d_data->legendRatio)); + dim = qMin( hint.width(), int( rect.width() * d_data->legendRatio ) ); - if ( !(options & IgnoreScrollbars) ) + if ( !( options & IgnoreScrollbars ) ) { if ( hint.height() > rect.height() ) { // The legend will need additional - // space for the vertical scrollbar. + // space for the vertical scrollbar. dim += d_data->layoutData.legend.vScrollBarWidth; } @@ -738,26 +731,26 @@ QRect QwtPlotLayout::layoutLegend(int options, } else { - dim = qwtMin(hint.height(), int(rect.height() * d_data->legendRatio)); - dim = qwtMax(dim, d_data->layoutData.legend.hScrollBarHeight); + dim = qMin( hint.height(), int( rect.height() * d_data->legendRatio ) ); + dim = qMax( dim, d_data->layoutData.legend.hScrollBarHeight ); } - QRect legendRect = rect; - switch(d_data->legendPos) + QRectF legendRect = rect; + switch ( d_data->legendPos ) { case QwtPlot::LeftLegend: - legendRect.setWidth(dim); + legendRect.setWidth( dim ); break; case QwtPlot::RightLegend: - legendRect.setX(rect.right() - dim + 1 ); - legendRect.setWidth(dim); + legendRect.setX( rect.right() - dim ); + legendRect.setWidth( dim ); break; case QwtPlot::TopLegend: - legendRect.setHeight(dim); + legendRect.setHeight( dim ); break; case QwtPlot::BottomLegend: - legendRect.setY(rect.bottom() - dim + 1); - legendRect.setHeight(dim); + legendRect.setY( rect.bottom() - dim ); + legendRect.setHeight( dim ); break; case QwtPlot::ExternalLegend: break; @@ -772,26 +765,26 @@ QRect QwtPlotLayout::layoutLegend(int options, \param legendRect Maximum geometry for the legend \return Geometry for the aligned legend */ -QRect QwtPlotLayout::alignLegend(const QRect &canvasRect, - const QRect &legendRect) const +QRectF QwtPlotLayout::alignLegend( const QRectF &canvasRect, + const QRectF &legendRect ) const { - QRect alignedRect = legendRect; + QRectF alignedRect = legendRect; - if ( d_data->legendPos == QwtPlot::BottomLegend + if ( d_data->legendPos == QwtPlot::BottomLegend || d_data->legendPos == QwtPlot::TopLegend ) { if ( d_data->layoutData.legend.hint.width() < canvasRect.width() ) { - alignedRect.setX(canvasRect.x()); - alignedRect.setWidth(canvasRect.width()); + alignedRect.setX( canvasRect.x() ); + alignedRect.setWidth( canvasRect.width() ); } } else { if ( d_data->layoutData.legend.hint.height() < canvasRect.height() ) { - alignedRect.setY(canvasRect.y()); - alignedRect.setHeight(canvasRect.height()); + alignedRect.setY( canvasRect.y() ); + alignedRect.setHeight( canvasRect.height() ); } } @@ -809,25 +802,25 @@ QRect QwtPlotLayout::alignLegend(const QRect &canvasRect, \sa Options */ -void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, - int &dimTitle, int dimAxis[QwtPlot::axisCnt]) const +void QwtPlotLayout::expandLineBreaks( int options, const QRectF &rect, + int &dimTitle, int dimAxis[QwtPlot::axisCnt] ) const { dimTitle = 0; for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) dimAxis[axis] = 0; int backboneOffset[QwtPlot::axisCnt]; - for (int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { backboneOffset[axis] = 0; if ( !d_data->alignCanvasToScales ) backboneOffset[axis] += d_data->canvasMargin[axis]; - if ( !(options & IgnoreFrames) ) + if ( !( options & IgnoreFrames ) ) backboneOffset[axis] += d_data->layoutData.canvas.frameWidth; } bool done = false; - while (!done) + while ( !done ) { done = true; @@ -847,11 +840,11 @@ void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, != d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) { // center to the canvas - w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; + w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; } - int d = d_data->layoutData.title.text.heightForWidth(w); - if ( !(options & IgnoreFrames) ) + int d = qCeil( d_data->layoutData.title.text.heightForWidth( w ) ); + if ( !( options & IgnoreFrames ) ) d += 2 * d_data->layoutData.title.frameWidth; if ( d > dimTitle ) @@ -863,29 +856,29 @@ void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { - const struct LayoutData::t_scaleData &scaleData = + const struct LayoutData::t_scaleData &scaleData = d_data->layoutData.scale[axis]; - if (scaleData.isEnabled) + if ( scaleData.isEnabled ) { int length; if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom ) { - length = rect.width() - dimAxis[QwtPlot::yLeft] + length = rect.width() - dimAxis[QwtPlot::yLeft] - dimAxis[QwtPlot::yRight]; length -= scaleData.start + scaleData.end; if ( dimAxis[QwtPlot::yRight] > 0 ) length -= 1; - length += qwtMin(dimAxis[QwtPlot::yLeft], - scaleData.start - backboneOffset[QwtPlot::yLeft]); - length += qwtMin(dimAxis[QwtPlot::yRight], - scaleData.end - backboneOffset[QwtPlot::yRight]); + length += qMin( dimAxis[QwtPlot::yLeft], + scaleData.start - backboneOffset[QwtPlot::yLeft] ); + length += qMin( dimAxis[QwtPlot::yRight], + scaleData.end - backboneOffset[QwtPlot::yRight] ); } else // QwtPlot::yLeft, QwtPlot::yRight { - length = rect.height() - dimAxis[QwtPlot::xTop] + length = rect.height() - dimAxis[QwtPlot::xTop] - dimAxis[QwtPlot::xBottom]; length -= scaleData.start + scaleData.end; length -= 1; @@ -897,15 +890,15 @@ void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, if ( dimAxis[QwtPlot::xBottom] > 0 ) { - length += qwtMin( - d_data->layoutData.scale[QwtPlot::xBottom].tickOffset, - scaleData.start - backboneOffset[QwtPlot::xBottom]); + length += qMin( + d_data->layoutData.scale[QwtPlot::xBottom].tickOffset, + scaleData.start - backboneOffset[QwtPlot::xBottom] ); } if ( dimAxis[QwtPlot::xTop] > 0 ) { - length += qwtMin( - d_data->layoutData.scale[QwtPlot::xTop].tickOffset, - scaleData.end - backboneOffset[QwtPlot::xTop]); + length += qMin( + d_data->layoutData.scale[QwtPlot::xTop].tickOffset, + scaleData.end - backboneOffset[QwtPlot::xTop] ); } if ( dimTitle > 0 ) @@ -915,7 +908,7 @@ void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, int d = scaleData.dimWithoutTitle; if ( !scaleData.scaleWidget->title().isEmpty() ) { - d += scaleData.scaleWidget->titleHeightForWidth(length); + d += scaleData.scaleWidget->titleHeightForWidth( length ); } @@ -936,22 +929,20 @@ void QwtPlotLayout::expandLineBreaks(int options, const QRect &rect, \sa Options */ -void QwtPlotLayout::alignScales(int options, - QRect &canvasRect, QRect scaleRect[QwtPlot::axisCnt]) const +void QwtPlotLayout::alignScales( int options, + QRectF &canvasRect, QRectF scaleRect[QwtPlot::axisCnt] ) const { - int axis; - int backboneOffset[QwtPlot::axisCnt]; - for (axis = 0; axis < QwtPlot::axisCnt; axis++ ) + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { backboneOffset[axis] = 0; if ( !d_data->alignCanvasToScales ) backboneOffset[axis] += d_data->canvasMargin[axis]; - if ( !(options & IgnoreFrames) ) + if ( !( options & IgnoreFrames ) ) backboneOffset[axis] += d_data->layoutData.canvas.frameWidth; } - for (axis = 0; axis < QwtPlot::axisCnt; axis++ ) + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { if ( !scaleRect[axis].isValid() ) continue; @@ -959,112 +950,156 @@ void QwtPlotLayout::alignScales(int options, const int startDist = d_data->layoutData.scale[axis].start; const int endDist = d_data->layoutData.scale[axis].end; - QRect &axisRect = scaleRect[axis]; + QRectF &axisRect = scaleRect[axis]; if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom ) { - for (int leftAxis = QwtPlot::yLeft3; - leftAxis <= QwtPlot::yLeft; leftAxis++) - { - const int leftOffset = - backboneOffset[leftAxis] - startDist; + const QRectF &leftScaleRect = scaleRect[QwtPlot::yLeft]; + const int leftOffset = + backboneOffset[QwtPlot::yLeft] - startDist; - if ( scaleRect[leftAxis].isValid() ) - { - int minLeft = scaleRect[leftAxis].left(); - int left = axisRect.left() + leftOffset; - axisRect.setLeft(qwtMax(left, minLeft)); - } - else - { - if ( d_data->alignCanvasToScales && leftOffset < 0 ) - { - canvasRect.setLeft(qwtMax(canvasRect.left(), - axisRect.left() - leftOffset)); - } - else - { + if ( leftScaleRect.isValid() ) + { + const int dx = leftOffset + leftScaleRect.width(); + if ( d_data->alignCanvasToScales && dx < 0 ) + { + /* + The axis needs more space than the width + of the left scale. + */ + canvasRect.setLeft( qMax( canvasRect.left(), + axisRect.left() - dx ) ); + } + else + { + const double minLeft = leftScaleRect.left(); + const double left = axisRect.left() + leftOffset; + axisRect.setLeft( qMax( left, minLeft ) ); + } + } + else + { + if ( d_data->alignCanvasToScales && leftOffset < 0 ) + { + canvasRect.setLeft( qMax( canvasRect.left(), + axisRect.left() - leftOffset ) ); + } + else + { if ( leftOffset > 0 ) - axisRect.setLeft(axisRect.left() + leftOffset); - } - } - } + axisRect.setLeft( axisRect.left() + leftOffset ); + } + } - for (int rightAxis = QwtPlot::yRight; - rightAxis <= QwtPlot::yRight3; rightAxis++) - { - const int rightOffset = - backboneOffset[rightAxis] - endDist + 1; + const QRectF &rightScaleRect = scaleRect[QwtPlot::yRight]; + const int rightOffset = + backboneOffset[QwtPlot::yRight] - endDist + 1; - if ( scaleRect[rightAxis].isValid() ) - { - int maxRight = scaleRect[rightAxis].right(); - int right = axisRect.right() - rightOffset; - axisRect.setRight(qwtMin(right, maxRight)); - } - else - { - if ( d_data->alignCanvasToScales && rightOffset < 0 ) - { - canvasRect.setRight( qwtMin(canvasRect.right(), - axisRect.right() + rightOffset) ); - } - else - { + if ( rightScaleRect.isValid() ) + { + const int dx = rightOffset + rightScaleRect.width(); + if ( d_data->alignCanvasToScales && dx < 0 ) + { + /* + The axis needs more space than the width + of the right scale. + */ + canvasRect.setRight( qMin( canvasRect.right(), + axisRect.right() + dx ) ); + } + + const double maxRight = rightScaleRect.right(); + const double right = axisRect.right() - rightOffset; + axisRect.setRight( qMin( right, maxRight ) ); + } + else + { + if ( d_data->alignCanvasToScales && rightOffset < 0 ) + { + canvasRect.setRight( qMin( canvasRect.right(), + axisRect.right() + rightOffset ) ); + } + else + { if ( rightOffset > 0 ) - axisRect.setRight(axisRect.right() - rightOffset); - } - } - } + axisRect.setRight( axisRect.right() - rightOffset ); + } + } } else // QwtPlot::yLeft, QwtPlot::yRight { - const int bottomOffset = + const QRectF &bottomScaleRect = scaleRect[QwtPlot::xBottom]; + const int bottomOffset = backboneOffset[QwtPlot::xBottom] - endDist + 1; - if ( scaleRect[QwtPlot::xBottom].isValid() ) + if ( bottomScaleRect.isValid() ) { - int maxBottom = scaleRect[QwtPlot::xBottom].top() + - d_data->layoutData.scale[QwtPlot::xBottom].tickOffset; - - int bottom = axisRect.bottom() - bottomOffset; - axisRect.setBottom(qwtMin(bottom, maxBottom)); + const int dy = bottomOffset + bottomScaleRect.height(); + if ( d_data->alignCanvasToScales && dy < 0 ) + { + /* + The axis needs more space than the height + of the bottom scale. + */ + canvasRect.setBottom( qMin( canvasRect.bottom(), + axisRect.bottom() + dy ) ); + } + else + { + const double maxBottom = bottomScaleRect.top() + + d_data->layoutData.scale[QwtPlot::xBottom].tickOffset; + const double bottom = axisRect.bottom() - bottomOffset; + axisRect.setBottom( qMin( bottom, maxBottom ) ); + } } else { if ( d_data->alignCanvasToScales && bottomOffset < 0 ) { - canvasRect.setBottom(qwtMin(canvasRect.bottom(), - axisRect.bottom() + bottomOffset)); + canvasRect.setBottom( qMin( canvasRect.bottom(), + axisRect.bottom() + bottomOffset ) ); } else { if ( bottomOffset > 0 ) - axisRect.setBottom(axisRect.bottom() - bottomOffset); + axisRect.setBottom( axisRect.bottom() - bottomOffset ); } } - + + const QRectF &topScaleRect = scaleRect[QwtPlot::xTop]; const int topOffset = backboneOffset[QwtPlot::xTop] - startDist; - if ( scaleRect[QwtPlot::xTop].isValid() ) + if ( topScaleRect.isValid() ) { - int minTop = scaleRect[QwtPlot::xTop].bottom() - - d_data->layoutData.scale[QwtPlot::xTop].tickOffset; - - int top = axisRect.top() + topOffset; - axisRect.setTop(qwtMax(top, minTop)); + const int dy = topOffset + topScaleRect.height(); + if ( d_data->alignCanvasToScales && dy < 0 ) + { + /* + The axis needs more space than the height + of the top scale. + */ + canvasRect.setTop( qMax( canvasRect.top(), + axisRect.top() - dy ) ); + } + else + { + const double minTop = topScaleRect.bottom() - + d_data->layoutData.scale[QwtPlot::xTop].tickOffset; + const double top = axisRect.top() + topOffset; + axisRect.setTop( qMax( top, minTop ) ); + } } else { if ( d_data->alignCanvasToScales && topOffset < 0 ) { - canvasRect.setTop(qwtMax(canvasRect.top(), - axisRect.top() - topOffset)); + canvasRect.setTop( qMax( canvasRect.top(), + axisRect.top() - topOffset ) ); } else { if ( topOffset > 0 ) - axisRect.setTop(axisRect.top() + topOffset); + axisRect.setTop( axisRect.top() + topOffset ); } } } @@ -1078,110 +1113,93 @@ void QwtPlotLayout::alignScales(int options, */ int fw = 0; - if ( !(options & IgnoreFrames) ) + if ( !( options & IgnoreFrames ) ) fw = d_data->layoutData.canvas.frameWidth; - if ( scaleRect[QwtPlot::xBottom].isValid() && - scaleRect[QwtPlot::xTop].isValid() ) + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { - for ( int axis = QwtPlot::xBottom; axis <= QwtPlot::xTop; axis++ ) + if ( !scaleRect[axis].isValid() ) + continue; + + if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) { - scaleRect[axis].setLeft(canvasRect.left() + fw - - d_data->layoutData.scale[axis].start); - scaleRect[axis].setRight(canvasRect.right() - fw - 1 - + d_data->layoutData.scale[axis].end); + scaleRect[axis].setLeft( canvasRect.left() + fw + - d_data->layoutData.scale[axis].start ); + scaleRect[axis].setRight( canvasRect.right() - fw - 1 + + d_data->layoutData.scale[axis].end ); + } + else + { + scaleRect[axis].setTop( canvasRect.top() + fw + - d_data->layoutData.scale[axis].start ); + scaleRect[axis].setBottom( canvasRect.bottom() - fw - 1 + + d_data->layoutData.scale[axis].end ); } } - if ( scaleRect[QwtPlot::yLeft].isValid() && - scaleRect[QwtPlot::yRight].isValid() ) - { - for ( int axis = QwtPlot::yLeft; axis <= QwtPlot::yRight; axis++ ) - { - scaleRect[axis].setTop(canvasRect.top() + fw - - d_data->layoutData.scale[axis].start); - scaleRect[axis].setBottom(canvasRect.bottom() - fw - 1 - + d_data->layoutData.scale[axis].end); - } - } + if ( scaleRect[QwtPlot::xTop].isValid() ) + scaleRect[QwtPlot::xTop].setBottom( canvasRect.top() ); + if ( scaleRect[QwtPlot::xBottom].isValid() ) + scaleRect[QwtPlot::xBottom].setTop( canvasRect.bottom() ); + if ( scaleRect[QwtPlot::yLeft].isValid() ) + scaleRect[QwtPlot::yLeft].setRight( canvasRect.left() ); + if ( scaleRect[QwtPlot::yRight].isValid() ) + scaleRect[QwtPlot::yRight].setLeft( canvasRect.right() ); } } /*! - \brief Recalculate the geometry of all components. + \brief Recalculate the geometry of all components. \param plot Plot to be layout \param plotRect Rect where to place the components - \param options Options + \param options Layout options - \sa invalidate(), Options, titleRect(), + \sa invalidate(), titleRect(), legendRect(), scaleRect(), canvasRect() */ -void QwtPlotLayout::activate(const QwtPlot *plot, - const QRect &plotRect, int options) +void QwtPlotLayout::activate( const QwtPlot *plot, + const QRectF &plotRect, Options options ) { invalidate(); - QRect rect(plotRect); // undistributed rest of the plot rect - - if ( !(options & IgnoreMargin) ) - { - // subtract the margin - - rect.setRect( - rect.x() + d_data->margin, - rect.y() + d_data->margin, - rect.width() - 2 * d_data->margin, - rect.height() - 2 * d_data->margin - ); - } + QRectF rect( plotRect ); // undistributed rest of the plot rect // We extract all layout relevant data from the widgets, // filter them through pfilter and save them to d_data->layoutData. - d_data->layoutData.init(plot, rect); + d_data->layoutData.init( plot, rect ); - if (!(options & IgnoreLegend) + if ( !( options & IgnoreLegend ) && d_data->legendPos != QwtPlot::ExternalLegend && plot->legend() && !plot->legend()->isEmpty() ) { - d_data->legendRect = layoutLegend(options, rect); + d_data->legendRect = layoutLegend( options, rect ); // subtract d_data->legendRect from rect - const QRegion region(rect); - rect = region.subtract(d_data->legendRect).boundingRect(); + const QRegion region( rect.toRect() ); + rect = region.subtract( d_data->legendRect.toRect() ).boundingRect(); - if ( d_data->layoutData.legend.frameWidth && - !(options & IgnoreFrames ) ) + switch ( d_data->legendPos ) { - // In case of a frame we have to insert a spacing. - // Otherwise the leading of the font separates - // legend and scale/canvas - - switch(d_data->legendPos) - { - case QwtPlot::LeftLegend: - rect.setLeft(rect.left() + d_data->spacing); - break; - case QwtPlot::RightLegend: - rect.setRight(rect.right() - d_data->spacing); - break; - case QwtPlot::TopLegend: - rect.setTop(rect.top() + d_data->spacing); - break; - case QwtPlot::BottomLegend: - rect.setBottom(rect.bottom() - d_data->spacing); - break; - case QwtPlot::ExternalLegend: - break; // suppress compiler warning - } + case QwtPlot::LeftLegend: + rect.setLeft( rect.left() + d_data->spacing ); + break; + case QwtPlot::RightLegend: + rect.setRight( rect.right() - d_data->spacing ); + break; + case QwtPlot::TopLegend: + rect.setTop( rect.top() + d_data->spacing ); + break; + case QwtPlot::BottomLegend: + rect.setBottom( rect.bottom() - d_data->spacing ); + break; + case QwtPlot::ExternalLegend: + break; // suppress compiler warning } } -#ifdef __GNUC__ -#warning Layout code needs to be reorganized -#endif /* +---+-----------+---+ | Title | @@ -1200,17 +1218,17 @@ void QwtPlotLayout::activate(const QwtPlot *plot, // axes and title include text labels. The height of each // label depends on its line breaks, that depend on the width // for the label. A line break in a horizontal text will reduce - // the available width for vertical texts and vice versa. + // the available width for vertical texts and vice versa. // expandLineBreaks finds the height/width for title and axes // including all line breaks. int dimTitle, dimAxes[QwtPlot::axisCnt]; - expandLineBreaks(options, rect, dimTitle, dimAxes); + expandLineBreaks( options, rect, dimTitle, dimAxes ); - if (dimTitle > 0 ) + if ( dimTitle > 0 ) { - d_data->titleRect = QRect(rect.x(), rect.y(), - rect.width(), dimTitle); + d_data->titleRect = QRect( rect.x(), rect.y(), + rect.width(), dimTitle ); if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled != d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) @@ -1218,24 +1236,30 @@ void QwtPlotLayout::activate(const QwtPlot *plot, // if only one of the y axes is missing we align // the title centered to the canvas - d_data->titleRect.setX(rect.x() + dimAxes[QwtPlot::yLeft]); - d_data->titleRect.setWidth(rect.width() - - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight]); + d_data->titleRect.setX( rect.x() + dimAxes[QwtPlot::yLeft] ); + d_data->titleRect.setWidth( rect.width() + - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] ); } - // subtract title - rect.setTop(rect.top() + dimTitle + d_data->spacing); + // subtract title + rect.setTop( rect.top() + dimTitle + d_data->spacing ); } - d_data->canvasRect.setRect( - rect.x() + dimAxes[QwtPlot::yLeft3] + dimAxes[QwtPlot::yLeft2] + dimAxes[QwtPlot::yLeft1] + dimAxes[QwtPlot::yLeft] + 1, + /*d_data->canvasRect.setRect( + rect.x() + dimAxes[QwtPlot::yLeft], rect.y() + dimAxes[QwtPlot::xTop], - rect.width() - ( - dimAxes[QwtPlot::yRight] + dimAxes[QwtPlot::yRight1] - + dimAxes[QwtPlot::yRight2] + dimAxes[QwtPlot::yRight3] - ) - (dimAxes[QwtPlot::yLeft] + dimAxes[QwtPlot::yLeft1] + - dimAxes[QwtPlot::yLeft2] + dimAxes[QwtPlot::yLeft3]), - rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop]); + rect.width() - dimAxes[QwtPlot::yRight] - dimAxes[QwtPlot::yLeft], + rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop] );*/ + d_data->canvasRect.setRect( + rect.x() + dimAxes[QwtPlot::yLeft3] + dimAxes[QwtPlot::yLeft2] + dimAxes[QwtPlot::yLeft1] + dimAxes[QwtPlot::yLeft] + 1, + rect.y() + dimAxes[QwtPlot::xTop], + rect.width() - ( + dimAxes[QwtPlot::yRight] + dimAxes[QwtPlot::yRight1] + + dimAxes[QwtPlot::yRight2] + dimAxes[QwtPlot::yRight3] + ) - (dimAxes[QwtPlot::yLeft] + dimAxes[QwtPlot::yLeft1] + + dimAxes[QwtPlot::yLeft2] + dimAxes[QwtPlot::yLeft3]), + rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop]); + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { @@ -1244,10 +1268,10 @@ void QwtPlotLayout::activate(const QwtPlot *plot, if ( dimAxes[axis] ) { int dim = dimAxes[axis]; - QRect &scaleRect = d_data->scaleRect[axis]; + QRectF &scaleRect = d_data->scaleRect[axis]; scaleRect = d_data->canvasRect; - switch(axis) + switch ( axis ) { case QwtPlot::yLeft3: scaleRect.setX(d_data->canvasRect.left() - dim - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yLeft1] - dimAxes[QwtPlot::yLeft2]); @@ -1261,14 +1285,16 @@ void QwtPlotLayout::activate(const QwtPlot *plot, scaleRect.setX(d_data->canvasRect.left() - dim - dimAxes[QwtPlot::yLeft]); scaleRect.setWidth(dim); break; + case QwtPlot::yLeft: - scaleRect.setX(d_data->canvasRect.left() - dim); - scaleRect.setWidth(dim); + scaleRect.setX( d_data->canvasRect.left() - dim ); + scaleRect.setWidth( dim ); break; case QwtPlot::yRight: - scaleRect.setX(d_data->canvasRect.right() + 1); - scaleRect.setWidth(dim); + scaleRect.setX( d_data->canvasRect.right() ); + scaleRect.setWidth( dim ); break; + case QwtPlot::yRight1: scaleRect.setX(d_data->canvasRect.right() + 1 + dimAxes[QwtPlot::yRight]); //working scaleRect.setWidth(dim); @@ -1281,20 +1307,17 @@ void QwtPlotLayout::activate(const QwtPlot *plot, scaleRect.setX(d_data->canvasRect.right() + 1 + dimAxes[QwtPlot::yRight] + dimAxes[QwtPlot::yRight1] + dimAxes[QwtPlot::yRight2]); scaleRect.setWidth(dim); break; + case QwtPlot::xBottom: - scaleRect.setY(d_data->canvasRect.bottom() + 1); - scaleRect.setHeight(dim); + scaleRect.setY( d_data->canvasRect.bottom() ); + scaleRect.setHeight( dim ); break; case QwtPlot::xTop: - scaleRect.setY(d_data->canvasRect.top() - dim); - scaleRect.setHeight(dim); + scaleRect.setY( d_data->canvasRect.top() - dim ); + scaleRect.setHeight( dim ); break; } -#if QT_VERSION < 0x040000 - scaleRect = scaleRect.normalize(); -#else scaleRect = scaleRect.normalized(); -#endif } } @@ -1317,14 +1340,14 @@ void QwtPlotLayout::activate(const QwtPlot *plot, // be aligned to the canvas. So we try to use the empty // corners to extend the axes, so that the label texts // left/right of the min/max ticks are moved into them. - - alignScales(options, d_data->canvasRect, d_data->scaleRect); - if (!d_data->legendRect.isEmpty() ) + alignScales( options, d_data->canvasRect, d_data->scaleRect ); + + if ( !d_data->legendRect.isEmpty() ) { // We prefer to align the legend to the canvas - not to // the complete plot - if possible. - d_data->legendRect = alignLegend(d_data->canvasRect, d_data->legendRect); + d_data->legendRect = alignLegend( d_data->canvasRect, d_data->legendRect ); } } diff --git a/qwt/src/qwt_plot_layout.h b/qwt/src/qwt_plot_layout.h index 22fa50752..5686513db 100644 --- a/qwt/src/qwt_plot_layout.h +++ b/qwt/src/qwt_plot_layout.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -26,78 +26,73 @@ class QWT_EXPORT QwtPlotLayout public: /*! Options to configure the plot layout engine - - - AlignScales\n - Unused - - IgnoreScrollbars\n - Ignore the dimension of the scrollbars. There are no - scrollbars, when the plot is rendered to a paint device - (QwtPlot::print() ). - - IgnoreFrames\n - Ignore all frames. QwtPlot::print() doesn't paint them. - - IgnoreMargin\n - Ignore the margin(). - - IgnoreLegend\n - Ignore the legend. - - \sa activate() + \sa activate(), QwtPlotRenderer */ - enum Options + enum Option { - AlignScales = 1, - IgnoreScrollbars = 2, - IgnoreFrames = 4, - IgnoreMargin = 8, - IgnoreLegend = 16 + //! Unused + AlignScales = 0x01, + + /*! + Ignore the dimension of the scrollbars. There are no + scrollbars, when the plot is not rendered to widgets. + */ + IgnoreScrollbars = 0x02, + + //! Ignore all frames. + IgnoreFrames = 0x04, + + //! Ignore the legend. + IgnoreLegend = 0x08 }; + //! Layout options + typedef QFlags

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 diff --git a/qwt/doc/qwt.dox b/qwt/doc/qwt.dox deleted file mode 100644 index f379ce630..000000000 --- a/qwt/doc/qwt.dox +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -/* - This file contains NO source code, just some documentation for doxygen to - parse. -*/ - -/*! - \mainpage Qwt - Qt Widgets for Technical Applications - -The Qwt library contains GUI Components and utility classes which are primarily -useful for programs with a technical background. Beside a 2D plot widget -it provides scales, sliders, dials, compasses, thermometers, wheels and knobs -to control or display values, arrays, or ranges of type double. - - \image html plot.png - - \if homepage - \section homepage Project page - The official project page is hosted at - sourceforge - \endif - - \section license License - - Qwt is distributed under the terms of the \ref qwtlicense. - - \section platforms Platforms - - Qwt 5.x might be usable in all environments where you find - Qt. - It is compatible with Qt 3.3.x and Qt 4.x, but the documentation - is generated for Qt 4.x.\n - - \section screenshotsonmainpage Screenshots - - \ref curvescreenshots\n - - \ref scatterscreenshots\n - - \ref spectrogramscreenshots\n - - \ref histogramscreenshots\n - - \ref controlscreenshots\n - - \latexonly Screenshots are only available in the HTML docs.\endlatexonly - - \section downloads Downloads - Stable releases, prereleases and snapshots are available at the Qwt project page. - - For getting a snapshot with all bugfixes for the latest 5.2 release: - \code svn co https://qwt.svn.sourceforge.net/svnroot/qwt/branches/qwt-5.2 \endcode - - For getting a development snapshot from the SVN repository: - \code svn co https://qwt.svn.sourceforge.net/svnroot/qwt/trunk/qwt \endcode - - Qwt doesn't distribute binary packages, but today all major Linux distributors - offer one. Note, that these packages often don't include the examples. - - \section installonmainpage Installation - - Have a look at the qwt.pro project file. It is prepared for building - dynamic libraries in Win32 and Unix/X11 environments. - If you don't know what to do with it, read the file \ref qwtinstall and/or - Trolltechs - qmake documentation. Once you have build the library you have to install - all files from the lib, include and doc directories. - - \section support Support - - Mailing list\n - For all kind of Qwt related questions use the Qwt mailing list.\n - If you prefer newsgroups use the mail to news gateway of Gmane. - - - Forum\n - Qt Centre is a great resource for Qt - related questions. It has a sub forum, that is dedicated to - Qwt related questions. - - - Individual support\n - If you are looking for individual support, or need someone who implements - your Qwt component/application contact qwt-support@tigertal.de. - - \section relatedprojects Related Projects - - QwtPolar, a polar plot widget.\n - QwtPlot3D, an OpenGL 3D plot widget.\n - QtiPlot, - data analysis and scientific plotting tool, using QwtPlot. - - \section languagebindings Language Bindings - - PyQwt, a set of Qwt Python bindings.\n - Korundum/QtRuby, including a set of Qwt Ruby bindings.\n - - \section donations Donations - - Sourceforge offers a Donation System via PayPal. You can use it, if you like to support the development of Qwt. - - \section credits Credits: - \par Authors: - Uwe Rathmann, Josef Wilgen ( <= Qwt 0.2 ) - \par Project admin: - Uwe Rathmann \ -*/ - -/*! - \page qwtlicense Qwt License, Version 1.0 - \include "COPYING" -*/ - -/*! - \page qwtinstall INSTALL - \include "INSTALL" -*/ - -/*! - \page curvescreenshots Curve Plots - \image html plot.png - - \image html sinus.png - - \image html cpuplot.png - - \image html graph.png - - \image html curves.png -*/ - -/*! - \page scatterscreenshots Scatter Plot - \image html scatterplot.png -*/ - -/*! - \page spectrogramscreenshots Spectrogram, Contour Plot - \image html spectrogram1.png - - \image html spectrogram2.png - - \image html spectrogram3.png - -/*! - \page histogramscreenshots Histogram - \image html histogram.png -*/ - -/*! - \page controlscreenshots Dials, Compasses, Knobs, Wheels, Sliders, Thermos - \image html radio.png - - \image html sliders.png - - \image html dials1.png - - \image html dials2.png - - \image html sysinfo.png -*/ diff --git a/qwt/examples/bode/bode.pro b/qwt/examples/bode/bode.pro index b2a925087..bc10f56ab 100644 --- a/qwt/examples/bode/bode.pro +++ b/qwt/examples/bode/bode.pro @@ -1,23 +1,23 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = bode -QT += svg HEADERS = \ - bode.h \ - bode_plot.h \ - cplx.h \ - pixmaps.h + mainwindow.h \ + plot.h \ + complexnumber.h \ + pixmaps.h SOURCES = \ - bode.cpp \ - bode_plot.cpp + plot.cpp \ + mainwindow.cpp \ + main.cpp diff --git a/qwt/examples/bode/bode_plot.h b/qwt/examples/bode/bode_plot.h deleted file mode 100644 index cd04f042f..000000000 --- a/qwt/examples/bode/bode_plot.h +++ /dev/null @@ -1,25 +0,0 @@ -#include - -class QwtPlotCurve; -class QwtPlotMarker; - -class BodePlot: public QwtPlot -{ - Q_OBJECT -public: - BodePlot(QWidget *parent); - -public slots: - void setDamp(double damping); - -private: - void showData(double *frequency, double *amplitude, - double *phase, int count); - void showPeak(double freq, double amplitude); - void show3dB(double freq); - - QwtPlotCurve *d_crv1; - QwtPlotCurve *d_crv2; - QwtPlotMarker *d_mrk1; - QwtPlotMarker *d_mrk2; -}; diff --git a/qwt/examples/bode/complexnumber.h b/qwt/examples/bode/complexnumber.h new file mode 100644 index 000000000..744a56d7d --- /dev/null +++ b/qwt/examples/bode/complexnumber.h @@ -0,0 +1,83 @@ +#ifndef _COMPLEX_NUMBER_H_ +#define _COMPLEX_NUMBER_H_ + +#include + +class ComplexNumber +{ +public: + ComplexNumber() ; + ComplexNumber(double r, double i = 0.0); + + double real() const; + double imag() const; + + friend ComplexNumber operator*( + const ComplexNumber &, const ComplexNumber &); + + friend ComplexNumber operator+( + const ComplexNumber &, const ComplexNumber &); + + friend ComplexNumber operator-( + const ComplexNumber &, const ComplexNumber &); + friend ComplexNumber operator/( + const ComplexNumber &, const ComplexNumber &); + +private: + double d_real; + double d_imag; +}; + +inline ComplexNumber::ComplexNumber(): + d_real(0.0), + d_imag(-0.0) +{ +} + +inline ComplexNumber::ComplexNumber(double re, double im): + d_real(re), + d_imag(im) +{ +} + +inline double ComplexNumber::real() const +{ + return d_real; +} + +inline double ComplexNumber::imag() const +{ + return d_imag; +} + +inline ComplexNumber operator+( + const ComplexNumber &x1, const ComplexNumber &x2) +{ + return ComplexNumber(x1.d_real + x2.d_real, x1.d_imag + x2.d_imag); +} + +inline ComplexNumber operator-( + const ComplexNumber &x1, const ComplexNumber &x2) +{ + return ComplexNumber(x1.d_real - x2.d_real, x1.d_imag - x2.d_imag); +} + +inline ComplexNumber operator*( + const ComplexNumber &x1, const ComplexNumber &x2) +{ + return ComplexNumber(x1.d_real * x2.d_real - x1.d_imag * x2.d_imag, + x1.d_real * x2.d_imag + x2.d_real * x1.d_imag); +} + +inline ComplexNumber operator/( + const ComplexNumber &x1, const ComplexNumber &x2) +{ + double denom = x2.d_real * x2.d_real + x2.d_imag * x2.d_imag; + + return ComplexNumber( + (x1.d_real * x2.d_real + x1.d_imag * x2.d_imag) / denom, + (x1.d_imag * x2.d_real - x2.d_imag * x1.d_real) / denom + ); +} + +#endif diff --git a/qwt/examples/bode/cplx.h b/qwt/examples/bode/cplx.h deleted file mode 100644 index d95344cc3..000000000 --- a/qwt/examples/bode/cplx.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef BODE_CPLX_H -#define BODE_CPLX_H - -#include - - -class cplx { -private: - double re,im; - -public: - - double real() {return re;} - double imag() {return im;} - - cplx() { - re = 0.0; - im = -0.0; - } - - cplx& operator= (cplx a) { - re = a.re; - im = a.im; - return *this; - } - - cplx(double r, double i = 0.0) { - re = r; - im = i; - } - - friend cplx operator * (cplx x1, cplx x2); - friend cplx operator + (cplx x1, cplx x2); - friend cplx operator - (cplx x1, cplx x2); - friend cplx operator / (cplx x1, cplx x2); - -}; - -inline cplx operator+(cplx x1, cplx x2) -{ - return cplx(x1.re + x2.re, x1.im + x2.im); -} - -inline cplx operator-(cplx x1, cplx x2) -{ - return cplx(x1.re - x2.re, x1.im - x2.im); -} - -inline cplx operator*(cplx x1, cplx x2) -{ - return cplx(x1.re * x2.re - x1.im * x2.im, - x1.re * x2.im + x2.re * x1.im); -} - -inline cplx operator/(cplx x1, cplx x2) -{ - double denom = x2.re * x2.re + x2.im * x2.im; - return cplx( (x1.re * x2.re + x1.im * x2.im) /denom, - (x1.im * x2.re - x2.im * x1.re) / denom); -} - -#endif diff --git a/qwt/examples/bode/main.cpp b/qwt/examples/bode/main.cpp new file mode 100644 index 000000000..b352d05bd --- /dev/null +++ b/qwt/examples/bode/main.cpp @@ -0,0 +1,13 @@ +#include +#include "mainwindow.h" + +int main (int argc, char **argv) +{ + QApplication a(argc, argv); + + MainWindow w; + w.resize(540,400); + w.show(); + + return a.exec(); +} diff --git a/qwt/examples/bode/bode.cpp b/qwt/examples/bode/mainwindow.cpp similarity index 55% rename from qwt/examples/bode/bode.cpp rename to qwt/examples/bode/mainwindow.cpp index fcfe4b1ba..00ccd2add 100644 --- a/qwt/examples/bode/bode.cpp +++ b/qwt/examples/bode/mainwindow.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -9,25 +8,19 @@ #include #include #include -#if QT_VERSION >= 0x040300 -#ifdef QT_SVG_LIB -#include -#endif -#endif -#if QT_VERSION >= 0x040000 +#include #include #include -#else -#include -#endif #include +#include #include #include +#include #include #include #include "pixmaps.h" -#include "bode_plot.h" -#include "bode.h" +#include "plot.h" +#include "mainwindow.h" class Zoomer: public QwtPlotZoomer { @@ -35,20 +28,14 @@ public: Zoomer(int xAxis, int yAxis, QwtPlotCanvas *canvas): QwtPlotZoomer(xAxis, yAxis, canvas) { - setSelectionFlags(QwtPicker::DragSelection | QwtPicker::CornerToCorner); setTrackerMode(QwtPicker::AlwaysOff); setRubberBand(QwtPicker::NoRubberBand); // RightButton: zoom out by 1 // Ctrl+RightButton: zoom out to full size -#if QT_VERSION < 0x040000 - setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlButton); -#else setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); -#endif setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); } @@ -64,17 +51,17 @@ public: // //----------------------------------------------------------------- -MainWin::MainWin(QWidget *parent): +MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) { - d_plot = new BodePlot(this); - d_plot->setMargin(5); + d_plot = new Plot(this); + + const int margin = 5; + d_plot->setContentsMargins( margin, margin, margin, 0 ); -#if QT_VERSION >= 0x040000 setContextMenuPolicy(Qt::NoContextMenu); -#endif - d_zoomer[0] = new Zoomer( QwtPlot::xBottom, QwtPlot::yLeft, + d_zoomer[0] = new Zoomer( QwtPlot::xBottom, QwtPlot::yLeft, d_plot->canvas()); d_zoomer[0]->setRubberBand(QwtPicker::RectRubberBand); d_zoomer[0]->setRubberBandPen(QColor(Qt::green)); @@ -83,14 +70,14 @@ MainWin::MainWin(QWidget *parent): d_zoomer[1] = new Zoomer(QwtPlot::xTop, QwtPlot::yRight, d_plot->canvas()); - + d_panner = new QwtPlotPanner(d_plot->canvas()); d_panner->setMouseButton(Qt::MidButton); d_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, - QwtPicker::PointSelection | QwtPicker::DragSelection, - QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, + QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, d_plot->canvas()); + d_picker->setStateMachine(new QwtPickerDragPointMachine()); d_picker->setRubberBandPen(QColor(Qt::green)); d_picker->setRubberBand(QwtPicker::CrossRubberBand); d_picker->setTrackerPen(QColor(Qt::white)); @@ -100,52 +87,29 @@ MainWin::MainWin(QWidget *parent): QToolBar *toolBar = new QToolBar(this); QToolButton *btnZoom = new QToolButton(toolBar); -#if QT_VERSION >= 0x040000 btnZoom->setText("Zoom"); btnZoom->setIcon(QIcon(zoom_xpm)); btnZoom->setCheckable(true); btnZoom->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); -#else - btnZoom->setTextLabel("Zoom"); - btnZoom->setPixmap(zoom_xpm); - btnZoom->setToggleButton(true); - btnZoom->setUsesTextLabel(true); -#endif + toolBar->addWidget(btnZoom); + connect(btnZoom, SIGNAL(toggled(bool)), SLOT(enableZoomMode(bool))); +#ifndef QT_NO_PRINTER QToolButton *btnPrint = new QToolButton(toolBar); -#if QT_VERSION >= 0x040000 btnPrint->setText("Print"); btnPrint->setIcon(QIcon(print_xpm)); btnPrint->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); -#else - btnPrint->setTextLabel("Print"); - btnPrint->setPixmap(print_xpm); - btnPrint->setUsesTextLabel(true); -#endif - -#if QT_VERSION < 0x040000 - QToolButton *btnSVG = new QToolButton(toolBar); - btnSVG->setTextLabel("SVG"); - btnSVG->setPixmap(print_xpm); - btnSVG->setUsesTextLabel(true); -#elif QT_VERSION >= 0x040300 -#ifdef QT_SVG_LIB - QToolButton *btnSVG = new QToolButton(toolBar); - btnSVG->setText("SVG"); - btnSVG->setIcon(QIcon(print_xpm)); - btnSVG->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); -#endif -#endif - -#if QT_VERSION >= 0x040000 - toolBar->addWidget(btnZoom); toolBar->addWidget(btnPrint); -#if QT_VERSION >= 0x040300 -#ifdef QT_SVG_LIB - toolBar->addWidget(btnSVG); -#endif -#endif + connect(btnPrint, SIGNAL(clicked()), SLOT(print())); #endif + + QToolButton *btnExport = new QToolButton(toolBar); + btnExport->setText("Export"); + btnExport->setIcon(QIcon(print_xpm)); + btnExport->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + toolBar->addWidget(btnExport); + connect(btnExport, SIGNAL(clicked()), SLOT(exportDocument())); + toolBar->addSeparator(); QWidget *hBox = new QWidget(toolBar); @@ -159,14 +123,10 @@ MainWin::MainWin(QWidget *parent): QwtCounter *cntDamp = new QwtCounter(hBox); cntDamp->setRange(0.0, 5.0, 0.01); cntDamp->setValue(0.0); - + layout->addWidget(cntDamp, 0); -#if QT_VERSION >= 0x040000 (void)toolBar->addWidget(hBox); -#else - toolBar->setStretchableWidget(hBox); -#endif addToolBar(toolBar); #ifndef QT_NO_STATUSBAR @@ -176,39 +136,20 @@ MainWin::MainWin(QWidget *parent): enableZoomMode(false); showInfo(); - connect(cntDamp, SIGNAL(valueChanged(double)), - d_plot, SLOT(setDamp(double))); - - connect(btnPrint, SIGNAL(clicked()), SLOT(print())); -#if QT_VERSION < 0x040000 - connect(btnSVG, SIGNAL(clicked()), SLOT(exportSVG())); -#elif QT_VERSION >= 0x040300 -#ifdef QT_SVG_LIB - connect(btnSVG, SIGNAL(clicked()), SLOT(exportSVG())); -#endif -#endif - connect(btnZoom, SIGNAL(toggled(bool)), SLOT(enableZoomMode(bool))); + connect(cntDamp, SIGNAL(valueChanged(double)), + d_plot, SLOT(setDamp(double))); connect(d_picker, SIGNAL(moved(const QPoint &)), SLOT(moved(const QPoint &))); - connect(d_picker, SIGNAL(selected(const QwtPolygon &)), - SLOT(selected(const QwtPolygon &))); + connect(d_picker, SIGNAL(selected(const QPolygon &)), + SLOT(selected(const QPolygon &))); } -void MainWin::print() +#ifndef QT_NO_PRINTER + +void MainWindow::print() { -#if 1 - QPrinter printer; -#else QPrinter printer(QPrinter::HighResolution); -#if QT_VERSION < 0x040000 - printer.setOutputToFile(true); - printer.setOutputFileName("/tmp/bode.ps"); - printer.setColorMode(QPrinter::Color); -#else - printer.setOutputFileName("/tmp/bode.pdf"); -#endif -#endif QString docName = d_plot->title().text(); if ( !docName.isEmpty() ) @@ -220,71 +161,75 @@ void MainWin::print() printer.setCreator("Bode example"); printer.setOrientation(QPrinter::Landscape); -#if QT_VERSION >= 0x040000 QPrintDialog dialog(&printer); if ( dialog.exec() ) { -#else - if (printer.setup()) - { -#endif - QwtPlotPrintFilter filter; + QwtPlotRenderer renderer; + if ( printer.colorMode() == QPrinter::GrayScale ) { - int options = QwtPlotPrintFilter::PrintAll; - options &= ~QwtPlotPrintFilter::PrintBackground; - options |= QwtPlotPrintFilter::PrintFrameWithScales; - filter.setOptions(options); + renderer.setDiscardFlag(QwtPlotRenderer::DiscardCanvasBackground); + renderer.setLayoutFlag(QwtPlotRenderer::FrameWithScales); } - d_plot->print(printer, filter); + + renderer.renderTo(d_plot, printer); } } -void MainWin::exportSVG() +#endif + +void MainWindow::exportDocument() { - QString fileName = "bode.svg"; - -#if QT_VERSION < 0x040000 +#ifndef QT_NO_PRINTER + QString fileName = "bode.pdf"; +#else + QString fileName = "bode.png"; +#endif #ifndef QT_NO_FILEDIALOG - fileName = QFileDialog::getSaveFileName( - "bode.svg", "SVG Documents (*.svg)", this); + const QList imageFormats = + QImageWriter::supportedImageFormats(); + + QStringList filter; + filter += "PDF Documents (*.pdf)"; +#ifndef QWT_NO_SVG + filter += "SVG Documents (*.svg)"; #endif - if ( !fileName.isEmpty() ) + filter += "Postscript Documents (*.ps)"; + + if ( imageFormats.size() > 0 ) { - // enable workaround for Qt3 misalignments - QwtPainter::setSVGMode(true); + QString imageFilter("Images ("); + for ( int i = 0; i < imageFormats.size(); i++ ) + { + if ( i > 0 ) + imageFilter += " "; + imageFilter += "*."; + imageFilter += imageFormats[i]; + } + imageFilter += ")"; - QPicture picture; - - QPainter p(&picture); - d_plot->print(&p, QRect(0, 0, 800, 600)); - p.end(); - - picture.save(fileName, "svg"); + filter += imageFilter; } -#elif QT_VERSION >= 0x040300 - -#ifdef QT_SVG_LIB -#ifndef QT_NO_FILEDIALOG fileName = QFileDialog::getSaveFileName( - this, "Export File Name", QString(), - "SVG Documents (*.svg)"); + this, "Export File Name", fileName, + filter.join(";;"), NULL, QFileDialog::DontConfirmOverwrite); #endif + if ( !fileName.isEmpty() ) { - QSvgGenerator generator; - generator.setFileName(fileName); - generator.setSize(QSize(800, 600)); + QwtPlotRenderer renderer; - d_plot->print(generator); + // flags to make the document look like the widget + renderer.setDiscardFlag(QwtPlotRenderer::DiscardBackground, false); + renderer.setLayoutFlag(QwtPlotRenderer::KeepFrames, true); + + renderer.renderDocument(d_plot, fileName, QSizeF(300, 200), 85); } -#endif -#endif } -void MainWin::enableZoomMode(bool on) +void MainWindow::enableZoomMode(bool on) { d_panner->setEnabled(on); @@ -299,7 +244,7 @@ void MainWin::enableZoomMode(bool on) showInfo(); } -void MainWin::showInfo(QString text) +void MainWindow::showInfo(QString text) { if ( text == QString::null ) { @@ -310,15 +255,11 @@ void MainWin::showInfo(QString text) } #ifndef QT_NO_STATUSBAR -#if QT_VERSION >= 0x040000 statusBar()->showMessage(text); -#else - statusBar()->message(text); -#endif #endif } -void MainWin::moved(const QPoint &pos) +void MainWindow::moved(const QPoint &pos) { QString info; info.sprintf("Freq=%g, Ampl=%g, Phase=%g", @@ -329,22 +270,7 @@ void MainWin::moved(const QPoint &pos) showInfo(info); } -void MainWin::selected(const QwtPolygon &) +void MainWindow::selected(const QPolygon &) { showInfo(); } - -int main (int argc, char **argv) -{ - QApplication a(argc, argv); - - MainWin w; -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif - w.resize(540,400); - w.show(); - - int rv = a.exec(); - return rv; -} diff --git a/qwt/examples/bode/bode.h b/qwt/examples/bode/mainwindow.h similarity index 60% rename from qwt/examples/bode/bode.h rename to qwt/examples/bode/mainwindow.h index 81c9de5e5..a846cf6d8 100644 --- a/qwt/examples/bode/bode.h +++ b/qwt/examples/bode/mainwindow.h @@ -1,30 +1,33 @@ #include -#include class QwtPlotZoomer; class QwtPlotPicker; class QwtPlotPanner; -class BodePlot; +class Plot; +class QPolygon; -class MainWin : public QMainWindow +class MainWindow : public QMainWindow { Q_OBJECT public: - MainWin(QWidget *parent = 0); + MainWindow(QWidget *parent = 0); -private slots: +private Q_SLOTS: void moved(const QPoint &); - void selected(const QwtPolygon &); - + void selected(const QPolygon &); + +#ifndef QT_NO_PRINTER void print(); - void exportSVG(); +#endif + + void exportDocument(); void enableZoomMode(bool); private: void showInfo(QString text = QString::null); - BodePlot *d_plot; + Plot *d_plot; QwtPlotZoomer *d_zoomer[2]; QwtPlotPicker *d_picker; diff --git a/qwt/examples/bode/bode_plot.cpp b/qwt/examples/bode/plot.cpp similarity index 55% rename from qwt/examples/bode/bode_plot.cpp rename to qwt/examples/bode/plot.cpp index 040dce84c..ad16f9258 100644 --- a/qwt/examples/bode/bode_plot.cpp +++ b/qwt/examples/bode/plot.cpp @@ -6,11 +6,17 @@ #include #include #include -#include "cplx.h" -#include "bode_plot.h" +#include +#include "complexnumber.h" +#include "plot.h" + +#if QT_VERSION < 0x040601 +#define qExp(x) ::exp(x) +#define qAtan2(y, x) ::atan2(y, x) +#endif static void logSpace(double *array, int size, double xmin, double xmax) -{ +{ if ((xmin <= 0.0) || (xmax <= 0.0) || (size <= 0)) return; @@ -24,10 +30,10 @@ static void logSpace(double *array, int size, double xmin, double xmax) const double lstep = (lxmax - lxmin) / double(imax); for (int i = 1; i < imax; i++) - array[i] = exp(lxmin + double(i) * lstep); + array[i] = qExp(lxmin + double(i) * lstep); } -BodePlot::BodePlot(QWidget *parent): +Plot::Plot(QWidget *parent): QwtPlot(parent) { setAutoReplot(false); @@ -38,10 +44,9 @@ BodePlot::BodePlot(QWidget *parent): // legend QwtLegend *legend = new QwtLegend; - legend->setFrameStyle(QFrame::Box|QFrame::Sunken); insertLegend(legend, QwtPlot::BottomLegend); - // grid + // grid QwtPlotGrid *grid = new QwtPlotGrid; grid->enableXMin(true); grid->setMajPen(QPen(Qt::white, 0, Qt::DotLine)); @@ -57,53 +62,51 @@ BodePlot::BodePlot(QWidget *parent): setAxisMaxMajor(QwtPlot::xBottom, 6); setAxisMaxMinor(QwtPlot::xBottom, 10); setAxisScaleEngine(QwtPlot::xBottom, new QwtLog10ScaleEngine); - + // curves - d_crv1 = new QwtPlotCurve("Amplitude"); -#if QT_VERSION >= 0x040000 - d_crv1->setRenderHint(QwtPlotItem::RenderAntialiased); -#endif - d_crv1->setPen(QPen(Qt::yellow)); - d_crv1->setYAxis(QwtPlot::yLeft); - d_crv1->attach(this); + d_curve1 = new QwtPlotCurve("Amplitude"); + d_curve1->setRenderHint(QwtPlotItem::RenderAntialiased); + d_curve1->setPen(QPen(Qt::yellow)); + d_curve1->setLegendAttribute(QwtPlotCurve::LegendShowLine); + d_curve1->setYAxis(QwtPlot::yLeft); + d_curve1->attach(this); + + d_curve2 = new QwtPlotCurve("Phase"); + d_curve2->setRenderHint(QwtPlotItem::RenderAntialiased); + d_curve2->setPen(QPen(Qt::cyan)); + d_curve2->setLegendAttribute(QwtPlotCurve::LegendShowLine); + d_curve2->setYAxis(QwtPlot::yRight); + d_curve2->attach(this); - d_crv2 = new QwtPlotCurve("Phase"); -#if QT_VERSION >= 0x040000 - d_crv2->setRenderHint(QwtPlotItem::RenderAntialiased); -#endif - d_crv2->setPen(QPen(Qt::cyan)); - d_crv2->setYAxis(QwtPlot::yRight); - d_crv2->attach(this); - // marker - d_mrk1 = new QwtPlotMarker(); - d_mrk1->setValue(0.0, 0.0); - d_mrk1->setLineStyle(QwtPlotMarker::VLine); - d_mrk1->setLabelAlignment(Qt::AlignRight | Qt::AlignBottom); - d_mrk1->setLinePen(QPen(Qt::green, 0, Qt::DashDotLine)); - d_mrk1->attach(this); + d_marker1 = new QwtPlotMarker(); + d_marker1->setValue(0.0, 0.0); + d_marker1->setLineStyle(QwtPlotMarker::VLine); + d_marker1->setLabelAlignment(Qt::AlignRight | Qt::AlignBottom); + d_marker1->setLinePen(QPen(Qt::green, 0, Qt::DashDotLine)); + d_marker1->attach(this); - d_mrk2 = new QwtPlotMarker(); - d_mrk2->setLineStyle(QwtPlotMarker::HLine); - d_mrk2->setLabelAlignment(Qt::AlignRight | Qt::AlignBottom); - d_mrk2->setLinePen(QPen(QColor(200,150,0), 0, Qt::DashDotLine)); - d_mrk2->setSymbol( QwtSymbol(QwtSymbol::Diamond, + d_marker2 = new QwtPlotMarker(); + d_marker2->setLineStyle(QwtPlotMarker::HLine); + d_marker2->setLabelAlignment(Qt::AlignRight | Qt::AlignBottom); + d_marker2->setLinePen(QPen(QColor(200,150,0), 0, Qt::DashDotLine)); + d_marker2->setSymbol( new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::yellow), QColor(Qt::green), QSize(7,7))); - d_mrk2->attach(this); + d_marker2->attach(this); setDamp(0.0); setAutoReplot(true); } -void BodePlot::showData(double *frequency, double *amplitude, - double *phase, int count) +void Plot::showData(const double *frequency, const double *amplitude, + const double *phase, int count) { - d_crv1->setData(frequency, amplitude, count); - d_crv2->setData(frequency, phase, count); + d_curve1->setSamples(frequency, amplitude, count); + d_curve2->setSamples(frequency, phase, count); } -void BodePlot::showPeak(double freq, double amplitude) +void Plot::showPeak(double freq, double amplitude) { QString label; label.sprintf("Peak: %.3g dB", amplitude); @@ -112,11 +115,11 @@ void BodePlot::showPeak(double freq, double amplitude) text.setFont(QFont("Helvetica", 10, QFont::Bold)); text.setColor(QColor(200,150,0)); - d_mrk2->setValue(freq, amplitude); - d_mrk2->setLabel(text); + d_marker2->setValue(freq, amplitude); + d_marker2->setLabel(text); } -void BodePlot::show3dB(double freq) +void Plot::show3dB(double freq) { QString label; label.sprintf("-3 dB at f = %.3g", freq); @@ -125,14 +128,14 @@ void BodePlot::show3dB(double freq) text.setFont(QFont("Helvetica", 10, QFont::Bold)); text.setColor(Qt::green); - d_mrk1->setValue(freq, 0.0); - d_mrk1->setLabel(text); + d_marker1->setValue(freq, 0.0); + d_marker1->setLabel(text); } // // re-calculate frequency response // -void BodePlot::setDamp(double damping) +void Plot::setDamp(double damping) { const bool doReplot = autoReplot(); setAutoReplot(false); @@ -149,28 +152,30 @@ void BodePlot::setDamp(double damping) int i3 = 1; double fmax = 1; double amax = -1000.0; - + for (int i = 0; i < ArraySize; i++) { double f = frequency[i]; - cplx g = cplx(1.0) / cplx(1.0 - f * f, 2.0 * damping * f); - amplitude[i] = 20.0 * log10(sqrt( g.real()*g.real() + g.imag()*g.imag())); - phase[i] = atan2(g.imag(), g.real()) * (180.0 / M_PI); + const ComplexNumber g = + ComplexNumber(1.0) / ComplexNumber(1.0 - f * f, 2.0 * damping * f); - if ((i3 <= 1) && (amplitude[i] < -3.0)) + amplitude[i] = 20.0 * log10(qSqrt( g.real() * g.real() + g.imag() * g.imag())); + phase[i] = qAtan2(g.imag(), g.real()) * (180.0 / M_PI); + + if ((i3 <= 1) && (amplitude[i] < -3.0)) i3 = i; if (amplitude[i] > amax) { amax = amplitude[i]; fmax = frequency[i]; } - + } - - double f3 = frequency[i3] - - (frequency[i3] - frequency[i3 - 1]) + + double f3 = frequency[i3] - + (frequency[i3] - frequency[i3 - 1]) / (amplitude[i3] - amplitude[i3 -1]) * (amplitude[i3] + 3); - + showPeak(fmax, amax); show3dB(f3); showData(frequency, amplitude, phase, ArraySize); diff --git a/qwt/examples/bode/plot.h b/qwt/examples/bode/plot.h new file mode 100644 index 000000000..d80dfb057 --- /dev/null +++ b/qwt/examples/bode/plot.h @@ -0,0 +1,31 @@ +#ifndef _PLOT_H_ +#define _PLOT_H_ + +#include + +class QwtPlotCurve; +class QwtPlotMarker; + +class Plot: public QwtPlot +{ + Q_OBJECT + +public: + Plot(QWidget *parent); + +public Q_SLOTS: + void setDamp(double damping); + +private: + void showData(const double *frequency, const double *amplitude, + const double *phase, int count); + void showPeak(double freq, double amplitude); + void show3dB(double freq); + + QwtPlotCurve *d_curve1; + QwtPlotCurve *d_curve2; + QwtPlotMarker *d_marker1; + QwtPlotMarker *d_marker2; +}; + +#endif diff --git a/qwt/examples/cpuplot/cpupiemarker.cpp b/qwt/examples/cpuplot/cpupiemarker.cpp index be563633e..814e0d709 100644 --- a/qwt/examples/cpuplot/cpupiemarker.cpp +++ b/qwt/examples/cpuplot/cpupiemarker.cpp @@ -7,9 +7,7 @@ CpuPieMarker::CpuPieMarker() { setZ(1000); -#if QT_VERSION >= 0x040000 setRenderHint(QwtPlotItem::RenderAntialiased, true); -#endif } int CpuPieMarker::rtti() const @@ -17,32 +15,32 @@ int CpuPieMarker::rtti() const return QwtPlotItem::Rtti_PlotUserItem; } -void CpuPieMarker::draw(QPainter *p, +void CpuPieMarker::draw(QPainter *p, const QwtScaleMap &, const QwtScaleMap &, - const QRect &rect) const + const QRectF &rect) const { const CpuPlot *cpuPlot = (CpuPlot *)plot(); const QwtScaleMap yMap = cpuPlot->canvasMap(QwtPlot::yLeft); const int margin = 5; - + QRect pieRect; pieRect.setX(rect.x() + margin); pieRect.setY(rect.y() + margin); - pieRect.setHeight(yMap.transform(80.0)); - pieRect.setWidth(pieRect.height()); - + pieRect.setHeight( qRound(yMap.transform(80.0)) ); + pieRect.setWidth( pieRect.height() ); + const int dataType[] = { CpuPlot::User, CpuPlot::System, CpuPlot::Idle }; int angle = (int)(5760 * 0.75); - for ( unsigned int i = 0; + for ( unsigned int i = 0; i < sizeof(dataType) / sizeof(dataType[0]); i++ ) { const QwtPlotCurve *curve = cpuPlot->cpuCurve(dataType[i]); if ( curve->dataSize() > 0 ) { - const int value = (int)(5760 * curve->y(0) / 100.0); + const int value = (int)(5760 * curve->sample(0).y() / 100.0); p->save(); p->setBrush(QBrush(curve->pen().color(), Qt::SolidPattern)); @@ -54,4 +52,3 @@ void CpuPieMarker::draw(QPainter *p, } } } - diff --git a/qwt/examples/cpuplot/cpupiemarker.h b/qwt/examples/cpuplot/cpupiemarker.h index 165e9a49d..2ab9fd371 100644 --- a/qwt/examples/cpuplot/cpupiemarker.h +++ b/qwt/examples/cpuplot/cpupiemarker.h @@ -14,5 +14,5 @@ public: virtual void draw(QPainter *p, const QwtScaleMap &, const QwtScaleMap &, - const QRect &rect) const; + const QRectF &rect) const; }; diff --git a/qwt/examples/cpuplot/cpuplot.cpp b/qwt/examples/cpuplot/cpuplot.cpp index fc91df668..ddea5091e 100644 --- a/qwt/examples/cpuplot/cpuplot.cpp +++ b/qwt/examples/cpuplot/cpuplot.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "cpupiemarker.h" #include "cpuplot.h" @@ -42,10 +43,10 @@ public: virtual void draw(QPainter *painter, const QwtScaleMap &, const QwtScaleMap &yMap, - const QRect &rect) const + const QRectF &rect) const { QColor c(Qt::white); - QRect r = rect; + QRectF r = rect; for ( int i = 100; i > 0; i -= 10 ) { @@ -64,23 +65,16 @@ public: CpuCurve(const QString &title): QwtPlotCurve(title) { -#if QT_VERSION >= 0x040000 setRenderHint(QwtPlotItem::RenderAntialiased); -#endif } void setColor(const QColor &color) { -#if QT_VERSION >= 0x040000 QColor c = color; c.setAlpha(150); setPen(c); setBrush(c); -#else - setPen(color); - setBrush(QBrush(color, Qt::Dense4Pattern)); -#endif } }; @@ -90,6 +84,8 @@ CpuPlot::CpuPlot(QWidget *parent): { setAutoReplot(false); + canvas()->setBorderRadius( 10 ); + plotLayout()->setAlignCanvasToScales(true); QwtLegend *legend = new QwtLegend; @@ -97,7 +93,7 @@ CpuPlot::CpuPlot(QWidget *parent): insertLegend(legend, QwtPlot::RightLegend); setAxisTitle(QwtPlot::xBottom, " System Uptime [h:m:s]"); - setAxisScaleDraw(QwtPlot::xBottom, + setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw(cpuStat.upTime())); setAxisScale(QwtPlot::xBottom, 0, HISTORY); setAxisLabelRotation(QwtPlot::xBottom, -50.0); @@ -124,7 +120,7 @@ CpuPlot::CpuPlot(QWidget *parent): CpuPieMarker *pie = new CpuPieMarker(); pie->attach(this); - + CpuCurve *curve; curve = new CpuCurve("System"); @@ -177,7 +173,7 @@ void CpuPlot::timerEvent(QTimerEvent *) cpuStat.statistic(data[User].data[0], data[System].data[0]); - data[Total].data[0] = data[User].data[0] + + data[Total].data[0] = data[User].data[0] + data[System].data[0]; data[Idle].data[0] = 100.0 - data[Total].data[0]; @@ -187,12 +183,12 @@ void CpuPlot::timerEvent(QTimerEvent *) for ( int j = 0; j < HISTORY; j++ ) timeData[j]++; - setAxisScale(QwtPlot::xBottom, + setAxisScale(QwtPlot::xBottom, timeData[HISTORY - 1], timeData[0]); for ( int c = 0; c < NCpuData; c++ ) { - data[c].curve->setRawData( + data[c].curve->setRawSamples( timeData, data[c].data, dataCount); } @@ -205,24 +201,22 @@ void CpuPlot::showCurve(QwtPlotItem *item, bool on) QWidget *w = legend()->find(item); if ( w && w->inherits("QwtLegendItem") ) ((QwtLegendItem *)w)->setChecked(on); - + replot(); } int main(int argc, char **argv) { - QApplication a(argc, argv); - + QApplication a(argc, argv); + QWidget vBox; -#if QT_VERSION >= 0x040000 vBox.setWindowTitle("Cpu Plot"); -#else - vBox.setCaption("Cpu Plot"); -#endif CpuPlot *plot = new CpuPlot(&vBox); plot->setTitle("History"); - plot->setMargin(5); + + const int margin = 5; + plot->setContentsMargins(margin, margin, margin, margin); QString info("Press the legend to en/disable a curve"); @@ -232,13 +226,8 @@ int main(int argc, char **argv) layout->addWidget(plot); layout->addWidget(label); -#if QT_VERSION < 0x040000 - a.setMainWidget(&vBox); -#endif - vBox.resize(600,400); vBox.show(); - return a.exec(); -} - + return a.exec(); +} diff --git a/qwt/examples/cpuplot/cpuplot.h b/qwt/examples/cpuplot/cpuplot.h index 873c9528a..b16a66c87 100644 --- a/qwt/examples/cpuplot/cpuplot.h +++ b/qwt/examples/cpuplot/cpuplot.h @@ -5,7 +5,7 @@ class QwtPlotCurve; -class CpuPlot : public QwtPlot +class CpuPlot : public QwtPlot { Q_OBJECT public: @@ -26,7 +26,7 @@ public: protected: void timerEvent(QTimerEvent *e); -private slots: +private Q_SLOTS: void showCurve(QwtPlotItem *, bool on); private: diff --git a/qwt/examples/cpuplot/cpuplot.pro b/qwt/examples/cpuplot/cpuplot.pro index 043a8031b..037f4b944 100644 --- a/qwt/examples/cpuplot/cpuplot.pro +++ b/qwt/examples/cpuplot/cpuplot.pro @@ -1,22 +1,22 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = cpuplot HEADERS = \ - cpuplot.h \ - cpustat.h \ - cpupiemarker.h + cpuplot.h \ + cpustat.h \ + cpupiemarker.h SOURCES = \ - cpuplot.cpp \ - cpustat.cpp \ - cpupiemarker.cpp + cpuplot.cpp \ + cpustat.cpp \ + cpupiemarker.cpp diff --git a/qwt/examples/cpuplot/cpustat.cpp b/qwt/examples/cpuplot/cpustat.cpp index 73bf987be..1f6dc072a 100644 --- a/qwt/examples/cpuplot/cpustat.cpp +++ b/qwt/examples/cpuplot/cpustat.cpp @@ -41,11 +41,7 @@ void CpuStat::statistic(double &user, double &system) void CpuStat::lookUp(double values[NValues]) const { QFile file("/proc/stat"); -#if QT_VERSION >= 0x040000 if ( !file.open(QIODevice::ReadOnly) ) -#else - if ( !file.open(IO_ReadOnly) ) -#endif { static double dummyValues[][NValues] = { @@ -193,11 +189,11 @@ void CpuStat::lookUp(double values[NValues]) const { 109371, 0, 24019, 827486 }, }; static int counter = 0; - + for ( int i = 0; i < NValues; i++ ) values[i] = dummyValues[counter][i]; - counter = (counter + 1) + counter = (counter + 1) % (sizeof(dummyValues) / sizeof(dummyValues[0])); } else @@ -205,19 +201,11 @@ void CpuStat::lookUp(double values[NValues]) const QTextStream textStream(&file); do { QString line = textStream.readLine(); -#if QT_VERSION < 0x040000 - line = line.stripWhiteSpace(); -#else line = line.trimmed(); -#endif if ( line.startsWith("cpu ") ) { const QStringList valueList = -#if QT_VERSION < 0x040000 - QStringList::split(" ", line); -#else line.split(" ", QString::SkipEmptyParts); -#endif if ( valueList.count() >= 5 ) { for ( int i = 0; i < NValues; i++ ) @@ -225,11 +213,6 @@ void CpuStat::lookUp(double values[NValues]) const } break; } - } -#if QT_VERSION < 0x040000 - while(!textStream.eof()); -#else - while(!textStream.atEnd()); -#endif + } while(!textStream.atEnd()); } } diff --git a/qwt/examples/cpuplot/cpustat.h b/qwt/examples/cpuplot/cpustat.h index 828ac0dac..5515354c8 100644 --- a/qwt/examples/cpuplot/cpustat.h +++ b/qwt/examples/cpuplot/cpustat.h @@ -1,6 +1,6 @@ #include -class CpuStat +class CpuStat { public: CpuStat(); diff --git a/qwt/examples/curvdemo1/curvdemo1.cpp b/qwt/examples/curvdemo1/curvdemo1.cpp index d69ee8c98..3b3a520d5 100644 --- a/qwt/examples/curvdemo1/curvdemo1.cpp +++ b/qwt/examples/curvdemo1/curvdemo1.cpp @@ -1,11 +1,12 @@ -#include -#include + #include #include #include +#include #include #include -#include +#include +#include //------------------------------------------------------------ // curvdemo1 @@ -19,38 +20,32 @@ // Array Sizes // const int Size = 27; -#if QT_VERSION >= 0x040000 const int CurvCnt = 6; -#else -const int CurvCnt = 5; -#endif // // Arrays holding the values // double xval[Size]; double yval[Size]; -QwtScaleMap xMap; +QwtScaleMap xMap; QwtScaleMap yMap; -class MainWin : public QFrame +class MainWin : public QFrame { public: MainWin(); - + protected: -#if QT_VERSION >= 0x040000 virtual void paintEvent(QPaintEvent *); -#endif void drawContents(QPainter *p); private: void shiftDown(QRect &rect, int offset) const; - QwtPlotCurve crv[CurvCnt]; + QwtPlotCurve d_curves[CurvCnt]; }; -MainWin::MainWin() +MainWin::MainWin() { int i; @@ -59,7 +54,7 @@ MainWin::MainWin() // // Frame style - // + // setFrameStyle(QFrame::Box|QFrame::Raised); setLineWidth(2); setMidLineWidth(3); @@ -68,54 +63,45 @@ MainWin::MainWin() // Calculate values // for(i=0; i= 0x040000 - crv[i].setPen(QColor(Qt::darkBlue)); - crv[i].setStyle(QwtPlotCurve::Lines); - crv[i].setRenderHint(QwtPlotItem::RenderAntialiased); - i++; -#endif - - - crv[i].setPen(QColor(Qt::darkCyan)); - crv[i].setStyle(QwtPlotCurve::Steps); + d_curves[i].setPen(QColor(Qt::darkBlue)); + d_curves[i].setStyle(QwtPlotCurve::Lines); + d_curves[i].setRenderHint(QwtPlotItem::RenderAntialiased); i++; - sym.setStyle(QwtSymbol::XCross); - sym.setPen(QColor(Qt::darkMagenta)); - crv[i].setSymbol(sym); - crv[i].setStyle(QwtPlotCurve::NoCurve); + d_curves[i].setPen(QColor(Qt::darkCyan)); + d_curves[i].setStyle(QwtPlotCurve::Steps); + i++; + + d_curves[i].setSymbol(new QwtSymbol(QwtSymbol::XCross, Qt::NoBrush, + QPen(Qt::darkMagenta), QSize(5, 5) ) ); + d_curves[i].setStyle(QwtPlotCurve::NoCurve); i++; @@ -123,19 +109,14 @@ MainWin::MainWin() // attach data // for(i=0;i= 0x040000 void MainWin::paintEvent(QPaintEvent *event) { QFrame::paintEvent(event); @@ -144,7 +125,6 @@ void MainWin::paintEvent(QPaintEvent *event) painter.setClipRect(contentsRect()); drawContents(&painter); } -#endif // @@ -168,11 +148,9 @@ void MainWin::drawContents(QPainter *painter) xMap.setPaintInterval(r.left(), r.right()); yMap.setPaintInterval(r.top(), r.bottom()); -#if QT_VERSION >= 0x040000 painter->setRenderHint(QPainter::Antialiasing, - crv[i].testRenderHint(QwtPlotItem::RenderAntialiased) ); -#endif - crv[i].draw(painter, xMap, yMap, r); + d_curves[i].testRenderHint(QwtPlotItem::RenderAntialiased) ); + d_curves[i].draw(painter, xMap, yMap, r); shiftDown(r, deltay); } @@ -182,7 +160,7 @@ void MainWin::drawContents(QPainter *painter) // r = contentsRect(); // reset r painter->setFont(QFont("Helvetica", 8)); - + const int alignment = Qt::AlignTop|Qt::AlignHCenter; painter->setPen(Qt::black); @@ -194,22 +172,19 @@ void MainWin::drawContents(QPainter *painter) painter->drawText(0,r.top(),r.width(), painter->fontMetrics().height(), alignment, "Style: Sticks, Symbol: Ellipse"); shiftDown(r, deltay); - + painter->drawText(0 ,r.top(),r.width(), painter->fontMetrics().height(), alignment, "Style: Lines, Symbol: None"); shiftDown(r, deltay); -#if QT_VERSION >= 0x040000 painter->drawText(0 ,r.top(),r.width(), painter->fontMetrics().height(), alignment, "Style: Lines, Symbol: None, Antialiased"); shiftDown(r, deltay); -#endif - - + painter->drawText(0, r.top(),r.width(), painter->fontMetrics().height(), alignment, "Style: Steps, Symbol: None"); shiftDown(r, deltay); - + painter->drawText(0,r.top(),r.width(), painter->fontMetrics().height(), alignment, "Style: NoCurve, Symbol: XCross"); } @@ -220,9 +195,6 @@ int main (int argc, char **argv) MainWin w; -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif w.resize(300,600); w.show(); diff --git a/qwt/examples/curvdemo1/curvdemo1.pro b/qwt/examples/curvdemo1/curvdemo1.pro index 047c735e4..298c97744 100644 --- a/qwt/examples/curvdemo1/curvdemo1.pro +++ b/qwt/examples/curvdemo1/curvdemo1.pro @@ -1,15 +1,15 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = curvdemo1 SOURCES = \ - curvdemo1.cpp + curvdemo1.cpp diff --git a/qwt/examples/curvdemo2/curvdemo2.cpp b/qwt/examples/curvdemo2/curvdemo2.cpp index 80b9d41ff..25e60f44f 100644 --- a/qwt/examples/curvdemo2/curvdemo2.cpp +++ b/qwt/examples/curvdemo2/curvdemo2.cpp @@ -33,27 +33,24 @@ double vval[USize]; // // CONSTRUCT MAIN WINDOW // -MainWin::MainWin(): +MainWin::MainWin(): QFrame() { setFrameStyle(QFrame::Box|QFrame::Raised); setLineWidth(2); setMidLineWidth(3); - + const QColor bgColor(30,30,50); -#if QT_VERSION < 0x040000 - setPaletteBackgroundColor(bgColor); -#else + QPalette p = palette(); p.setColor(backgroundRole(), bgColor); setPalette(p); -#endif - QwtSplineCurveFitter* curveFitter; + QwtSplineCurveFitter* curveFitter; // // curve 1 - // + // int i = 0; xMap[i].setScaleInterval(-1.5, 1.5); yMap[i].setScaleInterval(0.0, 6.28); @@ -65,15 +62,14 @@ MainWin::MainWin(): curveFitter->setSplineSize(150); curve[i].setCurveFitter(curveFitter); - QwtSymbol sym; - sym.setStyle(QwtSymbol::XCross); - sym.setPen(QPen(Qt::yellow,2)); - sym.setSize(7); - - curve[i].setSymbol(sym); + QwtSymbol *symbol = new QwtSymbol(QwtSymbol::XCross); + symbol->setPen(QPen(Qt::yellow,2)); + symbol->setSize(7); + + curve[i].setSymbol(symbol); + + curve[i].setRawSamples(yval,xval,Size); - curve[i].setRawData(yval,xval,Size); - // // curve 2 // @@ -82,15 +78,15 @@ MainWin::MainWin(): yMap[i].setScaleInterval(-3.0, 1.1); curve[i].setPen(QPen(QColor(200,150,50))); curve[i].setStyle(QwtPlotCurve::Sticks); - curve[i].setSymbol(QwtSymbol(QwtSymbol::Ellipse, + curve[i].setSymbol(new QwtSymbol(QwtSymbol::Ellipse, QColor(Qt::blue), QColor(Qt::yellow), QSize(5,5))); - curve[i].setRawData(xval,zval,Size); + curve[i].setRawSamples(xval,zval,Size); + - // // curve 3 - // + // i++; xMap[i].setScaleInterval(-1.1, 3.0); yMap[i].setScaleInterval(-1.1, 3.0); @@ -102,7 +98,7 @@ MainWin::MainWin(): curveFitter->setSplineSize(200); curve[i].setCurveFitter(curveFitter); - curve[i].setRawData(yval,zval,Size); + curve[i].setRawSamples(yval,zval,Size); // @@ -118,18 +114,18 @@ MainWin::MainWin(): curveFitter->setSplineSize(200); curve[i].setCurveFitter(curveFitter); - curve[i].setRawData(uval,vval,USize); + curve[i].setRawSamples(uval,vval,USize); // // initialize values // double base = 2.0 * M_PI / double(USize - 1); - double toggle = 1.0; + double toggle = 1.0; for (i = 0; i < USize; i++) { - uval[i] = toggle * cos( double(i) * base); - vval[i] = toggle * sin( double(i) * base); - + uval[i] = toggle * qCos( double(i) * base); + vval[i] = toggle * qSin( double(i) * base); + if (toggle == 1.0) toggle = 0.5; else @@ -141,10 +137,9 @@ MainWin::MainWin(): // // start timer // - (void)startTimer(250); + (void)startTimer(250); } -#if QT_VERSION >= 0x040000 void MainWin::paintEvent(QPaintEvent *event) { QFrame::paintEvent(event); @@ -153,7 +148,6 @@ void MainWin::paintEvent(QPaintEvent *event) painter.setClipRect(contentsRect()); drawContents(&painter); } -#endif void MainWin::drawContents(QPainter *painter) { @@ -184,27 +178,27 @@ void MainWin::newValues() int i; static double phs = 0.0; double s,c,u; - + for (i=0;i 6.28) phs = 0.0; - + } int main (int argc, char **argv) @@ -213,9 +207,6 @@ int main (int argc, char **argv) MainWin w; -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif w.resize(300,300); w.show(); diff --git a/qwt/examples/curvdemo2/curvdemo2.h b/qwt/examples/curvdemo2/curvdemo2.h index 9a08301f1..f8612c860 100644 --- a/qwt/examples/curvdemo2/curvdemo2.h +++ b/qwt/examples/curvdemo2/curvdemo2.h @@ -2,7 +2,7 @@ #include #include -class MainWin : public QFrame +class MainWin : public QFrame { public: enum { curveCount = 4 }; @@ -13,12 +13,10 @@ public: public: MainWin(); - + protected: virtual void timerEvent(QTimerEvent *t); -#if QT_VERSION >= 0x040000 virtual void paintEvent(QPaintEvent *); -#endif virtual void drawContents(QPainter *); private: diff --git a/qwt/examples/curvdemo2/curvdemo2.pro b/qwt/examples/curvdemo2/curvdemo2.pro index da6a2caa2..2418a7388 100644 --- a/qwt/examples/curvdemo2/curvdemo2.pro +++ b/qwt/examples/curvdemo2/curvdemo2.pro @@ -1,18 +1,18 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = curvdemo2 HEADERS = \ - curvdemo2.h + curvdemo2.h SOURCES = \ - curvdemo2.cpp + curvdemo2.cpp diff --git a/qwt/examples/data_plot/data_plot.cpp b/qwt/examples/data_plot/data_plot.cpp deleted file mode 100644 index adc9d5983..000000000 --- a/qwt/examples/data_plot/data_plot.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "data_plot.h" - -// -// Initialize main window -// -DataPlot::DataPlot(QWidget *parent): - QwtPlot(parent), - d_interval(0), - d_timerId(-1) -{ - // Disable polygon clipping - QwtPainter::setDeviceClipping(false); - - // We don't need the cache here - canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); - canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false); - -#if QT_VERSION >= 0x040000 -#ifdef Q_WS_X11 - /* - Qt::WA_PaintOnScreen is only supported for X11, but leads - to substantial bugs with Qt 4.2.x/Windows - */ - canvas()->setAttribute(Qt::WA_PaintOnScreen, true); -#endif -#endif - - alignScales(); - - // Initialize data - for (int i = 0; i< PLOT_SIZE; i++) - { - d_x[i] = 0.5 * i; // time axis - d_y[i] = 0; - d_z[i] = 0; - } - - // Assign a title - setTitle("A Test for High Refresh Rates"); - insertLegend(new QwtLegend(), QwtPlot::BottomLegend); - - // Insert new curves - QwtPlotCurve *cRight = new QwtPlotCurve("Data Moving Right"); - cRight->attach(this); - - QwtPlotCurve *cLeft = new QwtPlotCurve("Data Moving Left"); - cLeft->attach(this); - - // Set curve styles - cRight->setPen(QPen(Qt::red)); - cLeft->setPen(QPen(Qt::blue)); - - // Attach (don't copy) data. Both curves use the same x array. - cRight->setRawData(d_x, d_y, PLOT_SIZE); - cLeft->setRawData(d_x, d_z, PLOT_SIZE); - -#if 0 - // Insert zero line at y = 0 - QwtPlotMarker *mY = new QwtPlotMarker(); - mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); - mY->setLineStyle(QwtPlotMarker::HLine); - mY->setYValue(0.0); - mY->attach(this); -#endif - - // Axis - setAxisTitle(QwtPlot::xBottom, "Time/seconds"); - setAxisScale(QwtPlot::xBottom, 0, 100); - - setAxisTitle(QwtPlot::yLeft, "Values"); - setAxisScale(QwtPlot::yLeft, -1.5, 1.5); - - setTimerInterval(0.0); -} - -// -// Set a plain canvas frame and align the scales to it -// -void DataPlot::alignScales() -{ - // The code below shows how to align the scales to - // the canvas frame, but is also a good example demonstrating - // why the spreaded API needs polishing. - - canvas()->setFrameStyle(QFrame::Box | QFrame::Plain ); - canvas()->setLineWidth(1); - - for ( int i = 0; i < QwtPlot::axisCnt; i++ ) - { - QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(i); - if ( scaleWidget ) - scaleWidget->setMargin(0); - - QwtScaleDraw *scaleDraw = (QwtScaleDraw *)axisScaleDraw(i); - if ( scaleDraw ) - scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false); - } -} - -void DataPlot::setTimerInterval(double ms) -{ - d_interval = qRound(ms); - - if ( d_timerId >= 0 ) - { - killTimer(d_timerId); - d_timerId = -1; - } - if (d_interval >= 0 ) - d_timerId = startTimer(d_interval); -} - -// Generate new values -void DataPlot::timerEvent(QTimerEvent *) -{ - static double phase = 0.0; - - if (phase > (M_PI - 0.0001)) - phase = 0.0; - - // y moves from left to right: - // Shift y array right and assign new value to y[0]. - - for ( int i = PLOT_SIZE - 1; i > 0; i-- ) - d_y[i] = d_y[i-1]; - d_y[0] = sin(phase) * (-1.0 + 2.0 * double(rand()) / double(RAND_MAX)); - - for ( int j = 0; j < PLOT_SIZE - 1; j++ ) - d_z[j] = d_z[j+1]; - - d_z[PLOT_SIZE - 1] = 0.8 - (2.0 * phase/M_PI) + 0.4 * - double(rand()) / double(RAND_MAX); - - // update the display - replot(); - - phase += M_PI * 0.02; -} diff --git a/qwt/examples/data_plot/data_plot.h b/qwt/examples/data_plot/data_plot.h deleted file mode 100644 index 058966ac0..000000000 --- a/qwt/examples/data_plot/data_plot.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _DATA_PLOT_H -#define _DATA_PLOT_H 1 - -#include - -const int PLOT_SIZE = 201; // 0 to 200 - -class DataPlot : public QwtPlot -{ - Q_OBJECT - -public: - DataPlot(QWidget* = NULL); - -public slots: - void setTimerInterval(double interval); - -protected: - virtual void timerEvent(QTimerEvent *e); - -private: - void alignScales(); - - double d_x[PLOT_SIZE]; - double d_y[PLOT_SIZE]; - double d_z[PLOT_SIZE]; - - int d_interval; // timer in ms - int d_timerId; -}; - -#endif diff --git a/qwt/examples/data_plot/main.cpp b/qwt/examples/data_plot/main.cpp deleted file mode 100644 index 04e56f45a..000000000 --- a/qwt/examples/data_plot/main.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "data_plot.h" - -class MainWindow: public QMainWindow -{ -public: - MainWindow() - { - QToolBar *toolBar = new QToolBar(this); - toolBar->setFixedHeight(80); - -#if QT_VERSION < 0x040000 - setDockEnabled(TornOff, true); - setRightJustification(true); -#else - toolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); -#endif - QWidget *hBox = new QWidget(toolBar); - QLabel *label = new QLabel("Timer Interval", hBox); - QwtCounter *counter = new QwtCounter(hBox); - counter->setRange(-1.0, 100.0, 1.0); - - QHBoxLayout *layout = new QHBoxLayout(hBox); - layout->addWidget(label); - layout->addWidget(counter); - layout->addWidget(new QWidget(hBox), 10); // spacer); - -#if QT_VERSION >= 0x040000 - toolBar->addWidget(hBox); -#endif - addToolBar(toolBar); - - - DataPlot *plot = new DataPlot(this); - setCentralWidget(plot); - - connect(counter, SIGNAL(valueChanged(double)), - plot, SLOT(setTimerInterval(double)) ); - - counter->setValue(20.0); - } -}; - -int main(int argc, char **argv) -{ - QApplication a(argc, argv); - - MainWindow mainWindow; -#if QT_VERSION < 0x040000 - a.setMainWidget(&mainWindow); -#endif - - mainWindow.resize(600,400); - mainWindow.show(); - - return a.exec(); -} diff --git a/qwt/examples/dials/attitude_indicator.cpp b/qwt/examples/dials/attitude_indicator.cpp index 910ed09de..10b26ca69 100644 --- a/qwt/examples/dials/attitude_indicator.cpp +++ b/qwt/examples/dials/attitude_indicator.cpp @@ -1,57 +1,38 @@ +#include "attitude_indicator.h" +#include #include #include -#include -#include -#include "attitude_indicator.h" +#include AttitudeIndicatorNeedle::AttitudeIndicatorNeedle(const QColor &c) { QPalette palette; for ( int i = 0; i < QPalette::NColorGroups; i++ ) { -#if QT_VERSION < 0x040000 - palette.setColor((QPalette::ColorGroup)i, - QColorGroup::Text, c); -#else palette.setColor((QPalette::ColorGroup)i, QPalette::Text, c); -#endif } setPalette(palette); } -void AttitudeIndicatorNeedle::draw(QPainter *painter, const QPoint ¢er, - int length, double direction, QPalette::ColorGroup cg) const +void AttitudeIndicatorNeedle::drawNeedle(QPainter *painter, + double length, QPalette::ColorGroup colorGroup) const { - direction *= M_PI / 180.0; - int triangleSize = qRound(length * 0.1); + double triangleSize = length * 0.1; + double pos = length - 2.0; - painter->save(); + QPainterPath path; + path.moveTo( pos, 0 ); + path.lineTo( pos - 2 * triangleSize, triangleSize ); + path.lineTo( pos - 2 * triangleSize, -triangleSize ); + path.closeSubpath(); - const QPoint p0(QPoint(center.x() + 1, center.y() + 1)); + painter->setBrush( palette().brush(colorGroup, QPalette::Text ) ); + painter->drawPath( path ); - const QPoint p1 = qwtPolar2Pos(p0, - length - 2 * triangleSize - 2, direction); - - QwtPolygon pa(3); - pa.setPoint(0, qwtPolar2Pos(p1, 2 * triangleSize, direction)); - pa.setPoint(1, qwtPolar2Pos(p1, triangleSize, direction + M_PI_2)); - pa.setPoint(2, qwtPolar2Pos(p1, triangleSize, direction - M_PI_2)); - - const QColor color = -#if QT_VERSION < 0x040000 - palette().color(cg, QColorGroup::Text); -#else - palette().color(cg, QPalette::Text); -#endif - painter->setBrush(color); - painter->drawPolygon(pa); - - painter->setPen(QPen(color, 3)); - painter->drawLine(qwtPolar2Pos(p0, length - 2, direction + M_PI_2), - qwtPolar2Pos(p0, length - 2, direction - M_PI_2)); - - painter->restore(); + double l = length - 2; + painter->setPen( QPen(palette().color( colorGroup, QPalette::Text ), 3) ); + painter->drawLine( 0, -l, 0, l ); } AttitudeIndicator::AttitudeIndicator( @@ -63,16 +44,10 @@ AttitudeIndicator::AttitudeIndicator( setWrapping(true); setOrigin(270.0); - setScaleOptions(ScaleTicks); + setScaleComponents( QwtAbstractScaleDraw::Ticks ); setScale(0, 0, 30.0); - const QColor color = -#if QT_VERSION < 0x040000 - colorGroup().text(); -#else - palette().color(QPalette::Text); -#endif - + const QColor color = palette().color(QPalette::Text); setNeedle(new AttitudeIndicatorNeedle(color)); } @@ -90,34 +65,35 @@ void AttitudeIndicator::setGradient(double gradient) } } -void AttitudeIndicator::drawScale(QPainter *painter, const QPoint ¢er, - int radius, double origin, double minArc, double maxArc) const +void AttitudeIndicator::drawScale(QPainter *painter, const QPointF ¢er, + double radius, double origin, double minArc, double maxArc) const { - double dir = (360.0 - origin) * M_PI / 180.0; // counter clockwise, radian + // counter clockwise, radian - int offset = 4; - - const QPoint p0 = qwtPolar2Pos(center, offset, dir + M_PI); + const double dir = (360.0 - origin) * M_PI / 180.0; + const double offset = 4.0; - const int w = contentsRect().width(); + const QPointF p0 = qwtPolar2Pos( center, offset, dir + M_PI ); - QwtPolygon pa(4); - pa.setPoint(0, qwtPolar2Pos(p0, w, dir - M_PI_2)); - pa.setPoint(1, qwtPolar2Pos(pa.point(0), 2 * w, dir + M_PI_2)); - pa.setPoint(2, qwtPolar2Pos(pa.point(1), w, dir)); - pa.setPoint(3, qwtPolar2Pos(pa.point(2), 2 * w, dir - M_PI_2)); + const double w = innerRect().width(); + + QPainterPath path; + path.moveTo( qwtPolar2Pos( p0, w, dir - M_PI_2 ) ); + path.lineTo( qwtPolar2Pos( path.currentPosition(), 2 * w, dir + M_PI_2 ) ); + path.lineTo( qwtPolar2Pos( path.currentPosition(), w, dir ) ); + path.lineTo( qwtPolar2Pos( path.currentPosition(), w, dir - M_PI_2 ) ); painter->save(); - painter->setClipRegion(pa); // swallow 180 - 360 degrees + painter->setClipPath( path ); // swallow 180 - 360 degrees - QwtDial::drawScale(painter, center, radius, origin, - minArc, maxArc); + QwtDial::drawScale(painter, + center, radius, origin, minArc, maxArc); painter->restore(); } void AttitudeIndicator::drawScaleContents(QPainter *painter, - const QPoint &, int) const + const QPointF &, double) const { int dir = 360 - qRound(origin() - value()); // counter clockwise int arc = 90 + qRound(gradient() * 90); @@ -126,8 +102,8 @@ void AttitudeIndicator::drawScaleContents(QPainter *painter, painter->save(); painter->setBrush(skyColor); - painter->drawChord(scaleContentsRect(), - (dir - arc) * 16, 2 * arc * 16 ); + painter->drawChord(scaleInnerRect(), + (dir - arc) * 16, 2 * arc * 16 ); painter->restore(); } @@ -138,7 +114,7 @@ void AttitudeIndicator::keyPressEvent(QKeyEvent *e) case Qt::Key_Plus: setGradient(gradient() + 0.05); break; - + case Qt::Key_Minus: setGradient(gradient() - 0.05); break; diff --git a/qwt/examples/dials/attitude_indicator.h b/qwt/examples/dials/attitude_indicator.h index 00c4b433e..57aa5c4c4 100644 --- a/qwt/examples/dials/attitude_indicator.h +++ b/qwt/examples/dials/attitude_indicator.h @@ -6,8 +6,9 @@ class AttitudeIndicatorNeedle: public QwtDialNeedle public: AttitudeIndicatorNeedle(const QColor &); - virtual void draw(QPainter *, const QPoint &, int length, - double direction, QPalette::ColorGroup) const; +protected: + virtual void drawNeedle(QPainter *, + double length, QPalette::ColorGroup) const; }; class AttitudeIndicator: public QwtDial @@ -20,18 +21,18 @@ public: double angle() const { return value(); } double gradient() const { return d_gradient; } -public slots: +public Q_SLOTS: void setGradient(double); void setAngle(double angle) { setValue(angle); } protected: virtual void keyPressEvent(QKeyEvent *); - virtual void drawScale(QPainter *, const QPoint ¢er, - int radius, double origin, double arcMin, double arcMax) const; + virtual void drawScale(QPainter *, const QPointF ¢er, + double radius, double origin, double arcMin, double arcMax) const; virtual void drawScaleContents(QPainter *painter, - const QPoint ¢er, int radius) const; + const QPointF ¢er, double radius) const; private: double d_gradient; diff --git a/qwt/examples/dials/cockpit_grid.cpp b/qwt/examples/dials/cockpit_grid.cpp index eb4dc224d..324ef48e1 100644 --- a/qwt/examples/dials/cockpit_grid.cpp +++ b/qwt/examples/dials/cockpit_grid.cpp @@ -5,18 +5,10 @@ #include "speedo_meter.h" #include "cockpit_grid.h" -#if QT_VERSION < 0x040000 -typedef QColorGroup Palette; -#else -typedef QPalette Palette; -#endif - CockpitGrid::CockpitGrid(QWidget *parent): QFrame(parent) { -#if QT_VERSION >= 0x040100 setAutoFillBackground(true); -#endif setPalette(colorTheme(QColor(Qt::darkGray).dark(150))); @@ -31,13 +23,8 @@ CockpitGrid::CockpitGrid(QWidget *parent): layout->addWidget(dial, 0, i); } -#if QT_VERSION < 0x040000 - for ( i = 0; i < layout->numCols(); i++ ) - layout->setColStretch(i, 1); -#else for ( i = 0; i < layout->columnCount(); i++ ) layout->setColumnStretch(i, 1); -#endif } QwtDial *CockpitGrid::createDial(int pos) @@ -61,7 +48,7 @@ QwtDial *CockpitGrid::createDial(int pos) handColor = Qt::gray; width = 5; } - + QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle( QwtDialSimpleNeedle::Arrow, true, handColor, knobColor); hand->setWidth(width); @@ -70,7 +57,7 @@ QwtDial *CockpitGrid::createDial(int pos) } QTimer *timer = new QTimer(d_clock); - timer->connect(timer, SIGNAL(timeout()), + timer->connect(timer, SIGNAL(timeout()), d_clock, SLOT(setCurrentTime())); timer->start(1000); @@ -84,7 +71,7 @@ QwtDial *CockpitGrid::createDial(int pos) d_speedo->setScale(-1, 2, 20); QTimer *timer = new QTimer(d_speedo); - timer->connect(timer, SIGNAL(timeout()), + timer->connect(timer, SIGNAL(timeout()), this, SLOT(changeSpeed())); timer->start(50); @@ -96,12 +83,12 @@ QwtDial *CockpitGrid::createDial(int pos) d_ai = new AttitudeIndicator(this); QTimer *gradientTimer = new QTimer(d_ai); - gradientTimer->connect(gradientTimer, SIGNAL(timeout()), + gradientTimer->connect(gradientTimer, SIGNAL(timeout()), this, SLOT(changeGradient())); gradientTimer->start(100); QTimer *angleTimer = new QTimer(d_ai); - angleTimer->connect(angleTimer, SIGNAL(timeout()), + angleTimer->connect(angleTimer, SIGNAL(timeout()), this, SLOT(changeAngle())); angleTimer->start(100); @@ -136,13 +123,13 @@ QPalette CockpitGrid::colorTheme(const QColor &base) const { QPalette::ColorGroup cg = (QPalette::ColorGroup)i; - palette.setColor(cg, Palette::Base, base); - palette.setColor(cg, Palette::Background, background); - palette.setColor(cg, Palette::Mid, mid); - palette.setColor(cg, Palette::Light, light); - palette.setColor(cg, Palette::Dark, dark); - palette.setColor(cg, Palette::Text, text); - palette.setColor(cg, Palette::Foreground, foreground); + palette.setColor(cg, QPalette::Base, base); + palette.setColor(cg, QPalette::Window, background); + palette.setColor(cg, QPalette::Mid, mid); + palette.setColor(cg, QPalette::Light, light); + palette.setColor(cg, QPalette::Dark, dark); + palette.setColor(cg, QPalette::Text, text); + palette.setColor(cg, QPalette::WindowText, foreground); } return palette; @@ -154,7 +141,7 @@ void CockpitGrid::changeSpeed() double speed = d_speedo->value(); - if ( (speed < 40.0 && offset < 0.0 ) || + if ( (speed < 40.0 && offset < 0.0 ) || (speed > 160.0 && offset > 0.0) ) { offset = -offset; diff --git a/qwt/examples/dials/cockpit_grid.h b/qwt/examples/dials/cockpit_grid.h index 58101c306..de088261b 100644 --- a/qwt/examples/dials/cockpit_grid.h +++ b/qwt/examples/dials/cockpit_grid.h @@ -13,7 +13,7 @@ class CockpitGrid: public QFrame public: CockpitGrid(QWidget *parent = NULL); -private slots: +private Q_SLOTS: void changeSpeed(); void changeGradient(); void changeAngle(); diff --git a/qwt/examples/dials/compass_grid.cpp b/qwt/examples/dials/compass_grid.cpp index 0d924580e..1344818f6 100644 --- a/qwt/examples/dials/compass_grid.cpp +++ b/qwt/examples/dials/compass_grid.cpp @@ -4,26 +4,14 @@ #include #include "compass_grid.h" -#if QT_VERSION < 0x040000 -typedef QColorGroup Palette; -#else -typedef QPalette Palette; -#endif - CompassGrid::CompassGrid(QWidget *parent): QFrame(parent) { -#if QT_VERSION < 0x040000 - setBackgroundColor(Qt::gray); -#else QPalette p = palette(); p.setColor(backgroundRole(), Qt::gray); setPalette(p); -#endif -#if QT_VERSION >= 0x040100 setAutoFillBackground(true); -#endif QGridLayout *layout = new QGridLayout(this); layout->setSpacing(5); @@ -36,31 +24,22 @@ CompassGrid::CompassGrid(QWidget *parent): layout->addWidget(compass, i / 3, i % 3); } -#if QT_VERSION < 0x040000 - for ( i = 0; i < layout->numCols(); i++ ) - layout->setColStretch(i, 1); -#else for ( i = 0; i < layout->columnCount(); i++ ) layout->setColumnStretch(i, 1); -#endif } QwtCompass *CompassGrid::createCompass(int pos) { int c; - Palette colorGroup; - for ( c = 0; c < Palette::NColorRoles; c++ ) - colorGroup.setColor((Palette::ColorRole)c, QColor()); + QPalette colorGroup; + for ( c = 0; c < QPalette::NColorRoles; c++ ) + colorGroup.setColor((QPalette::ColorRole)c, QColor()); -#if QT_VERSION < 0x040000 - colorGroup.setColor(Palette::Base, backgroundColor().light(120)); -#else - colorGroup.setColor(Palette::Base, + colorGroup.setColor(QPalette::Base, palette().color(backgroundRole()).light(120)); -#endif - colorGroup.setColor(Palette::Foreground, - colorGroup.color(Palette::Base)); + colorGroup.setColor(QPalette::WindowText, + colorGroup.color(QPalette::Base)); QwtCompass *compass = new QwtCompass(this); compass->setLineWidth(4); @@ -111,12 +90,13 @@ QwtCompass *CompassGrid::createCompass(int pos) a ticks for each degree. */ - colorGroup.setColor(Palette::Base, Qt::darkBlue); - colorGroup.setColor(Palette::Foreground, + colorGroup.setColor(QPalette::Base, Qt::darkBlue); + colorGroup.setColor(QPalette::WindowText, QColor(Qt::darkBlue).dark(120)); - colorGroup.setColor(Palette::Text, Qt::white); + colorGroup.setColor(QPalette::Text, Qt::white); - compass->setScaleOptions(QwtDial::ScaleTicks | QwtDial::ScaleLabel); + compass->setScaleComponents( + QwtAbstractScaleDraw::Ticks | QwtAbstractScaleDraw::Labels); compass->setScaleTicks(1, 1, 3); compass->setScale(36, 5, 0); @@ -132,18 +112,14 @@ QwtCompass *CompassGrid::createCompass(int pos) A compass without a frame, showing numbers as tick labels. The origin is at 220.0 */ -#if QT_VERSION < 0x040000 - colorGroup.setColor(Palette::Base, backgroundColor()); -#else - colorGroup.setColor(Palette::Base, + colorGroup.setColor(QPalette::Base, palette().color(backgroundRole())); -#endif - colorGroup.setColor(Palette::Foreground, Qt::blue); - + colorGroup.setColor(QPalette::WindowText, Qt::blue); + compass->setLineWidth(0); - compass->setScaleOptions(QwtDial::ScaleBackbone | - QwtDial::ScaleTicks | QwtDial::ScaleLabel); + compass->setScaleComponents( QwtAbstractScaleDraw::Backbone | + QwtAbstractScaleDraw::Ticks | QwtAbstractScaleDraw::Labels ); compass->setScaleTicks(0, 0, 3); QMap map; @@ -157,7 +133,7 @@ QwtCompass *CompassGrid::createCompass(int pos) compass->setScale(36, 5, 0); compass->setNeedle(new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Ray, - false, Qt::white)); + true, Qt::white)); compass->setOrigin(220.0); compass->setValue(20.0); break; @@ -167,7 +143,8 @@ QwtCompass *CompassGrid::createCompass(int pos) /* A compass showing another needle */ - compass->setScaleOptions(QwtDial::ScaleTicks | QwtDial::ScaleLabel); + compass->setScaleComponents( + QwtAbstractScaleDraw::Ticks | QwtAbstractScaleDraw::Labels ); compass->setScaleTicks(0, 0, 3); compass->setNeedle(new QwtCompassMagnetNeedle( @@ -180,7 +157,7 @@ QwtCompass *CompassGrid::createCompass(int pos) /* A compass with a yellow on black ray */ - colorGroup.setColor(Palette::Foreground, Qt::black); + colorGroup.setColor(QPalette::WindowText, Qt::black); compass->setNeedle(new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Ray, false, Qt::yellow)); @@ -190,16 +167,16 @@ QwtCompass *CompassGrid::createCompass(int pos) } QPalette newPalette = compass->palette(); - for ( c = 0; c < Palette::NColorRoles; c++ ) + for ( c = 0; c < QPalette::NColorRoles; c++ ) { - if ( colorGroup.color((Palette::ColorRole)c).isValid() ) + if ( colorGroup.color((QPalette::ColorRole)c).isValid() ) { for ( int cg = 0; cg < QPalette::NColorGroups; cg++ ) - { + { newPalette.setColor( - (QPalette::ColorGroup)cg, - (Palette::ColorRole)c, - colorGroup.color((Palette::ColorRole)c)); + (QPalette::ColorGroup)cg, + (QPalette::ColorRole)c, + colorGroup.color((QPalette::ColorRole)c)); } } } @@ -208,16 +185,16 @@ QwtCompass *CompassGrid::createCompass(int pos) { QPalette::ColorGroup cg = (QPalette::ColorGroup)i; - const QColor light = - newPalette.color(cg, Palette::Base).light(170); - const QColor dark = newPalette.color(cg, Palette::Base).dark(170); + const QColor light = + newPalette.color(cg, QPalette::Base).light(170); + const QColor dark = newPalette.color(cg, QPalette::Base).dark(170); const QColor mid = compass->frameShadow() == QwtDial::Raised - ? newPalette.color(cg, Palette::Base).dark(110) - : newPalette.color(cg, Palette::Base).light(110); - - newPalette.setColor(cg, Palette::Dark, dark); - newPalette.setColor(cg, Palette::Mid, mid); - newPalette.setColor(cg, Palette::Light, light); + ? newPalette.color(cg, QPalette::Base).dark(110) + : newPalette.color(cg, QPalette::Base).light(110); + + newPalette.setColor(cg, QPalette::Dark, dark); + newPalette.setColor(cg, QPalette::Mid, mid); + newPalette.setColor(cg, QPalette::Light, light); } compass->setPalette(newPalette); diff --git a/qwt/examples/dials/dials.cpp b/qwt/examples/dials/dials.cpp index ce0c4db61..40ef20853 100644 --- a/qwt/examples/dials/dials.cpp +++ b/qwt/examples/dials/dials.cpp @@ -14,17 +14,10 @@ int main (int argc, char **argv) QApplication a(argc, argv); QTabWidget tabWidget; -#if QT_VERSION < 0x040000 - tabWidget.addTab(new CompassGrid(&tabWidget), "Compass"); - tabWidget.addTab(new CockpitGrid(&tabWidget), "Cockpit"); - a.setMainWidget(&tabWidget); -#else tabWidget.addTab(new CompassGrid, "Compass"); tabWidget.addTab(new CockpitGrid, "Cockpit"); -#endif tabWidget.show(); return a.exec(); } - diff --git a/qwt/examples/dials/dials.pro b/qwt/examples/dials/dials.pro index 02c8a7374..1d4a6a43b 100644 --- a/qwt/examples/dials/dials.pro +++ b/qwt/examples/dials/dials.pro @@ -1,13 +1,13 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = dials @@ -23,4 +23,3 @@ SOURCES = \ cockpit_grid.cpp \ compass_grid.cpp \ dials.cpp - diff --git a/qwt/examples/dials/speedo_meter.cpp b/qwt/examples/dials/speedo_meter.cpp index 358f65f79..66f8785b1 100644 --- a/qwt/examples/dials/speedo_meter.cpp +++ b/qwt/examples/dials/speedo_meter.cpp @@ -14,11 +14,12 @@ SpeedoMeter::SpeedoMeter(QWidget *parent): scaleDraw()->setSpacing(8); QwtDialSimpleNeedle *needle = new QwtDialSimpleNeedle( - QwtDialSimpleNeedle::Arrow, true, Qt::red, + QwtDialSimpleNeedle::Arrow, true, Qt::red, QColor(Qt::gray).light(130)); setNeedle(needle); - setScaleOptions(ScaleTicks | ScaleLabel); + setScaleComponents( + QwtAbstractScaleDraw::Ticks | QwtAbstractScaleDraw::Labels); setScaleTicks(0, 4, 8); } @@ -34,17 +35,12 @@ QString SpeedoMeter::label() const } void SpeedoMeter::drawScaleContents(QPainter *painter, - const QPoint ¢er, int radius) const + const QPointF ¢er, double radius) const { - QRect rect(0, 0, 2 * radius, 2 * radius - 10); + QRectF rect( 0.0, 0.0, 2.0 * radius, 2.0 * radius - 10.0); rect.moveCenter(center); - const QColor color = -#if QT_VERSION < 0x040000 - colorGroup().text(); -#else - palette().color(QPalette::Text); -#endif + const QColor color = palette().color(QPalette::Text); painter->setPen(color); const int flags = Qt::AlignBottom | Qt::AlignHCenter; diff --git a/qwt/examples/dials/speedo_meter.h b/qwt/examples/dials/speedo_meter.h index d779cd151..24653a493 100644 --- a/qwt/examples/dials/speedo_meter.h +++ b/qwt/examples/dials/speedo_meter.h @@ -11,7 +11,7 @@ public: protected: virtual void drawScaleContents(QPainter *painter, - const QPoint ¢er, int radius) const; + const QPointF ¢er, double radius) const; private: QString d_label; diff --git a/qwt/examples/event_filter/canvaspicker.cpp b/qwt/examples/event_filter/canvaspicker.cpp index 1fd3a8c87..bab21714c 100644 --- a/qwt/examples/event_filter/canvaspicker.cpp +++ b/qwt/examples/event_filter/canvaspicker.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "canvaspicker.h" CanvasPicker::CanvasPicker(QwtPlot *plot): @@ -21,16 +22,9 @@ CanvasPicker::CanvasPicker(QwtPlot *plot): // We want the focus, but no focus rect. The // selected point will be highlighted instead. -#if QT_VERSION >= 0x040000 canvas->setFocusPolicy(Qt::StrongFocus); #ifndef QT_NO_CURSOR canvas->setCursor(Qt::PointingHandCursor); -#endif -#else - canvas->setFocusPolicy(QWidget::StrongFocus); -#ifndef QT_NO_CURSOR - canvas->setCursor(Qt::pointingHandCursor); -#endif #endif canvas->setFocusIndicator(QwtPlotCanvas::ItemFocusIndicator); canvas->setFocus(); @@ -43,11 +37,7 @@ CanvasPicker::CanvasPicker(QwtPlot *plot): "- Left, ´-´:\tSelect next point\n" "- Right, ´+´:\tSelect previous point\n" "- 7, 8, 9, 4, 6, 1, 2, 3:\tMove selected point"; -#if QT_VERSION >= 0x040000 canvas->setWhatsThis(text); -#else - QWhatsThis::add(canvas, text); -#endif shiftCurveCursor(true); } @@ -75,19 +65,19 @@ bool CanvasPicker::eventFilter(QObject *object, QEvent *e) showCursor(false); case QEvent::Paint: - { + { QApplication::postEvent(this, new QEvent(QEvent::User)); break; } case QEvent::MouseButtonPress: { select(((QMouseEvent *)e)->pos()); - return true; + return true; } case QEvent::MouseMove: { move(((QMouseEvent *)e)->pos()); - return true; + return true; } case QEvent::KeyPress: { @@ -97,7 +87,7 @@ bool CanvasPicker::eventFilter(QObject *object, QEvent *e) case Qt::Key_Up: shiftCurveCursor(true); return true; - + case Qt::Key_Down: shiftCurveCursor(false); return true; @@ -120,20 +110,20 @@ bool CanvasPicker::eventFilter(QObject *object, QEvent *e) // The following keys represent a direction, they are // organized on the keyboard. - - case Qt::Key_1: + + case Qt::Key_1: moveBy(-delta, delta); break; case Qt::Key_2: moveBy(0, delta); break; - case Qt::Key_3: + case Qt::Key_3: moveBy(delta, delta); break; case Qt::Key_4: moveBy(-delta, 0); break; - case Qt::Key_6: + case Qt::Key_6: moveBy(delta, 0); break; case Qt::Key_7: @@ -179,7 +169,7 @@ void CanvasPicker::select(const QPoint &pos) curve = c; index = idx; dist = d; - } + } } } @@ -204,12 +194,15 @@ void CanvasPicker::moveBy(int dx, int dy) if ( !d_selectedCurve ) return; - const int x = plot()->transform(d_selectedCurve->xAxis(), - d_selectedCurve->x(d_selectedPoint)) + dx; - const int y = plot()->transform(d_selectedCurve->yAxis(), - d_selectedCurve->y(d_selectedPoint)) + dy; + const QPointF sample = + d_selectedCurve->sample(d_selectedPoint); - move(QPoint(x, y)); + const double x = plot()->transform( + d_selectedCurve->xAxis(), sample.x()); + const double y = plot()->transform( + d_selectedCurve->yAxis(), sample.y()); + + move( QPoint(qRound(x + dx), qRound(y + dy)) ); } // Move the selected point @@ -218,25 +211,35 @@ void CanvasPicker::move(const QPoint &pos) if ( !d_selectedCurve ) return; - QwtArray xData(d_selectedCurve->dataSize()); - QwtArray yData(d_selectedCurve->dataSize()); + QVector xData(d_selectedCurve->dataSize()); + QVector yData(d_selectedCurve->dataSize()); - for ( int i = 0; i < d_selectedCurve->dataSize(); i++ ) + for ( int i = 0; i < (int)d_selectedCurve->dataSize(); i++ ) { if ( i == d_selectedPoint ) { - xData[i] = plot()->invTransform(d_selectedCurve->xAxis(), pos.x());; - yData[i] = plot()->invTransform(d_selectedCurve->yAxis(), pos.y());; + xData[i] = plot()->invTransform( + d_selectedCurve->xAxis(), pos.x()); + yData[i] = plot()->invTransform( + d_selectedCurve->yAxis(), pos.y()); } else { - xData[i] = d_selectedCurve->x(i); - yData[i] = d_selectedCurve->y(i); + const QPointF sample = d_selectedCurve->sample(i); + xData[i] = sample.x(); + yData[i] = sample.y(); } } - d_selectedCurve->setData(xData, yData); + d_selectedCurve->setSamples(xData, yData); + /* + Enable QwtPlotCanvas::ImmediatePaint, so that the canvas has been + updated before we paint the cursor on it. + */ + plot()->canvas()->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, true); plot()->replot(); + plot()->canvas()->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false); + showCursor(true); } @@ -246,24 +249,20 @@ void CanvasPicker::showCursor(bool showIt) if ( !d_selectedCurve ) return; - const QwtSymbol symbol = d_selectedCurve->symbol(); + QwtSymbol *symbol = const_cast( d_selectedCurve->symbol() ); - QwtSymbol newSymbol = symbol; + const QBrush brush = symbol->brush(); if ( showIt ) - newSymbol.setBrush(symbol.brush().color().dark(150)); + symbol->setBrush(symbol->brush().color().dark(180)); - const bool doReplot = plot()->autoReplot(); + QwtPlotDirectPainter directPainter; + directPainter.drawSeries(d_selectedCurve, d_selectedPoint, d_selectedPoint); - plot()->setAutoReplot(false); - d_selectedCurve->setSymbol(newSymbol); - - d_selectedCurve->draw(d_selectedPoint, d_selectedPoint); - - d_selectedCurve->setSymbol(symbol); - plot()->setAutoReplot(doReplot); + if ( showIt ) + symbol->setBrush(brush); // reset brush } -// Select the next/previous curve +// Select the next/previous curve void CanvasPicker::shiftCurveCursor(bool up) { QwtPlotItemIterator it; @@ -304,7 +303,7 @@ void CanvasPicker::shiftCurveCursor(bool up) --it; } } - + showCursor(false); d_selectedPoint = 0; d_selectedCurve = (QwtPlotCurve *)*it; diff --git a/qwt/examples/event_filter/colorbar.cpp b/qwt/examples/event_filter/colorbar.cpp index ab4fbecce..8d24ddd3c 100644 --- a/qwt/examples/event_filter/colorbar.cpp +++ b/qwt/examples/event_filter/colorbar.cpp @@ -11,12 +11,8 @@ ColorBar::ColorBar(Qt::Orientation o, QWidget *parent): d_dark(Qt::black) { #ifndef QT_NO_CURSOR -#if QT_VERSION < 0x040000 - setCursor(Qt::pointingHandCursor); -#else setCursor(Qt::PointingHandCursor); #endif -#endif } void ColorBar::setOrientation(Qt::Orientation o) @@ -52,13 +48,9 @@ void ColorBar::mousePressEvent(QMouseEvent *e) // happened const QPixmap pm = QPixmap::grabWidget(this); -#if QT_VERSION < 0x040000 - const QRgb rgb = pm.convertToImage().pixel(e->x(), e->y()); -#else const QRgb rgb = pm.toImage().pixel(e->x(), e->y()); -#endif - - emit selected(QColor(rgb)); + + Q_EMIT selected(QColor(rgb)); e->accept(); } } @@ -74,13 +66,8 @@ void ColorBar::drawColorBar(QPainter *painter, const QRect &rect) const int h1, s1, v1; int h2, s2, v2; -#if QT_VERSION < 0x040000 - d_light.hsv(&h1, &s1, &v1); - d_dark.hsv(&h2, &s2, &v2); -#else d_light.getHsv(&h1, &s1, &v1); d_dark.getHsv(&h2, &s2, &v2); -#endif painter->save(); painter->setClipRect(rect); @@ -89,7 +76,7 @@ void ColorBar::drawColorBar(QPainter *painter, const QRect &rect) const painter->fillRect(rect, d_dark); const int sectionSize = 2; - + int numIntervalls; if ( d_orientation == Qt::Horizontal ) numIntervalls = rect.width() / sectionSize; @@ -122,4 +109,3 @@ void ColorBar::drawColorBar(QPainter *painter, const QRect &rect) const painter->restore(); } - diff --git a/qwt/examples/event_filter/colorbar.h b/qwt/examples/event_filter/colorbar.h index 30907874c..cafb2040c 100644 --- a/qwt/examples/event_filter/colorbar.h +++ b/qwt/examples/event_filter/colorbar.h @@ -5,7 +5,7 @@ class ColorBar: public QWidget Q_OBJECT public: - ColorBar(Qt::Orientation = Qt::Horizontal, + ColorBar(Qt::Orientation = Qt::Horizontal, QWidget * = NULL); virtual void setOrientation(Qt::Orientation o); @@ -18,7 +18,7 @@ public: QColor light() const { return d_light; } QColor dark() const { return d_dark; } -signals: +Q_SIGNALS: void selected(const QColor &); protected: diff --git a/qwt/examples/event_filter/event_filter.cpp b/qwt/examples/event_filter/event_filter.cpp index 291a555f3..9a0e140fb 100644 --- a/qwt/examples/event_filter/event_filter.cpp +++ b/qwt/examples/event_filter/event_filter.cpp @@ -17,14 +17,10 @@ int main (int argc, char **argv) QMainWindow mainWindow; QToolBar *toolBar = new QToolBar(&mainWindow); -#if QT_VERSION >= 0x040000 QAction *action = QWhatsThis::createAction(toolBar); toolBar->addAction(action); mainWindow.addToolBar(toolBar); -#else - (void)QWhatsThis::whatsThisButton(toolBar); -#endif - + Plot *plot = new Plot(&mainWindow); // The canvas picker handles all mouse and key @@ -40,9 +36,6 @@ int main (int argc, char **argv) plot, SLOT(insertCurve(int, double))); mainWindow.setCentralWidget(plot); -#if QT_VERSION < 0x040000 - a.setMainWidget(&mainWindow); -#endif mainWindow.resize(540, 400); mainWindow.show(); @@ -51,11 +44,7 @@ int main (int argc, char **argv) "An useless plot to demonstrate how to use event filtering.\n\n" "You can click on the color bar, the scales or move the wheel.\n" "All points can be moved using the mouse or the keyboard."; -#if QT_VERSION < 0x040000 - QWhatsThis::add(plot, text); -#else plot->setWhatsThis(text); -#endif int rv = a.exec(); return rv; diff --git a/qwt/examples/event_filter/event_filter.pro b/qwt/examples/event_filter/event_filter.pro index 43139d61b..008d9904d 100644 --- a/qwt/examples/event_filter/event_filter.pro +++ b/qwt/examples/event_filter/event_filter.pro @@ -1,25 +1,25 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = event_filter HEADERS = \ - colorbar.h \ - scalepicker.h \ - canvaspicker.h \ - plot.h + colorbar.h \ + scalepicker.h \ + canvaspicker.h \ + plot.h SOURCES = \ - colorbar.cpp \ - scalepicker.cpp \ - canvaspicker.cpp \ - plot.cpp \ - event_filter.cpp + colorbar.cpp \ + scalepicker.cpp \ + canvaspicker.cpp \ + plot.cpp \ + event_filter.cpp diff --git a/qwt/examples/event_filter/plot.cpp b/qwt/examples/event_filter/plot.cpp index 278600420..1a013e248 100644 --- a/qwt/examples/event_filter/plot.cpp +++ b/qwt/examples/event_filter/plot.cpp @@ -1,9 +1,6 @@ #include "plot.h" #include "colorbar.h" #include -#if QT_VERSION < 0x040000 -#include -#endif #include #include #include @@ -33,8 +30,7 @@ Plot::Plot(QWidget *parent): // appear/disappear when scrolling vertically QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); - sd->setMinimumExtent( sd->extent(QPen(), - axisWidget(QwtPlot::yLeft)->font())); + sd->setMinimumExtent( sd->extent(axisWidget(QwtPlot::yLeft)->font())); plotLayout()->setAlignCanvasToScales(true); @@ -53,17 +49,13 @@ Plot::Plot(QWidget *parent): scaleWidget->setMargin(10); // area for the color bar d_colorBar = new ColorBar(Qt::Vertical, scaleWidget); d_colorBar->setRange(Qt::red, Qt::darkBlue); -#if QT_VERSION >= 0x040000 - d_colorBar->setFocusPolicy( Qt::TabFocus ); -#else - d_colorBar->setFocusPolicy( QWidget::TabFocus ); -#endif + d_colorBar->setFocusPolicy(Qt::TabFocus); connect(d_colorBar, SIGNAL(selected(const QColor &)), SLOT(setCanvasColor(const QColor &))); // we need the resize events, to lay out the color bar - scaleWidget->installEventFilter(this); + scaleWidget->installEventFilter(this); // ------------------------------------ // We add a wheel to the canvas @@ -82,16 +74,6 @@ Plot::Plot(QWidget *parent): // we need the resize events, to lay out the wheel canvas()->installEventFilter(this); -#if QT_VERSION < 0x040000 - QWhatsThis::add(d_colorBar, - "Selecting a color will change the background of the plot."); - QWhatsThis::add(scaleWidget, - "Selecting a value at the scale will insert a new curve."); - QWhatsThis::add(d_wheel, - "With the wheel you can move the visible area."); - QWhatsThis::add(axisWidget(xBottom), - "Selecting a value at the scale will insert a new curve."); -#else d_colorBar->setWhatsThis( "Selecting a color will change the background of the plot."); scaleWidget->setWhatsThis( @@ -100,8 +82,6 @@ Plot::Plot(QWidget *parent): "With the wheel you can move the visible area."); axisWidget(xBottom)->setWhatsThis( "Selecting a value at the scale will insert a new curve."); -#endif - } void Plot::setCanvasColor(const QColor &c) @@ -158,7 +138,7 @@ void Plot::insertCurve(int axis, double base) o = Qt::Horizontal; else o = Qt::Vertical; - + QRgb rgb = (uint)rand(); insertCurve(o, QColor(rgb), base); replot(); @@ -170,7 +150,7 @@ void Plot::insertCurve(Qt::Orientation o, QwtPlotCurve *curve = new QwtPlotCurve(); curve->setPen(c); - curve->setSymbol(QwtSymbol(QwtSymbol::Ellipse, + curve->setSymbol(new QwtSymbol(QwtSymbol::Ellipse, Qt::gray, c, QSize(8, 8))); double x[10]; @@ -190,7 +170,7 @@ void Plot::insertCurve(Qt::Orientation o, y[i] = v; } } - - curve->setData(x, y, sizeof(x) / sizeof(x[0])); + + curve->setSamples(x, y, sizeof(x) / sizeof(x[0])); curve->attach(this); } diff --git a/qwt/examples/event_filter/plot.h b/qwt/examples/event_filter/plot.h index 9523acd88..5a2f760ee 100644 --- a/qwt/examples/event_filter/plot.h +++ b/qwt/examples/event_filter/plot.h @@ -10,11 +10,11 @@ public: Plot(QWidget *parent = NULL); virtual bool eventFilter(QObject *, QEvent *); -public slots: +public Q_SLOTS: void setCanvasColor(const QColor &); void insertCurve(int axis, double base); -private slots: +private Q_SLOTS: void scrollLeftAxis(double); private: diff --git a/qwt/examples/event_filter/scalepicker.cpp b/qwt/examples/event_filter/scalepicker.cpp index 57ffeae17..5b2c81625 100644 --- a/qwt/examples/event_filter/scalepicker.cpp +++ b/qwt/examples/event_filter/scalepicker.cpp @@ -16,7 +16,7 @@ ScalePicker::ScalePicker(QwtPlot *plot): bool ScalePicker::eventFilter(QObject *object, QEvent *e) { - if ( object->inherits("QwtScaleWidget") && + if ( object->inherits("QwtScaleWidget") && e->type() == QEvent::MouseButtonPress ) { mouseClicked((const QwtScaleWidget *)object, @@ -27,7 +27,7 @@ bool ScalePicker::eventFilter(QObject *object, QEvent *e) return QObject::eventFilter(object, e); } -void ScalePicker::mouseClicked(const QwtScaleWidget *scale, const QPoint &pos) +void ScalePicker::mouseClicked(const QwtScaleWidget *scale, const QPoint &pos) { QRect rect = scaleRect(scale); @@ -37,40 +37,40 @@ void ScalePicker::mouseClicked(const QwtScaleWidget *scale, const QPoint &pos) if ( rect.contains(pos) ) // No click on the title { - // translate the position in a value on the scale + // translate the position in a value on the scale double value = 0.0; int axis = -1; const QwtScaleDraw *sd = scale->scaleDraw(); - switch(scale->alignment()) + switch(scale->alignment()) { case QwtScaleDraw::LeftScale: { - value = sd->map().invTransform(pos.y()); + value = sd->scaleMap().invTransform(pos.y()); axis = QwtPlot::yLeft; break; } case QwtScaleDraw::RightScale: { - value = sd->map().invTransform(pos.y()); + value = sd->scaleMap().invTransform(pos.y()); axis = QwtPlot::yRight; break; } case QwtScaleDraw::BottomScale: { - value = sd->map().invTransform(pos.x()); + value = sd->scaleMap().invTransform(pos.x()); axis = QwtPlot::xBottom; break; } case QwtScaleDraw::TopScale: { - value = sd->map().invTransform(pos.x()); + value = sd->scaleMap().invTransform(pos.x()); axis = QwtPlot::xTop; break; } } - emit clicked(axis, value); + Q_EMIT clicked(axis, value); } } @@ -78,12 +78,12 @@ void ScalePicker::mouseClicked(const QwtScaleWidget *scale, const QPoint &pos) QRect ScalePicker::scaleRect(const QwtScaleWidget *scale) const { const int bld = scale->margin(); - const int mjt = scale->scaleDraw()->majTickLength(); + const int mjt = scale->scaleDraw()->maxTickLength(); const int sbd = scale->startBorderDist(); const int ebd = scale->endBorderDist(); QRect rect; - switch(scale->alignment()) + switch(scale->alignment()) { case QwtScaleDraw::LeftScale: { @@ -99,13 +99,13 @@ QRect ScalePicker::scaleRect(const QwtScaleWidget *scale) const } case QwtScaleDraw::BottomScale: { - rect.setRect(sbd, bld, + rect.setRect(sbd, bld, scale->width() - sbd - ebd, mjt); break; } case QwtScaleDraw::TopScale: { - rect.setRect(sbd, scale->height() - bld - mjt, + rect.setRect(sbd, scale->height() - bld - mjt, scale->width() - sbd - ebd, mjt); break; } diff --git a/qwt/examples/event_filter/scalepicker.h b/qwt/examples/event_filter/scalepicker.h index f40399eee..b15fca1f5 100644 --- a/qwt/examples/event_filter/scalepicker.h +++ b/qwt/examples/event_filter/scalepicker.h @@ -11,7 +11,7 @@ public: ScalePicker(QwtPlot *plot); virtual bool eventFilter(QObject *, QEvent *); -signals: +Q_SIGNALS: void clicked(int axis, double value); private: diff --git a/qwt/examples/examples.pri b/qwt/examples/examples.pri index 617af51b6..a6911c8de 100644 --- a/qwt/examples/examples.pri +++ b/qwt/examples/examples.pri @@ -1,4 +1,4 @@ -# -*- mode: sh -*- ################################################ +################################################################ # Qwt Widget Library # Copyright (C) 1997 Josef Wilgen # Copyright (C) 2002 Uwe Rathmann @@ -7,55 +7,43 @@ # modify it under the terms of the Qwt License, Version 1.0 ################################################################### -QWT_ROOT = ../.. - +QWT_ROOT = $${PWD}/.. include( $${QWT_ROOT}/qwtconfig.pri ) - -SUFFIX_STR = -VVERSION = $$[QT_VERSION] -isEmpty(VVERSION) { - - # Qt 3 - debug { - SUFFIX_STR = $${DEBUG_SUFFIX} - } - else { - SUFFIX_STR = $${RELEASE_SUFFIX} - } -} -else { - CONFIG(debug, debug|release) { - SUFFIX_STR = $${DEBUG_SUFFIX} - } - else { - SUFFIX_STR = $${RELEASE_SUFFIX} - } -} +include( $${QWT_ROOT}/qwtbuild.pri ) TEMPLATE = app -MOC_DIR = moc INCLUDEPATH += $${QWT_ROOT}/src DEPENDPATH += $${QWT_ROOT}/src -OBJECTS_DIR = obj$${SUFFIX_STR} -DESTDIR = $${QWT_ROOT}/examples/bin$${SUFFIX_STR} +DESTDIR = $${QWT_ROOT}/examples/bin -QWTLIB = qwt$${SUFFIX_STR} +QMAKE_RPATHDIR *= $${QWT_ROOT}/lib -win32 { - contains(CONFIG, QwtDll) { - DEFINES += QT_DLL QWT_DLL - QWTLIB = $${QWTLIB}$${VER_MAJ} - } +contains(QWT_CONFIG, QwtFramework) { - win32-msvc:LIBS += $${QWT_ROOT}/lib/$${QWTLIB}.lib - win32-msvc.net:LIBS += $${QWT_ROOT}/lib/$${QWTLIB}.lib - win32-msvc2002:LIBS += $${QWT_ROOT}/lib/$${QWTLIB}.lib - win32-msvc2003:LIBS += $${QWT_ROOT}/lib/$${QWTLIB}.lib - win32-msvc2005:LIBS += $${QWT_ROOT}/lib/$${QWTLIB}.lib - win32-msvc2008:LIBS += $${QWT_ROOT}/lib/$${QWTLIB}.lib - win32-g++:LIBS += -L$${QWT_ROOT}/lib -l$${QWTLIB} + LIBS += -F$${QWT_ROOT}/lib } else { - LIBS += -L$${QWT_ROOT}/lib -l$${QWTLIB} + + LIBS += -L$${QWT_ROOT}/lib +} + +IPATH = $${INCLUDEPATH} +qtAddLibrary(qwt) +INCLUDEPATH = $${IPATH} + +contains(QWT_CONFIG, QwtSvg) { + + QT += svg +} +else { + + DEFINES += QWT_NO_SVG +} + + +win32 { + contains(QWT_CONFIG, QwtDll) { + DEFINES += QT_DLL QWT_DLL + } } diff --git a/qwt/examples/examples.pro b/qwt/examples/examples.pro index 876a449ec..b3b0f5fd3 100644 --- a/qwt/examples/examples.pro +++ b/qwt/examples/examples.pro @@ -1,50 +1,52 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../qwtconfig.pri ) +include( $${PWD}/../qwtconfig.pri ) TEMPLATE = subdirs -contains(CONFIG, QwtPlot) { - - SUBDIRS += \ - cpuplot \ - curvdemo1 \ - curvdemo2 \ - many_axes \ - simple_plot \ - realtime_plot \ - spectrogram \ - histogram +contains(QWT_CONFIG, QwtPlot) { - contains(CONFIG, QwtWidgets) { + SUBDIRS += \ + cpuplot \ + curvdemo1 \ + curvdemo2 \ + friedberg \ + sinusplot \ + realtime \ + refreshtest \ + navigation \ + plotmatrix \ + spectrogram \ + rasterview \ + tvplot - SUBDIRS += \ - bode \ - data_plot \ - event_filter - } - - contains(CONFIG, QwtSVGItem) { + contains(QWT_CONFIG, QwtWidgets) { - SUBDIRS += \ - svgmap - } + SUBDIRS += \ + bode \ + event_filter \ + oscilloscope + } + + contains(QWT_CONFIG, QwtSvg) { + + SUBDIRS += \ + svgmap + } } -contains(CONFIG, QwtWidgets) { +contains(QWT_CONFIG, QwtWidgets) { - SUBDIRS += \ - sysinfo \ - radio \ - dials \ - sliders + SUBDIRS += \ + sysinfo \ + radio \ + dials \ + sliders } - - diff --git a/qwt/examples/friedberg/friedberg.pro b/qwt/examples/friedberg/friedberg.pro new file mode 100644 index 000000000..3a15c5b6b --- /dev/null +++ b/qwt/examples/friedberg/friedberg.pro @@ -0,0 +1,21 @@ +################################################################ +# 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( $${PWD}/../examples.pri ) + +TARGET = friedberg + +HEADERS = \ + plot.h \ + friedberg2007.h + +SOURCES = \ + friedberg2007.cpp \ + plot.cpp \ + main.cpp diff --git a/qwt/examples/friedberg/friedberg2007.cpp b/qwt/examples/friedberg/friedberg2007.cpp new file mode 100644 index 000000000..19f688e9e --- /dev/null +++ b/qwt/examples/friedberg/friedberg2007.cpp @@ -0,0 +1,384 @@ +#include "friedberg2007.h" + +// Temperature 2007 from Friedberg somewhere in Germany +// See: http://wetter61169.de + +Temperature friedberg2007[] = +{ + /* 01.01 */ Temperature( 2.6, 9.8, 7.07862 ), + /* 02.01 */ Temperature( 0.8, 5.8, 3.6993 ), + /* 03.01 */ Temperature( 2, 7, 5.02388 ), + /* 04.01 */ Temperature( 5.3, 7.8, 6.37778 ), + /* 05.01 */ Temperature( 5.6, 7.7, 6.83149 ), + /* 06.01 */ Temperature( 7.2, 8.9, 8.0816 ), + /* 07.01 */ Temperature( 4.2, 9.9, 7.54704 ), + /* 08.01 */ Temperature( 3.5, 8.9, 6.71951 ), + /* 09.01 */ Temperature( 8.2, 12.9, 10.8594 ), + /* 10.01 */ Temperature( 6.3, 11.9, 9.76424 ), + /* 11.01 */ Temperature( 3.9, 9.2, 6.18223 ), + /* 12.01 */ Temperature( 6.9, 9.7, 8.44236 ), + /* 13.01 */ Temperature( 9, 12.3, 10.6649 ), + /* 14.01 */ Temperature( 1.8, 10.8, 7.23438 ), + /* 15.01 */ Temperature( -2.8, 1.8, -0.518403 ), + /* 16.01 */ Temperature( -0.6, 4.5, 2.39479 ), + /* 17.01 */ Temperature( 4.3, 10.2, 7.23472 ), + /* 18.01 */ Temperature( 9.1, 13.6, 10.9316 ), + /* 19.01 */ Temperature( 6.9, 12.4, 9.4128 ), + /* 20.01 */ Temperature( 7.1, 13.3, 10.5083 ), + /* 21.01 */ Temperature( 3.5, 9.6, 6.10871 ), + /* 22.01 */ Temperature( -1.8, 6, 2.89028 ), + /* 23.01 */ Temperature( -5.4, 1.7, -2.46678 ), + /* 24.01 */ Temperature( -5.3, -1.3, -3.71483 ), + /* 25.01 */ Temperature( -7.5, 3.3, -3.36736 ), + /* 26.01 */ Temperature( -11.1, 0.3, -5.50662 ), + /* 27.01 */ Temperature( 0.2, 3.2, 1.95345 ), + /* 28.01 */ Temperature( 1.9, 5.2, 3.43633 ), + /* 29.01 */ Temperature( 4.4, 9.1, 6.24236 ), + /* 30.01 */ Temperature( 2.3, 11.5, 6.03114 ), + /* 31.01 */ Temperature( 4.6, 10.2, 6.04192 ), + + /* 01.02 */ Temperature( 4.8, 13.8, 7.87674 ), + /* 02.02 */ Temperature( 5.7, 10, 7.28646 ), + /* 03.02 */ Temperature( 2.9, 8.2, 5.71771 ), + /* 04.02 */ Temperature( -1.5, 7.2, 4.71319 ), + /* 05.02 */ Temperature( -2.6, 4.4, 1.23542 ), + /* 06.02 */ Temperature( 0.3, 9.2, 2.59965 ), + /* 07.02 */ Temperature( -0.4, 2.4, 0.641667 ), + /* 08.02 */ Temperature( -1.7, 3.8, 0.811458 ), + /* 09.02 */ Temperature( 0.7, 7, 3.58328 ), + /* 10.02 */ Temperature( 1, 6, 3.51181 ), + /* 11.02 */ Temperature( 4.7, 9.6, 6.14913 ), + /* 12.02 */ Temperature( 5.3, 8.7, 6.80552 ), + /* 13.02 */ Temperature( 4.4, 10.3, 6.84552 ), + /* 14.02 */ Temperature( 2.6, 6.5, 4.58681 ), + /* 15.02 */ Temperature( -0.8, 13.4, 6.38542 ), + /* 16.02 */ Temperature( -3, 14.4, 4.11336 ), + /* 17.02 */ Temperature( 0.5, 13, 5.87457 ), + /* 18.02 */ Temperature( -2.2, 14.1, 4.36528 ), + /* 19.02 */ Temperature( 3.9, 5.6, 4.63737 ), + /* 20.02 */ Temperature( -0.4, 9.2, 4.37014 ), + /* 21.02 */ Temperature( -1.9, 5.5, 1.85675 ), + /* 22.02 */ Temperature( 1, 13.1, 5.41176 ), + /* 23.02 */ Temperature( 1.9, 13.9, 7.74251 ), + /* 24.02 */ Temperature( 3.8, 9.6, 7.19306 ), + /* 25.02 */ Temperature( 5.8, 10.8, 7.80312 ), + /* 26.02 */ Temperature( 5.2, 10.4, 6.79481 ), + /* 27.02 */ Temperature( 3.2, 7.4, 5.22986 ), + /* 28.02 */ Temperature( 6.4, 13.4, 9.13356 ), + + /* 01.03 */ Temperature( 4.6, 11.4, 7.70554 ), + /* 02.03 */ Temperature( 3.4, 10.9, 5.98408 ), + /* 03.03 */ Temperature( 2.9, 10.5, 5.45675 ), + /* 04.03 */ Temperature( -0.7, 16.8, 7.29585 ), + /* 05.03 */ Temperature( 4.2, 13.4, 8.35862 ), + /* 06.03 */ Temperature( 3, 13, 7.76644 ), + /* 07.03 */ Temperature( 2, 13.3, 8.24618 ), + /* 08.03 */ Temperature( -0.8, 15, 6.11765 ), + /* 09.03 */ Temperature( -0.7, 11, 5.7568 ), + /* 10.03 */ Temperature( 1.2, 14.4, 6.61389 ), + /* 11.03 */ Temperature( -1.7, 18, 6.66146 ), + /* 12.03 */ Temperature( -0.6, 21.9, 8.9816 ), + /* 13.03 */ Temperature( -0.9, 19.6, 9.08299 ), + /* 14.03 */ Temperature( 5.3, 18.9, 10.5562 ), + /* 15.03 */ Temperature( 2, 20.5, 9.65156 ), + /* 16.03 */ Temperature( 0.2, 16.7, 7.8699 ), + /* 17.03 */ Temperature( 4.5, 10.6, 7.87535 ), + /* 18.03 */ Temperature( 2.7, 9.7, 6.71806 ), + /* 19.03 */ Temperature( 0.4, 10.9, 3.92404 ), + /* 20.03 */ Temperature( -2, 12.7, 4.01359 ), + /* 21.03 */ Temperature( 0.3, 6.8, 3.00382 ), + /* 22.03 */ Temperature( 0.9, 4.2, 2.2816 ), + /* 23.03 */ Temperature( 2, 5.7, 3.39233 ), + /* 24.03 */ Temperature( 3.9, 9.3, 6.41076 ), + /* 25.03 */ Temperature( 4.2, 19.1, 9.92182 ), + /* 26.03 */ Temperature( 2.3, 22, 12.5716 ), + /* 27.03 */ Temperature( 4.9, 20.6, 13.4568 ), + /* 28.03 */ Temperature( 0.3, 22.8, 10.755 ), + /* 29.03 */ Temperature( 1.8, 17.2, 9.43924 ), + /* 30.03 */ Temperature( 1.9, 19.8, 10.25 ), + /* 31.03 */ Temperature( 6.7, 17, 11.1324 ), + + /* 01.04 */ Temperature( 5.7, 22, 12.8457 ), + /* 02.04 */ Temperature( 6.4, 22.1, 13.3847 ), + /* 03.04 */ Temperature( 5.8, 17.5, 10.5614 ), + /* 04.04 */ Temperature( 2.8, 16.2, 8.06574 ), + /* 05.04 */ Temperature( -0.6, 20.8, 9.18062 ), + /* 06.04 */ Temperature( 2.1, 24, 13.0069 ), + /* 07.04 */ Temperature( 5.3, 16.2, 10.2771 ), + /* 08.04 */ Temperature( 0.1, 20.7, 9.79861 ), + /* 09.04 */ Temperature( 0.3, 18.9, 10.0087 ), + /* 10.04 */ Temperature( 4, 16.4, 11.4208 ), + /* 11.04 */ Temperature( 2.3, 23.4, 13.083 ), + /* 12.04 */ Temperature( 7, 29.4, 16.5826 ), + /* 13.04 */ Temperature( 10.6, 31.5, 19.2249 ), + /* 14.04 */ Temperature( 11.8, 34, 21.441 ), + /* 15.04 */ Temperature( 11.6, 33.8, 21.0201 ), + /* 16.04 */ Temperature( 8.7, 31.1, 18.7885 ), + /* 17.04 */ Temperature( 5.5, 27.2, 16.1432 ), + /* 18.04 */ Temperature( 6.1, 17.2, 10.6688 ), + /* 19.04 */ Temperature( -0.6, 21.3, 10.4806 ), + /* 20.04 */ Temperature( 5.9, 21.6, 12.6257 ), + /* 21.04 */ Temperature( 2.1, 21.6, 11.0858 ), + /* 22.04 */ Temperature( 3.9, 25.9, 14.2108 ), + /* 23.04 */ Temperature( 3.1, 27.8, 15.7111 ), + /* 24.04 */ Temperature( 13.7, 29, 19.6397 ), + /* 25.04 */ Temperature( 9.8, 31.6, 19.601 ), + /* 26.04 */ Temperature( 8.2, 32.4, 20.0389 ), + /* 27.04 */ Temperature( 11.8, 32.1, 21.0726 ), + /* 28.04 */ Temperature( 12.6, 33.3, 21.6993 ), + /* 29.04 */ Temperature( 10.5, 27.4, 19.1206 ), + /* 30.04 */ Temperature( 5.3, 26.4, 15.0972 ), + + /* 01.05 */ Temperature( 6.9, 25.3, 15.2802 ), + /* 02.05 */ Temperature( 4.3, 26.2, 14.8401 ), + /* 03.05 */ Temperature( 7.1, 28.5, 17.2145 ), + /* 04.05 */ Temperature( 11, 28.5, 18.537 ), + /* 05.05 */ Temperature( 12, 28, 18.1672 ), + /* 06.05 */ Temperature( 10.4, 29, 18.3844 ), + /* 07.05 */ Temperature( 13, 18.1, 15.0028 ), + /* 08.05 */ Temperature( 10.7, 18.3, 13.2014 ), + /* 09.05 */ Temperature( 10.8, 14.4, 12.5208 ), + /* 10.05 */ Temperature( 11.9, 23.5, 16.9632 ), + /* 11.05 */ Temperature( 9.8, 16.9, 15.0795 ), + /* 12.05 */ Temperature( 9.2, 19.6, 13.8521 ), + /* 13.05 */ Temperature( 8.9, 26.3, 16.2028 ), + /* 14.05 */ Temperature( 11.1, 17.5, 13.2934 ), + /* 15.05 */ Temperature( 6.5, 17, 11.7743 ), + /* 16.05 */ Temperature( 4.9, 13.6, 9.75625 ), + /* 17.05 */ Temperature( 6.8, 16.6, 9.96701 ), + /* 18.05 */ Temperature( 2.4, 21.2, 11.4311 ), + /* 19.05 */ Temperature( 8.2, 24.4, 15.4188 ), + /* 20.05 */ Temperature( 14.1, 31.7, 21.3303 ), + /* 21.05 */ Temperature( 11, 30.9, 21.5359 ), + /* 22.05 */ Temperature( 13.8, 31, 21.5177 ), + /* 23.05 */ Temperature( 16, 27.8, 21.0271 ), + /* 24.05 */ Temperature( 15, 34, 23.4142 ), + /* 25.05 */ Temperature( 14.3, 31.8, 22.8903 ), + /* 26.05 */ Temperature( 13.6, 33.1, 22.6156 ), + /* 27.05 */ Temperature( 11.2, 23.4, 16.6192 ), + /* 28.05 */ Temperature( 9.6, 13.1, 11.3222 ), + /* 29.05 */ Temperature( 8.3, 11.2, 10.3529 ), + /* 30.05 */ Temperature( 4.2, 20.8, 12.6218 ), + /* 31.05 */ Temperature( 9.2, 23.6, 15.1073 ), + + /* 01.06 */ Temperature( 10.8, 24.4, 16.3205 ), + /* 02.06 */ Temperature( 13, 26.5, 18.9649 ), + /* 03.06 */ Temperature( 14, 25.1, 18.5398 ), + /* 04.06 */ Temperature( 13, 28, 20.2139 ), + /* 05.06 */ Temperature( 14, 28.8, 20.438 ), + /* 06.06 */ Temperature( 14, 30.4, 21.7821 ), + /* 07.06 */ Temperature( 17, 34.8, 25.3087 ), + /* 08.06 */ Temperature( 17.9, 35.7, 25.7872 ), + /* 09.06 */ Temperature( 17.8, 31.6, 22.0788 ), + /* 10.06 */ Temperature( 15.5, 33.4, 22.4458 ), + /* 11.06 */ Temperature( 16.6, 28.3, 19.8797 ), + /* 12.06 */ Temperature( 14, 27.3, 20.2566 ), + /* 13.06 */ Temperature( 13.2, 28.2, 19.4233 ), + /* 14.06 */ Temperature( 12.7, 30, 20.1427 ), + /* 15.06 */ Temperature( 15.2, 22.6, 18.5917 ), + /* 16.06 */ Temperature( 13.2, 24, 17.7014 ), + /* 17.06 */ Temperature( 11.7, 27.9, 19.8229 ), + /* 18.06 */ Temperature( 15.9, 27.2, 20.3358 ), + /* 19.06 */ Temperature( 12.6, 33.7, 22.2427 ), + /* 20.06 */ Temperature( 15.7, 30.8, 23.7507 ), + /* 21.06 */ Temperature( 14.8, 22.6, 18.2538 ), + /* 22.06 */ Temperature( 12.4, 21.3, 15.9969 ), + /* 23.06 */ Temperature( 12.6, 21.6, 15.8149 ), + /* 24.06 */ Temperature( 13, 26, 18.4176 ), + /* 25.06 */ Temperature( 12.9, 24.4, 17.1299 ), + /* 26.06 */ Temperature( 10.8, 18.8, 13.2913 ), + /* 27.06 */ Temperature( 9.9, 18.8, 13.5465 ), + /* 28.06 */ Temperature( 12, 19.8, 14.8434 ), + /* 29.06 */ Temperature( 12, 19, 15.155 ), + /* 30.06 */ Temperature( 12.4, 22.4, 17.1354 ), + + /* 01.07 */ Temperature( 12.1, 24.9, 19.1639 ), + /* 02.07 */ Temperature( 15.7, 24.3, 18.4554 ), + /* 03.07 */ Temperature( 12.7, 17.2, 14.6564 ), + /* 04.07 */ Temperature( 11.2, 19, 13.9529 ), + /* 05.07 */ Temperature( 11.5, 19, 14.6422 ), + /* 06.07 */ Temperature( 12.4, 22, 16.6146 ), + /* 07.07 */ Temperature( 11.6, 24, 17.666 ), + /* 08.07 */ Temperature( 9, 28, 19.1351 ), + /* 09.07 */ Temperature( 11.3, 21.5, 16.5271 ), + /* 10.07 */ Temperature( 11.3, 20.2, 14.2326 ), + /* 11.07 */ Temperature( 10.2, 19.2, 14.0649 ), + /* 12.07 */ Temperature( 13.2, 23.1, 16.6346 ), + /* 13.07 */ Temperature( 15, 27, 19.6844 ), + /* 14.07 */ Temperature( 13.4, 32.4, 23.845 ), + /* 15.07 */ Temperature( 15, 38.2, 26.8559 ), + /* 16.07 */ Temperature( 16.1, 36.5, 26.4483 ), + /* 17.07 */ Temperature( 19.7, 30.5, 24.189 ), + /* 18.07 */ Temperature( 14.2, 29.3, 22.1363 ), + /* 19.07 */ Temperature( 16.4, 25.9, 19.0819 ), + /* 20.07 */ Temperature( 16.2, 30.8, 22.151 ), + /* 21.07 */ Temperature( 14, 24.3, 18.6573 ), + /* 22.07 */ Temperature( 13.2, 24.5, 18.3301 ), + /* 23.07 */ Temperature( 10.6, 23.4, 16.6903 ), + /* 24.07 */ Temperature( 13.2, 20.8, 16.2743 ), + /* 25.07 */ Temperature( 12.2, 25.8, 18.8267 ), + /* 26.07 */ Temperature( 11.9, 28.9, 20.5522 ), + /* 27.07 */ Temperature( 17.6, 25.8, 21.5691 ), + /* 28.07 */ Temperature( 16.6, 24.6, 19.2295 ), + /* 29.07 */ Temperature( 13, 19, 15.9021 ), + /* 30.07 */ Temperature( 9.6, 19.7, 13.875 ), + /* 31.07 */ Temperature( 8, 22, 14.5284 ), + + /* 01.08 */ Temperature( 7.6, 27.5, 17.5684 ), + /* 02.08 */ Temperature( 9.2, 22.2, 16.1035 ), + /* 03.08 */ Temperature( 12.7, 25.3, 18.2958 ), + /* 04.08 */ Temperature( 8.6, 31.3, 19.7941 ), + /* 05.08 */ Temperature( 10.3, 32.7, 21.492 ), + /* 06.08 */ Temperature( 10, 33.4, 22.4431 ), + /* 07.08 */ Temperature( 16.8, 22.6, 19.5583 ), + /* 08.08 */ Temperature( 13.5, 16.7, 15.0264 ), + /* 09.08 */ Temperature( 13.2, 18.8, 15.6003 ), + /* 10.08 */ Temperature( 14.6, 27.9, 18.8292 ), + /* 11.08 */ Temperature( 16.3, 26.4, 20.3837 ), + /* 12.08 */ Temperature( 12.1, 28.7, 19.9892 ), + /* 13.08 */ Temperature( 15, 27.4, 19.7542 ), + /* 14.08 */ Temperature( 11.3, 28.3, 20.5656 ), + /* 15.08 */ Temperature( 18.6, 28.4, 23.1215 ), + /* 16.08 */ Temperature( 16, 23.6, 19.491 ), + /* 17.08 */ Temperature( 12.6, 22, 17.0437 ), + /* 18.08 */ Temperature( 8.5, 25.7, 16.5589 ), + /* 19.08 */ Temperature( 13.4, 25.8, 18.0543 ), + /* 20.08 */ Temperature( 10.9, 21.5, 16.1306 ), + /* 21.08 */ Temperature( 10.6, 19.2, 14.6177 ), + /* 22.08 */ Temperature( 14, 24.6, 17.3841 ), + /* 23.08 */ Temperature( 13.8, 30.4, 20.6125 ), + /* 24.08 */ Temperature( 12.3, 30.3, 20.7622 ), + /* 25.08 */ Temperature( 12.8, 30.2, 21.6736 ), + /* 26.08 */ Temperature( 15, 29.3, 21.266 ), + /* 27.08 */ Temperature( 12.9, 25.9, 18.791 ), + /* 28.08 */ Temperature( 9.3, 24.6, 16.2833 ), + /* 29.08 */ Temperature( 10.8, 25, 16.8459 ), + /* 30.08 */ Temperature( 8.2, 24.4, 15.9267 ), + /* 31.08 */ Temperature( 14.1, 20.5, 16.6128 ), + + /* 01.09 */ Temperature( 13.4, 21.9, 16.2205 ), + /* 02.09 */ Temperature( 12, 20.7, 16.0882 ), + /* 03.09 */ Temperature( 10.8, 21.3, 14.7913 ), + /* 04.09 */ Temperature( 7.8, 18.2, 12.2747 ), + /* 05.09 */ Temperature( 8.1, 22.2, 12.9406 ), + /* 06.09 */ Temperature( 10, 23.8, 13.8785 ), + /* 07.09 */ Temperature( 10.7, 21.2, 15.4823 ), + /* 08.09 */ Temperature( 12.4, 21, 15.8194 ), + /* 09.09 */ Temperature( 12.7, 16.9, 14.7212 ), + /* 10.09 */ Temperature( 10.3, 17.7, 12.9271 ), + /* 11.09 */ Temperature( 10.6, 20.8, 14.4788 ), + /* 12.09 */ Temperature( 10.8, 21.9, 15.0184 ), + /* 13.09 */ Temperature( 6.9, 24.6, 14.5222 ), + /* 14.09 */ Temperature( 8.1, 24, 15.6583 ), + /* 15.09 */ Temperature( 8.8, 22.8, 15.941 ), + /* 16.09 */ Temperature( 3.1, 24.5, 14.1486 ), + /* 17.09 */ Temperature( 12.4, 21.2, 16.0497 ), + /* 18.09 */ Temperature( 7.8, 16.1, 12.024 ), + /* 19.09 */ Temperature( 5.3, 18.1, 10.3003 ), + /* 20.09 */ Temperature( 6.4, 20.3, 12.3177 ), + /* 21.09 */ Temperature( 6, 23.8, 13.6247 ), + /* 22.09 */ Temperature( 5.7, 27, 14.6847 ), + /* 23.09 */ Temperature( 7.8, 28, 16.6238 ), + /* 24.09 */ Temperature( 9.6, 24.9, 16.7191 ), + /* 25.09 */ Temperature( 8.4, 17.6, 12.636 ), + /* 26.09 */ Temperature( 4.3, 18.9, 10.0809 ), + /* 27.09 */ Temperature( 9.4, 11.2, 10.3344 ), + /* 28.09 */ Temperature( 7.7, 12.6, 10.5337 ), + /* 29.09 */ Temperature( 9.8, 15.3, 11.9306 ), + /* 30.09 */ Temperature( 9.6, 21.1, 13.6635 ), + + /* 01.10 */ Temperature( 8.9, 24.5, 14.8163 ), + /* 02.10 */ Temperature( 13.5, 20.2, 16.1628 ), + /* 03.10 */ Temperature( 12.5, 18, 15.4691 ), + /* 04.10 */ Temperature( 13.8, 25, 17.2073 ), + /* 05.10 */ Temperature( 9.1, 23.2, 14.6181 ), + /* 06.10 */ Temperature( 6.4, 23.4, 12.8625 ), + /* 07.10 */ Temperature( 4.6, 22.1, 11.0052 ), + /* 08.10 */ Temperature( 2, 22.2, 10.1677 ), + /* 09.10 */ Temperature( 7.8, 21.6, 12.2139 ), + /* 10.10 */ Temperature( 7.1, 22.7, 13.0115 ), + /* 11.10 */ Temperature( 6.1, 21.2, 11.4333 ), + /* 12.10 */ Temperature( 4.3, 15.2, 10.6104 ), + /* 13.10 */ Temperature( 5.8, 23, 12.8875 ), + /* 14.10 */ Temperature( 1, 23, 9.72986 ), + /* 15.10 */ Temperature( 1, 19.3, 9.33021 ), + /* 16.10 */ Temperature( 8.5, 20.4, 13.2639 ), + /* 17.10 */ Temperature( 6.8, 17.3, 11.8174 ), + /* 18.10 */ Temperature( 5.2, 15.6, 9.06076 ), + /* 19.10 */ Temperature( 2.7, 13.5, 7.1309 ), + /* 20.10 */ Temperature( -0.2, 15.8, 6.01667 ), + /* 21.10 */ Temperature( 2.6, 6.1, 4.9441 ), + /* 22.10 */ Temperature( -0.8, 13.2, 4.50694 ), + /* 23.10 */ Temperature( -0.4, 13.3, 4.71007 ), + /* 24.10 */ Temperature( 2.9, 8.1, 5.96979 ), + /* 25.10 */ Temperature( 6.3, 10.5, 8.01206 ), + /* 26.10 */ Temperature( 7, 10.8, 8.14965 ), + /* 27.10 */ Temperature( 6.6, 9.7, 7.7809 ), + /* 28.10 */ Temperature( 1.7, 10.8, 6.95728 ), + /* 29.10 */ Temperature( 2.2, 9.9, 6.62917 ), + /* 30.10 */ Temperature( 5.8, 15, 8.76181 ), + /* 31.10 */ Temperature( 0.7, 15, 6.01528 ), + + /* 01.11 */ Temperature( -0.2, 9.7, 3.75842 ), + /* 02.11 */ Temperature( 6.4, 9.6, 8.00138 ), + /* 03.11 */ Temperature( 8.7, 13.1, 10.5676 ), + /* 04.11 */ Temperature( 8, 11.8, 9.54306 ), + /* 05.11 */ Temperature( 5.8, 15.9, 8.52345 ), + /* 06.11 */ Temperature( 5.5, 10.8, 7.16493 ), + /* 07.11 */ Temperature( 5.5, 8.9, 7.30172 ), + /* 08.11 */ Temperature( 7, 11.7, 8.96701 ), + /* 09.11 */ Temperature( 2.5, 8.4, 4.86528 ), + /* 10.11 */ Temperature( 3.7, 9, 5.20828 ), + /* 11.11 */ Temperature( 2.8, 10.6, 6.80756 ), + /* 12.11 */ Temperature( 2.7, 9.5, 5.07647 ), + /* 13.11 */ Temperature( 0.1, 5.4, 3.3945 ), + /* 14.11 */ Temperature( -0.7, 7.9, 2.02234 ), + /* 15.11 */ Temperature( -1.8, 6.5, 1.07778 ), + /* 16.11 */ Temperature( -4.4, 5.1, -0.693772 ), + /* 17.11 */ Temperature( -0.3, 3.4, 1.33229 ), + /* 18.11 */ Temperature( -0.4, 4.3, 2.4622 ), + /* 19.11 */ Temperature( 1.8, 3.6, 2.78282 ), + /* 20.11 */ Temperature( 1.3, 5.6, 2.95979 ), + /* 21.11 */ Temperature( 1.6, 5.7, 3.62284 ), + /* 22.11 */ Temperature( 3.1, 7.3, 5.60277 ), + /* 23.11 */ Temperature( 4.2, 7.7, 6.28166 ), + /* 24.11 */ Temperature( -0.5, 11.5, 3.25931 ), + /* 25.11 */ Temperature( -1, 8.8, 2.86505 ), + /* 26.11 */ Temperature( 1.2, 6.8, 3.09414 ), + /* 27.11 */ Temperature( -0.8, 7.5, 3.17805 ), + /* 28.11 */ Temperature( -2.8, 3.1, -0.920139 ), + /* 29.11 */ Temperature( -2.6, 1.7, -0.491696 ), + /* 30.11 */ Temperature( 1.3, 6.5, 3.85 ), + + /* 01.12 */ Temperature( 4.1, 8.7, 5.88924 ), + /* 02.12 */ Temperature( 4.8, 9, 6.81667 ), + /* 03.12 */ Temperature( 3.5, 8.5, 6.23633 ), + /* 04.12 */ Temperature( 2.7, 6.6, 4.63045 ), + /* 05.12 */ Temperature( 4.3, 8.6, 6.85993 ), + /* 06.12 */ Temperature( 5.5, 9.3, 7.79201 ), + /* 07.12 */ Temperature( 3.1, 13.4, 8.79444 ), + /* 08.12 */ Temperature( 2.6, 6.3, 4.67093 ), + /* 09.12 */ Temperature( 3, 10.4, 5.75724 ), + /* 10.12 */ Temperature( 4.1, 6.8, 5.31834 ), + /* 11.12 */ Temperature( 4.1, 7.4, 5.28993 ), + /* 12.12 */ Temperature( 3.9, 6.4, 4.64479 ), + /* 13.12 */ Temperature( 1.7, 9.1, 4.15363 ), + /* 14.12 */ Temperature( 0.4, 1.8, 0.934602 ), + /* 15.12 */ Temperature( -4.5, 2.1, -1.17292 ), + /* 16.12 */ Temperature( -5, 4.8, -2.17431 ), + /* 17.12 */ Temperature( -5.6, 6.1, -1.35448 ), + /* 18.12 */ Temperature( -4.9, 6.4, -1.25502 ), + /* 19.12 */ Temperature( -4.4, 6.6, -1.02396 ), + /* 20.12 */ Temperature( -7.3, 5.2, -2.63854 ), + /* 21.12 */ Temperature( -8.5, 5.7, -3.58333 ), + /* 22.12 */ Temperature( -7.9, -5.3, -6.13438 ), + /* 23.12 */ Temperature( -6.1, -4.4, -5.23472 ), + /* 24.12 */ Temperature( -4.6, -3.3, -3.84291 ), + /* 25.12 */ Temperature( -4.9, -2.8, -3.9066 ), + /* 26.12 */ Temperature( -4.7, -1.9, -3.10379 ), + /* 27.12 */ Temperature( -1.9, -0.2, -0.679791 ), + /* 28.12 */ Temperature( -1.8, 0.5, -0.521875 ), + /* 29.12 */ Temperature( -2.2, 2.3, -0.430796 ), + /* 30.12 */ Temperature( 0.9, 5.2, 2.83437 ), + /* 31.12 */ Temperature( -1, 8.3, 2.27093 ) +}; diff --git a/qwt/examples/friedberg/friedberg2007.h b/qwt/examples/friedberg/friedberg2007.h new file mode 100644 index 000000000..691f10141 --- /dev/null +++ b/qwt/examples/friedberg/friedberg2007.h @@ -0,0 +1,28 @@ +#ifndef _FRIEDBERG_2007_H_ +#define _FRIEDBERG_2007_H_ + +class Temperature +{ +public: + Temperature(): + minValue( 0.0 ), + maxValue( 0.0 ), + averageValue( 0.0 ) + { + } + + Temperature( double min, double max, double average ): + minValue( min ), + maxValue( max ), + averageValue( average ) + { + } + + double minValue; + double maxValue; + double averageValue; +}; + +extern Temperature friedberg2007[]; + +#endif diff --git a/qwt/examples/friedberg/main.cpp b/qwt/examples/friedberg/main.cpp new file mode 100644 index 000000000..1c1f603b6 --- /dev/null +++ b/qwt/examples/friedberg/main.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include +#include "plot.h" + +class MainWindow: public QMainWindow +{ +public: + MainWindow( QWidget * = NULL ); + +private: + Plot *d_plot; +}; + +MainWindow::MainWindow( QWidget *parent ): + QMainWindow( parent ) +{ + d_plot = new Plot( this ); + setCentralWidget( d_plot ); + + QToolBar *toolBar = new QToolBar( this ); + + QComboBox *typeBox = new QComboBox( toolBar ); + typeBox->addItem( "Bars" ); + typeBox->addItem( "Tube" ); + typeBox->setCurrentIndex( 1 ); + typeBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + + QToolButton *btnExport = new QToolButton( toolBar ); + btnExport->setText( "Export" ); + btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon ); + connect( btnExport, SIGNAL( clicked() ), d_plot, SLOT( exportPlot() ) ); + + toolBar->addWidget( typeBox ); + toolBar->addWidget( btnExport ); + addToolBar( toolBar ); + + d_plot->setMode( typeBox->currentIndex() ); + connect( typeBox, SIGNAL( currentIndexChanged( int ) ), + d_plot, SLOT( setMode( int ) ) ); +} + +int main( int argc, char **argv ) +{ + QApplication a( argc, argv ); + + MainWindow w; + w.setObjectName( "MainWindow" ); + w.resize( 600, 400 ); + w.show(); + + return a.exec(); +} diff --git a/qwt/examples/friedberg/plot.cpp b/qwt/examples/friedberg/plot.cpp new file mode 100644 index 000000000..299612cd3 --- /dev/null +++ b/qwt/examples/friedberg/plot.cpp @@ -0,0 +1,252 @@ +#include "plot.h" +#include "friedberg2007.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Grid: public QwtPlotGrid +{ +public: + Grid() + { + enableXMin( true ); + setMajPen( QPen( Qt::white, 0, Qt::DotLine ) ); + setMinPen( QPen( Qt::gray, 0 , Qt::DotLine ) ); + } + + virtual void updateScaleDiv( const QwtScaleDiv &xMap, + const QwtScaleDiv &yMap ) + { + QList ticks[QwtScaleDiv::NTickTypes]; + + ticks[QwtScaleDiv::MajorTick] = + xMap.ticks( QwtScaleDiv::MediumTick ); + ticks[QwtScaleDiv::MinorTick] = + xMap.ticks( QwtScaleDiv::MinorTick ); + + QwtPlotGrid::updateScaleDiv( + QwtScaleDiv( xMap.lowerBound(), xMap.upperBound(), ticks ), + yMap ); + } +}; + +class YearScaleDraw: public QwtScaleDraw +{ +public: + YearScaleDraw() + { + setTickLength( QwtScaleDiv::MajorTick, 0 ); + setTickLength( QwtScaleDiv::MinorTick, 0 ); + setTickLength( QwtScaleDiv::MediumTick, 6 ); + + setLabelRotation( -60.0 ); + setLabelAlignment( Qt::AlignLeft | Qt::AlignVCenter ); + + setSpacing( 15 ); + } + + virtual QwtText label( double value ) const + { + return QDate::longMonthName( int( value / 30 ) + 1 ); + } +}; + +Plot::Plot( QWidget *parent ): + QwtPlot( parent ) +{ + setObjectName( "FriedbergPlot" ); + setTitle( "Temperature of Friedberg/Germany" ); + + setAxisTitle( QwtPlot::xBottom, "2007" ); + setAxisScaleDiv( QwtPlot::xBottom, yearScaleDiv() ); + setAxisScaleDraw( QwtPlot::xBottom, new YearScaleDraw() ); + + setAxisTitle( QwtPlot::yLeft, + QString( "Temperature [%1C]" ).arg( QChar( 0x00B0 ) ) ); + + // grid + QwtPlotGrid *grid = new Grid; + grid->attach( this ); + + insertLegend( new QwtLegend(), QwtPlot::RightLegend ); + + const int numDays = 365; + QVector averageData( numDays ); + QVector rangeData( numDays ); + + for ( int i = 0; i < numDays; i++ ) + { + const Temperature &t = friedberg2007[i]; + averageData[i] = QPointF( double( i ), t.averageValue ); + rangeData[i] = QwtIntervalSample( double( i ), + QwtInterval( t.minValue, t.maxValue ) ); + } + + insertCurve( "Average", averageData, Qt::black ); + insertErrorBars( "Range", rangeData, Qt::blue ); + + // LeftButton for the zooming + // MidButton for the panning + // RightButton: zoom out by 1 + // Ctrl+RighButton: zoom out to full size + + QwtPlotZoomer* zoomer = new QwtPlotZoomer( canvas() ); + zoomer->setRubberBandPen( QColor( Qt::black ) ); + zoomer->setTrackerPen( QColor( Qt::black ) ); + zoomer->setMousePattern( QwtEventPattern::MouseSelect2, + Qt::RightButton, Qt::ControlModifier ); + zoomer->setMousePattern( QwtEventPattern::MouseSelect3, + Qt::RightButton ); + + QwtPlotPanner *panner = new QwtPlotPanner( canvas() ); + panner->setMouseButton( Qt::MidButton ); + + canvas()->setPalette( Qt::darkGray ); + canvas()->setBorderRadius( 10 ); +} + +QwtScaleDiv Plot::yearScaleDiv() const +{ + const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + QList ticks[QwtScaleDiv::NTickTypes]; + + QList &mediumTicks = ticks[QwtScaleDiv::MediumTick]; + mediumTicks += 0.0; + for ( uint i = 0; i < sizeof( days ) / sizeof( days[0] ); i++ ) + mediumTicks += mediumTicks.last() + days[i]; + + QList &minorTicks = ticks[QwtScaleDiv::MinorTick]; + for ( int i = 1; i <= 365; i += 7 ) + minorTicks += i; + + QList &majorTicks = ticks[QwtScaleDiv::MajorTick]; + for ( int i = 0; i < 12; i++ ) + majorTicks += i * 30 + 15; + + QwtScaleDiv scaleDiv( mediumTicks.first(), mediumTicks.last() + 1, ticks ); + return scaleDiv; +} + +void Plot::insertCurve( const QString& title, + const QVector& samples, const QColor &color ) +{ + d_curve = new QwtPlotCurve( title ); + d_curve->setRenderHint( QwtPlotItem::RenderAntialiased ); + d_curve->setStyle( QwtPlotCurve::NoCurve ); + d_curve->setLegendAttribute( QwtPlotCurve::LegendShowSymbol ); + + QwtSymbol *symbol = new QwtSymbol( QwtSymbol::XCross ); + symbol->setSize( 4 ); + symbol->setPen( QPen( color ) ); + d_curve->setSymbol( symbol ); + + d_curve->setSamples( samples ); + d_curve->attach( this ); +} + +void Plot::insertErrorBars( + const QString &title, + const QVector& samples, + const QColor &color ) +{ + d_intervalCurve = new QwtPlotIntervalCurve( title ); + d_intervalCurve->setRenderHint( QwtPlotItem::RenderAntialiased ); + d_intervalCurve->setPen( QPen( Qt::white ) ); + + QColor bg( color ); + bg.setAlpha( 150 ); + d_intervalCurve->setBrush( QBrush( bg ) ); + d_intervalCurve->setStyle( QwtPlotIntervalCurve::Tube ); + + d_intervalCurve->setSamples( samples ); + d_intervalCurve->attach( this ); +} + +void Plot::setMode( int style ) +{ + if ( style == Tube ) + { + d_intervalCurve->setStyle( QwtPlotIntervalCurve::Tube ); + d_intervalCurve->setSymbol( NULL ); + d_intervalCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true ); + } + else + { + d_intervalCurve->setStyle( QwtPlotIntervalCurve::NoCurve ); + + QColor c( d_intervalCurve->brush().color().rgb() ); // skip alpha + + QwtIntervalSymbol *errorBar = + new QwtIntervalSymbol( QwtIntervalSymbol::Bar ); + errorBar->setWidth( 8 ); // should be something even + errorBar->setPen( c ); + + d_intervalCurve->setSymbol( errorBar ); + d_intervalCurve->setRenderHint( QwtPlotItem::RenderAntialiased, false ); + } + + replot(); +} + +void Plot::exportPlot() +{ +#ifndef QT_NO_PRINTER + QString fileName = "friedberg.pdf"; +#else + QString fileName = "friedberg.png"; +#endif + +#ifndef QT_NO_FILEDIALOG + const QList imageFormats = + QImageWriter::supportedImageFormats(); + + QStringList filter; + filter += "PDF Documents (*.pdf)"; +#ifndef QWT_NO_SVG + filter += "SVG Documents (*.svg)"; +#endif + filter += "Postscript Documents (*.ps)"; + + if ( imageFormats.size() > 0 ) + { + QString imageFilter("Images ("); + for ( int i = 0; i < imageFormats.size(); i++ ) + { + if ( i > 0 ) + imageFilter += " "; + imageFilter += "*."; + imageFilter += imageFormats[i]; + } + imageFilter += ")"; + + filter += imageFilter; + } + + fileName = QFileDialog::getSaveFileName( + this, "Export File Name", fileName, + filter.join(";;"), NULL, QFileDialog::DontConfirmOverwrite); +#endif + if ( !fileName.isEmpty() ) + { + QwtPlotRenderer renderer; + renderer.setDiscardFlag(QwtPlotRenderer::DiscardBackground, false); + + renderer.renderDocument(this, fileName, QSizeF(300, 200), 85); + } +} diff --git a/qwt/examples/friedberg/plot.h b/qwt/examples/friedberg/plot.h new file mode 100644 index 000000000..387655433 --- /dev/null +++ b/qwt/examples/friedberg/plot.h @@ -0,0 +1,43 @@ +#ifndef _PLOT_H_ +#define _PLOT_H_ + +#include +#include +#include + +class QwtPlotCurve; +class QwtPlotIntervalCurve; + +class Plot: public QwtPlot +{ + Q_OBJECT + +public: + enum Mode + { + Bars, + Tube + }; + + Plot( QWidget * = NULL ); + +public Q_SLOTS: + void setMode( int ); + void exportPlot(); + +private: + void insertCurve( const QString &title, + const QVector &, const QColor & ); + + void insertErrorBars( const QString &title, + const QVector &, + const QColor &color ); + + + QwtScaleDiv yearScaleDiv() const; + + QwtPlotIntervalCurve *d_intervalCurve; + QwtPlotCurve *d_curve; +}; + +#endif diff --git a/qwt/examples/histogram/histogram_item.cpp b/qwt/examples/histogram/histogram_item.cpp deleted file mode 100644 index 12b145343..000000000 --- a/qwt/examples/histogram/histogram_item.cpp +++ /dev/null @@ -1,283 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "histogram_item.h" - -class HistogramItem::PrivateData -{ -public: - int attributes; - QwtIntervalData data; - QColor color; - double reference; -}; - -HistogramItem::HistogramItem(const QwtText &title): - QwtPlotItem(title) -{ - init(); -} - -HistogramItem::HistogramItem(const QString &title): - QwtPlotItem(QwtText(title)) -{ - init(); -} - -HistogramItem::~HistogramItem() -{ - delete d_data; -} - -void HistogramItem::init() -{ - d_data = new PrivateData(); - d_data->reference = 0.0; - d_data->attributes = HistogramItem::Auto; - - setItemAttribute(QwtPlotItem::AutoScale, true); - setItemAttribute(QwtPlotItem::Legend, true); - - setZ(20.0); -} - -void HistogramItem::setBaseline(double reference) -{ - if ( d_data->reference != reference ) - { - d_data->reference = reference; - itemChanged(); - } -} - -double HistogramItem::baseline() const -{ - return d_data->reference; -} - -void HistogramItem::setData(const QwtIntervalData &data) -{ - d_data->data = data; - itemChanged(); -} - -const QwtIntervalData &HistogramItem::data() const -{ - return d_data->data; -} - -void HistogramItem::setColor(const QColor &color) -{ - if ( d_data->color != color ) - { - d_data->color = color; - itemChanged(); - } -} - -QColor HistogramItem::color() const -{ - return d_data->color; -} - -QwtDoubleRect HistogramItem::boundingRect() const -{ - QwtDoubleRect rect = d_data->data.boundingRect(); - if ( !rect.isValid() ) - return rect; - - if ( d_data->attributes & Xfy ) - { - rect = QwtDoubleRect( rect.y(), rect.x(), - rect.height(), rect.width() ); - - if ( rect.left() > d_data->reference ) - rect.setLeft( d_data->reference ); - else if ( rect.right() < d_data->reference ) - rect.setRight( d_data->reference ); - } - else - { - if ( rect.bottom() < d_data->reference ) - rect.setBottom( d_data->reference ); - else if ( rect.top() > d_data->reference ) - rect.setTop( d_data->reference ); - } - - return rect; -} - - -int HistogramItem::rtti() const -{ - return QwtPlotItem::Rtti_PlotHistogram; -} - -void HistogramItem::setHistogramAttribute(HistogramAttribute attribute, bool on) -{ - if ( bool(d_data->attributes & attribute) == on ) - return; - - if ( on ) - d_data->attributes |= attribute; - else - d_data->attributes &= ~attribute; - - itemChanged(); -} - -bool HistogramItem::testHistogramAttribute(HistogramAttribute attribute) const -{ - return d_data->attributes & attribute; -} - -void HistogramItem::draw(QPainter *painter, const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRect &) const -{ - const QwtIntervalData &iData = d_data->data; - - painter->setPen(QPen(d_data->color)); - - const int x0 = xMap.transform(baseline()); - const int y0 = yMap.transform(baseline()); - - for ( int i = 0; i < (int)iData.size(); i++ ) - { - if ( d_data->attributes & HistogramItem::Xfy ) - { - const int x2 = xMap.transform(iData.value(i)); - if ( x2 == x0 ) - continue; - - int y1 = yMap.transform( iData.interval(i).minValue()); - int y2 = yMap.transform( iData.interval(i).maxValue()); - if ( y1 > y2 ) - qSwap(y1, y2); - - if ( i < (int)iData.size() - 2 ) - { - const int yy1 = yMap.transform(iData.interval(i+1).minValue()); - const int yy2 = yMap.transform(iData.interval(i+1).maxValue()); - - if ( y2 == qwtMin(yy1, yy2) ) - { - const int xx2 = xMap.transform( - iData.interval(i+1).minValue()); - if ( xx2 != x0 && ( (xx2 < x0 && x2 < x0) || - (xx2 > x0 && x2 > x0) ) ) - { - // One pixel distance between neighboured bars - y2++; - } - } - } - - drawBar(painter, Qt::Horizontal, - QRect(x0, y1, x2 - x0, y2 - y1)); - } - else - { - const int y2 = yMap.transform(iData.value(i)); - if ( y2 == y0 ) - continue; - - int x1 = xMap.transform(iData.interval(i).minValue()); - int x2 = xMap.transform(iData.interval(i).maxValue()); - if ( x1 > x2 ) - qSwap(x1, x2); - - if ( i < (int)iData.size() - 2 ) - { - const int xx1 = xMap.transform(iData.interval(i+1).minValue()); - const int xx2 = xMap.transform(iData.interval(i+1).maxValue()); - - if ( x2 == qwtMin(xx1, xx2) ) - { - const int yy2 = yMap.transform(iData.value(i+1)); - if ( yy2 != y0 && ( (yy2 < y0 && y2 < y0) || - (yy2 > y0 && y2 > y0) ) ) - { - // One pixel distance between neighboured bars - x2--; - } - } - } - drawBar(painter, Qt::Vertical, - QRect(x1, y0, x2 - x1, y2 - y0) ); - } - } -} - -void HistogramItem::drawBar(QPainter *painter, - Qt::Orientation, const QRect& rect) const -{ - painter->save(); - - const QColor color(painter->pen().color()); -#if QT_VERSION >= 0x040000 - const QRect r = rect.normalized(); -#else - const QRect r = rect.normalize(); -#endif - - const int factor = 125; - const QColor light(color.light(factor)); - const QColor dark(color.dark(factor)); - - painter->setBrush(color); - painter->setPen(Qt::NoPen); - QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1, - r.width() - 2, r.height() - 2); - painter->setBrush(Qt::NoBrush); - - painter->setPen(QPen(light, 2)); -#if QT_VERSION >= 0x040000 - QwtPainter::drawLine(painter, - r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2); -#else - QwtPainter::drawLine(painter, - r.left(), r.top() + 2, r.right() + 1, r.top() + 2); -#endif - - painter->setPen(QPen(dark, 2)); -#if QT_VERSION >= 0x040000 - QwtPainter::drawLine(painter, - r.left() + 1, r.bottom(), r.right() + 1, r.bottom()); -#else - QwtPainter::drawLine(painter, - r.left(), r.bottom(), r.right() + 1, r.bottom()); -#endif - - painter->setPen(QPen(light, 1)); - -#if QT_VERSION >= 0x040000 - QwtPainter::drawLine(painter, - r.left(), r.top() + 1, r.left(), r.bottom()); - QwtPainter::drawLine(painter, - r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1); -#else - QwtPainter::drawLine(painter, - r.left(), r.top() + 1, r.left(), r.bottom() + 1); - QwtPainter::drawLine(painter, - r.left() + 1, r.top() + 2, r.left() + 1, r.bottom()); -#endif - - painter->setPen(QPen(dark, 1)); - -#if QT_VERSION >= 0x040000 - QwtPainter::drawLine(painter, - r.right() + 1, r.top() + 1, r.right() + 1, r.bottom()); - QwtPainter::drawLine(painter, - r.right(), r.top() + 2, r.right(), r.bottom() - 1); -#else - QwtPainter::drawLine(painter, - r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() + 1); - QwtPainter::drawLine(painter, - r.right(), r.top() + 2, r.right(), r.bottom()); -#endif - - painter->restore(); -} diff --git a/qwt/examples/histogram/histogram_item.h b/qwt/examples/histogram/histogram_item.h deleted file mode 100644 index b5edf3275..000000000 --- a/qwt/examples/histogram/histogram_item.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ - -#ifndef HISTOGRAM_ITEM_H -#define HISTOGRAM_ITEM_H - -#include -#include - -#include "qwt_plot_item.h" - -class QwtIntervalData; -class QString; - -class HistogramItem: public QwtPlotItem -{ -public: - explicit HistogramItem(const QString &title = QString::null); - explicit HistogramItem(const QwtText &title); - virtual ~HistogramItem(); - - void setData(const QwtIntervalData &data); - const QwtIntervalData &data() const; - - void setColor(const QColor &); - QColor color() const; - - virtual QwtDoubleRect boundingRect() const; - - virtual int rtti() const; - - virtual void draw(QPainter *, const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRect &) const; - - void setBaseline(double reference); - double baseline() const; - - enum HistogramAttribute - { - Auto = 0, - Xfy = 1 - }; - - void setHistogramAttribute(HistogramAttribute, bool on = true); - bool testHistogramAttribute(HistogramAttribute) const; - -protected: - virtual void drawBar(QPainter *, - Qt::Orientation o, const QRect &) const; - -private: - void init(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/qwt/examples/histogram/main.cpp b/qwt/examples/histogram/main.cpp deleted file mode 100644 index 932c38953..000000000 --- a/qwt/examples/histogram/main.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "histogram_item.h" - -int main(int argc, char **argv) -{ - QApplication a(argc, argv); - - QwtPlot plot; - plot.setCanvasBackground(QColor(Qt::white)); - plot.setTitle("Histogram"); - - QwtPlotGrid *grid = new QwtPlotGrid; - grid->enableXMin(true); - grid->enableYMin(true); - grid->setMajPen(QPen(Qt::black, 0, Qt::DotLine)); - grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine)); - grid->attach(&plot); - - HistogramItem *histogram = new HistogramItem(); - histogram->setColor(Qt::darkCyan); - - const int numValues = 20; - - QwtArray intervals(numValues); - QwtArray values(numValues); - - double pos = 0.0; - for ( int i = 0; i < (int)intervals.size(); i++ ) - { - const int width = 5 + rand() % 15; - const int value = rand() % 100; - - intervals[i] = QwtDoubleInterval(pos, pos + double(width)); - values[i] = value; - - pos += width; - } - - histogram->setData(QwtIntervalData(intervals, values)); - histogram->attach(&plot); - - plot.setAxisScale(QwtPlot::yLeft, 0.0, 100.0); - plot.setAxisScale(QwtPlot::xBottom, 0.0, pos); - plot.replot(); - -#if QT_VERSION < 0x040000 - a.setMainWidget(&plot); -#endif - - plot.resize(600,400); - plot.show(); - - return a.exec(); -} diff --git a/qwt/examples/many_axes/mainwindow.cpp b/qwt/examples/many_axes/mainwindow.cpp deleted file mode 100644 index 9e6a8ef8c..000000000 --- a/qwt/examples/many_axes/mainwindow.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include "plot.h" -#include "mainwindow.h" - -MainWindow::MainWindow() -{ - QFrame *w = new QFrame(this); - - // create the box of checkboxes - - QGroupBox *panel = new QGroupBox("Axes", w); - QVBoxLayout *vLayout = new QVBoxLayout(panel); - - QStringList list; - list << "yLeft" << "yLeft1" << "yLeft2" << "yLeft3"; - list << "yRight" << "yRight1" << "yRight2" << "yRight3"; - - QSignalMapper* signalMapper = new QSignalMapper(this); - - QCheckBox* checkBox; - for(int i = 0; i < 8; i++) - { - checkBox = new QCheckBox(list[i], panel); - checkBox->setChecked(true); - connect(checkBox, SIGNAL(clicked()), signalMapper, SLOT(map())); - signalMapper->setMapping(checkBox, i); - vLayout->addWidget(checkBox); - } - - connect(signalMapper, SIGNAL(mapped(int)), - this, SLOT(axisCheckBoxToggled(int))); - - vLayout->addStretch(10); - - // create the plot widget - - d_plot = new Plot(w); - d_plot->replot(); - - // put the widgets in a horizontal box - - QHBoxLayout *hLayout = new QHBoxLayout(w); - hLayout->setMargin(0); - hLayout->addWidget(panel, 10); - hLayout->addWidget(d_plot, 10); - - setCentralWidget(w); -} - -void MainWindow::axisCheckBoxToggled(int axis) -{ - d_plot->enableAxis(axis, !d_plot->axisEnabled(axis)); -} diff --git a/qwt/examples/many_axes/mainwindow.h b/qwt/examples/many_axes/mainwindow.h deleted file mode 100644 index 76ad93154..000000000 --- a/qwt/examples/many_axes/mainwindow.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _MAINWINDOW_H_ -#define _MAINWINDOW_H_ - -#include - -class Plot; - -class MainWindow: public QMainWindow -{ - Q_OBJECT - - public: - MainWindow(); - - private slots: - void axisCheckBoxToggled(int axis); - - private: - Plot *d_plot; -}; - -#endif // _MAINWINDOW_H_ diff --git a/qwt/examples/many_axes/many_axes.cpp b/qwt/examples/many_axes/many_axes.cpp deleted file mode 100644 index 5975fcec8..000000000 --- a/qwt/examples/many_axes/many_axes.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include "mainwindow.h" - -//----------------------------------------------------------------- -// many_axes.cpp -// -// An example that demonstrates a plot with many axes. -//----------------------------------------------------------------- - -int main(int argc, char **argv) -{ - QApplication a(argc, argv); - - MainWindow mainWindow; - mainWindow.show(); - return a.exec(); -} diff --git a/qwt/examples/many_axes/plot.h b/qwt/examples/many_axes/plot.h deleted file mode 100644 index 0d4a41d32..000000000 --- a/qwt/examples/many_axes/plot.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef _PLOT_H_ -#define _PLOT_H_ - -#include -#include -#include -#include -#include -#include - -/*class FunctionData: public QwtSyntheticPointData -{ - public: - FunctionData(double(*y)(double)): - QwtSyntheticPointData(100), - d_y(y) - { - } - - virtual QwtSeriesData *copy() const - { - return new FunctionData(d_y); - } - - virtual double y(double x) const - { - return d_y(x); - } - - private: - double(*d_y)(double); -};*/ - -//----------------------------------------------------------------- -// simple.cpp -// -// A simple example which shows how to use QwtPlot and QwtData -//----------------------------------------------------------------- - -class SimpleData: public QwtData -{ - // The x values depend on its index and the y values - // can be calculated from the corresponding x value. - // So we don´t need to store the values. - // Such an implementation is slower because every point - // has to be recalculated for every replot, but it demonstrates how - // QwtData can be used. - -public: - SimpleData(double(*y)(double), size_t size): - d_size(size), - d_y(y) - { - } - - virtual QwtData *copy() const - { - return new SimpleData(d_y, d_size); - } - - virtual size_t size() const - { - return d_size; - } - - virtual double x(size_t i) const - { - return 0.1 * i; - } - - virtual double y(size_t i) const - { - return d_y(x(i)); - } -private: - size_t d_size; - double(*d_y)(double); -}; - -class Plot : public QwtPlot -{ - public: - Plot(QWidget* widget) : - QwtPlot(widget) - { - setTitle("A Simple QwtPlot Demonstration"); - insertLegend(new QwtLegend(), QwtPlot::RightLegend); - - // Set axes - setAxisTitle(xBottom, "xBottom"); - setAxisScale(xBottom, 0.0, 10.0); - - setAxisTitle(yLeft, "yLeft"); - setAxisScale(yLeft, -1.0, 1.0); - enableAxis(yLeft1); - setAxisTitle(yLeft1, "yLeft1"); - enableAxis(yLeft2); - setAxisTitle(yLeft2, "yLeft2"); - enableAxis(yLeft3); - setAxisTitle(yLeft3, "yLeft3"); - enableAxis(yRight); - setAxisTitle(yRight, "yRight"); - enableAxis(yRight1); - setAxisTitle(yRight1, "yRight1"); - enableAxis(yRight2); - setAxisTitle(yRight2, "yRight2"); - enableAxis(yRight3); - setAxisTitle(yRight3, "yRight3"); - - // Insert new curves - QwtPlotCurve *cSin = new QwtPlotCurve("y = sin(x)"); -#if QT_VERSION >= 0x040000 - cSin->setRenderHint(QwtPlotItem::RenderAntialiased); -#endif - cSin->setPen(QPen(Qt::red)); - cSin->attach(this); - //cSin->setAxis(QwtPlot::xBottom, QwtPlot::yLeft); - - QwtPlotCurve *cCos = new QwtPlotCurve("y = cos(x)"); -#if QT_VERSION >= 0x040000 - cCos->setRenderHint(QwtPlotItem::RenderAntialiased); -#endif - cCos->setPen(QPen(Qt::blue)); - cCos->attach(this); - //cCos->setAxis(QwtPlot::xBottom, QwtPlot::yRight); - - // Create sin and cos data - const int nPoints = 100; - cSin->setData(SimpleData(::sin, nPoints)); - cCos->setData(SimpleData(::cos, nPoints)); - - // Insert markers - - // ...a horizontal line at y = 0... - QwtPlotMarker *mY = new QwtPlotMarker(); - mY->setLabel(QString::fromLatin1("y = 0")); - mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); - mY->setLineStyle(QwtPlotMarker::HLine); - mY->setYValue(0.0); - mY->attach(this); - - // ...a vertical line at x = 2 * pi - QwtPlotMarker *mX = new QwtPlotMarker(); - mX->setLabel(QString::fromLatin1("x = 2 pi")); - mX->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); - mX->setLineStyle(QwtPlotMarker::VLine); - mX->setXValue(6.284); - mX->attach(this); - } -}; - -#endif // _PLOT_H_ diff --git a/qwt/examples/navigation/main.cpp b/qwt/examples/navigation/main.cpp new file mode 100644 index 000000000..2afb77977 --- /dev/null +++ b/qwt/examples/navigation/main.cpp @@ -0,0 +1,14 @@ +#include +#include "mainwindow.h" + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + MainWindow mainWindow; + + mainWindow.resize(800,600); + mainWindow.show(); + + return a.exec(); +} diff --git a/qwt/examples/navigation/mainwindow.cpp b/qwt/examples/navigation/mainwindow.cpp new file mode 100644 index 000000000..4b8b615da --- /dev/null +++ b/qwt/examples/navigation/mainwindow.cpp @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "plot.h" +#include "mainwindow.h" + +MainWindow::MainWindow() +{ + QFrame *w = new QFrame(this); + + QWidget *panel = createPanel(w); + panel->setFixedWidth(2 * panel->sizeHint().width()); + d_plot = createPlot(w); + + QHBoxLayout *layout = new QHBoxLayout(w); + layout->setMargin(0); + layout->addWidget(panel, 0); + layout->addWidget(d_plot, 10); + + setCentralWidget(w); + + setRescaleMode(0); + setMouseMode(0); + + (void)statusBar(); +} + +QWidget *MainWindow::createPanel(QWidget *parent) +{ + QGroupBox *panel = new QGroupBox("Navigation Panel", parent); + + QComboBox *navigationBox = new QComboBox(panel); + navigationBox->setEditable(false); + navigationBox->insertItem(Tracking, "Tracking"); + navigationBox->insertItem(Zooming, "Zooming"); + navigationBox->insertItem(Panning, "Panning"); + + connect(navigationBox, SIGNAL(activated(int)), SLOT(setMouseMode(int))); + + d_navigationInfo = new QLabel(panel); + d_navigationInfo->setSizePolicy( + QSizePolicy::Expanding, QSizePolicy::Expanding); + d_navigationInfo->setWordWrap(true); + + QComboBox *rescaleBox = new QComboBox(panel); + rescaleBox->setEditable(false); + rescaleBox->insertItem(KeepScales, "None"); + rescaleBox->insertItem(Fixed, "Fixed"); + rescaleBox->insertItem(Expanding, "Expanding"); + rescaleBox->insertItem(Fitting, "Fitting"); + + connect(rescaleBox, SIGNAL(activated(int)), SLOT(setRescaleMode(int))); + + d_rescaleInfo = new QLabel(panel); + d_rescaleInfo->setSizePolicy( + QSizePolicy::Expanding, QSizePolicy::Expanding); + d_rescaleInfo->setWordWrap(true); + + QVBoxLayout *layout = new QVBoxLayout(panel); + layout->addWidget(navigationBox); + layout->addWidget(d_navigationInfo); + layout->addWidget(rescaleBox); + layout->addWidget(d_rescaleInfo); + layout->addStretch(10); + + return panel; +} + +Plot *MainWindow::createPlot(QWidget *parent) +{ + Plot *plot = new Plot(parent, QwtInterval(0.0, 1000.0)); + plot->replot(); + + d_rescaler = new QwtPlotRescaler(plot->canvas()); + d_rescaler->setReferenceAxis(QwtPlot::xBottom); + d_rescaler->setAspectRatio(QwtPlot::yLeft, 1.0); + d_rescaler->setAspectRatio(QwtPlot::yRight, 0.0); + d_rescaler->setAspectRatio(QwtPlot::xTop, 0.0); + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + d_rescaler->setIntervalHint(axis, QwtInterval(0.0, 1000.0)); + + connect(plot, SIGNAL(resized(double, double)), + SLOT(showRatio(double, double))); + return plot; +} + +void MainWindow::setMouseMode(int mode) +{ + switch(mode) + { + case Tracking: + { + d_navigationInfo->setText("Tracking"); + break; + } + case Zooming: + { + d_navigationInfo->setText("Zooming"); + break; + } + case Panning: + { + d_navigationInfo->setText("Panning"); + break; + } + } +} + +void MainWindow::setRescaleMode(int mode) +{ + bool doEnable = true; + QString info; + QRectF rectOfInterest; + QwtPlotRescaler::ExpandingDirection direction = QwtPlotRescaler::ExpandUp; + + switch(mode) + { + case KeepScales: + { + doEnable = false; + info = "All scales remain unchanged, when the plot is resized"; + break; + } + case Fixed: + { + d_rescaler->setRescalePolicy(QwtPlotRescaler::Fixed); + info = "The scale of the bottom axis remains unchanged, " + "when the plot is resized. All other scales are changed, " + "so that a pixel on screen means the same distance for" + "all scales."; + break; + } + case Expanding: + { + d_rescaler->setRescalePolicy(QwtPlotRescaler::Expanding); + info = "The scales of all axis are shrinked/expanded, when " + "resizing the plot, keeping the distance that is represented " + "by one pixel."; + d_rescaleInfo->setText("Expanding"); + break; + } + case Fitting: + { + d_rescaler->setRescalePolicy(QwtPlotRescaler::Fitting); + const QwtInterval xIntv = + d_rescaler->intervalHint(QwtPlot::xBottom); + const QwtInterval yIntv = + d_rescaler->intervalHint(QwtPlot::yLeft); + + rectOfInterest = QRectF( xIntv.minValue(), yIntv.minValue(), + xIntv.width(), yIntv.width()); + direction = QwtPlotRescaler::ExpandBoth; + + info = "Fitting"; + break; + } + } + + d_plot->setRectOfInterest(rectOfInterest); + + d_rescaleInfo->setText(info); + d_rescaler->setEnabled(doEnable); + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + d_rescaler->setExpandingDirection(direction); + + if ( doEnable ) + d_rescaler->rescale(); + else + d_plot->replot(); +} + +void MainWindow::showRatio(double xRatio, double yRatio) +{ + const QString msg = QString("%1, %2").arg(xRatio).arg(yRatio); + statusBar()->showMessage(msg); +} diff --git a/qwt/examples/navigation/mainwindow.h b/qwt/examples/navigation/mainwindow.h new file mode 100644 index 000000000..0c52836eb --- /dev/null +++ b/qwt/examples/navigation/mainwindow.h @@ -0,0 +1,49 @@ +#ifndef _MAINWINDOW_H_ +#define _MAINWINDOW_H_ 1 + +#include +#include + +class QwtPlotRescaler; +class QLabel; +class Plot; + +class MainWindow: public QMainWindow +{ + Q_OBJECT + +public: + enum MouseMode + { + Tracking, + Zooming, + Panning + }; + + enum RescaleMode + { + KeepScales, + Fixed, + Expanding, + Fitting + }; + + MainWindow(); + +private Q_SLOTS: + void setMouseMode(int); + void setRescaleMode(int); + void showRatio(double, double); + +private: + QWidget *createPanel(QWidget *); + Plot *createPlot(QWidget *); + + QwtPlotRescaler *d_rescaler; + QLabel *d_navigationInfo; + QLabel *d_rescaleInfo; + + Plot *d_plot; +}; + +#endif diff --git a/qwt/examples/navigation/navigation.pro b/qwt/examples/navigation/navigation.pro new file mode 100644 index 000000000..588982ecf --- /dev/null +++ b/qwt/examples/navigation/navigation.pro @@ -0,0 +1,21 @@ +################################################################ +# 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( $${PWD}/../examples.pri ) + +TARGET = navigation + +HEADERS = \ + mainwindow.h \ + plot.h + +SOURCES = \ + mainwindow.cpp \ + plot.cpp \ + main.cpp diff --git a/qwt/examples/navigation/plot.cpp b/qwt/examples/navigation/plot.cpp new file mode 100644 index 000000000..434880ff8 --- /dev/null +++ b/qwt/examples/navigation/plot.cpp @@ -0,0 +1,146 @@ +#include "plot.h" +#include +#include +#include +#include +#include +#include +#include +#include + +class RectItem: public QwtPlotItem +{ +public: + enum Type + { + Rect, + Ellipse + }; + + RectItem(Type type): + d_type(type) + { + } + + void setPen(const QPen &pen) + { + if ( pen != d_pen ) + { + d_pen = pen; + itemChanged(); + } + } + + void setBrush(const QBrush &brush) + { + if ( brush != d_brush ) + { + d_brush = brush; + itemChanged(); + } + } + void setRect(const QRectF &rect) + { + if ( d_rect != rect ) + { + d_rect = rect; + itemChanged(); + } + } + + virtual QRectF boundingRect() const + { + return d_rect; + } + + virtual void draw(QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &) const + { + if ( d_rect.isValid() ) + { + const QRectF rect = QwtScaleMap::transform( + xMap, yMap, d_rect); + painter->setPen(d_pen); + painter->setBrush(d_brush); + if ( d_type == Ellipse ) + QwtPainter::drawEllipse(painter, rect); + else + QwtPainter::drawRect(painter, rect); + } + } +private: + QPen d_pen; + QBrush d_brush; + QRectF d_rect; + Type d_type; +}; + +Plot::Plot(QWidget *parent, const QwtInterval &interval): + QwtPlot(parent) +{ + for ( int axis = 0; axis < QwtPlot::axisCnt; axis ++ ) + setAxisScale(axis, interval.minValue(), interval.maxValue()); + + setCanvasBackground(QColor(Qt::darkBlue)); + plotLayout()->setAlignCanvasToScales(true); + + // grid + QwtPlotGrid *grid = new QwtPlotGrid; + //grid->enableXMin(true); + grid->setMajPen(QPen(Qt::white, 0, Qt::DotLine)); + grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine)); + grid->attach(this); + + const int numEllipses = 10; + + for ( int i = 0; i < numEllipses; i++ ) + { + const double x = interval.minValue() + + qrand() % qRound(interval.width()); + const double y = interval.minValue() + + qrand() % qRound(interval.width()); + const double r = interval.minValue() + + qrand() % qRound(interval.width() / 6); + + const QRectF area(x - r, y - r , 2 * r, 2 * r); + + RectItem *item = new RectItem(RectItem::Ellipse); + item->setRenderHint(QwtPlotItem::RenderAntialiased, true); + item->setRect(area); + item->setPen(QPen(Qt::yellow)); + item->attach(this); + } + + + d_rectOfInterest = new RectItem(RectItem::Rect); + d_rectOfInterest->setPen(Qt::NoPen); + QColor c = Qt::gray; + c.setAlpha(100); + d_rectOfInterest->setBrush(QBrush(c)); + d_rectOfInterest->attach(this); +} + +void Plot::updateLayout() +{ + QwtPlot::updateLayout(); + + const QwtScaleMap xMap = canvasMap(QwtPlot::xBottom); + const QwtScaleMap yMap = canvasMap(QwtPlot::yLeft); + + const QRect cr = canvas()->contentsRect(); + const double x1 = xMap.invTransform(cr.left()); + const double x2 = xMap.invTransform(cr.right()); + const double y1 = yMap.invTransform(cr.bottom()); + const double y2 = yMap.invTransform(cr.top()); + + const double xRatio = (x2 - x1) / cr.width(); + const double yRatio = (y2 - y1) / cr.height(); + + Q_EMIT resized(xRatio, yRatio); +} + +void Plot::setRectOfInterest(const QRectF &rect) +{ + d_rectOfInterest->setRect(rect); +} diff --git a/qwt/examples/navigation/plot.h b/qwt/examples/navigation/plot.h new file mode 100644 index 000000000..3cfd7c9da --- /dev/null +++ b/qwt/examples/navigation/plot.h @@ -0,0 +1,26 @@ +#ifndef _PLOT_H_ +#define _PLOT_H_ 1 + +#include + +class RectItem; +class QwtInterval; + +class Plot: public QwtPlot +{ + Q_OBJECT + +public: + Plot(QWidget *parent, const QwtInterval &); + virtual void updateLayout(); + + void setRectOfInterest(const QRectF &); + +Q_SIGNALS: + void resized(double xRatio, double yRatio); + +private: + RectItem *d_rectOfInterest; +}; + +#endif diff --git a/qwt/examples/oscilloscope/curvedata.cpp b/qwt/examples/oscilloscope/curvedata.cpp new file mode 100644 index 000000000..70ea567aa --- /dev/null +++ b/qwt/examples/oscilloscope/curvedata.cpp @@ -0,0 +1,27 @@ +#include "curvedata.h" +#include "signaldata.h" + +const SignalData &CurveData::values() const +{ + return SignalData::instance(); +} + +SignalData &CurveData::values() +{ + return SignalData::instance(); +} + +QPointF CurveData::sample(size_t i) const +{ + return SignalData::instance().value(i); +} + +size_t CurveData::size() const +{ + return SignalData::instance().size(); +} + +QRectF CurveData::boundingRect() const +{ + return SignalData::instance().boundingRect(); +} diff --git a/qwt/examples/oscilloscope/curvedata.h b/qwt/examples/oscilloscope/curvedata.h new file mode 100644 index 000000000..5f208e1af --- /dev/null +++ b/qwt/examples/oscilloscope/curvedata.h @@ -0,0 +1,16 @@ +#include +#include + +class SignalData; + +class CurveData: public QwtSeriesData +{ +public: + const SignalData &values() const; + SignalData &values(); + + virtual QPointF sample(size_t i) const; + virtual size_t size() const; + + virtual QRectF boundingRect() const; +}; diff --git a/qwt/examples/oscilloscope/knob.cpp b/qwt/examples/oscilloscope/knob.cpp new file mode 100644 index 000000000..9ca0845d0 --- /dev/null +++ b/qwt/examples/oscilloscope/knob.cpp @@ -0,0 +1,86 @@ +#include "knob.h" +#include +#include +#include +#include +#include +#include +#include + +Knob::Knob(const QString &title, double min, double max, QWidget *parent): + QWidget(parent) +{ + QFont font("Helvetica", 10); + + d_knob = new QwtKnob(this); + d_knob->setFont(font); + d_knob->setRange(min, max); + + QwtScaleDiv scaleDiv = + d_knob->scaleEngine()->divideScale(min, max, 5, 3); + + QList ticks = scaleDiv.ticks(QwtScaleDiv::MajorTick); + if ( ticks.size() > 0 && ticks[0] > min ) + { + if ( ticks.first() > min ) + ticks.prepend(min); + if ( ticks.last() < max ) + ticks.append(max); + } + scaleDiv.setTicks(QwtScaleDiv::MajorTick, ticks); + d_knob->setScale(scaleDiv); + + d_knob->setKnobWidth(50); + + font.setBold(true); + d_label = new QLabel(title, this); + d_label->setFont(font); + d_label->setAlignment(Qt::AlignTop | Qt::AlignHCenter); + + setSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding); + + connect(d_knob, SIGNAL(valueChanged(double)), + this, SIGNAL(valueChanged(double))); +} + +QSize Knob::sizeHint() const +{ + QSize sz1 = d_knob->sizeHint(); + QSize sz2 = d_label->sizeHint(); + + const int w = qMax(sz1.width(), sz2.width()); + const int h = sz1.height() + sz2.height(); + + int off = d_knob->scaleDraw()->extent(d_knob->font()); + off -= 10; // spacing + + return QSize(w, h - off); +} + +void Knob::setValue(double value) +{ + d_knob->setValue(value); +} + +double Knob::value() const +{ + return d_knob->value(); +} + +void Knob::resizeEvent(QResizeEvent *e) +{ + const QSize sz = e->size(); + + int h = d_label->sizeHint().height(); + + d_label->setGeometry(0, sz.height() - h, + sz.width(), h); + + h = d_knob->sizeHint().height(); + int off = d_knob->scaleDraw()->extent(d_knob->font()); + off -= 10; // spacing + + d_knob->setGeometry(0, d_label->pos().y() - h + off, + sz.width(), h); +} diff --git a/qwt/examples/oscilloscope/knob.h b/qwt/examples/oscilloscope/knob.h new file mode 100644 index 000000000..6b06c65a3 --- /dev/null +++ b/qwt/examples/oscilloscope/knob.h @@ -0,0 +1,33 @@ +#ifndef _KNOB_H_ +#define _KNOB_H_ + +#include + +class QwtKnob; +class QLabel; + +class Knob: public QWidget +{ + Q_OBJECT + +public: + Knob(const QString &title, + double min, double max, QWidget *parent = NULL); + + virtual QSize sizeHint() const; + + void setValue(double value); + double value() const; + +Q_SIGNALS: + double valueChanged(double); + +protected: + virtual void resizeEvent(QResizeEvent *); + +private: + QwtKnob *d_knob; + QLabel *d_label; +}; + +#endif diff --git a/qwt/examples/oscilloscope/main.cpp b/qwt/examples/oscilloscope/main.cpp new file mode 100644 index 000000000..1ee6e9347 --- /dev/null +++ b/qwt/examples/oscilloscope/main.cpp @@ -0,0 +1,35 @@ +#include +#include "mainwindow.h" +#include "samplingthread.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + MainWindow window; + window.resize(800,400); + + SamplingThread samplingThread; + samplingThread.setFrequency(window.frequency()); + samplingThread.setAmplitude(window.amplitude()); + samplingThread.setInterval(window.signalInterval()); + + window.connect(&window, SIGNAL(frequencyChanged(double)), + &samplingThread, SLOT(setFrequency(double))); + window.connect(&window, SIGNAL(amplitudeChanged(double)), + &samplingThread, SLOT(setAmplitude(double))); + window.connect(&window, SIGNAL(signalIntervalChanged(double)), + &samplingThread, SLOT(setInterval(double))); + + window.show(); + + samplingThread.start(); + window.start(); + + bool ok = app.exec(); + + samplingThread.stop(); + samplingThread.wait(1000); + + return ok; +} diff --git a/qwt/examples/oscilloscope/mainwindow.cpp b/qwt/examples/oscilloscope/mainwindow.cpp new file mode 100644 index 000000000..abc158136 --- /dev/null +++ b/qwt/examples/oscilloscope/mainwindow.cpp @@ -0,0 +1,69 @@ +#include "mainwindow.h" +#include "plot.h" +#include "knob.h" +#include "wheelbox.h" +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent): + QWidget(parent) +{ + const double intervalLength = 10.0; // seconds + + d_plot = new Plot(this); + d_plot->setIntervalLength(intervalLength); + + d_amplitudeKnob = new Knob("Amplitude", 0.0, 200.0, this); + d_amplitudeKnob->setValue(160.0); + + d_frequencyKnob = new Knob("Frequency [Hz]", 0.1, 20.0, this); + d_frequencyKnob->setValue(17.8); + + d_intervalWheel = new WheelBox("Displayed [s]", 1.0, 100.0, 1.0, this); + d_intervalWheel->setValue(intervalLength); + + d_timerWheel = new WheelBox("Sample Interval [ms]", 0.0, 20.0, 0.1, this); + d_timerWheel->setValue(10.0); + + QVBoxLayout* vLayout1 = new QVBoxLayout(); + vLayout1->addWidget(d_intervalWheel); + vLayout1->addWidget(d_timerWheel); + vLayout1->addStretch(10); + vLayout1->addWidget(d_amplitudeKnob); + vLayout1->addWidget(d_frequencyKnob); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->addWidget(d_plot, 10); + layout->addLayout(vLayout1); + + connect(d_amplitudeKnob, SIGNAL(valueChanged(double)), + SIGNAL(amplitudeChanged(double))); + connect(d_frequencyKnob, SIGNAL(valueChanged(double)), + SIGNAL(frequencyChanged(double))); + connect(d_timerWheel, SIGNAL(valueChanged(double)), + SIGNAL(signalIntervalChanged(double))); + + connect(d_intervalWheel, SIGNAL(valueChanged(double)), + d_plot, SLOT(setIntervalLength(double)) ); +} + +void MainWindow::start() +{ + d_plot->start(); +} + +double MainWindow::frequency() const +{ + return d_frequencyKnob->value(); +} + +double MainWindow::amplitude() const +{ + return d_amplitudeKnob->value(); +} + +double MainWindow::signalInterval() const +{ + return d_timerWheel->value(); +} diff --git a/qwt/examples/oscilloscope/mainwindow.h b/qwt/examples/oscilloscope/mainwindow.h new file mode 100644 index 000000000..8f360f9c3 --- /dev/null +++ b/qwt/examples/oscilloscope/mainwindow.h @@ -0,0 +1,32 @@ +#include + +class Plot; +class Knob; +class WheelBox; + +class MainWindow : public QWidget +{ + Q_OBJECT + +public: + MainWindow(QWidget * = NULL); + + void start(); + + double amplitude() const; + double frequency() const; + double signalInterval() const; + +Q_SIGNALS: + void amplitudeChanged(double); + void frequencyChanged(double); + void signalIntervalChanged(double); + +private: + Knob *d_frequencyKnob; + Knob *d_amplitudeKnob; + WheelBox *d_timerWheel; + WheelBox *d_intervalWheel; + + Plot *d_plot; +}; diff --git a/qwt/examples/oscilloscope/oscilloscope.pro b/qwt/examples/oscilloscope/oscilloscope.pro new file mode 100644 index 000000000..6f2755262 --- /dev/null +++ b/qwt/examples/oscilloscope/oscilloscope.pro @@ -0,0 +1,31 @@ +################################################################ +# 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( $${PWD}/../examples.pri ) + +TARGET = oscilloscope + +HEADERS = \ + signaldata.h \ + plot.h \ + knob.h \ + wheelbox.h \ + samplingthread.h \ + curvedata.h \ + mainwindow.h + +SOURCES = \ + signaldata.cpp \ + plot.cpp \ + knob.cpp \ + wheelbox.cpp \ + samplingthread.cpp \ + curvedata.cpp \ + mainwindow.cpp \ + main.cpp diff --git a/qwt/examples/oscilloscope/plot.cpp b/qwt/examples/oscilloscope/plot.cpp new file mode 100644 index 000000000..df58b036b --- /dev/null +++ b/qwt/examples/oscilloscope/plot.cpp @@ -0,0 +1,232 @@ +#include "plot.h" +#include "curvedata.h" +#include "signaldata.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Plot::Plot(QWidget *parent): + QwtPlot(parent), + d_paintedPoints(0), + d_interval(0.0, 10.0), + d_timerId(-1) +{ + d_directPainter = new QwtPlotDirectPainter(); + + setAutoReplot(false); + + // The backing store is important, when working with widget + // overlays ( f.e rubberbands for zooming ). + // Here we don't have them and the internal + // backing store of QWidget is good enough. + + canvas()->setPaintAttribute(QwtPlotCanvas::BackingStore, false); + + +#if defined(Q_WS_X11) + // Even if not recommended by TrollTech, Qt::WA_PaintOutsidePaintEvent + // works on X11. This has a nice effect on the performance. + + canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); + + // Disabling the backing store of Qt improves the performance + // for the direct painter even more, but the canvas becomes + // a native window of the window system, receiving paint events + // for resize and expose operations. Those might be expensive + // when there are many points and the backing store of + // the canvas is disabled. So in this application + // we better don't both backing stores. + + if ( canvas()->testPaintAttribute( QwtPlotCanvas::BackingStore ) ) + { + canvas()->setAttribute(Qt::WA_PaintOnScreen, true); + canvas()->setAttribute(Qt::WA_NoSystemBackground, true); + } + +#endif + + initGradient(); + + plotLayout()->setAlignCanvasToScales(true); + + setAxisTitle(QwtPlot::xBottom, "Time [s]"); + setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); + setAxisScale(QwtPlot::yLeft, -200.0, 200.0); + + QwtPlotGrid *grid = new QwtPlotGrid(); + grid->setPen(QPen(Qt::gray, 0.0, Qt::DotLine)); + grid->enableX(true); + grid->enableXMin(true); + grid->enableY(true); + grid->enableYMin(false); + grid->attach(this); + + d_origin = new QwtPlotMarker(); + d_origin->setLineStyle(QwtPlotMarker::Cross); + d_origin->setValue(d_interval.minValue() + d_interval.width() / 2.0, 0.0); + d_origin->setLinePen(QPen(Qt::gray, 0.0, Qt::DashLine)); + d_origin->attach(this); + + d_curve = new QwtPlotCurve(); + d_curve->setStyle(QwtPlotCurve::Lines); + d_curve->setPen(QPen(Qt::green)); +#if 1 + d_curve->setRenderHint(QwtPlotItem::RenderAntialiased, true); +#endif +#if 1 + d_curve->setPaintAttribute(QwtPlotCurve::ClipPolygons, false); +#endif + d_curve->setData(new CurveData()); + d_curve->attach(this); +} + +Plot::~Plot() +{ + delete d_directPainter; +} + +void Plot::initGradient() +{ + QPalette pal = canvas()->palette(); + +#if QT_VERSION >= 0x040400 + QLinearGradient gradient( 0.0, 0.0, 1.0, 0.0 ); + gradient.setCoordinateMode( QGradient::StretchToDeviceMode ); + gradient.setColorAt(0.0, QColor( 0, 49, 110 ) ); + gradient.setColorAt(1.0, QColor( 0, 87, 174 ) ); + + pal.setBrush(QPalette::Window, QBrush(gradient)); +#else + pal.setBrush(QPalette::Window, QBrush( color )); +#endif + + canvas()->setPalette(pal); +} + +void Plot::start() +{ + d_clock.start(); + d_timerId = startTimer(10); +} + +void Plot::replot() +{ + CurveData *data = (CurveData *)d_curve->data(); + data->values().lock(); + + QwtPlot::replot(); + d_paintedPoints = data->size(); + + data->values().unlock(); +} + +void Plot::setIntervalLength(double interval) +{ + if ( interval > 0.0 && interval != d_interval.width() ) + { + d_interval.setMaxValue(d_interval.minValue() + interval); + setAxisScale(QwtPlot::xBottom, + d_interval.minValue(), d_interval.maxValue()); + + replot(); + } +} + +void Plot::updateCurve() +{ + CurveData *data = (CurveData *)d_curve->data(); + data->values().lock(); + + const int numPoints = data->size(); + if ( numPoints > d_paintedPoints ) + { + const bool doClip = !canvas()->testAttribute( Qt::WA_PaintOnScreen ); + if ( doClip ) + { + /* + Depending on the platform setting a clip might be an important + performance issue. F.e. for Qt Embedded this reduces the + part of the backing store that has to be copied out - maybe + to an unaccelerated frame buffer device. + */ + + const QwtScaleMap xMap = canvasMap( d_curve->xAxis() ); + const QwtScaleMap yMap = canvasMap( d_curve->yAxis() ); + + QRectF br = qwtBoundingRect( *data, + d_paintedPoints - 1, numPoints - 1 ); + + const QRect clipRect = QwtScaleMap::transform( xMap, yMap, br ).toRect(); + d_directPainter->setClipRegion( clipRect ); + } + + d_directPainter->drawSeries(d_curve, + d_paintedPoints - 1, numPoints - 1); + d_paintedPoints = numPoints; + } + + data->values().unlock(); +} + +void Plot::incrementInterval() +{ + d_interval = QwtInterval(d_interval.maxValue(), + d_interval.maxValue() + d_interval.width()); + + CurveData *data = (CurveData *)d_curve->data(); + data->values().clearStaleValues(d_interval.minValue()); + + // To avoid, that the grid is jumping, we disable + // the autocalculation of the ticks and shift them + // manually instead. + + QwtScaleDiv scaleDiv = *axisScaleDiv(QwtPlot::xBottom); + scaleDiv.setInterval(d_interval); + + for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) + { + QList ticks = scaleDiv.ticks(i); + for ( int j = 0; j < ticks.size(); j++ ) + ticks[j] += d_interval.width(); + scaleDiv.setTicks(i, ticks); + } + setAxisScaleDiv(QwtPlot::xBottom, scaleDiv); + + d_origin->setValue(d_interval.minValue() + d_interval.width() / 2.0, 0.0); + + d_paintedPoints = 0; + replot(); +} + +void Plot::timerEvent(QTimerEvent *event) +{ + if ( event->timerId() == d_timerId ) + { + updateCurve(); + + const double elapsed = d_clock.elapsed() / 1000.0; + if ( elapsed > d_interval.maxValue() ) + incrementInterval(); + + return; + } + + QwtPlot::timerEvent(event); +} + +void Plot::resizeEvent(QResizeEvent *event) +{ + d_directPainter->reset(); + QwtPlot::resizeEvent(event); +} + +void Plot::showEvent( QShowEvent * ) +{ + replot(); +} diff --git a/qwt/examples/oscilloscope/plot.h b/qwt/examples/oscilloscope/plot.h new file mode 100644 index 000000000..27a9d3210 --- /dev/null +++ b/qwt/examples/oscilloscope/plot.h @@ -0,0 +1,44 @@ +#include +#include +#include + +class QwtPlotCurve; +class QwtPlotMarker; +class QwtPlotDirectPainter; + +class Plot: public QwtPlot +{ + Q_OBJECT + +public: + Plot(QWidget * = NULL); + virtual ~Plot(); + + void start(); + virtual void replot(); + +public Q_SLOTS: + void setIntervalLength(double); + +protected: + virtual void showEvent(QShowEvent *); + virtual void resizeEvent(QResizeEvent *); + virtual void timerEvent(QTimerEvent *); + +private: + void initGradient(); + + void updateCurve(); + void incrementInterval(); + + QwtPlotMarker *d_origin; + QwtPlotCurve *d_curve; + int d_paintedPoints; + + QwtPlotDirectPainter *d_directPainter; + + QwtInterval d_interval; + int d_timerId; + + QwtSystemClock d_clock; +}; diff --git a/qwt/examples/oscilloscope/samplingthread.cpp b/qwt/examples/oscilloscope/samplingthread.cpp new file mode 100644 index 000000000..9d617e52c --- /dev/null +++ b/qwt/examples/oscilloscope/samplingthread.cpp @@ -0,0 +1,54 @@ +#include "samplingthread.h" +#include "signaldata.h" +#include +#include + +#if QT_VERSION < 0x040600 +#define qFastSin(x) ::sin(x) +#endif + +SamplingThread::SamplingThread(QObject *parent): + QwtSamplingThread(parent), + d_frequency(5.0), + d_amplitude(20.0) +{ +} + +void SamplingThread::setFrequency(double frequency) +{ + d_frequency = frequency; +} + +double SamplingThread::frequency() const +{ + return d_frequency; +} + +void SamplingThread::setAmplitude(double amplitude) +{ + d_amplitude = amplitude; +} + +double SamplingThread::amplitude() const +{ + return d_amplitude; +} + +void SamplingThread::sample(double elapsed) +{ + if ( d_frequency > 0.0 ) + { + const QPointF s(elapsed, value(elapsed)); + SignalData::instance().append(s); + } +} + +double SamplingThread::value(double timeStamp) const +{ + const double period = 1.0 / d_frequency; + + const double x = ::fmod(timeStamp, period); + const double v = d_amplitude * qFastSin(x / period * 2 * M_PI); + + return v; +} diff --git a/qwt/examples/oscilloscope/samplingthread.h b/qwt/examples/oscilloscope/samplingthread.h new file mode 100644 index 000000000..551d8acca --- /dev/null +++ b/qwt/examples/oscilloscope/samplingthread.h @@ -0,0 +1,25 @@ +#include + +class SamplingThread: public QwtSamplingThread +{ + Q_OBJECT + +public: + SamplingThread(QObject *parent = NULL); + + double frequency() const; + double amplitude() const; + +public Q_SLOTS: + void setAmplitude(double); + void setFrequency(double); + +protected: + virtual void sample(double elapsed); + +private: + virtual double value(double timeStamp) const; + + double d_frequency; + double d_amplitude; +}; diff --git a/qwt/examples/oscilloscope/signaldata.cpp b/qwt/examples/oscilloscope/signaldata.cpp new file mode 100644 index 000000000..1e07cc389 --- /dev/null +++ b/qwt/examples/oscilloscope/signaldata.cpp @@ -0,0 +1,133 @@ +#include "signaldata.h" +#include +#include +#include + +class SignalData::PrivateData +{ +public: + PrivateData(): + boundingRect(1.0, 1.0, -2.0, -2.0) // invalid + { + values.reserve(1000); + } + + inline void append(const QPointF &sample) + { + values.append(sample); + + // adjust the bounding rectangle + + if ( boundingRect.width() < 0 || boundingRect.height() < 0 ) + { + boundingRect.setRect(sample.x(), sample.y(), 0.0, 0.0); + } + else + { + boundingRect.setRight(sample.x()); + + if ( sample.y() > boundingRect.bottom() ) + boundingRect.setBottom(sample.y()); + + if ( sample.y() < boundingRect.top() ) + boundingRect.setTop(sample.y()); + } + } + + QReadWriteLock lock; + + QVector values; + QRectF boundingRect; + + QMutex mutex; // protecting pendingValues + QVector pendingValues; +}; + +SignalData::SignalData() +{ + d_data = new PrivateData(); +} + +SignalData::~SignalData() +{ + delete d_data; +} + +int SignalData::size() const +{ + return d_data->values.size(); +} + +QPointF SignalData::value(int index) const +{ + return d_data->values[index]; +} + +QRectF SignalData::boundingRect() const +{ + return d_data->boundingRect; +} + +void SignalData::lock() +{ + d_data->lock.lockForRead(); +} + +void SignalData::unlock() +{ + d_data->lock.unlock(); +} + +void SignalData::append(const QPointF &sample) +{ + d_data->mutex.lock(); + d_data->pendingValues += sample; + + const bool isLocked = d_data->lock.tryLockForWrite(); + if ( isLocked ) + { + const int numValues = d_data->pendingValues.size(); + const QPointF *pendingValues = d_data->pendingValues.data(); + + for ( int i = 0; i < numValues; i++ ) + d_data->append(pendingValues[i]); + + d_data->pendingValues.clear(); + + d_data->lock.unlock(); + } + + d_data->mutex.unlock(); +} + +void SignalData::clearStaleValues(double limit) +{ + d_data->lock.lockForWrite(); + + d_data->boundingRect = QRectF(1.0, 1.0, -2.0, -2.0); // invalid + + const QVector values = d_data->values; + d_data->values.clear(); + d_data->values.reserve(values.size()); + + int index; + for ( index = values.size() - 1; index >= 0; index-- ) + { + if ( values[index].x() < limit ) + break; + } + + if ( index > 0 ) + d_data->append(values[index++]); + + while ( index < values.size() - 1 ) + d_data->append(values[index++]); + + d_data->lock.unlock(); +} + +SignalData &SignalData::instance() +{ + static SignalData valueVector; + return valueVector; +} diff --git a/qwt/examples/oscilloscope/signaldata.h b/qwt/examples/oscilloscope/signaldata.h new file mode 100644 index 000000000..d487a3ba9 --- /dev/null +++ b/qwt/examples/oscilloscope/signaldata.h @@ -0,0 +1,33 @@ +#ifndef _SIGNAL_DATA_H_ +#define _SIGNAL_DATA_H_ 1 + +#include + +class SignalData +{ +public: + static SignalData &instance(); + + void append(const QPointF &pos); + void clearStaleValues(double min); + + int size() const; + QPointF value(int index) const; + + QRectF boundingRect() const; + + void lock(); + void unlock(); + +private: + SignalData(); + SignalData(const SignalData &); + SignalData &operator=( const SignalData & ); + + virtual ~SignalData(); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/qwt/examples/oscilloscope/wheelbox.cpp b/qwt/examples/oscilloscope/wheelbox.cpp new file mode 100644 index 000000000..e89b8a453 --- /dev/null +++ b/qwt/examples/oscilloscope/wheelbox.cpp @@ -0,0 +1,90 @@ +#include "wheelbox.h" +#include +#include +#include +#include +#include +#include + +class Wheel: public QwtWheel +{ +public: + Wheel(WheelBox *parent): + QwtWheel(parent) + { + setFocusPolicy(Qt::WheelFocus); + parent->installEventFilter(this); + } + + virtual bool eventFilter(QObject *object, QEvent *ev) + { + if ( ev->type() == QEvent::Wheel ) + { + QWheelEvent *we = (QWheelEvent *)ev; + + QWheelEvent wheelEvent(QPoint(5, 5), we->delta(), + we->buttons(), we->modifiers(), + we->orientation()); + + QApplication::sendEvent(this, &wheelEvent); + return true; + } + return QwtWheel::eventFilter(object, ev); + } +}; + +WheelBox::WheelBox(const QString &title, + double min, double max, double stepSize, QWidget *parent): + QWidget(parent) +{ + + d_number = new QLCDNumber(this); + d_number->setSegmentStyle(QLCDNumber::Filled); + d_number->setAutoFillBackground(true); + d_number->setFixedHeight(d_number->sizeHint().height() * 2 ); + d_number->setFocusPolicy(Qt::WheelFocus); + + QPalette pal(Qt::black); + pal.setColor(QPalette::WindowText, Qt::green); + d_number->setPalette(pal); + + d_wheel = new Wheel(this); + d_wheel->setOrientation(Qt::Vertical); + d_wheel->setRange(min, max, stepSize); + d_wheel->setFixedSize( + qRound(d_number->height() / 2.5), d_number->height()); + + d_number->setFocusProxy(d_wheel); + + QFont font("Helvetica", 10); + font.setBold(true); + + d_label = new QLabel(title, this); + d_label->setFont(font); + + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->setContentsMargins(0, 0, 0, 0); + hLayout->setSpacing(2); + hLayout->addWidget(d_number, 10); + hLayout->addWidget(d_wheel); + + QVBoxLayout *vLayout = new QVBoxLayout(this); + vLayout->addLayout(hLayout, 10); + vLayout->addWidget(d_label, 0, Qt::AlignTop | Qt::AlignHCenter); + + connect(d_wheel, SIGNAL(valueChanged(double)), + d_number, SLOT(display(double))); + connect(d_wheel, SIGNAL(valueChanged(double)), + this, SIGNAL(valueChanged(double))); +} + +void WheelBox::setValue(double value) +{ + d_wheel->setValue(value); + d_number->display(value); +} + +double WheelBox::value() const +{ + return d_wheel->value(); +} diff --git a/qwt/examples/oscilloscope/wheelbox.h b/qwt/examples/oscilloscope/wheelbox.h new file mode 100644 index 000000000..d79963e42 --- /dev/null +++ b/qwt/examples/oscilloscope/wheelbox.h @@ -0,0 +1,36 @@ +#ifndef _WHEELBOX_H_ +#define _WHEELBOX_H_ + +#include + +class QwtWheel; +class QLabel; +class QLCDNumber; + +class WheelBox: public QWidget +{ + Q_OBJECT + +public: + WheelBox(const QString &title, + double min, double max, double stepSize, + QWidget *parent = NULL); + + void setUnit(const QString &); + QString unit() const; + + void setValue(double value); + double value() const; + +Q_SIGNALS: + double valueChanged(double); + +private: + QLCDNumber *d_number; + QwtWheel *d_wheel; + QLabel *d_label; + + QString d_unit; +}; + +#endif diff --git a/qwt/examples/plotmatrix/main.cpp b/qwt/examples/plotmatrix/main.cpp new file mode 100644 index 000000000..a17dc61e7 --- /dev/null +++ b/qwt/examples/plotmatrix/main.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include "plotmatrix.h" + +class MainWindow: public PlotMatrix +{ +public: + MainWindow(); +}; + +MainWindow::MainWindow(): + PlotMatrix(3, 4) +{ + enableAxis(QwtPlot::yLeft); + enableAxis(QwtPlot::yRight); + enableAxis(QwtPlot::xBottom); + + for ( int row = 0; row < numRows(); row++ ) + { + const double v = qPow(10.0, row); + setAxisScale(QwtPlot::yLeft, row, -v, v); + setAxisScale(QwtPlot::yRight, row, -v, v); + } + + for ( int col = 0; col < numColumns(); col++ ) + { + const double v = qPow(10.0, col); + setAxisScale(QwtPlot::xBottom, col, -v, v); + setAxisScale(QwtPlot::xTop, col, -v, v); + } + + for ( int row = 0; row < numRows(); row++ ) + { + for ( int col = 0; col < numColumns(); col++ ) + { + QwtPlot *plt = plot(row, col); + plt->setCanvasBackground(QColor(Qt::darkBlue)); + + QwtPlotGrid *grid = new QwtPlotGrid(); + grid->enableXMin(true); + grid->setMajPen(QPen(Qt::white, 0, Qt::DotLine)); + grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine)); + grid->attach(plt); + } + } +} + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + MainWindow mainWindow; + + mainWindow.resize(800,600); + mainWindow.show(); + + return a.exec(); +} diff --git a/qwt/examples/plotmatrix/plotmatrix.cpp b/qwt/examples/plotmatrix/plotmatrix.cpp new file mode 100644 index 000000000..b75b1d49e --- /dev/null +++ b/qwt/examples/plotmatrix/plotmatrix.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 + *****************************************************************************/ + +// vim: expandtab + +#include +#include +#include +#include +#include +#include "plotmatrix.h" + +class PlotMatrix::PrivateData +{ +public: + PrivateData(): + inScaleSync(false) + { + isAxisEnabled[QwtPlot::xBottom] = true; + isAxisEnabled[QwtPlot::xTop] = false; + isAxisEnabled[QwtPlot::yLeft] = true; + isAxisEnabled[QwtPlot::yRight] = false; + } + + bool isAxisEnabled[QwtPlot::axisCnt]; + QVector plotWidgets; + mutable bool inScaleSync; +}; + +PlotMatrix::PlotMatrix( int numRows, int numColumns, QWidget *parent): + QFrame(parent) +{ + d_data = new PrivateData(); + d_data->plotWidgets.resize(numRows * numColumns); + + QGridLayout *layout = new QGridLayout(this); + for ( int row = 0; row < numRows; row++ ) + { + for ( int col = 0; col < numColumns; col++ ) + { + QwtPlot *plot = new QwtPlot(this); + layout->addWidget(plot, row, col); + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + connect(plot->axisWidget(axis), + SIGNAL(scaleDivChanged()), SLOT(scaleDivChanged()) ); + } + d_data->plotWidgets[row * numColumns + col] = plot; + } + } + + updateLayout(); +} + +PlotMatrix::~PlotMatrix() +{ + delete d_data; +} + +int PlotMatrix::numRows() const +{ + const QGridLayout *l = qobject_cast(layout()); + if ( l ) + return l->rowCount(); + + return 0; +} + +int PlotMatrix::numColumns() const +{ + const QGridLayout *l = qobject_cast(layout()); + if ( l ) + return l->columnCount(); + return 0; +} + +QwtPlot* PlotMatrix::plot(int row, int column) +{ + const int index = row * numColumns() + column; + if ( index < (int)d_data->plotWidgets.size() ) + return d_data->plotWidgets[index]; + + return NULL; +} + +const QwtPlot* PlotMatrix::plot(int row, int column) const +{ + const int index = row * numColumns() + column; + if ( index < (int)d_data->plotWidgets.size() ) + return d_data->plotWidgets[index]; + + return NULL; +} + +void PlotMatrix::enableAxis(int axis, bool tf) +{ + if ( axis >= 0 && axis < QwtPlot::axisCnt ) + { + if ( tf != d_data->isAxisEnabled[axis] ) + { + d_data->isAxisEnabled[axis] = tf; + updateLayout(); + } + } +} + +bool PlotMatrix::axisEnabled(int axis) const +{ + if ( axis >= 0 && axis < QwtPlot::axisCnt ) + return d_data->isAxisEnabled[axis]; + + return false; +} + +void PlotMatrix::setAxisScale(int axis, int rowOrColumn, + double min, double max, double step) +{ + int row = 0; + int col = 0; + + if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) + col = rowOrColumn; + else + row = rowOrColumn; + + QwtPlot *plt = plot(row, col); + if ( plt ) + { + plt->setAxisScale(axis, min, max, step); + plt->updateAxes(); + } +} + +void PlotMatrix::scaleDivChanged() +{ + if ( d_data->inScaleSync ) + return; + + d_data->inScaleSync = true; + + QwtPlot *plt = NULL; + int axisId = -1; + int rowOrColumn = -1; + + // find the changed axis + for ( int row = 0; row < numRows(); row++ ) + { + for ( int col = 0; col < numColumns(); col++ ) + { + QwtPlot *p = plot(row, col); + if ( p ) + { + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + if ( p->axisWidget(axis) == sender() ) + { + plt = p; + axisId = axis; + if ( axisId == QwtPlot::xBottom || axisId == QwtPlot::xTop ) + rowOrColumn = col; + else + rowOrColumn = row; + + } + } + } + } + } + + if ( plt ) + { + + // synchronize the axes + if ( axisId == QwtPlot::xBottom || axisId == QwtPlot::xTop ) + { + for ( int row = 0; row < numRows(); row++ ) + { + QwtPlot *p = plot(row, rowOrColumn); + if ( p != plt ) + p->setAxisScaleDiv(axisId, *plt->axisScaleDiv(axisId)); + } + } + else + { + for ( int col = 0; col < numColumns(); col++ ) + { + QwtPlot *p = plot(rowOrColumn, col); + if ( p != plt ) + p->setAxisScaleDiv(axisId, *plt->axisScaleDiv(axisId)); + } + } + + updateLayout(); + } + + d_data->inScaleSync = false; +} + +void PlotMatrix::updateLayout() +{ + for ( int row = 0; row < numRows(); row++ ) + { + for ( int col = 0; col < numColumns(); col++ ) + { + QwtPlot *p = plot(row, col); + if ( p ) + { + bool showAxis[QwtPlot::axisCnt]; + showAxis[QwtPlot::xBottom] = + axisEnabled(QwtPlot::xBottom) && row == numRows() - 1; + showAxis[QwtPlot::xTop] = + axisEnabled(QwtPlot::xTop) && row == 0; + showAxis[QwtPlot::yLeft] = + axisEnabled(QwtPlot::yLeft) && col == 0; + showAxis[QwtPlot::yRight] = + axisEnabled(QwtPlot::yRight) && col == numColumns() - 1; + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) + p->enableAxis(axis, showAxis[axis]); + else + { + p->enableAxis(axis, true); + + QwtScaleDraw *sd = p->axisScaleDraw(axis); + sd->enableComponent( + QwtScaleDraw::Backbone, showAxis[axis]); + sd->enableComponent( + QwtScaleDraw::Ticks, showAxis[axis]); + sd->enableComponent( + QwtScaleDraw::Labels, showAxis[axis]); + } + } + } + } + } + + for ( int col = 0; col < numColumns(); col++ ) + { + alignVAxes(col, QwtPlot::yLeft); + alignVAxes(col, QwtPlot::yRight); + } + + for ( int row = 0; row < numRows(); row++ ) + { + for ( int col = 0; col < numColumns(); col++ ) + { + QwtPlot *p = plot(row, col); + if ( p ) + p->replot(); + } + } +} + +void PlotMatrix::alignVAxes(int col, int axis) +{ + if ( axis != QwtPlot::yLeft && axis != QwtPlot::yRight ) + return; + + int maxExtent = 0; + for ( int row = 0; row < numRows(); row++ ) + { + QwtPlot *p = plot(row, col); + if ( p ) + { + QwtScaleWidget *scaleWidget = p->axisWidget(axis); + + QwtScaleDraw *sd = scaleWidget->scaleDraw(); + sd->setMinimumExtent(0); + + const int extent = sd->extent( scaleWidget->font() ); + if ( extent > maxExtent ) + maxExtent = extent; + } + } + for ( int row = 0; row < numRows(); row++ ) + { + QwtPlot *p = plot(row, col); + if ( p ) + { + QwtScaleWidget *scaleWidget = p->axisWidget(axis); + scaleWidget->scaleDraw()->setMinimumExtent(maxExtent); + } + } +} diff --git a/qwt/examples/plotmatrix/plotmatrix.h b/qwt/examples/plotmatrix/plotmatrix.h new file mode 100644 index 000000000..ab20f29f7 --- /dev/null +++ b/qwt/examples/plotmatrix/plotmatrix.h @@ -0,0 +1,38 @@ +#ifndef _PLOT_MATRIX_H_ +#define _PLOT_MATRIX_H_ + +#include +#include + +class PlotMatrix: public QFrame +{ + Q_OBJECT + +public: + PlotMatrix( int rows, int columns, QWidget * parent = NULL); + virtual ~PlotMatrix(); + + int numRows() const; + int numColumns() const; + + QwtPlot* plot(int row, int column); + const QwtPlot* plot(int row, int column) const; + + void enableAxis(int axisId, bool tf = true); + bool axisEnabled(int axisId) const; + + void setAxisScale(int axisId, int rowOrColumn, + double min, double max, double step = 0); + +private Q_SLOTS: + void scaleDivChanged(); + +private: + void updateLayout(); + void alignVAxes(int col, int axis); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/qwt/examples/many_axes/many_axes.pro b/qwt/examples/plotmatrix/plotmatrix.pro similarity index 61% rename from qwt/examples/many_axes/many_axes.pro rename to qwt/examples/plotmatrix/plotmatrix.pro index 553b3ee41..f092bebe7 100644 --- a/qwt/examples/many_axes/many_axes.pro +++ b/qwt/examples/plotmatrix/plotmatrix.pro @@ -1,21 +1,19 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) -TARGET = many_axes -CONFIG += static - -SOURCES = \ - many_axes.cpp \ - mainwindow.cpp +TARGET = plotmatrix HEADERS = \ - plot.h \ - mainwindow.h + plotmatrix.h + +SOURCES = \ + plotmatrix.cpp \ + main.cpp diff --git a/qwt/examples/radio/ampfrm.cpp b/qwt/examples/radio/ampfrm.cpp index a40580280..2e0dec3de 100644 --- a/qwt/examples/radio/ampfrm.cpp +++ b/qwt/examples/radio/ampfrm.cpp @@ -1,13 +1,18 @@ #include "ampfrm.h" #include +#include +#include +#include #include #include #include #include #include -#include -#include -#include + +#if QT_VERSION < 0x040600 +#define qFastSin(x) ::sin(x) +#define qFastCos(x) ::cos(x) +#endif class Knob: public QWidget { @@ -19,12 +24,20 @@ public: d_knob->setRange(min, max, 0,1); d_knob->setScaleMaxMajor(10); + d_knob->setKnobStyle(QwtKnob::Raised); d_knob->setKnobWidth(50); + d_knob->setBorderWidth(2); + d_knob->setMarkerStyle(QwtKnob::Notch); + d_knob->setMarkerSize( 8 ); + + d_knob->scaleDraw()->setTickLength( QwtScaleDiv::MinorTick, 4 ); + d_knob->scaleDraw()->setTickLength( QwtScaleDiv::MediumTick, 4 ); + d_knob->scaleDraw()->setTickLength( QwtScaleDiv::MajorTick, 6 ); d_label = new QLabel(title, this); d_label->setAlignment(Qt::AlignTop | Qt::AlignHCenter); - setSizePolicy(QSizePolicy::MinimumExpanding, + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); } @@ -33,20 +46,25 @@ public: QSize sz1 = d_knob->sizeHint(); QSize sz2 = d_label->sizeHint(); - const int w = qwtMax(sz1.width(), sz2.width()); + const int w = qMax(sz1.width(), sz2.width()); const int h = sz1.height() + sz2.height(); - - int off = d_knob->scaleDraw()->extent(QPen(), d_knob->font()); + + int off = d_knob->scaleDraw()->extent(d_knob->font()); off -= 10; // spacing return QSize(w, h - off); } + void setValue( double value ) + { + d_knob->setValue( value ); + } + double value() const { return d_knob->value(); } - + protected: virtual void resizeEvent(QResizeEvent *e) { @@ -58,7 +76,7 @@ protected: sz.width(), h); h = d_knob->sizeHint().height(); - int off = d_knob->scaleDraw()->extent(QPen(), d_knob->font()); + int off = d_knob->scaleDraw()->extent(d_knob->font()); off -= 10; // spacing d_knob->setGeometry(0, d_label->pos().y() - h + off, @@ -76,13 +94,13 @@ public: Thermo(const QString &title, QWidget *parent): QWidget(parent) { - d_thermo = new QwtThermo(this); - d_thermo->setPipeWidth(6); - d_thermo->setRange(-40,10); - d_thermo->setFillColor(Qt::green); - d_thermo->setAlarmColor(Qt::red); - d_thermo->setAlarmLevel(0.0); - d_thermo->setAlarmEnabled(true); + d_thermo = new QwtThermo( this ); + d_thermo->setPipeWidth( 6 ); + d_thermo->setRange( -40, 10 ); + d_thermo->setFillBrush( Qt::green ); + d_thermo->setAlarmBrush( Qt::red ); + d_thermo->setAlarmLevel( 0.0 ); + d_thermo->setAlarmEnabled( true ); QLabel *label = new QLabel(title, this); label->setAlignment(Qt::AlignTop | Qt::AlignLeft); @@ -103,7 +121,7 @@ private: QwtThermo *d_thermo; }; -AmpFrame::AmpFrame(QWidget *p): +AmpFrame::AmpFrame(QWidget *p): QFrame(p) { d_knbVolume = new Knob("Volume", 0.0, 10.0, this); @@ -127,33 +145,34 @@ AmpFrame::AmpFrame(QWidget *p): layout->addSpacing(10); layout->addWidget(d_thmRight); - (void)startTimer(50); + d_knbVolume->setValue( 7.0 ); + (void)startTimer(50); } void AmpFrame::timerEvent(QTimerEvent *) { static double phs = 0; - + // // This amplifier generates its own input signal... // - const double sig_bass = (1.0 + 0.1 * d_knbBass->value()) - * sin(13.0 * phs); - const double sig_mid_l = sin(17.0 * phs); - const double sig_mid_r = cos(17.5 * phs); - const double sig_trbl_l = 0.5 * (1.0 + 0.1 * d_knbTreble->value()) - * sin(35.0 * phs); - const double sig_trbl_r = 0.5 * (1.0 + 0.1 * d_knbTreble->value()) - * sin(34.0 * phs); + const double sig_bass = (1.0 + 0.1 * d_knbBass->value()) + * qFastSin(13.0 * phs); + const double sig_mid_l = qFastSin(17.0 * phs); + const double sig_mid_r = qFastCos(17.5 * phs); + const double sig_trbl_l = 0.5 * (1.0 + 0.1 * d_knbTreble->value()) + * qFastSin(35.0 * phs); + const double sig_trbl_r = 0.5 * (1.0 + 0.1 * d_knbTreble->value()) + * qFastSin(34.0 * phs); - double sig_l = 0.05 * d_master * d_knbVolume->value() + double sig_l = 0.05 * d_master * d_knbVolume->value() * qwtSqr(sig_bass + sig_mid_l + sig_trbl_l); - double sig_r = 0.05 * d_master * d_knbVolume->value() + double sig_r = 0.05 * d_master * d_knbVolume->value() * qwtSqr(sig_bass + sig_mid_r + sig_trbl_r); - - double balance = 0.1 * d_knbBalance->value(); - if (balance > 0) + + double balance = 0.1 * d_knbBalance->value(); + if (balance > 0) sig_l *= (1.0 - balance); else sig_r *= (1.0 + balance); @@ -166,13 +185,13 @@ void AmpFrame::timerEvent(QTimerEvent *) if (sig_r > 0.01) sig_r = 20.0 * log10(sig_r); else - sig_r = - 40.0; + sig_r = - 40.0; d_thmLeft->setValue(sig_l); d_thmRight->setValue(sig_r); phs += M_PI / 100; - if (phs > M_PI) + if (phs > M_PI) phs = 0; } diff --git a/qwt/examples/radio/ampfrm.h b/qwt/examples/radio/ampfrm.h index c642a57cc..940b9cad0 100644 --- a/qwt/examples/radio/ampfrm.h +++ b/qwt/examples/radio/ampfrm.h @@ -9,21 +9,18 @@ class AmpFrame : public QFrame public: AmpFrame(QWidget *); -public slots: +public Q_SLOTS: void setMaster(double v); protected: void timerEvent(QTimerEvent *); private: - Knob *d_knbVolume; - Knob *d_knbBalance; - Knob *d_knbTreble; - Knob *d_knbBass; + Knob *d_knbVolume; + Knob *d_knbBalance; + Knob *d_knbTreble; + Knob *d_knbBass; Thermo *d_thmLeft; Thermo *d_thmRight; double d_master; }; - - - diff --git a/qwt/examples/radio/mainwindow.cpp b/qwt/examples/radio/mainwindow.cpp new file mode 100644 index 000000000..838078799 --- /dev/null +++ b/qwt/examples/radio/mainwindow.cpp @@ -0,0 +1,60 @@ +#include +#include "tunerfrm.h" +#include "ampfrm.h" +#include "mainwindow.h" + +MainWindow::MainWindow(): + QWidget() +{ + TunerFrame *frmTuner = new TunerFrame(this); + frmTuner->setFrameStyle(QFrame::Panel|QFrame::Raised); + + AmpFrame *frmAmp = new AmpFrame(this); + frmAmp->setFrameStyle(QFrame::Panel|QFrame::Raised); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(frmTuner); + layout->addWidget(frmAmp); + + connect(frmTuner, SIGNAL(fieldChanged(double)), + frmAmp, SLOT(setMaster(double))); + + frmTuner->setFreq(90.0); + + setPalette( QPalette( QColor( 192, 192, 192 ) ) ); + updateGradient(); +} + +void MainWindow::resizeEvent( QResizeEvent * ) +{ +#ifdef Q_WS_X11 + updateGradient(); +#endif +} + +void MainWindow::updateGradient() +{ + QPalette pal = palette(); + + const QColor buttonColor = pal.color( QPalette::Button ); + const QColor lightColor = pal.color( QPalette::Light ); + const QColor midLightColor = pal.color( QPalette::Midlight ); + +#ifdef Q_WS_X11 + // Qt 4.7.1: QGradient::StretchToDeviceMode is buggy on X11 + + QLinearGradient gradient( rect().topLeft(), rect().topRight() ); +#else + QLinearGradient gradient( 0, 0, 1, 0 ); + gradient.setCoordinateMode( QGradient::StretchToDeviceMode ); +#endif + + gradient.setColorAt( 0.0, midLightColor ); + gradient.setColorAt( 0.7, buttonColor ); + gradient.setColorAt( 1.0, buttonColor ); + + pal.setBrush( QPalette::Window, gradient ); + setPalette( pal ); +} diff --git a/qwt/examples/radio/mainwindow.h b/qwt/examples/radio/mainwindow.h new file mode 100644 index 000000000..4159f4a9b --- /dev/null +++ b/qwt/examples/radio/mainwindow.h @@ -0,0 +1,13 @@ +#include + +class MainWindow : public QWidget +{ +public: + MainWindow(); + +protected: + virtual void resizeEvent( QResizeEvent * ); + +private: + void updateGradient(); +}; diff --git a/qwt/examples/radio/radio.cpp b/qwt/examples/radio/radio.cpp index 377f871c2..646df24f9 100644 --- a/qwt/examples/radio/radio.cpp +++ b/qwt/examples/radio/radio.cpp @@ -1,39 +1,11 @@ #include -#include -#include "tunerfrm.h" -#include "ampfrm.h" -#include "radio.h" - -MainWin::MainWin(): - QWidget() -{ - TunerFrame *frmTuner = new TunerFrame(this); - frmTuner->setFrameStyle(QFrame::Panel|QFrame::Raised); - - AmpFrame *frmAmp = new AmpFrame(this); - frmAmp->setFrameStyle(QFrame::Panel|QFrame::Raised); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(frmTuner); - layout->addWidget(frmAmp); - - connect(frmTuner, SIGNAL(fieldChanged(double)), - frmAmp, SLOT(setMaster(double))); - - frmTuner->setFreq(90.0); -} +#include "mainwindow.h" int main (int argc, char **argv) { QApplication a(argc, argv); - MainWin w; - -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif + MainWindow w; w.show(); return a.exec(); diff --git a/qwt/examples/radio/radio.h b/qwt/examples/radio/radio.h deleted file mode 100644 index 79fe1f6ca..000000000 --- a/qwt/examples/radio/radio.h +++ /dev/null @@ -1,9 +0,0 @@ -#include - -class MainWin : public QWidget -{ -public: - MainWin(); -}; - - diff --git a/qwt/examples/radio/radio.pro b/qwt/examples/radio/radio.pro index 0fc4730ce..6149808f8 100644 --- a/qwt/examples/radio/radio.pro +++ b/qwt/examples/radio/radio.pro @@ -1,22 +1,23 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = radio HEADERS = \ - radio.h \ - ampfrm.h \ - tunerfrm.h + mainwindow.h \ + ampfrm.h \ + tunerfrm.h SOURCES = \ - radio.cpp \ - ampfrm.cpp \ - tunerfrm.cpp + mainwindow.cpp \ + ampfrm.cpp \ + tunerfrm.cpp \ + radio.cpp diff --git a/qwt/examples/radio/tunerfrm.cpp b/qwt/examples/radio/tunerfrm.cpp index c26c581c5..ad9440d9c 100644 --- a/qwt/examples/radio/tunerfrm.cpp +++ b/qwt/examples/radio/tunerfrm.cpp @@ -6,6 +6,11 @@ #include #include "tunerfrm.h" +#if QT_VERSION < 0x040600 +#define qFastSin(x) ::sin(x) +#define qFastCos(x) ::cos(x) +#endif + class TuningThermo: public QWidget { public: @@ -15,7 +20,7 @@ public: d_thermo = new QwtThermo(this); d_thermo->setOrientation(Qt::Horizontal, QwtThermo::NoScale); d_thermo->setRange(0.0, 1.0); - d_thermo->setFillColor(Qt::green); + d_thermo->setFillBrush( Qt::green ); QLabel *label = new QLabel("Tuning", this); label->setAlignment(Qt::AlignCenter); @@ -37,38 +42,38 @@ private: QwtThermo *d_thermo; }; -TunerFrame::TunerFrame(QWidget *parent): +TunerFrame::TunerFrame(QWidget *parent): QFrame(parent) { - d_sldFreq = new QwtSlider(this, Qt::Horizontal, QwtSlider::TopScale); - d_sldFreq->setRange(87.5, 108, 0.01, 10); - d_sldFreq->setScaleMaxMinor(5); - d_sldFreq->setScaleMaxMajor(12); - d_sldFreq->setThumbLength(80); - d_sldFreq->setBorderWidth(1); + d_sliderFrequency = new QwtSlider(this, Qt::Horizontal, QwtSlider::TopScale); + d_sliderFrequency->setRange(87.5, 108, 0.01, 10); + d_sliderFrequency->setScaleMaxMinor(5); + d_sliderFrequency->setScaleMaxMajor(12); + d_sliderFrequency->setHandleSize(80, 20 ); + d_sliderFrequency->setBorderWidth(1); - d_thmTune = new TuningThermo(this); + d_thermoTune = new TuningThermo(this); - d_whlFreq = new QwtWheel(this); - d_whlFreq->setMass(0.5); - d_whlFreq->setRange(87.5, 108, 0.01); - d_whlFreq->setTotalAngle(3600.0); - d_whlFreq->setFixedHeight(30); + d_wheelFrequency = new QwtWheel(this); + d_wheelFrequency->setMass(0.5); + d_wheelFrequency->setRange(87.5, 108, 0.01); + d_wheelFrequency->setTotalAngle(3600.0); + d_wheelFrequency->setFixedHeight(30); - connect(d_whlFreq, SIGNAL(valueChanged(double)), SLOT(adjustFreq(double))); - connect(d_sldFreq, SIGNAL(valueChanged(double)), SLOT(adjustFreq(double))); + connect(d_wheelFrequency, SIGNAL(valueChanged(double)), SLOT(adjustFreq(double))); + connect(d_sliderFrequency, SIGNAL(valueChanged(double)), SLOT(adjustFreq(double))); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setMargin(10); mainLayout->setSpacing(5); - mainLayout->addWidget(d_sldFreq); + mainLayout->addWidget(d_sliderFrequency); QHBoxLayout *hLayout = new QHBoxLayout; hLayout->setMargin(0); - hLayout->addWidget(d_thmTune, 0); + hLayout->addWidget(d_thermoTune, 0); hLayout->addStretch(5); - hLayout->addWidget(d_whlFreq, 2); + hLayout->addWidget(d_wheelFrequency, 2); mainLayout->addLayout(hLayout); } @@ -78,19 +83,19 @@ void TunerFrame::adjustFreq(double frq) const double factor = 13.0 / (108 - 87.5); const double x = (frq - 87.5) * factor; - const double field = qwtSqr(sin(x) * cos(4.0 * x)); - - d_thmTune->setValue(field); + const double field = qwtSqr(qFastSin(x) * qFastCos(4.0 * x)); - if (d_sldFreq->value() != frq) - d_sldFreq->setValue(frq); - if (d_whlFreq->value() != frq) - d_whlFreq->setValue(frq); + d_thermoTune->setValue(field); - emit fieldChanged(field); + if (d_sliderFrequency->value() != frq) + d_sliderFrequency->setValue(frq); + if (d_wheelFrequency->value() != frq) + d_wheelFrequency->setValue(frq); + + Q_EMIT fieldChanged(field); } void TunerFrame::setFreq(double frq) { - d_whlFreq->setValue(frq); + d_wheelFrequency->setValue(frq); } diff --git a/qwt/examples/radio/tunerfrm.h b/qwt/examples/radio/tunerfrm.h index 017e0e30d..ddcaa532d 100644 --- a/qwt/examples/radio/tunerfrm.h +++ b/qwt/examples/radio/tunerfrm.h @@ -10,21 +10,17 @@ class TunerFrame : public QFrame public: TunerFrame(QWidget *p); -signals: +Q_SIGNALS: void fieldChanged(double f); -public slots: +public Q_SLOTS: void setFreq(double frq); -private slots: +private Q_SLOTS: void adjustFreq(double frq); private: - QwtWheel *d_whlFreq; - TuningThermo *d_thmTune; - QwtSlider *d_sldFreq; + QwtWheel *d_wheelFrequency; + TuningThermo *d_thermoTune; + QwtSlider *d_sliderFrequency; }; - - - - diff --git a/qwt/examples/rasterview/main.cpp b/qwt/examples/rasterview/main.cpp new file mode 100644 index 000000000..e915374f6 --- /dev/null +++ b/qwt/examples/rasterview/main.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include +#include "plot.h" + +class MainWindow: public QMainWindow +{ +public: + MainWindow(QWidget * = NULL); +}; + +MainWindow::MainWindow(QWidget *parent): + QMainWindow(parent) +{ + Plot *plot = new Plot(this); + setCentralWidget(plot); + + QToolBar *toolBar = new QToolBar(this); + + QComboBox *rasterBox = new QComboBox(toolBar); + rasterBox->setStyle(new QWindowsStyle() ); + rasterBox->addItem("Wikipedia"); + + toolBar->addWidget(new QLabel("Data ", toolBar)); + toolBar->addWidget(rasterBox); + toolBar->addSeparator(); + + QComboBox *modeBox = new QComboBox(toolBar); + modeBox->setStyle(new QWindowsStyle() ); + modeBox->addItem("Nearest Neighbour"); + modeBox->addItem("Bilinear Interpolation"); + + toolBar->addWidget(new QLabel("Resampling ", toolBar)); + toolBar->addWidget(modeBox); + + toolBar->addSeparator(); + + QToolButton *btnExport = new QToolButton(toolBar); + btnExport->setText("Export"); + btnExport->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + toolBar->addWidget(btnExport); + + addToolBar(toolBar); + + connect(modeBox, SIGNAL(activated(int)), plot, SLOT(setResampleMode(int))); + connect(btnExport, SIGNAL(clicked()), plot, SLOT(exportPlot()) ); +} + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + MainWindow mainWindow; + mainWindow.resize(600,400); + mainWindow.show(); + + return a.exec(); +} diff --git a/qwt/examples/rasterview/plot.cpp b/qwt/examples/rasterview/plot.cpp new file mode 100644 index 000000000..6472464dd --- /dev/null +++ b/qwt/examples/rasterview/plot.cpp @@ -0,0 +1,146 @@ +#include "plot.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RasterData: public QwtMatrixRasterData +{ +public: + RasterData() + { + const double matrix[] = + { + 1, 2, 4, 1, + 6, 3, 5, 2, + 4, 2, 1, 5, + 5, 4, 2, 3 + }; + + QVector values; + for ( uint i = 0; i < sizeof(matrix) / sizeof(double); i++ ) + values += matrix[i]; + + const int numColumns = 4; + setValueMatrix(values, numColumns); + + setInterval( Qt::XAxis, + QwtInterval( -0.5, 3.5, QwtInterval::ExcludeMaximum ) ); + setInterval( Qt::YAxis, + QwtInterval( -0.5, 3.5, QwtInterval::ExcludeMaximum ) ); + setInterval( Qt::ZAxis, QwtInterval(1.0, 6.0) ); + } +}; + +class ColorMap: public QwtLinearColorMap +{ +public: + ColorMap(): + QwtLinearColorMap(Qt::darkBlue, Qt::darkRed) + { + addColorStop(0.2, Qt::blue); + addColorStop(0.4, Qt::cyan); + addColorStop(0.6, Qt::yellow); + addColorStop(0.8, Qt::red); + } +}; + +Plot::Plot(QWidget *parent): + QwtPlot(parent) +{ +#if 0 + QwtPlotGrid *grid = new QwtPlotGrid(); + grid->setPen(QPen(Qt::DotLine)); + grid->attach(this); +#endif + + d_spectrogram = new QwtPlotSpectrogram(); + d_spectrogram->setRenderThreadCount(0); // use system specific thread count + + d_spectrogram->setColorMap( new ColorMap() ); + + d_spectrogram->setData(new RasterData()); + d_spectrogram->attach(this); + + const QwtInterval zInterval = d_spectrogram->data()->interval( Qt::ZAxis ); + // A color bar on the right axis + QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight); + rightAxis->setColorBarEnabled(true); + rightAxis->setColorBarWidth(40); + rightAxis->setColorMap(zInterval, new ColorMap() ); + + setAxisScale(QwtPlot::yRight, zInterval.minValue(), zInterval.maxValue() ); + enableAxis(QwtPlot::yRight); + + plotLayout()->setAlignCanvasToScales(true); + + setAxisScale(QwtPlot::xBottom, 0.0, 3.0); + setAxisMaxMinor(QwtPlot::xBottom, 0); + setAxisScale(QwtPlot::yLeft, 0.0, 3.0); + setAxisMaxMinor(QwtPlot::yLeft, 0); + + QwtPlotMagnifier *magnifier = new QwtPlotMagnifier( canvas() ); + magnifier->setAxisEnabled( QwtPlot::yRight, false); + + QwtPlotPanner *panner = new QwtPlotPanner( canvas() ); + panner->setAxisEnabled( QwtPlot::yRight, false); + + canvas()->setBorderRadius( 10 ); +} + +void Plot::exportPlot() +{ + QString fileName = "rasterview.pdf"; + +#ifndef QT_NO_FILEDIALOG + const QList imageFormats = + QImageWriter::supportedImageFormats(); + + QStringList filter; + filter += "PDF Documents (*.pdf)"; +#ifndef QWT_NO_SVG + filter += "SVG Documents (*.svg)"; +#endif + filter += "Postscript Documents (*.ps)"; + + if ( imageFormats.size() > 0 ) + { + QString imageFilter("Images ("); + for ( int i = 0; i < imageFormats.size(); i++ ) + { + if ( i > 0 ) + imageFilter += " "; + imageFilter += "*."; + imageFilter += imageFormats[i]; + } + imageFilter += ")"; + + filter += imageFilter; + } + + fileName = QFileDialog::getSaveFileName( + this, "Export File Name", fileName, + filter.join(";;"), NULL, QFileDialog::DontConfirmOverwrite); +#endif + if ( !fileName.isEmpty() ) + { + QwtPlotRenderer renderer; + renderer.renderDocument(this, fileName, QSizeF(300, 200), 85); + } +} + +void Plot::setResampleMode(int mode) +{ + RasterData *data = (RasterData *)d_spectrogram->data(); + data->setResampleMode( (QwtMatrixRasterData::ResampleMode) mode); + + replot(); +} diff --git a/qwt/examples/rasterview/plot.h b/qwt/examples/rasterview/plot.h new file mode 100644 index 000000000..e1cfe6a2d --- /dev/null +++ b/qwt/examples/rasterview/plot.h @@ -0,0 +1,17 @@ +#include +#include + +class Plot: public QwtPlot +{ + Q_OBJECT + +public: + Plot(QWidget * = NULL); + +public Q_SLOTS: + void exportPlot(); + void setResampleMode(int); + +private: + QwtPlotSpectrogram *d_spectrogram; +}; diff --git a/qwt/examples/data_plot/data_plot.pro b/qwt/examples/rasterview/rasterview.pro similarity index 65% rename from qwt/examples/data_plot/data_plot.pro rename to qwt/examples/rasterview/rasterview.pro index 81ce4104e..942877140 100644 --- a/qwt/examples/data_plot/data_plot.pro +++ b/qwt/examples/rasterview/rasterview.pro @@ -1,20 +1,19 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) -TARGET = data_plot +TARGET = rasterview HEADERS = \ - data_plot.h + plot.h SOURCES = \ - data_plot.cpp \ - main.cpp - + plot.cpp \ + main.cpp diff --git a/qwt/examples/realtime_plot/README b/qwt/examples/realtime/README similarity index 89% rename from qwt/examples/realtime_plot/README rename to qwt/examples/realtime/README index 32c7f1393..68776401f 100644 --- a/qwt/examples/realtime_plot/README +++ b/qwt/examples/realtime/README @@ -1,7 +1,7 @@ 1) Incremental plots IncrementalPlot shows an example how to implement a plot that -displays growing data. +displays growing data. The example produces random data when you push the start button. With 'Timer' you can adjust the intervall between the @@ -9,8 +9,8 @@ the generation of the points, with 'Points' you can set the number of points to be generated. Unfortunately in Qt4 incremental painting is not possible with QPaintEngines -that doesn't support the QPaintEngine::PaintOutsidePaintEvent feature. -( These are all common paint engines beside the OpenGL engine, but this one +that doesn't support the QPaintEngine::PaintOutsidePaintEvent feature. +( These are all common paint engines beside the OpenGL engine, but this one is not supported by Qwt yet. ) That is the reason why you can see much faster repaints with Qt3. @@ -19,7 +19,7 @@ That is the reason why you can see much faster repaints with Qt3. ScrollZoomer adds scrollbars for zooming. There are a couple of reasons why the implementation is a hack and therefore the class is not part of the Qwt lib, but it should be working with all -types of QwtPlots. Copy the code of scrollbar.[h|cpp] and +types of QwtPlots. Copy the code of scrollbar.[h|cpp] and scrollzoomer.[h|cpp] to the application code. Uwe diff --git a/qwt/examples/realtime_plot/clear.xpm b/qwt/examples/realtime/clear.xpm similarity index 100% rename from qwt/examples/realtime_plot/clear.xpm rename to qwt/examples/realtime/clear.xpm diff --git a/qwt/examples/realtime/incrementalplot.cpp b/qwt/examples/realtime/incrementalplot.cpp new file mode 100644 index 000000000..81307db65 --- /dev/null +++ b/qwt/examples/realtime/incrementalplot.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include "incrementalplot.h" +#include + +class CurveData: public QwtArraySeriesData +{ +public: + CurveData() + { + } + + virtual QRectF boundingRect() const + { + if ( d_boundingRect.width() < 0.0 ) + d_boundingRect = qwtBoundingRect( *this ); + + return d_boundingRect; + } + + inline void append( const QPointF &point ) + { + d_samples += point; + } + + void clear() + { + d_samples.clear(); + d_samples.squeeze(); + d_boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); + } +}; + +IncrementalPlot::IncrementalPlot(QWidget *parent): + QwtPlot(parent), + d_curve(NULL) +{ + d_directPainter = new QwtPlotDirectPainter(this); + +#if defined(Q_WS_X11) + canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); + canvas()->setAttribute(Qt::WA_PaintOnScreen, true); +#endif + + d_curve = new QwtPlotCurve("Test Curve"); + d_curve->setStyle(QwtPlotCurve::NoCurve); + d_curve->setData( new CurveData() ); + + d_curve->setSymbol(new QwtSymbol(QwtSymbol::XCross, + Qt::NoBrush, QPen(Qt::white), QSize( 4, 4 ) ) ); + + d_curve->attach(this); + + setAutoReplot(false); +} + +IncrementalPlot::~IncrementalPlot() +{ + delete d_curve; +} + +void IncrementalPlot::appendPoint( const QPointF &point ) +{ + CurveData *data = static_cast( d_curve->data() ); + data->append(point); + + const bool doClip = !canvas()->testAttribute( Qt::WA_PaintOnScreen ); + if ( doClip ) + { + /* + Depending on the platform setting a clip might be an important + performance issue. F.e. for Qt Embedded this reduces the + part of the backing store that has to be copied out - maybe + to an unaccelerated frame buffer device. + */ + const QwtScaleMap xMap = canvasMap( d_curve->xAxis() ); + const QwtScaleMap yMap = canvasMap( d_curve->yAxis() ); + + QRegion clipRegion; + + const QSize symbolSize = d_curve->symbol()->size(); + QRect r( 0, 0, symbolSize.width() + 2, symbolSize.height() + 2 ); + + const QPointF center = + QwtScaleMap::transform( xMap, yMap, point ); + r.moveCenter( center.toPoint() ); + clipRegion += r; + + d_directPainter->setClipRegion( clipRegion ); + } + + d_directPainter->drawSeries(d_curve, + data->size() - 1, data->size() - 1); +} + +void IncrementalPlot::clearPoints() +{ + CurveData *data = static_cast( d_curve->data() ); + data->clear(); + + replot(); +} diff --git a/qwt/examples/realtime/incrementalplot.h b/qwt/examples/realtime/incrementalplot.h new file mode 100644 index 000000000..8372dbe00 --- /dev/null +++ b/qwt/examples/realtime/incrementalplot.h @@ -0,0 +1,25 @@ +#ifndef _INCREMENTALPLOT_H_ +#define _INCREMENTALPLOT_H_ 1 + +#include + +class QwtPlotCurve; +class QwtPlotDirectPainter; + +class IncrementalPlot : public QwtPlot +{ + Q_OBJECT + +public: + IncrementalPlot(QWidget *parent = NULL); + virtual ~IncrementalPlot(); + + void appendPoint( const QPointF &); + void clearPoints(); + +private: + QwtPlotCurve *d_curve; + QwtPlotDirectPainter *d_directPainter; +}; + +#endif // _INCREMENTALPLOT_H_ diff --git a/qwt/examples/realtime_plot/realtime.cpp b/qwt/examples/realtime/main.cpp similarity index 75% rename from qwt/examples/realtime_plot/realtime.cpp rename to qwt/examples/realtime/main.cpp index 3c3f03a7f..30f9c6d10 100644 --- a/qwt/examples/realtime_plot/realtime.cpp +++ b/qwt/examples/realtime/main.cpp @@ -7,9 +7,6 @@ int main(int argc, char **argv) MainWindow w; w.show(); -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif return a.exec(); } diff --git a/qwt/examples/realtime_plot/mainwindow.cpp b/qwt/examples/realtime/mainwindow.cpp similarity index 69% rename from qwt/examples/realtime_plot/mainwindow.cpp rename to qwt/examples/realtime/mainwindow.cpp index 24befe594..18775703e 100644 --- a/qwt/examples/realtime_plot/mainwindow.cpp +++ b/qwt/examples/realtime/mainwindow.cpp @@ -21,17 +21,15 @@ public: void addSpacing(int spacing) { QLabel *label = new QLabel(this); -#if QT_VERSION >= 0x040000 addWidget(label); -#endif label->setFixedWidth(spacing); - } + } }; class Counter: public QWidget { public: - Counter(QWidget *parent, + Counter(QWidget *parent, const QString &prefix, const QString &suffix, int min, int max, int step): QWidget(parent) @@ -41,13 +39,9 @@ public: if ( !prefix.isEmpty() ) layout->addWidget(new QLabel(prefix + " ", this)); -#if QT_VERSION < 0x040000 - d_counter = new QSpinBox(min, max, step, this); -#else d_counter = new QSpinBox(this); d_counter->setRange(min, max); d_counter->setSingleStep(step); -#endif layout->addWidget(d_counter); if ( !suffix.isEmpty() ) @@ -63,42 +57,31 @@ private: MainWindow::MainWindow() { -#if QT_VERSION < 0x040000 - setDockEnabled(TornOff, true); - setRightJustification(true); -#endif - addToolBar(toolBar()); #ifndef QT_NO_STATUSBAR (void)statusBar(); #endif d_plot = new RandomPlot(this); - d_plot->setMargin(4); + const int margin = 4; + d_plot->setContentsMargins( margin, margin, margin, margin); setCentralWidget(d_plot); -#if QT_VERSION >= 0x040000 - connect(d_startAction, SIGNAL(toggled(bool)), this, SLOT(appendPoints(bool))); - connect(d_clearAction, SIGNAL(triggered()), d_plot, SLOT(clear())); -#else - connect(d_startBtn, SIGNAL(toggled(bool)), this, SLOT(appendPoints(bool))); - connect(d_clearBtn, SIGNAL(clicked()), d_plot, SLOT(clear())); -#endif - connect(d_plot, SIGNAL(running(bool)), this, SLOT(showRunning(bool))); + connect(d_startAction, SIGNAL( toggled(bool) ), this, SLOT( appendPoints(bool) ) ); + connect(d_clearAction, SIGNAL( triggered() ), d_plot, SLOT( clear() ) ); + connect(d_plot, SIGNAL( running(bool) ), this, SLOT( showRunning(bool) ) ); + connect(d_plot, SIGNAL( elapsed(int) ), this, SLOT( showElapsed( int ) ) ); initWhatsThis(); -#if QT_VERSION >= 0x040000 setContextMenuPolicy(Qt::NoContextMenu); -#endif } QToolBar *MainWindow::toolBar() { MyToolBar *toolBar = new MyToolBar(this); -#if QT_VERSION >= 0x040000 toolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); setToolButtonStyle(Qt::ToolButtonTextUnderIcon); @@ -113,25 +96,10 @@ QToolBar *MainWindow::toolBar() toolBar->addAction(whatsThisAction); setIconSize(QSize(22, 22)); -#else - d_startBtn = new QToolButton(toolBar); - d_startBtn->setUsesTextLabel(true); - d_startBtn->setPixmap(QPixmap(start_xpm)); - d_startBtn->setToggleButton(true); - - d_clearBtn = new QToolButton(toolBar); - d_clearBtn->setUsesTextLabel(true); - d_clearBtn->setPixmap(QPixmap(clear_xpm)); - d_clearBtn->setTextLabel("Clear", false); - - QToolButton *helpBtn = QWhatsThis::whatsThisButton(toolBar); - helpBtn->setUsesTextLabel(true); - helpBtn->setTextLabel("Help", false); -#endif QWidget *hBox = new QWidget(toolBar); - d_randomCount = + d_randomCount = new Counter(hBox, "Points", QString::null, 1, 100000, 100); d_randomCount->setValue(1000); @@ -149,15 +117,7 @@ QToolBar *MainWindow::toolBar() showRunning(false); -#if QT_VERSION < 0x040000 - toolBar->setStretchableWidget(hBox); - - d_startBtn->setMinimumWidth(helpBtn->sizeHint().width() + 20); - d_clearBtn->setMinimumWidth(helpBtn->sizeHint().width() + 20); - helpBtn->setMinimumWidth(helpBtn->sizeHint().width() + 20); -#else toolBar->addWidget(hBox); -#endif return toolBar; } @@ -175,13 +135,17 @@ void MainWindow::showRunning(bool running) { d_randomCount->setEnabled(!running); d_timerCount->setEnabled(!running); -#if QT_VERSION < 0x040000 - d_startBtn->setOn(running); - d_startBtn->setTextLabel(running ? "Stop" : "Start", false); -#else d_startAction->setChecked(running); d_startAction->setText(running ? "Stop" : "Start"); -#endif +} + +void MainWindow::showElapsed(int ms) +{ + QString text; + text.setNum(ms); + text += " ms"; + + statusBar()->showMessage( text ); } void MainWindow::initWhatsThis() @@ -213,18 +177,9 @@ void MainWindow::initWhatsThis() const char *text5 = "Remove all points."; -#if QT_VERSION < 0x040000 - QWhatsThis::add(d_plot, text1); - QWhatsThis::add(d_randomCount, text2); - QWhatsThis::add(d_timerCount, text3); - QWhatsThis::add(d_startBtn, text4); - QWhatsThis::add(d_clearBtn, text5); -#else d_plot->setWhatsThis(text1); d_randomCount->setWhatsThis(text2); d_timerCount->setWhatsThis(text3); d_startAction->setWhatsThis(text4); d_clearAction->setWhatsThis(text5); -#endif } - diff --git a/qwt/examples/realtime_plot/mainwindow.h b/qwt/examples/realtime/mainwindow.h similarity index 66% rename from qwt/examples/realtime_plot/mainwindow.h rename to qwt/examples/realtime/mainwindow.h index 0418c3c4b..4dee7297f 100644 --- a/qwt/examples/realtime_plot/mainwindow.h +++ b/qwt/examples/realtime/mainwindow.h @@ -2,11 +2,7 @@ #define _MAINWINDOW_H_ 1 #include -#if QT_VERSION < 0x040000 -#include -#else #include -#endif class QSpinBox; class QPushButton; @@ -19,9 +15,10 @@ class MainWindow: public QMainWindow public: MainWindow(); -private slots: - void showRunning(bool); - void appendPoints(bool); +private Q_SLOTS: + void showRunning( bool ); + void appendPoints( bool ); + void showElapsed( int ); private: QToolBar *toolBar(); @@ -30,14 +27,8 @@ private: private: Counter *d_randomCount; Counter *d_timerCount; -#if QT_VERSION < 0x040000 - QToolButton *d_startBtn; - QToolButton *d_clearBtn; -#else QAction *d_startAction; QAction *d_clearAction; -#endif - RandomPlot *d_plot; }; diff --git a/qwt/examples/realtime_plot/randomplot.cpp b/qwt/examples/realtime/randomplot.cpp similarity index 68% rename from qwt/examples/realtime_plot/randomplot.cpp rename to qwt/examples/realtime/randomplot.cpp index df7335c53..1a04d8e72 100644 --- a/qwt/examples/realtime_plot/randomplot.cpp +++ b/qwt/examples/realtime/randomplot.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -16,6 +16,20 @@ public: Zoomer(QwtPlotCanvas *canvas): ScrollZoomer(canvas) { +#if 0 + setRubberBandPen(QPen(Qt::red, 2, Qt::DotLine)); +#else + setRubberBandPen(QPen(Qt::red)); +#endif + } + + virtual QwtText trackerTextF(const QPointF &pos) const + { + QColor bg(Qt::white); + + QwtText text = QwtPlotZoomer::trackerTextF(pos); + text.setBackgroundBrush( QBrush( bg )); + return text; } virtual void rescale() @@ -31,7 +45,7 @@ public: // because of the different widths of the labels // So we better use a fixed extent. - minExtent = sd->spacing() + sd->majTickLength() + 1; + minExtent = sd->spacing() + sd->maxTickLength() + 1; minExtent += sd->labelSize( scaleWidget->font(), c_rangeMax).width(); } @@ -61,14 +75,12 @@ RandomPlot::RandomPlot(QWidget *parent): setAxisScale(xBottom, 0, c_rangeMax); setAxisScale(yLeft, 0, c_rangeMax); - + replot(); // enable zooming - Zoomer *zoomer = new Zoomer(canvas()); - zoomer->setRubberBandPen(QPen(Qt::red, 2, Qt::DotLine)); - zoomer->setTrackerPen(QPen(Qt::red)); + (void) new Zoomer(canvas()); } QSize RandomPlot::sizeHint() const @@ -78,13 +90,13 @@ QSize RandomPlot::sizeHint() const void RandomPlot::appendPoint() { - double x = rand() % c_rangeMax; - x += ( rand() % 100 ) / 100; + double x = qrand() % c_rangeMax; + x += ( qrand() % 100 ) / 100; - double y = rand() % c_rangeMax; - y += ( rand() % 100 ) / 100; + double y = qrand() % c_rangeMax; + y += ( qrand() % 100 ) / 100; - appendData(x, y); + IncrementalPlot::appendPoint( QPointF( x, y ) ); if ( --d_timerCount <= 0 ) stop(); @@ -100,25 +112,28 @@ void RandomPlot::append(int timeout, int count) d_timerCount = count; - emit running(true); + Q_EMIT running(true); + d_timeStamp.start(); - canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); + canvas()->setPaintAttribute(QwtPlotCanvas::BackingStore, false); d_timer->start(timeout); } void RandomPlot::stop() { + Q_EMIT elapsed( d_timeStamp.elapsed() ); + if ( d_timer ) { d_timer->stop(); - emit running(false); + Q_EMIT running(false); } - canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, true); + canvas()->setPaintAttribute(QwtPlotCanvas::BackingStore, true); } void RandomPlot::clear() { - removeData(); + clearPoints(); replot(); } diff --git a/qwt/examples/realtime_plot/randomplot.h b/qwt/examples/realtime/randomplot.h similarity index 67% rename from qwt/examples/realtime_plot/randomplot.h rename to qwt/examples/realtime/randomplot.h index 554cd468a..498c27354 100644 --- a/qwt/examples/realtime_plot/randomplot.h +++ b/qwt/examples/realtime/randomplot.h @@ -2,6 +2,7 @@ #define _RANDOMPLOT_H_ 1 #include "incrementalplot.h" +#include class QTimer; @@ -14,15 +15,16 @@ public: virtual QSize sizeHint() const; -signals: - void running(bool); +Q_SIGNALS: + void running( bool ); + void elapsed( int ms ); -public slots: +public Q_SLOTS: void clear(); void stop(); - void append(int timeout, int count); + void append( int timeout, int count ); -private slots: +private Q_SLOTS: void appendPoint(); private: @@ -30,6 +32,8 @@ private: QTimer *d_timer; int d_timerCount; + + QTime d_timeStamp; }; #endif // _RANDOMPLOT_H_ diff --git a/qwt/examples/realtime_plot/realtime_plot.pro b/qwt/examples/realtime/realtime.pro similarity index 50% rename from qwt/examples/realtime_plot/realtime_plot.pro rename to qwt/examples/realtime/realtime.pro index 0f0f68a0d..c4ba7b989 100644 --- a/qwt/examples/realtime_plot/realtime_plot.pro +++ b/qwt/examples/realtime/realtime.pro @@ -1,28 +1,27 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = realtime HEADERS = \ - mainwindow.h \ - scrollzoomer.h \ - scrollbar.h \ - incrementalplot.h \ - randomplot.h + mainwindow.h \ + scrollzoomer.h \ + scrollbar.h \ + incrementalplot.h \ + randomplot.h SOURCES = \ - realtime.cpp \ - mainwindow.cpp \ - scrollzoomer.cpp \ - scrollbar.cpp \ - incrementalplot.cpp \ - randomplot.cpp - + main.cpp \ + mainwindow.cpp \ + scrollzoomer.cpp \ + scrollbar.cpp \ + incrementalplot.cpp \ + randomplot.cpp diff --git a/qwt/examples/realtime_plot/scrollbar.cpp b/qwt/examples/realtime/scrollbar.cpp similarity index 86% rename from qwt/examples/realtime_plot/scrollbar.cpp rename to qwt/examples/realtime/scrollbar.cpp index 1027b5fa6..bf6a5f5a2 100644 --- a/qwt/examples/realtime_plot/scrollbar.cpp +++ b/qwt/examples/realtime/scrollbar.cpp @@ -1,7 +1,5 @@ #include -#if QT_VERSION >= 0x040000 #include -#endif #include "scrollbar.h" ScrollBar::ScrollBar(QWidget * parent): @@ -10,14 +8,14 @@ ScrollBar::ScrollBar(QWidget * parent): init(); } -ScrollBar::ScrollBar(Qt::Orientation o, +ScrollBar::ScrollBar(Qt::Orientation o, QWidget *parent): QScrollBar(o, parent) { init(); } -ScrollBar::ScrollBar(double minBase, double maxBase, +ScrollBar::ScrollBar(double minBase, double maxBase, Qt::Orientation o, QWidget *parent): QScrollBar(o, parent) { @@ -65,7 +63,7 @@ void ScrollBar::setBase(double min, double max) void ScrollBar::moveSlider(double min, double max) { - const int sliderTicks = qRound((max - min) / + const int sliderTicks = qRound((max - min) / (d_maxBase - d_minBase) * d_baseTicks); // setRange initiates a valueChanged of the scrollbars @@ -79,23 +77,14 @@ void ScrollBar::moveSlider(double min, double max) if ( steps <= 0 ) steps = 1; -#if QT_VERSION < 0x040000 - setSteps(steps, sliderTicks); -#else setSingleStep(steps); setPageStep(sliderTicks); -#endif int tick = mapToTick(min + (max - min) / 2); if ( isInverted() ) tick = d_baseTicks - tick; -#if QT_VERSION < 0x040000 - directSetValue(tick); - rangeChange(); -#else setSliderPosition(tick); -#endif blockSignals(false); } @@ -137,12 +126,12 @@ double ScrollBar::maxSliderValue() const } int ScrollBar::mapToTick(double v) const -{ +{ return (int) ( ( v - d_minBase) / (d_maxBase - d_minBase ) * d_baseTicks ); } double ScrollBar::mapFromTick(int tick) const -{ +{ return d_minBase + ( d_maxBase - d_minBase ) * tick / d_baseTicks; } @@ -150,21 +139,18 @@ void ScrollBar::catchValueChanged(int value) { double min, max; sliderRange(value, min, max); - emit valueChanged(orientation(), min, max); + Q_EMIT valueChanged(orientation(), min, max); } void ScrollBar::catchSliderMoved(int value) { double min, max; sliderRange(value, min, max); - emit sliderMoved(orientation(), min, max); + Q_EMIT sliderMoved(orientation(), min, max); } int ScrollBar::extent() const { -#if QT_VERSION < 0x040000 - return style().pixelMetric(QStyle::PM_ScrollBarExtent, this); -#else QStyleOptionSlider opt; opt.init(this); opt.subControls = QStyle::SC_None; @@ -180,5 +166,4 @@ int ScrollBar::extent() const if (orientation() == Qt::Horizontal) opt.state |= QStyle::State_Horizontal; return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this); -#endif } diff --git a/qwt/examples/realtime_plot/scrollbar.h b/qwt/examples/realtime/scrollbar.h similarity index 92% rename from qwt/examples/realtime_plot/scrollbar.h rename to qwt/examples/realtime/scrollbar.h index 2bd148d3b..518aa679d 100644 --- a/qwt/examples/realtime_plot/scrollbar.h +++ b/qwt/examples/realtime/scrollbar.h @@ -10,7 +10,7 @@ class ScrollBar: public QScrollBar public: ScrollBar(QWidget *parent = NULL); ScrollBar(Qt::Orientation, QWidget *parent = NULL); - ScrollBar(double minBase, double maxBase, + ScrollBar(double minBase, double maxBase, Qt::Orientation o, QWidget *parent = NULL); void setInverted(bool); @@ -24,11 +24,11 @@ public: int extent() const; -signals: +Q_SIGNALS: void sliderMoved(Qt::Orientation, double, double); void valueChanged(Qt::Orientation, double, double); -public slots: +public Q_SLOTS: virtual void setBase(double min, double max); virtual void moveSlider(double min, double max); @@ -37,7 +37,7 @@ protected: int mapToTick(double) const; double mapFromTick(int) const; -private slots: +private Q_SLOTS: void catchValueChanged(int value); void catchSliderMoved(int value); diff --git a/qwt/examples/realtime_plot/scrollzoomer.cpp b/qwt/examples/realtime/scrollzoomer.cpp similarity index 88% rename from qwt/examples/realtime_plot/scrollzoomer.cpp rename to qwt/examples/realtime/scrollzoomer.cpp index 9a0a39cb1..2b3daa083 100644 --- a/qwt/examples/realtime_plot/scrollzoomer.cpp +++ b/qwt/examples/realtime/scrollzoomer.cpp @@ -12,11 +12,7 @@ public: ScrollData(): scrollBar(NULL), position(ScrollZoomer::OppositeToScale), -#if QT_VERSION < 0x040000 - mode(QScrollView::Auto) -#else mode(Qt::ScrollBarAsNeeded) -#endif { } @@ -27,11 +23,7 @@ public: ScrollBar *scrollBar; ScrollZoomer::ScrollBarPosition position; -#if QT_VERSION < 0x040000 - QScrollView::ScrollBarMode mode; -#else Qt::ScrollBarPolicy mode; -#endif }; ScrollZoomer::ScrollZoomer(QwtPlotCanvas *canvas): @@ -79,8 +71,8 @@ void ScrollZoomer::rescale() if ( !d_inZoom ) { /* - We set a minimum border distance. - Otherwise the canvas size changes when scrolling, + We set a minimum border distance. + Otherwise the canvas size changes when scrolling, between situations where the major ticks are at the canvas borders (requiring extra space for the label) and situations where all labels can be painted below/top @@ -108,7 +100,7 @@ void ScrollZoomer::rescale() ScrollBar *ScrollZoomer::scrollBar(Qt::Orientation o) { - ScrollBar *&sb = (o == Qt::Vertical) + ScrollBar *&sb = (o == Qt::Vertical) ? d_vScrollData->scrollBar : d_hScrollData->scrollBar; if ( sb == NULL ) @@ -131,12 +123,8 @@ ScrollBar *ScrollZoomer::verticalScrollBar() const { return d_vScrollData->scrollBar; } - -#if QT_VERSION < 0x040000 -void ScrollZoomer::setHScrollBarMode(QScrollView::ScrollBarMode mode) -#else + void ScrollZoomer::setHScrollBarMode(Qt::ScrollBarPolicy mode) -#endif { if ( hScrollBarMode() != mode ) { @@ -145,11 +133,7 @@ void ScrollZoomer::setHScrollBarMode(Qt::ScrollBarPolicy mode) } } -#if QT_VERSION < 0x040000 -void ScrollZoomer::setVScrollBarMode(QScrollView::ScrollBarMode mode) -#else void ScrollZoomer::setVScrollBarMode(Qt::ScrollBarPolicy mode) -#endif { if ( vScrollBarMode() != mode ) { @@ -158,20 +142,12 @@ void ScrollZoomer::setVScrollBarMode(Qt::ScrollBarPolicy mode) } } -#if QT_VERSION < 0x040000 -QScrollView::ScrollBarMode ScrollZoomer::hScrollBarMode() const -#else Qt::ScrollBarPolicy ScrollZoomer::hScrollBarMode() const -#endif { return d_hScrollData->mode; } -#if QT_VERSION < 0x040000 -QScrollView::ScrollBarMode ScrollZoomer::vScrollBarMode() const -#else Qt::ScrollBarPolicy ScrollZoomer::vScrollBarMode() const -#endif { return d_vScrollData->mode; } @@ -213,13 +189,7 @@ void ScrollZoomer::setCornerWidget(QWidget *w) delete d_cornerWidget; d_cornerWidget = w; if ( d_cornerWidget->parent() != canvas() ) - { -#if QT_VERSION < 0x040000 - d_cornerWidget->reparent(canvas(), QPoint(0, 0)); -#else d_cornerWidget->setParent(canvas()); -#endif - } updateScrollBars(); } @@ -269,11 +239,7 @@ bool ScrollZoomer::eventFilter(QObject *o, QEvent *e) bool ScrollZoomer::needScrollBar(Qt::Orientation o) const { -#if QT_VERSION < 0x040000 - QScrollView::ScrollBarMode mode; -#else Qt::ScrollBarPolicy mode; -#endif double zoomMin, zoomMax, baseMin, baseMax; if ( o == Qt::Horizontal ) @@ -296,18 +262,10 @@ bool ScrollZoomer::needScrollBar(Qt::Orientation o) const bool needed = false; switch(mode) { -#if QT_VERSION < 0x040000 - case QScrollView::AlwaysOn: -#else case Qt::ScrollBarAlwaysOn: -#endif needed = true; break; -#if QT_VERSION < 0x040000 - case QScrollView::AlwaysOff: -#else case Qt::ScrollBarAlwaysOff: -#endif needed = false; break; default: @@ -333,8 +291,8 @@ void ScrollZoomer::updateScrollBars() xScrollBarAxis = oppositeAxis(xScrollBarAxis); int yScrollBarAxis = yAxis; - if ( vScrollBarPosition() == OppositeToScale ) - yScrollBarAxis = oppositeAxis(yScrollBarAxis); + if ( vScrollBarPosition() == OppositeToScale ) + yScrollBarAxis = oppositeAxis(yScrollBarAxis); QwtPlotLayout *layout = plot()->plotLayout(); @@ -355,7 +313,7 @@ void ScrollZoomer::updateScrollBars() if ( !sb->isVisibleTo(canvas()) ) { sb->show(); - layout->setCanvasMargin(layout->canvasMargin(xScrollBarAxis) + layout->setCanvasMargin(layout->canvasMargin(xScrollBarAxis) + sb->extent(), xScrollBarAxis); } } @@ -364,7 +322,7 @@ void ScrollZoomer::updateScrollBars() if ( horizontalScrollBar() ) { horizontalScrollBar()->hide(); - layout->setCanvasMargin(layout->canvasMargin(xScrollBarAxis) + layout->setCanvasMargin(layout->canvasMargin(xScrollBarAxis) - horizontalScrollBar()->extent(), xScrollBarAxis); } } @@ -385,7 +343,7 @@ void ScrollZoomer::updateScrollBars() if ( !sb->isVisibleTo(canvas()) ) { sb->show(); - layout->setCanvasMargin(layout->canvasMargin(yScrollBarAxis) + layout->setCanvasMargin(layout->canvasMargin(yScrollBarAxis) + sb->extent(), yScrollBarAxis); } } @@ -394,7 +352,7 @@ void ScrollZoomer::updateScrollBars() if ( verticalScrollBar() ) { verticalScrollBar()->hide(); - layout->setCanvasMargin(layout->canvasMargin(yScrollBarAxis) + layout->setCanvasMargin(layout->canvasMargin(yScrollBarAxis) - verticalScrollBar()->extent(), yScrollBarAxis); } } @@ -404,9 +362,7 @@ void ScrollZoomer::updateScrollBars() if ( d_cornerWidget == NULL ) { d_cornerWidget = new QWidget(canvas()); -#if QT_VERSION >= 0x040100 d_cornerWidget->setAutoFillBackground(true); -#endif d_cornerWidget->setPalette(plot()->palette()); } d_cornerWidget->show(); @@ -436,11 +392,11 @@ void ScrollZoomer::layoutScrollBars(const QRect &rect) const int hdim = hScrollBar ? hScrollBar->extent() : 0; const int vdim = vScrollBar ? vScrollBar->extent() : 0; - + if ( hScrollBar && hScrollBar->isVisible() ) { int x = rect.x(); - int y = (hPos == QwtPlot::xTop) + int y = (hPos == QwtPlot::xTop) ? rect.top() : rect.bottom() - hdim + 1; int w = rect.width(); @@ -469,7 +425,7 @@ void ScrollZoomer::layoutScrollBars(const QRect &rect) { if ( hPos == QwtPlot::xTop ) y += hdim; - + h -= hdim; } @@ -488,14 +444,17 @@ void ScrollZoomer::layoutScrollBars(const QRect &rect) } } -void ScrollZoomer::scrollBarMoved(Qt::Orientation o, double min, double) +void ScrollZoomer::scrollBarMoved( + Qt::Orientation o, double min, double max) { - if ( o == Qt::Horizontal ) - move(min, zoomRect().top()); - else - move(zoomRect().left(), min); + Q_UNUSED(max); - emit zoomed(zoomRect()); + if ( o == Qt::Horizontal ) + moveTo( QPointF( min, zoomRect().top() ) ); + else + moveTo( QPointF( zoomRect().left(), min ) ); + + Q_EMIT zoomed(zoomRect()); } int ScrollZoomer::oppositeAxis(int axis) const diff --git a/qwt/examples/realtime_plot/scrollzoomer.h b/qwt/examples/realtime/scrollzoomer.h similarity index 78% rename from qwt/examples/realtime_plot/scrollzoomer.h rename to qwt/examples/realtime/scrollzoomer.h index 7f0c37f93..9b9c3aa73 100644 --- a/qwt/examples/realtime_plot/scrollzoomer.h +++ b/qwt/examples/realtime/scrollzoomer.h @@ -2,9 +2,6 @@ #define _SCROLLZOOMER_H #include -#if QT_VERSION < 0x040000 -#include -#endif #include class ScrollData; @@ -26,19 +23,11 @@ public: ScrollBar *horizontalScrollBar() const; ScrollBar *verticalScrollBar() const; -#if QT_VERSION < 0x040000 - void setHScrollBarMode(QScrollView::ScrollBarMode); - void setVScrollBarMode(QScrollView::ScrollBarMode); - - QScrollView::ScrollBarMode vScrollBarMode () const; - QScrollView::ScrollBarMode hScrollBarMode () const; -#else void setHScrollBarMode(Qt::ScrollBarPolicy); void setVScrollBarMode(Qt::ScrollBarPolicy); Qt::ScrollBarPolicy vScrollBarMode () const; Qt::ScrollBarPolicy hScrollBarMode () const; -#endif void setHScrollBarPosition(ScrollBarPosition); void setVScrollBarPosition(ScrollBarPosition); @@ -47,8 +36,8 @@ public: ScrollBarPosition vScrollBarPosition() const; QWidget* cornerWidget() const; - virtual void setCornerWidget(QWidget *); - + virtual void setCornerWidget(QWidget *); + virtual bool eventFilter(QObject *, QEvent *); virtual void rescale(); @@ -58,7 +47,7 @@ protected: virtual void updateScrollBars(); virtual void layoutScrollBars(const QRect &); -private slots: +private Q_SLOTS: void scrollBarMoved(Qt::Orientation o, double min, double max); private: @@ -73,5 +62,5 @@ private: bool d_inZoom; bool d_alignCanvasToScales; }; - + #endif diff --git a/qwt/examples/realtime_plot/start.xpm b/qwt/examples/realtime/start.xpm similarity index 100% rename from qwt/examples/realtime_plot/start.xpm rename to qwt/examples/realtime/start.xpm diff --git a/qwt/examples/realtime_plot/incrementalplot.cpp b/qwt/examples/realtime_plot/incrementalplot.cpp deleted file mode 100644 index edba1cbb7..000000000 --- a/qwt/examples/realtime_plot/incrementalplot.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include -#include -#include "incrementalplot.h" -#if QT_VERSION >= 0x040000 -#include -#endif - -CurveData::CurveData(): - d_count(0) -{ -} - -void CurveData::append(double *x, double *y, int count) -{ - int newSize = ( (d_count + count) / 1000 + 1 ) * 1000; - if ( newSize > size() ) - { - d_x.resize(newSize); - d_y.resize(newSize); - } - - for ( register int i = 0; i < count; i++ ) - { - d_x[d_count + i] = x[i]; - d_y[d_count + i] = y[i]; - } - d_count += count; -} - -int CurveData::count() const -{ - return d_count; -} - -int CurveData::size() const -{ - return d_x.size(); -} - -const double *CurveData::x() const -{ - return d_x.data(); -} - -const double *CurveData::y() const -{ - return d_y.data(); -} - -IncrementalPlot::IncrementalPlot(QWidget *parent): - QwtPlot(parent), - d_data(NULL), - d_curve(NULL) -{ - setAutoReplot(false); -} - -IncrementalPlot::~IncrementalPlot() -{ - delete d_data; -} - -void IncrementalPlot::appendData(double x, double y) -{ - appendData(&x, &y, 1); -} - -void IncrementalPlot::appendData(double *x, double *y, int size) -{ - if ( d_data == NULL ) - d_data = new CurveData; - - if ( d_curve == NULL ) - { - d_curve = new QwtPlotCurve("Test Curve"); - d_curve->setStyle(QwtPlotCurve::NoCurve); - d_curve->setPaintAttribute(QwtPlotCurve::PaintFiltered); - - const QColor &c = Qt::white; - d_curve->setSymbol(QwtSymbol(QwtSymbol::XCross, - QBrush(c), QPen(c), QSize(5, 5)) ); - - d_curve->attach(this); - } - - d_data->append(x, y, size); - d_curve->setRawData(d_data->x(), d_data->y(), d_data->count()); -#ifdef __GNUC__ -#warning better use QwtData -#endif - - const bool cacheMode = - canvas()->testPaintAttribute(QwtPlotCanvas::PaintCached); - -#if QT_VERSION >= 0x040000 && defined(Q_WS_X11) - // Even if not recommended by TrollTech, Qt::WA_PaintOutsidePaintEvent - // works on X11. This has an tremendous effect on the performance.. - - canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); -#endif - - canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); - d_curve->draw(d_curve->dataSize() - size, d_curve->dataSize() - 1); - canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, cacheMode); - -#if QT_VERSION >= 0x040000 && defined(Q_WS_X11) - canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, false); -#endif -} - -void IncrementalPlot::removeData() -{ - delete d_curve; - d_curve = NULL; - - delete d_data; - d_data = NULL; - - replot(); -} diff --git a/qwt/examples/realtime_plot/incrementalplot.h b/qwt/examples/realtime_plot/incrementalplot.h deleted file mode 100644 index 263169d06..000000000 --- a/qwt/examples/realtime_plot/incrementalplot.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _INCREMENTALPLOT_H_ -#define _INCREMENTALPLOT_H_ 1 - -#include -#include - -class QwtPlotCurve; - -class CurveData -{ - // A container class for growing data -public: - - CurveData(); - - void append(double *x, double *y, int count); - - int count() const; - int size() const; - const double *x() const; - const double *y() const; - -private: - int d_count; - QwtArray d_x; - QwtArray d_y; -}; - -class IncrementalPlot : public QwtPlot -{ - Q_OBJECT -public: - IncrementalPlot(QWidget *parent = NULL); - virtual ~IncrementalPlot(); - - void appendData(double x, double y); - void appendData(double *x, double *y, int size); - - void removeData(); - -private: - CurveData *d_data; - QwtPlotCurve *d_curve; -}; - -#endif // _INCREMENTALPLOT_H_ diff --git a/qwt/examples/refreshtest/circularbuffer.cpp b/qwt/examples/refreshtest/circularbuffer.cpp new file mode 100644 index 000000000..097efde56 --- /dev/null +++ b/qwt/examples/refreshtest/circularbuffer.cpp @@ -0,0 +1,73 @@ +#include "circularbuffer.h" +#include + +CircularBuffer::CircularBuffer(double interval, size_t numPoints): + d_y(NULL), + d_referenceTime(0.0), + d_startIndex(0), + d_offset(0.0) +{ + fill(interval, numPoints); +} + +void CircularBuffer::fill(double interval, size_t numPoints) +{ + if ( interval <= 0.0 || numPoints < 2 ) + return; + + d_values.resize(numPoints); + d_values.fill(0.0); + + if ( d_y ) + { + d_step = interval / (numPoints - 2); + for ( size_t i = 0; i < numPoints; i++ ) + d_values[i] = d_y(i * d_step); + } + + d_interval = interval; +} + +void CircularBuffer::setFunction(double(*y)(double)) +{ + d_y = y; +} + +void CircularBuffer::setReferenceTime(double timeStamp) +{ + d_referenceTime = timeStamp; + + const double startTime = ::fmod(d_referenceTime, d_values.size() * d_step); + + d_startIndex = int(startTime / d_step); // floor + d_offset = ::fmod(startTime, d_step); +} + +double CircularBuffer::referenceTime() const +{ + return d_referenceTime; +} + +size_t CircularBuffer::size() const +{ + return d_values.size(); +} + +QPointF CircularBuffer::sample(size_t i) const +{ + const int size = d_values.size(); + + int index = d_startIndex + i; + if ( index >= size ) + index -= size; + + const double x = i * d_step - d_offset - d_interval; + const double y = d_values.data()[index]; + + return QPointF(x, y); +} + +QRectF CircularBuffer::boundingRect() const +{ + return QRectF(-1.0, -d_interval, 2.0, d_interval); +} \ No newline at end of file diff --git a/qwt/examples/refreshtest/circularbuffer.h b/qwt/examples/refreshtest/circularbuffer.h new file mode 100644 index 000000000..baf1f0849 --- /dev/null +++ b/qwt/examples/refreshtest/circularbuffer.h @@ -0,0 +1,35 @@ +#ifndef _CIRCULAR_BUFFER_H_ +#define _CIRCULAR_BUFFER_H_ + +#include +#include + +class CircularBuffer: public QwtSeriesData +{ +public: + CircularBuffer(double interval = 10.0, size_t numPoints = 1000); + void fill(double interval, size_t numPoints); + + void setReferenceTime(double); + double referenceTime() const; + + virtual size_t size() const; + virtual QPointF sample(size_t i) const; + + virtual QRectF boundingRect() const; + + void setFunction(double(*y)(double)); + +private: + double (*d_y)(double); + + double d_referenceTime; + double d_interval; + QVector d_values; + + double d_step; + int d_startIndex; + double d_offset; +}; + +#endif diff --git a/qwt/examples/refreshtest/main.cpp b/qwt/examples/refreshtest/main.cpp new file mode 100644 index 000000000..f1398ec7f --- /dev/null +++ b/qwt/examples/refreshtest/main.cpp @@ -0,0 +1,13 @@ +#include +#include "mainwindow.h" + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + MainWindow mainWindow; + mainWindow.resize(600,400); + mainWindow.show(); + + return a.exec(); +} diff --git a/qwt/examples/refreshtest/mainwindow.cpp b/qwt/examples/refreshtest/mainwindow.cpp new file mode 100644 index 000000000..2f03d6ec3 --- /dev/null +++ b/qwt/examples/refreshtest/mainwindow.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include "panel.h" +#include "plot.h" +#include "mainwindow.h" + +MainWindow::MainWindow(QWidget *parent): + QMainWindow(parent) +{ + QWidget *w = new QWidget(this); + + d_panel = new Panel(w); + + d_plot = new Plot(w); + d_plot->canvas()->installEventFilter(this); + + QHBoxLayout *hLayout = new QHBoxLayout(w); + hLayout->addWidget(d_panel); + hLayout->addWidget(d_plot, 10); + + setCentralWidget(w); + + d_frameCount = new QLabel(this); + statusBar()->addWidget(d_frameCount, 10); + + d_plot->setSettings(d_panel->settings()); + + connect(d_panel, SIGNAL(settingsChanged(const Settings &)), + d_plot, SLOT(setSettings(const Settings &))); +} + +bool MainWindow::eventFilter(QObject *object, QEvent *event) +{ + if ( object == d_plot->canvas() && event->type() == QEvent::Paint ) + { + static int counter; + static QTime timeStamp; + + if ( !timeStamp.isValid() ) + { + timeStamp.start(); + counter = 0; + } + else + { + counter++; + + const double elapsed = timeStamp.elapsed() / 1000.0; + if ( elapsed >= 1 ) + { + QString fps; + fps.setNum(qRound(counter / elapsed)); + fps += " Fps"; + + d_frameCount->setText(fps); + + counter = 0; + timeStamp.start(); + } + } + } + + return QMainWindow::eventFilter(object, event); +}; diff --git a/qwt/examples/refreshtest/mainwindow.h b/qwt/examples/refreshtest/mainwindow.h new file mode 100644 index 000000000..b725f8f11 --- /dev/null +++ b/qwt/examples/refreshtest/mainwindow.h @@ -0,0 +1,22 @@ +#ifndef _MAIN_WINDOW_H_ +#define _MAIN_WINDOW_H_ + +#include + +class Plot; +class Panel; +class QLabel; + +class MainWindow: public QMainWindow +{ +public: + MainWindow(QWidget *parent = NULL); + virtual bool eventFilter(QObject *, QEvent *); + +private: + Plot *d_plot; + Panel *d_panel; + QLabel *d_frameCount; +}; + +#endif diff --git a/qwt/examples/refreshtest/panel.cpp b/qwt/examples/refreshtest/panel.cpp new file mode 100644 index 000000000..cee9d0e5b --- /dev/null +++ b/qwt/examples/refreshtest/panel.cpp @@ -0,0 +1,264 @@ +#include "panel.h" +#include +#include +#include +#include +#include +#include + +class SpinBox: public QSpinBox +{ +public: + SpinBox(int min, int max, int step, QWidget *parent): + QSpinBox(parent) + { + setRange(min, max); + setSingleStep(step); + } +}; + +class CheckBox: public QCheckBox +{ +public: + CheckBox(const QString &title, QWidget *parent): + QCheckBox(title, parent) + { + } + + void setChecked(bool checked) + { + setCheckState(checked ? Qt::Checked : Qt::Unchecked); + } + + bool isChecked() const + { + return checkState() == Qt::Checked; + } +}; + +Panel::Panel(QWidget *parent): + QTabWidget(parent) +{ + setTabPosition(QTabWidget::West); + + addTab(createPlotTab(this), "Plot"); + addTab(createCanvasTab(this), "Canvas"); + addTab(createCurveTab(this), "Curve"); + + setSettings(Settings()); + + connect(d_numPoints, SIGNAL(valueChanged(int)), SLOT(edited()) ); + connect(d_updateInterval, SIGNAL(valueChanged(int)), SLOT(edited()) ); + connect(d_curveWidth, SIGNAL(valueChanged(int)), SLOT(edited()) ); + connect(d_paintCache, SIGNAL(stateChanged(int)), SLOT(edited()) ); + connect(d_paintOnScreen, SIGNAL(stateChanged(int)), SLOT(edited()) ); + connect(d_immediatePaint, SIGNAL(stateChanged(int)), SLOT(edited()) ); + connect(d_curveAntialiasing, SIGNAL(stateChanged(int)), SLOT(edited()) ); + connect(d_curveClipping, SIGNAL(stateChanged(int)), SLOT(edited()) ); + connect(d_lineSplitting, SIGNAL(stateChanged(int)), SLOT(edited()) ); + connect(d_curveFilled, SIGNAL(stateChanged(int)), SLOT(edited()) ); + + connect(d_updateType, SIGNAL(currentIndexChanged(int)), SLOT(edited()) ); + connect(d_gridStyle, SIGNAL(currentIndexChanged(int)), SLOT(edited()) ); + connect(d_curveType, SIGNAL(currentIndexChanged(int)), SLOT(edited()) ); + connect(d_curvePen, SIGNAL(currentIndexChanged(int)), SLOT(edited()) ); +} + +QWidget *Panel::createPlotTab(QWidget *parent) +{ + QWidget *page = new QWidget(parent); + + d_updateInterval = new SpinBox(0, 1000, 10, page); + d_numPoints = new SpinBox(10, 1000000, 1000, page); + + d_updateType = new QComboBox(page); + d_updateType->addItem("Repaint"); + d_updateType->addItem("Replot"); + + int row = 0; + + QGridLayout *layout = new QGridLayout(page); + + layout->addWidget(new QLabel("Updates", page), row, 0 ); + layout->addWidget(d_updateInterval, row, 1); + layout->addWidget(new QLabel("ms", page), row++, 2 ); + + layout->addWidget(new QLabel("Points", page), row, 0 ); + layout->addWidget(d_numPoints, row++, 1); + + layout->addWidget(new QLabel("Update", page), row, 0 ); + layout->addWidget(d_updateType, row++, 1); + + layout->addLayout(new QHBoxLayout(), row++, 0); + + layout->setColumnStretch(1, 10); + layout->setRowStretch(row, 10); + + return page; +} + +QWidget *Panel::createCanvasTab(QWidget *parent) +{ + QWidget *page = new QWidget(parent); + + d_gridStyle = new QComboBox(page); + d_gridStyle->addItem("None"); + d_gridStyle->addItem("Solid"); + d_gridStyle->addItem("Dashes"); + + d_paintCache = new CheckBox("Paint Cache", page); + d_paintOnScreen = new CheckBox("Paint On Screen", page); + d_immediatePaint = new CheckBox("Immediate Paint", page); + + int row = 0; + + QGridLayout *layout = new QGridLayout(page); + layout->addWidget(new QLabel("Grid", page), row, 0); + layout->addWidget(d_gridStyle, row++, 1); + + layout->addWidget(d_paintCache, row++, 0, 1, -1); + layout->addWidget(d_paintOnScreen, row++, 0, 1, -1); + layout->addWidget(d_immediatePaint, row++, 0, 1, -1); + + layout->addLayout(new QHBoxLayout(), row++, 0); + + layout->setColumnStretch(1, 10); + layout->setRowStretch(row, 10); + + return page; +} + +QWidget *Panel::createCurveTab(QWidget *parent) +{ + QWidget *page = new QWidget(parent); + + d_curveType = new QComboBox(page); + d_curveType->addItem("Wave"); + d_curveType->addItem("Noise"); + + d_curveAntialiasing = new CheckBox("Antialiasing", page); + d_curveClipping = new CheckBox("Clipping", page); + d_lineSplitting = new CheckBox("Split Lines", page); + + d_curveWidth = new SpinBox(0, 10, 1, page); + + d_curvePen = new QComboBox(page); + d_curvePen->addItem("Solid"); + d_curvePen->addItem("Dotted"); + + d_curveFilled = new CheckBox("Filled", page); + + int row = 0; + + QGridLayout *layout = new QGridLayout(page); + layout->addWidget(new QLabel("Type", page), row, 0 ); + layout->addWidget(d_curveType, row++, 1); + + layout->addWidget(d_curveAntialiasing, row++, 0, 1, -1); + layout->addWidget(d_curveClipping, row++, 0, 1, -1); + layout->addWidget(d_lineSplitting, row++, 0, 1, -1); + + layout->addWidget(new QLabel("Width", page), row, 0 ); + layout->addWidget(d_curveWidth, row++, 1); + + layout->addWidget(new QLabel("Style", page), row, 0 ); + layout->addWidget(d_curvePen, row++, 1); + + layout->addWidget(d_curveFilled, row++, 0, 1, -1); + + layout->addLayout(new QHBoxLayout(), row++, 0); + + layout->setColumnStretch(1, 10); + layout->setRowStretch(row, 10); + + return page; +} + +void Panel::edited() +{ + const Settings s = settings(); + Q_EMIT settingsChanged(s); +} + + +Settings Panel::settings() const +{ + Settings s; + + s.grid.pen = QPen(Qt::black); + + switch(d_gridStyle->currentIndex()) + { + case 0: + s.grid.pen.setStyle(Qt::NoPen); + break; + case 2: + s.grid.pen.setStyle(Qt::DashLine); + break; + } + + s.curve.pen.setStyle(d_curvePen->currentIndex() == 0 ? + Qt::SolidLine : Qt::DotLine); + s.curve.pen.setWidth(d_curveWidth->value()); + s.curve.brush.setStyle((d_curveFilled->isChecked()) ? + Qt::SolidPattern : Qt::NoBrush); + s.curve.numPoints = d_numPoints->value(); + s.curve.functionType = (Settings::FunctionType)d_curveType->currentIndex(); + if ( d_curveClipping->isChecked() ) + s.curve.paintAttributes |= QwtPlotCurve::ClipPolygons; + else + s.curve.paintAttributes &= ~QwtPlotCurve::ClipPolygons; + + if ( d_curveAntialiasing->isChecked() ) + s.curve.renderHint |= QwtPlotCurve::RenderAntialiased; + else + s.curve.renderHint &= ~QwtPlotCurve::RenderAntialiased; + + s.curve.lineSplitting = (d_lineSplitting->isChecked() ); + + s.canvas.useBackingStore = (d_paintCache->isChecked() ); + s.canvas.paintOnScreen = (d_paintOnScreen->isChecked() ); + s.canvas.immediatePaint = (d_immediatePaint->isChecked() ); + + s.updateInterval = d_updateInterval->value(); + s.updateType = (Settings::UpdateType)d_updateType->currentIndex(); + + return s; +} + +void Panel::setSettings(const Settings &s) +{ + d_numPoints->setValue(s.curve.numPoints); + d_updateInterval->setValue(s.updateInterval); + d_updateType->setCurrentIndex(s.updateType); + + switch(s.grid.pen.style()) + { + case Qt::NoPen: + d_gridStyle->setCurrentIndex(0); + break; + case Qt::DashLine: + d_gridStyle->setCurrentIndex(2); + break; + default: + d_gridStyle->setCurrentIndex(1); // Solid + } + + d_paintCache->setChecked(s.canvas.useBackingStore ); + d_paintOnScreen->setChecked(s.canvas.paintOnScreen); + d_immediatePaint->setChecked(s.canvas.immediatePaint); + + d_curveType->setCurrentIndex(s.curve.functionType); + d_curveAntialiasing->setChecked( + s.curve.renderHint & QwtPlotCurve::RenderAntialiased ); + + d_curveClipping->setChecked( + s.curve.paintAttributes & QwtPlotCurve::ClipPolygons); + + d_lineSplitting->setChecked(s.curve.lineSplitting ); + + d_curveWidth->setValue(s.curve.pen.width()); + d_curvePen->setCurrentIndex( + s.curve.pen.style() == Qt::SolidLine ? 0 : 1); + d_curveFilled->setChecked(s.curve.brush.style() != Qt::NoBrush); +} diff --git a/qwt/examples/refreshtest/panel.h b/qwt/examples/refreshtest/panel.h new file mode 100644 index 000000000..74a1e0555 --- /dev/null +++ b/qwt/examples/refreshtest/panel.h @@ -0,0 +1,50 @@ +#ifndef _PANEL_H_ +#define _PANEL_H_ 1 + +#include "settings.h" +#include + +class QComboBox; +class SpinBox; +class CheckBox; + +class Panel: public QTabWidget +{ + Q_OBJECT + +public: + Panel(QWidget * = NULL); + + Settings settings() const; + void setSettings(const Settings &); + +Q_SIGNALS: + void settingsChanged(const Settings &); + +private Q_SLOTS: + void edited(); + +private: + QWidget *createPlotTab(QWidget *); + QWidget *createCanvasTab(QWidget *); + QWidget *createCurveTab(QWidget *); + + SpinBox *d_numPoints; + SpinBox *d_updateInterval; + QComboBox *d_updateType; + + QComboBox *d_gridStyle; + CheckBox *d_paintCache; + CheckBox *d_paintOnScreen; + CheckBox *d_immediatePaint; + + QComboBox *d_curveType; + CheckBox *d_curveAntialiasing; + CheckBox *d_curveClipping; + CheckBox *d_lineSplitting; + SpinBox *d_curveWidth; + QComboBox *d_curvePen; + CheckBox *d_curveFilled; +}; + +#endif diff --git a/qwt/examples/refreshtest/plot.cpp b/qwt/examples/refreshtest/plot.cpp new file mode 100644 index 000000000..870507647 --- /dev/null +++ b/qwt/examples/refreshtest/plot.cpp @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "plot.h" +#include "circularbuffer.h" +#include "settings.h" + +static double wave(double x) +{ + const double period = 1.0; + const double c = 5.0; + + double v = ::fmod(x, period); + + const double amplitude = qAbs(x - qRound(x / c) * c) / ( 0.5 * c ); + v = amplitude * qSin(v / period * 2 * M_PI); + + return v; +} + +static double noise(double) +{ + return 2.0 * ( qrand() / ((double)RAND_MAX + 1) ) - 1.0; +} + +Plot::Plot(QWidget *parent): + QwtPlot(parent), + d_interval(10.0), // seconds + d_timerId(-1) +{ + // Assign a title + setTitle("Testing Refresh Rates"); + + setCanvasBackground(Qt::white); + + alignScales(); + + // Insert grid + d_grid = new QwtPlotGrid(); + d_grid->attach(this); + + // Insert curve + d_curve = new QwtPlotCurve("Data Moving Right"); + d_curve->setPen(QPen(Qt::black)); + d_curve->setData(new CircularBuffer(d_interval, 10)); + d_curve->attach(this); + + // Axis + setAxisTitle(QwtPlot::xBottom, "Seconds"); + setAxisScale(QwtPlot::xBottom, -d_interval, 0.0); + + setAxisTitle(QwtPlot::yLeft, "Values"); + setAxisScale(QwtPlot::yLeft, -1.0, 1.0); + + d_clock.start(); + + setSettings(d_settings); +} + +// +// Set a plain canvas frame and align the scales to it +// +void Plot::alignScales() +{ + // The code below shows how to align the scales to + // the canvas frame, but is also a good example demonstrating + // why the spreaded API needs polishing. + + canvas()->setFrameStyle(QFrame::Box | QFrame::Plain ); + canvas()->setLineWidth(1); + + for ( int i = 0; i < QwtPlot::axisCnt; i++ ) + { + QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(i); + if ( scaleWidget ) + scaleWidget->setMargin(0); + + QwtScaleDraw *scaleDraw = (QwtScaleDraw *)axisScaleDraw(i); + if ( scaleDraw ) + scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false); + } + + plotLayout()->setAlignCanvasToScales(true); +} + +void Plot::setSettings(const Settings &s) +{ + if ( d_timerId >= 0 ) + killTimer(d_timerId); + + d_timerId = startTimer(s.updateInterval); + + d_grid->setPen(s.grid.pen); + d_grid->setVisible(s.grid.pen.style() != Qt::NoPen); + + CircularBuffer *buffer = (CircularBuffer *)d_curve->data(); + if ( s.curve.numPoints != buffer->size() || + s.curve.functionType != d_settings.curve.functionType ) + { + + switch(s.curve.functionType) + { + case Settings::Wave: + buffer->setFunction(wave); + break; + case Settings::Noise: + buffer->setFunction(noise); + break; + default: + buffer->setFunction(NULL); + } + + buffer->fill(d_interval, s.curve.numPoints); + } + + d_curve->setPen(s.curve.pen); + d_curve->setBrush(s.curve.brush); + + d_curve->setPaintAttribute(QwtPlotCurve::ClipPolygons, + s.curve.paintAttributes & QwtPlotCurve::ClipPolygons); + d_curve->setRenderHint(QwtPlotCurve::RenderAntialiased, + s.curve.renderHint & QwtPlotCurve::RenderAntialiased); + + canvas()->setAttribute(Qt::WA_PaintOnScreen, s.canvas.paintOnScreen); + + canvas()->setPaintAttribute( + QwtPlotCanvas::BackingStore, s.canvas.useBackingStore); + canvas()->setPaintAttribute( + QwtPlotCanvas::ImmediatePaint, s.canvas.immediatePaint); + + QwtPainter::setPolylineSplitting(s.curve.lineSplitting); + + d_settings = s; +} + +void Plot::timerEvent(QTimerEvent *) +{ + CircularBuffer *buffer = (CircularBuffer *)d_curve->data(); + buffer->setReferenceTime(d_clock.elapsed() / 1000.0); + + switch(d_settings.updateType) + { + case Settings::RepaintCanvas: + { + // the axes in this example doesn't change. So all we need to do + // is to repaint the canvas. + + canvas()->replot(); + break; + } + default: + { + replot(); + } + } +} diff --git a/qwt/examples/refreshtest/plot.h b/qwt/examples/refreshtest/plot.h new file mode 100644 index 000000000..e28499604 --- /dev/null +++ b/qwt/examples/refreshtest/plot.h @@ -0,0 +1,38 @@ +#ifndef _PLOT_H_ +#define _PLOT_H_ 1 + +#include +#include +#include "settings.h" + +class QwtPlotGrid; +class QwtPlotCurve; + +class Plot: public QwtPlot +{ + Q_OBJECT + +public: + Plot(QWidget* = NULL); + +public Q_SLOTS: + void setSettings(const Settings &); + +protected: + virtual void timerEvent(QTimerEvent *e); + +private: + void alignScales(); + + QwtPlotGrid *d_grid; + QwtPlotCurve *d_curve; + + QwtSystemClock d_clock; + double d_interval; + + int d_timerId; + + Settings d_settings; +}; + +#endif diff --git a/qwt/examples/refreshtest/refreshtest.pro b/qwt/examples/refreshtest/refreshtest.pro new file mode 100644 index 000000000..33da0de1e --- /dev/null +++ b/qwt/examples/refreshtest/refreshtest.pro @@ -0,0 +1,26 @@ +################################################################ +# 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( $${PWD}/../examples.pri ) + +TARGET = refreshtest + +HEADERS = \ + settings.h \ + circularbuffer.h \ + panel.h \ + plot.h \ + mainwindow.h + +SOURCES = \ + circularbuffer.cpp \ + panel.cpp \ + plot.cpp \ + mainwindow.cpp \ + main.cpp diff --git a/qwt/examples/refreshtest/settings.h b/qwt/examples/refreshtest/settings.h new file mode 100644 index 000000000..6fbfc9ef3 --- /dev/null +++ b/qwt/examples/refreshtest/settings.h @@ -0,0 +1,70 @@ +#ifndef _SETTINGS_H_ +#define _SETTINGS_H_ + +#include +#include + +class Settings +{ +public: + enum FunctionType + { + NoFunction = -1, + + Wave, + Noise + }; + + enum UpdateType + { + RepaintCanvas, + Replot + }; + + Settings() + { + grid.pen = Qt::NoPen; + + curve.brush = Qt::NoBrush; + curve.numPoints = 1000; + curve.functionType = Wave; + curve.paintAttributes = 0; + curve.renderHint = 0; + curve.lineSplitting = true; + + canvas.useBackingStore = false; + canvas.paintOnScreen = false; + canvas.immediatePaint = true; + + updateType = RepaintCanvas; + updateInterval = 20; + } + + struct gridSettings + { + QPen pen; + } grid; + + struct curveSettings + { + QPen pen; + QBrush brush; + uint numPoints; + FunctionType functionType; + int paintAttributes; + int renderHint; + bool lineSplitting; + } curve; + + struct canvasSettings + { + bool useBackingStore; + bool paintOnScreen; + bool immediatePaint; + } canvas; + + UpdateType updateType; + int updateInterval; +}; + +#endif diff --git a/qwt/examples/simple_plot/simple.cpp b/qwt/examples/simple_plot/simple.cpp deleted file mode 100644 index 5d6612474..000000000 --- a/qwt/examples/simple_plot/simple.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//----------------------------------------------------------------- -// simple.cpp -// -// A simple example which shows how to use QwtPlot and QwtData -//----------------------------------------------------------------- - -class SimpleData: public QwtData -{ - // The x values depend on its index and the y values - // can be calculated from the corresponding x value. - // So we don´t need to store the values. - // Such an implementation is slower because every point - // has to be recalculated for every replot, but it demonstrates how - // QwtData can be used. - -public: - SimpleData(double(*y)(double), size_t size): - d_size(size), - d_y(y) - { - } - - virtual QwtData *copy() const - { - return new SimpleData(d_y, d_size); - } - - virtual size_t size() const - { - return d_size; - } - - virtual double x(size_t i) const - { - return 0.1 * i; - } - - virtual double y(size_t i) const - { - return d_y(x(i)); - } -private: - size_t d_size; - double(*d_y)(double); -}; - -class Plot : public QwtPlot -{ -public: - Plot(); -}; - - -Plot::Plot() -{ - setTitle("A Simple QwtPlot Demonstration"); - insertLegend(new QwtLegend(), QwtPlot::RightLegend); - - // Set axis titles - setAxisTitle(xBottom, "x -->"); - setAxisTitle(yLeft, "y -->"); - - // Insert new curves - QwtPlotCurve *cSin = new QwtPlotCurve("y = sin(x)"); -#if QT_VERSION >= 0x040000 - cSin->setRenderHint(QwtPlotItem::RenderAntialiased); -#endif - cSin->setPen(QPen(Qt::red)); - cSin->attach(this); - - QwtPlotCurve *cCos = new QwtPlotCurve("y = cos(x)"); -#if QT_VERSION >= 0x040000 - cCos->setRenderHint(QwtPlotItem::RenderAntialiased); -#endif - cCos->setPen(QPen(Qt::blue)); - cCos->attach(this); - - // Create sin and cos data - const int nPoints = 100; - cSin->setData(SimpleData(::sin, nPoints)); - cCos->setData(SimpleData(::cos, nPoints)); - - // Insert markers - - // ...a horizontal line at y = 0... - QwtPlotMarker *mY = new QwtPlotMarker(); - mY->setLabel(QString::fromLatin1("y = 0")); - mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); - mY->setLineStyle(QwtPlotMarker::HLine); - mY->setYValue(0.0); - mY->attach(this); - - // ...a vertical line at x = 2 * pi - QwtPlotMarker *mX = new QwtPlotMarker(); - mX->setLabel(QString::fromLatin1("x = 2 pi")); - mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom); - mX->setLabelOrientation(Qt::Vertical); - mX->setLineStyle(QwtPlotMarker::VLine); - mX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine)); - mX->setXValue(2.0 * M_PI); - mX->attach(this); -} - -int main(int argc, char **argv) -{ - QApplication a(argc, argv); - - Plot plot; -#if QT_VERSION < 0x040000 - a.setMainWidget(&plot); -#endif - plot.resize(600,400); - plot.show(); - return a.exec(); -} diff --git a/qwt/examples/sinusplot/sinusplot.cpp b/qwt/examples/sinusplot/sinusplot.cpp new file mode 100644 index 000000000..ec9e9e462 --- /dev/null +++ b/qwt/examples/sinusplot/sinusplot.cpp @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------- +// simple.cpp +// +// A simple example which shows how to use QwtPlot connected +// to a data class without any storage, calculating each values +// on the fly. +//----------------------------------------------------------------- + +class FunctionData: public QwtSyntheticPointData +{ +public: + FunctionData(double(*y)(double)): + QwtSyntheticPointData(100), + d_y(y) + { + } + + virtual double y(double x) const + { + return d_y(x); + } + +private: + double(*d_y)(double); +}; + +class Plot : public QwtPlot +{ +public: + Plot( QWidget *parent = NULL); + +protected: + virtual void resizeEvent( QResizeEvent * ); + +private: + void populate(); + void updateGradient(); +}; + + +Plot::Plot(QWidget *parent): + QwtPlot( parent ) +{ + // panning with the left mouse button + (void) new QwtPlotPanner( canvas() ); + + // zoom in/out with the wheel + (void) new QwtPlotMagnifier( canvas() ); + + setAutoFillBackground( true ); + setPalette( QPalette( QColor( 165, 193, 228 ) ) ); + updateGradient(); + + setTitle("A Simple QwtPlot Demonstration"); + insertLegend(new QwtLegend(), QwtPlot::RightLegend); + + // axes + setAxisTitle(xBottom, "x -->" ); + setAxisScale(xBottom, 0.0, 10.0); + + setAxisTitle(yLeft, "y -->"); + setAxisScale(yLeft, -1.0, 1.0); + + // canvas + canvas()->setLineWidth( 1 ); + canvas()->setFrameStyle( QFrame::Box | QFrame::Plain ); + canvas()->setBorderRadius( 15 ); + + QPalette canvasPalette( Qt::white ); + canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) ); + canvas()->setPalette( canvasPalette ); + + populate(); +} + +void Plot::populate() +{ + // Insert new curves + QwtPlotCurve *cSin = new QwtPlotCurve("y = sin(x)"); + cSin->setRenderHint(QwtPlotItem::RenderAntialiased); + cSin->setLegendAttribute(QwtPlotCurve::LegendShowLine, true); + cSin->setPen(QPen(Qt::red)); + cSin->attach(this); + + QwtPlotCurve *cCos = new QwtPlotCurve("y = cos(x)"); + cCos->setRenderHint(QwtPlotItem::RenderAntialiased); + cCos->setLegendAttribute(QwtPlotCurve::LegendShowLine, true); + cCos->setPen(QPen(Qt::blue)); + cCos->attach(this); + + // Create sin and cos data + cSin->setData(new FunctionData(::sin)); + cCos->setData(new FunctionData(::cos)); + + // Insert markers + + // ...a horizontal line at y = 0... + QwtPlotMarker *mY = new QwtPlotMarker(); + mY->setLabel(QString::fromLatin1("y = 0")); + mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop); + mY->setLineStyle(QwtPlotMarker::HLine); + mY->setYValue(0.0); + mY->attach(this); + + // ...a vertical line at x = 2 * pi + QwtPlotMarker *mX = new QwtPlotMarker(); + mX->setLabel(QString::fromLatin1("x = 2 pi")); + mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom); + mX->setLabelOrientation(Qt::Vertical); + mX->setLineStyle(QwtPlotMarker::VLine); + mX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine)); + mX->setXValue(2.0 * M_PI); + mX->attach(this); +} + +void Plot::updateGradient() +{ + QPalette pal = palette(); + + const QColor buttonColor = pal.color( QPalette::Button ); + +#ifdef Q_WS_X11 + // Qt 4.7.1: QGradient::StretchToDeviceMode is buggy on X11 + + QLinearGradient gradient( rect().topLeft(), rect().bottomLeft() ); + gradient.setColorAt( 0.0, Qt::white ); + gradient.setColorAt( 0.7, buttonColor ); + gradient.setColorAt( 1.0, buttonColor ); +#else + QLinearGradient gradient( 0, 0, 0, 1 ); + gradient.setCoordinateMode( QGradient::StretchToDeviceMode ); + gradient.setColorAt( 0.0, Qt::white ); + gradient.setColorAt( 0.7, buttonColor ); + gradient.setColorAt( 1.0, buttonColor ); +#endif + + pal.setBrush( QPalette::Window, gradient ); + setPalette( pal ); +} + +void Plot::resizeEvent( QResizeEvent *event ) +{ + QwtPlot::resizeEvent( event ); +#ifdef Q_WS_X11 + updateGradient(); +#endif +} + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + Plot *plot = new Plot(); + + // We put a dummy widget around to have + // so that Qt paints a widget background + // when resizing + + QWidget window; + QHBoxLayout *layout = new QHBoxLayout( &window ); + layout->setContentsMargins( 0, 0, 0, 0 ); + layout->addWidget( plot ); + + window.resize(600,400); + window.show(); + + return a.exec(); +} diff --git a/qwt/examples/simple_plot/simple_plot.pro b/qwt/examples/sinusplot/sinusplot.pro similarity index 67% rename from qwt/examples/simple_plot/simple_plot.pro rename to qwt/examples/sinusplot/sinusplot.pro index 387a9c525..e190dfd0b 100644 --- a/qwt/examples/simple_plot/simple_plot.pro +++ b/qwt/examples/sinusplot/sinusplot.pro @@ -1,16 +1,15 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) -TARGET = simple +TARGET = sinusplot SOURCES = \ - simple.cpp - + sinusplot.cpp diff --git a/qwt/examples/sliders/sliders.cpp b/qwt/examples/sliders/sliders.cpp index 0d6f62f5c..7590c28af 100644 --- a/qwt/examples/sliders/sliders.cpp +++ b/qwt/examples/sliders/sliders.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -11,11 +10,7 @@ class Layout: public QBoxLayout { public: Layout(Qt::Orientation o, QWidget *parent = NULL): -#if QT_VERSION < 0x040000 - QBoxLayout(parent, QBoxLayout::LeftToRight) -#else QBoxLayout(QBoxLayout::LeftToRight, parent) -#endif { if ( o == Qt::Vertical ) setDirection(QBoxLayout::TopToBottom); @@ -30,11 +25,7 @@ Slider::Slider(QWidget *parent, int sliderType): { d_slider = createSlider(this, sliderType); -#if QT_VERSION < 0x040000 - int alignment = Qt::AlignCenter; -#else QFlags alignment; -#endif switch(d_slider->scalePosition()) { case QwtSlider::NoScale: @@ -77,53 +68,52 @@ QwtSlider *Slider::createSlider(QWidget *parent, int sliderType) const { QwtSlider *slider = NULL; - switch(sliderType) + switch( sliderType ) { case 0: { - slider = new QwtSlider(parent, - Qt::Horizontal, QwtSlider::TopScale, QwtSlider::BgTrough); - slider->setThumbWidth(10); + slider = new QwtSlider(parent, Qt::Horizontal, + QwtSlider::TopScale, QwtSlider::Trough); + slider->setHandleSize( 30, 16 ); slider->setRange(-10.0, 10.0, 1.0, 0); // paging disabled break; } case 1: { - slider = new QwtSlider(parent, - Qt::Horizontal, QwtSlider::NoScale, QwtSlider::BgBoth); + slider = new QwtSlider(parent, Qt::Horizontal, + QwtSlider::NoScale, QwtSlider::Trough | QwtSlider::Groove ); slider->setRange(0.0, 1.0, 0.01, 5); break; } case 2: { - slider = new QwtSlider(parent, - Qt::Horizontal, QwtSlider::BottomScale, QwtSlider::BgSlot); - slider->setThumbWidth(25); - slider->setThumbLength(12); + slider = new QwtSlider(parent, Qt::Horizontal, + QwtSlider::BottomScale, QwtSlider::Groove); + slider->setHandleSize( 12, 25 ); slider->setRange(1000.0, 3000.0, 10.0, 10); break; } case 3: { - slider = new QwtSlider(parent, - Qt::Vertical, QwtSlider::LeftScale, QwtSlider::BgSlot); + slider = new QwtSlider(parent, Qt::Vertical, + QwtSlider::LeftScale, QwtSlider::Groove); slider->setRange(0.0, 100.0, 1.0, 5); slider->setScaleMaxMinor(5); break; } case 4: { - slider = new QwtSlider(parent, - Qt::Vertical, QwtSlider::NoScale, QwtSlider::BgTrough); + slider = new QwtSlider(parent, Qt::Vertical, + QwtSlider::NoScale, QwtSlider::Trough); slider->setRange(0.0,100.0,1.0, 10); break; } case 5: { - slider = new QwtSlider(parent, - Qt::Vertical, QwtSlider::RightScale, QwtSlider::BgBoth); + slider = new QwtSlider(parent, Qt::Vertical, + QwtSlider::RightScale, QwtSlider::Trough | QwtSlider::Groove); slider->setScaleEngine(new QwtLog10ScaleEngine); - slider->setThumbWidth(20); + slider->setHandleSize( 20, 32 ); slider->setBorderWidth(1); slider->setRange(0.0, 4.0, 0.01); slider->setScale(1.0, 1.0e4); @@ -132,15 +122,21 @@ QwtSlider *Slider::createSlider(QWidget *parent, int sliderType) const } } + if ( slider ) + { + QString name( "Slider %1" ); + slider->setObjectName( name.arg( sliderType ) ); + } + return slider; } -void Slider::setNum(double v) +void Slider::setNum( double v ) { if ( d_slider->scaleMap().transformation()->type() == QwtScaleTransformation::Log10 ) { - v = pow(10.0, v); + v = qPow(10.0, v); } QString text; @@ -149,7 +145,7 @@ void Slider::setNum(double v) d_label->setText(text); } -SliderDemo::SliderDemo(QWidget *p): +SliderDemo::SliderDemo(QWidget *p): QWidget(p) { int i; @@ -191,10 +187,6 @@ int main (int argc, char **argv) QApplication::setFont(QFont("Helvetica",10)); SliderDemo w; - -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif w.show(); return a.exec(); diff --git a/qwt/examples/sliders/sliders.h b/qwt/examples/sliders/sliders.h index e9e58ace2..02d10475b 100644 --- a/qwt/examples/sliders/sliders.h +++ b/qwt/examples/sliders/sliders.h @@ -10,7 +10,7 @@ class Slider: public QWidget public: Slider(QWidget *parent, int sliderType); -private slots: +private Q_SLOTS: void setNum(double v); private: diff --git a/qwt/examples/sliders/sliders.pro b/qwt/examples/sliders/sliders.pro index f7501703c..10cffc76b 100644 --- a/qwt/examples/sliders/sliders.pro +++ b/qwt/examples/sliders/sliders.pro @@ -1,19 +1,18 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = sliders HEADERS = \ - sliders.h + sliders.h SOURCES = \ - sliders.cpp - + sliders.cpp diff --git a/qwt/examples/spectrogram/main.cpp b/qwt/examples/spectrogram/main.cpp index f13c49e1e..0cb50c93e 100644 --- a/qwt/examples/spectrogram/main.cpp +++ b/qwt/examples/spectrogram/main.cpp @@ -23,56 +23,34 @@ MainWindow::MainWindow(QWidget *parent): QToolBar *toolBar = new QToolBar(this); QToolButton *btnSpectrogram = new QToolButton(toolBar); - QToolButton *btnContour = new QToolButton(toolBar); - QToolButton *btnPrint = new QToolButton(toolBar); - -#if QT_VERSION >= 0x040000 btnSpectrogram->setText("Spectrogram"); - //btnSpectrogram->setIcon(QIcon()); btnSpectrogram->setCheckable(true); btnSpectrogram->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); toolBar->addWidget(btnSpectrogram); + connect(btnSpectrogram, SIGNAL(toggled(bool)), + d_plot, SLOT(showSpectrogram(bool))); + QToolButton *btnContour = new QToolButton(toolBar); btnContour->setText("Contour"); - //btnContour->setIcon(QIcon()); btnContour->setCheckable(true); btnContour->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); toolBar->addWidget(btnContour); + connect(btnContour, SIGNAL(toggled(bool)), + d_plot, SLOT(showContour(bool))); - btnPrint->setText("Print"); +#ifndef QT_NO_PRINTER + QToolButton *btnPrint = new QToolButton(toolBar); + btnPrint->setText("Print"); btnPrint->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); toolBar->addWidget(btnPrint); -#else - btnSpectrogram->setTextLabel("Spectrogram"); - //btnSpectrogram->setPixmap(zoom_xpm); - btnSpectrogram->setToggleButton(true); - btnSpectrogram->setUsesTextLabel(true); - - btnContour->setTextLabel("Contour"); - //btnContour->setPixmap(zoom_xpm); - btnContour->setToggleButton(true); - btnContour->setUsesTextLabel(true); - - btnPrint->setTextLabel("Print"); - btnPrint->setUsesTextLabel(true); + connect(btnPrint, SIGNAL(clicked()), + d_plot, SLOT(printPlot()) ); #endif addToolBar(toolBar); - connect(btnSpectrogram, SIGNAL(toggled(bool)), - d_plot, SLOT(showSpectrogram(bool))); - connect(btnContour, SIGNAL(toggled(bool)), - d_plot, SLOT(showContour(bool))); - connect(btnPrint, SIGNAL(clicked()), - d_plot, SLOT(printPlot()) ); - -#if QT_VERSION >= 0x040000 btnSpectrogram->setChecked(true); btnContour->setChecked(false); -#else - btnSpectrogram->setOn(true); - btnContour->setOn(false); -#endif } int main(int argc, char **argv) @@ -80,12 +58,8 @@ int main(int argc, char **argv) QApplication a(argc, argv); MainWindow mainWindow; -#if QT_VERSION < 0x040000 - a.setMainWidget(&mainWindow); -#endif - mainWindow.resize(600,400); mainWindow.show(); - return a.exec(); + return a.exec(); } diff --git a/qwt/examples/spectrogram/plot.cpp b/qwt/examples/spectrogram/plot.cpp index 0a617f965..ca5d66a67 100644 --- a/qwt/examples/spectrogram/plot.cpp +++ b/qwt/examples/spectrogram/plot.cpp @@ -1,7 +1,5 @@ #include -#if QT_VERSION >= 0x040000 #include -#endif #include #include #include @@ -9,6 +7,7 @@ #include #include #include +#include #include "plot.h" class MyZoomer: public QwtPlotZoomer @@ -20,14 +19,12 @@ public: setTrackerMode(AlwaysOn); } - virtual QwtText trackerText(const QwtDoublePoint &pos) const + virtual QwtText trackerTextF(const QPointF &pos) const { QColor bg(Qt::white); -#if QT_VERSION >= 0x040300 bg.setAlpha(200); -#endif - QwtText text = QwtPlotZoomer::trackerText(pos); + QwtText text = QwtPlotZoomer::trackerTextF(pos); text.setBackgroundBrush( QBrush( bg )); return text; } @@ -36,19 +33,11 @@ public: class SpectrogramData: public QwtRasterData { public: - SpectrogramData(): - QwtRasterData(QwtDoubleRect(-1.5, -1.5, 3.0, 3.0)) + SpectrogramData() { - } - - virtual QwtRasterData *copy() const - { - return new SpectrogramData(); - } - - virtual QwtDoubleInterval range() const - { - return QwtDoubleInterval(0.0, 10.0); + setInterval( Qt::XAxis, QwtInterval( -1.5, 1.5 ) ); + setInterval( Qt::YAxis, QwtInterval( -1.5, 1.5 ) ); + setInterval( Qt::ZAxis, QwtInterval( 0.0, 10.0 ) ); } virtual double value(double x, double y) const @@ -62,36 +51,42 @@ public: } }; +class ColorMap: public QwtLinearColorMap +{ +public: + ColorMap(): + QwtLinearColorMap(Qt::darkCyan, Qt::red) + { + addColorStop(0.1, Qt::cyan); + addColorStop(0.6, Qt::green); + addColorStop(0.95, Qt::yellow); + } +}; + Plot::Plot(QWidget *parent): QwtPlot(parent) { d_spectrogram = new QwtPlotSpectrogram(); + d_spectrogram->setRenderThreadCount(0); // use system specific thread count - QwtLinearColorMap colorMap(Qt::darkCyan, Qt::red); - colorMap.addColorStop(0.1, Qt::cyan); - colorMap.addColorStop(0.6, Qt::green); - colorMap.addColorStop(0.95, Qt::yellow); + d_spectrogram->setColorMap(new ColorMap()); - d_spectrogram->setColorMap(colorMap); - - d_spectrogram->setData(SpectrogramData()); + d_spectrogram->setData(new SpectrogramData()); d_spectrogram->attach(this); - QwtValueList contourLevels; + QList contourLevels; for ( double level = 0.5; level < 10.0; level += 1.0 ) contourLevels += level; d_spectrogram->setContourLevels(contourLevels); + const QwtInterval zInterval = d_spectrogram->data()->interval( Qt::ZAxis ); // A color bar on the right axis QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight); rightAxis->setTitle("Intensity"); rightAxis->setColorBarEnabled(true); - rightAxis->setColorMap(d_spectrogram->data().range(), - d_spectrogram->colorMap()); + rightAxis->setColorMap( zInterval, new ColorMap()); - setAxisScale(QwtPlot::yRight, - d_spectrogram->data().range().minValue(), - d_spectrogram->data().range().maxValue() ); + setAxisScale(QwtPlot::yRight, zInterval.minValue(), zInterval.maxValue() ); enableAxis(QwtPlot::yRight); plotLayout()->setAlignCanvasToScales(true); @@ -103,13 +98,8 @@ Plot::Plot(QWidget *parent): // Ctrl+RighButton: zoom out to full size QwtPlotZoomer* zoomer = new MyZoomer(canvas()); -#if QT_VERSION < 0x040000 - zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlButton); -#else zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); -#endif zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); @@ -142,25 +132,27 @@ void Plot::showSpectrogram(bool on) replot(); } +#ifndef QT_NO_PRINTER + void Plot::printPlot() { +#if 1 QPrinter printer; - printer.setOrientation(QPrinter::Landscape); -#if QT_VERSION < 0x040000 - printer.setColorMode(QPrinter::Color); -#if 0 - printer.setOutputFileName("/tmp/spectrogram.ps"); -#endif - if (printer.setup()) #else -#if 0 - printer.setOutputFileName("/tmp/spectrogram.pdf"); + QPrinter printer(QPrinter::HighResolution); #endif + printer.setOrientation(QPrinter::Landscape); + printer.setOutputFileName("spectrogram.pdf"); QPrintDialog dialog(&printer); if ( dialog.exec() ) -#endif { - print(printer); + QwtPlotRenderer renderer; + + renderer.setDiscardFlag(QwtPlotRenderer::DiscardBackground, false); + renderer.setLayoutFlag(QwtPlotRenderer::KeepFrames, true); + + renderer.renderTo(this, printer); } } +#endif diff --git a/qwt/examples/spectrogram/plot.h b/qwt/examples/spectrogram/plot.h index 58aa90fc7..3d9da9f40 100644 --- a/qwt/examples/spectrogram/plot.h +++ b/qwt/examples/spectrogram/plot.h @@ -8,10 +8,13 @@ class Plot: public QwtPlot public: Plot(QWidget * = NULL); -public slots: +public Q_SLOTS: void showContour(bool on); void showSpectrogram(bool on); + +#ifndef QT_NO_PRINTER void printPlot(); +#endif private: QwtPlotSpectrogram *d_spectrogram; diff --git a/qwt/examples/spectrogram/spectrogram.pro b/qwt/examples/spectrogram/spectrogram.pro index 04b62873c..aea5ddcbd 100644 --- a/qwt/examples/spectrogram/spectrogram.pro +++ b/qwt/examples/spectrogram/spectrogram.pro @@ -1,19 +1,19 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = spectrogram HEADERS = \ - plot.h + plot.h SOURCES = \ - plot.cpp \ - main.cpp + plot.cpp \ + main.cpp diff --git a/qwt/examples/stylesheets/choco.css b/qwt/examples/stylesheets/choco.css new file mode 100644 index 000000000..e2fe171ad --- /dev/null +++ b/qwt/examples/stylesheets/choco.css @@ -0,0 +1,38 @@ +QwtPlot +{ + border: 1px solid white; + border-radius: 10px; + padding: 10px; + background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 Brown, stop: 0.5 Chocolate, stop: 1 Brown ); +} + +QwtPlotCanvas +{ + border: 1px solid White; + border-radius: 10px; + background-color: Tan; +} + +QwtScaleWidget +{ + color: palette(light); +} + +QwtTextLabel#QwtPlotTitle +{ + color: palette(light); +} + +QwtLegend +{ + border: 1px solid white; + border-radius: 10px; + padding: 10px; + background: brown; +} + +QwtLegendItem +{ + color: palette(light); +} diff --git a/qwt/examples/svgmap/main.cpp b/qwt/examples/svgmap/main.cpp index 2bea8c524..27091f1bc 100644 --- a/qwt/examples/svgmap/main.cpp +++ b/qwt/examples/svgmap/main.cpp @@ -7,28 +7,28 @@ class MainWindow: public QMainWindow { public: - MainWindow(QWidget *parent = NULL): - QMainWindow(parent) - { + MainWindow(const QString &fileName) + { Plot *plot = new Plot(this); + if ( !fileName.isEmpty() ) + plot->loadSVG(fileName); + setCentralWidget(plot); +#ifndef QT_NO_FILEDIALOG + QToolBar *toolBar = new QToolBar(this); QToolButton *btnLoad = new QToolButton(toolBar); - -#if QT_VERSION >= 0x040000 + btnLoad->setText("Load SVG"); btnLoad->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); toolBar->addWidget(btnLoad); -#else - btnLoad->setTextLabel("Load SVG"); - btnLoad->setUsesTextLabel(true); -#endif addToolBar(toolBar); - connect(btnLoad, SIGNAL(clicked()), plot, SLOT(loadSVG())); + connect(btnLoad, SIGNAL(clicked()), plot, SLOT(loadSVG())); +#endif } }; @@ -36,10 +36,11 @@ int main(int argc, char **argv) { QApplication a(argc, argv); - MainWindow w; -#if QT_VERSION < 0x040000 - a.setMainWidget(&w); -#endif + QString fileName; + if ( argc > 1 ) + fileName = argv[1]; + + MainWindow w(fileName); w.resize(600,400); w.show(); diff --git a/qwt/examples/svgmap/plot.cpp b/qwt/examples/svgmap/plot.cpp index 1b13777da..2d8cd6b70 100644 --- a/qwt/examples/svgmap/plot.cpp +++ b/qwt/examples/svgmap/plot.cpp @@ -11,7 +11,7 @@ Plot::Plot(QWidget *parent): QwtPlot(parent), d_mapItem(NULL), d_mapRect(0.0, 0.0, 100.0, 100.0) // something -{ +{ #if 1 /* d_mapRect is only a reference for zooming, but @@ -28,50 +28,46 @@ Plot::Plot(QWidget *parent): /* Navigation: - + Left Mouse Button: Panning Mouse Wheel: Zooming In/Out - Right Mouse Button: Reset to initial + Right Mouse Button: Reset to initial */ (void)new QwtPlotPanner(canvas()); (void)new QwtPlotMagnifier(canvas()); -#if QT_VERSION >= 0x040000 - using namespace Qt; -#endif - canvas()->setFocusPolicy(WheelFocus); + canvas()->setFocusPolicy(Qt::WheelFocus); rescale(); } +#ifndef QT_NO_FILEDIALOG + void Plot::loadSVG() { QString dir; -#if 0 - dir = "/dw/svg"; -#endif -#if QT_VERSION >= 0x040000 const QString fileName = QFileDialog::getOpenFileName( NULL, "Load a Scaleable Vector Graphic (SVG) Map", dir, "SVG Files (*.svg)"); -#else - const QString fileName = QFileDialog::getOpenFileName( - dir, "SVG Files (*.svg)", NULL, NULL, - "Load a Scaleable Vector Graphic (SVG) Map" ); -#endif + if ( !fileName.isEmpty() ) + loadSVG(fileName); +} + +#endif + +void Plot::loadSVG(const QString &fileName) +{ + if ( d_mapItem == NULL ) { - if ( d_mapItem == NULL ) - { - d_mapItem = new QwtPlotSvgItem(); - d_mapItem->attach(this); - } - - d_mapItem->loadFile(d_mapRect, fileName); - rescale(); - - replot(); + d_mapItem = new QwtPlotSvgItem(); + d_mapItem->attach(this); } + + d_mapItem->loadFile(d_mapRect, fileName); + rescale(); + + replot(); } void Plot::rescale() diff --git a/qwt/examples/svgmap/plot.h b/qwt/examples/svgmap/plot.h index 300c04fc5..392e4decd 100644 --- a/qwt/examples/svgmap/plot.h +++ b/qwt/examples/svgmap/plot.h @@ -1,5 +1,5 @@ #include -#include +#include class QwtPlotSvgItem; @@ -10,12 +10,17 @@ class Plot: public QwtPlot public: Plot(QWidget * = NULL); -public slots: +public Q_SLOTS: + +#ifndef QT_NO_FILEDIALOG void loadSVG(); +#endif + + void loadSVG(const QString &); private: void rescale(); QwtPlotSvgItem *d_mapItem; - const QwtDoubleRect d_mapRect; + const QRectF d_mapRect; }; diff --git a/qwt/examples/svgmap/svgmap.pro b/qwt/examples/svgmap/svgmap.pro index 4b9782405..1324f70de 100644 --- a/qwt/examples/svgmap/svgmap.pro +++ b/qwt/examples/svgmap/svgmap.pro @@ -1,20 +1,26 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) + +!contains(QWT_CONFIG, QwtSvg) { + + message(Are you trying to build Qwt with the Qt Creator as Shadow Build ?) + error(Qwt is configured without SVG support !) +} TARGET = svgmap QT += svg HEADERS = \ - plot.h + plot.h SOURCES = \ - plot.cpp \ - main.cpp + plot.cpp \ + main.cpp diff --git a/qwt/examples/sysinfo/sysinfo.cpp b/qwt/examples/sysinfo/sysinfo.cpp index ec883464c..6315b839a 100644 --- a/qwt/examples/sysinfo/sysinfo.cpp +++ b/qwt/examples/sysinfo/sysinfo.cpp @@ -5,50 +5,62 @@ #include #include #include +#include class ValueBar: public QWidget { public: - ValueBar(Qt::Orientation orientation, - const QString &text, QWidget *parent, double value = 0.0): - QWidget(parent) + ValueBar( Qt::Orientation orientation, + const QString &text, QWidget *parent, double value = 0.0 ): + QWidget( parent ) { - d_label = new QLabel(text, this); - d_label->setFont(QFont("Helvetica", 10)); + d_label = new QLabel( text, this ); + d_label->setFont( QFont( "Helvetica", 10 ) ); - d_thermo = new QwtThermo(this); - d_thermo->setRange(0.0,100.0); - d_thermo->setValue(value); - d_thermo->setFont(QFont("Helvetica", 8)); - d_thermo->setPipeWidth(6); - d_thermo->setScaleMaxMajor(6); - d_thermo->setScaleMaxMinor(5); - d_thermo->setMargin(10); - d_thermo->setFillColor(QColor("DarkMagenta")); + d_thermo = new QwtThermo( this ); + d_thermo->setRange( 0.0, 100.0 ); + d_thermo->setValue( value ); + d_thermo->setFont( QFont( "Helvetica", 8 ) ); + d_thermo->setPipeWidth( 6 ); + d_thermo->setScaleMaxMajor( 6 ); + d_thermo->setScaleMaxMinor( 5 ); + d_thermo->setFillBrush( Qt::darkMagenta ); - QVBoxLayout *layout = new QVBoxLayout(this); - layout->setMargin(0); - layout->setSpacing(0); +#if 0 + QwtLinearColorMap *colorMap = + new QwtLinearColorMap( Qt::blue, Qt::red ); + + colorMap->addColorStop( 0.2, Qt::yellow ); + colorMap->addColorStop( 0.3, Qt::cyan ); + colorMap->addColorStop( 0.4, Qt::green ); + colorMap->addColorStop( 0.5, Qt::magenta ); + colorMap->setMode( QwtLinearColorMap::FixedColors ); + d_thermo->setColorMap( colorMap ); +#endif + + QVBoxLayout *layout = new QVBoxLayout( this ); + layout->setMargin( 0 ); + layout->setSpacing( 0 ); if ( orientation == Qt::Horizontal ) { - d_label->setAlignment(Qt::AlignCenter); - d_thermo->setOrientation(orientation, QwtThermo::BottomScale); - layout->addWidget(d_label); - layout->addWidget(d_thermo); + d_label->setAlignment( Qt::AlignCenter ); + d_thermo->setOrientation( orientation, QwtThermo::BottomScale ); + layout->addWidget( d_label ); + layout->addWidget( d_thermo ); } else { - d_label->setAlignment(Qt::AlignRight); - d_thermo->setOrientation(orientation, QwtThermo::LeftScale); - layout->addWidget(d_thermo, 10, Qt::AlignHCenter); - layout->addWidget(d_label, 0); + d_label->setAlignment( Qt::AlignRight ); + d_thermo->setOrientation( orientation, QwtThermo::LeftScale ); + layout->addWidget( d_thermo, 10, Qt::AlignHCenter ); + layout->addWidget( d_label, 0 ); } } - void setValue(double value) + void setValue( double value ) { - d_thermo->setValue(value); + d_thermo->setValue( value ); } private: QLabel *d_label; @@ -58,53 +70,50 @@ private: class SysInfo : public QFrame { public: - SysInfo(QWidget *parent = NULL): - QFrame(parent) - { - QGroupBox *memBox = new QGroupBox("Memory Usage", this); - memBox->setFont(QFont("Helvetica", 10)); + SysInfo( QWidget *parent = NULL ): + QFrame( parent ) + { + QGroupBox *memBox = new QGroupBox( "Memory Usage", this ); + memBox->setFont( QFont( "Helvetica", 10 ) ); - QVBoxLayout *memLayout = new QVBoxLayout(memBox); - memLayout->setMargin(15); - memLayout->setSpacing(5); + QVBoxLayout *memLayout = new QVBoxLayout( memBox ); + memLayout->setMargin( 15 ); + memLayout->setSpacing( 5 ); Qt::Orientation o = Qt::Horizontal; - memLayout->addWidget(new ValueBar(o, "Used", memBox, 57)); - memLayout->addWidget(new ValueBar(o, "Shared", memBox, 17)); - memLayout->addWidget(new ValueBar(o, "Cache", memBox, 30)); - memLayout->addWidget(new ValueBar(o, "Buffers", memBox, 22)); - memLayout->addWidget(new ValueBar(o, "Swap Used", memBox, 57)); - memLayout->addWidget(new QWidget(memBox), 10); // spacer + memLayout->addWidget( new ValueBar( o, "Used", memBox, 57 ) ); + memLayout->addWidget( new ValueBar( o, "Shared", memBox, 17 ) ); + memLayout->addWidget( new ValueBar( o, "Cache", memBox, 30 ) ); + memLayout->addWidget( new ValueBar( o, "Buffers", memBox, 22 ) ); + memLayout->addWidget( new ValueBar( o, "Swap Used", memBox, 57 ) ); + memLayout->addWidget( new QWidget( memBox ), 10 ); // spacer - QGroupBox *cpuBox = new QGroupBox("Cpu Usage", this); - cpuBox->setFont(QFont("Helvetica", 10)); + QGroupBox *cpuBox = new QGroupBox( "Cpu Usage", this ); + cpuBox->setFont( QFont( "Helvetica", 10 ) ); - QHBoxLayout *cpuLayout = new QHBoxLayout(cpuBox); - cpuLayout->setMargin(15); - cpuLayout->setSpacing(5); + QHBoxLayout *cpuLayout = new QHBoxLayout( cpuBox ); + cpuLayout->setMargin( 15 ); + cpuLayout->setSpacing( 5 ); o = Qt::Vertical; - cpuLayout->addWidget(new ValueBar(o, "User", cpuBox, 57)); - cpuLayout->addWidget(new ValueBar(o, "Total", cpuBox, 73)); - cpuLayout->addWidget(new ValueBar(o, "System", cpuBox, 16)); - cpuLayout->addWidget(new ValueBar(o, "Idle", cpuBox, 27)); + cpuLayout->addWidget( new ValueBar( o, "User", cpuBox, 57 ) ); + cpuLayout->addWidget( new ValueBar( o, "Total", cpuBox, 73 ) ); + cpuLayout->addWidget( new ValueBar( o, "System", cpuBox, 16 ) ); + cpuLayout->addWidget( new ValueBar( o, "Idle", cpuBox, 27 ) ); - QHBoxLayout *layout = new QHBoxLayout(this); - layout->setMargin(10); - layout->addWidget(memBox, 10); - layout->addWidget(cpuBox, 0); + QHBoxLayout *layout = new QHBoxLayout( this ); + layout->setMargin( 10 ); + layout->addWidget( memBox, 10 ); + layout->addWidget( cpuBox, 0 ); } }; -int main (int argc, char **argv) +int main ( int argc, char **argv ) { - QApplication a(argc, argv); - + QApplication a( argc, argv ); + SysInfo info; - info.resize(info.sizeHint().expandedTo(QSize(600, 400))); -#if QT_VERSION < 0x040000 - a.setMainWidget(&info); -#endif + info.resize( info.sizeHint().expandedTo( QSize( 600, 400 ) ) ); info.show(); int rv = a.exec(); diff --git a/qwt/examples/sysinfo/sysinfo.pro b/qwt/examples/sysinfo/sysinfo.pro index f12d27354..c520f6de8 100644 --- a/qwt/examples/sysinfo/sysinfo.pro +++ b/qwt/examples/sysinfo/sysinfo.pro @@ -1,15 +1,15 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) TARGET = sysinfo SOURCES = \ - sysinfo.cpp + sysinfo.cpp diff --git a/qwt/examples/tvplot/main.cpp b/qwt/examples/tvplot/main.cpp new file mode 100644 index 000000000..0359bc11b --- /dev/null +++ b/qwt/examples/tvplot/main.cpp @@ -0,0 +1,14 @@ +#include +#include "tvplot.h" + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + TVPlot plot; + + plot.resize(600,400); + plot.show(); + + return a.exec(); +} diff --git a/qwt/examples/tvplot/tvplot.cpp b/qwt/examples/tvplot/tvplot.cpp new file mode 100644 index 000000000..7033072cf --- /dev/null +++ b/qwt/examples/tvplot/tvplot.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tvplot.h" + +class Histogram: public QwtPlotHistogram +{ +public: + Histogram(const QString &, const QColor &); + + void setColor(const QColor &); + void setValues(uint numValues, const double *); +}; + +Histogram::Histogram(const QString &title, const QColor &symbolColor): + QwtPlotHistogram(title) +{ + setStyle(QwtPlotHistogram::Columns); + + setColor(symbolColor); +} + +void Histogram::setColor(const QColor &symbolColor) +{ + QColor color = symbolColor; + color.setAlpha(180); + + setPen(QPen(Qt::black)); + setBrush(QBrush(color)); + + QwtColumnSymbol *symbol = new QwtColumnSymbol(QwtColumnSymbol::Box); + symbol->setFrameStyle(QwtColumnSymbol::Raised); + symbol->setLineWidth(2); + symbol->setPalette(QPalette(color)); + setSymbol(symbol); +} + +void Histogram::setValues(uint numValues, const double *values) +{ + QVector samples(numValues); + for ( uint i = 0; i < numValues; i++ ) + { + QwtInterval interval(double(i), i + 1.0); + interval.setBorderFlags(QwtInterval::ExcludeMaximum); + + samples[i] = QwtIntervalSample(values[i], interval); + } + + setData(new QwtIntervalSeriesData(samples)); +} + +TVPlot::TVPlot(QWidget *parent): + QwtPlot(parent) +{ + setTitle("Watching TV during a weekend"); + + setCanvasBackground(QColor(Qt::gray)); + plotLayout()->setAlignCanvasToScales(true); + + setAxisTitle(QwtPlot::yLeft, "Number of People"); + setAxisTitle(QwtPlot::xBottom, "Number of Hours"); + + QwtLegend *legend = new QwtLegend; + legend->setItemMode(QwtLegend::CheckableItem); + insertLegend(legend, QwtPlot::RightLegend); + + populate(); + + connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), + SLOT(showItem(QwtPlotItem *, bool))); + + replot(); // creating the legend items + + QwtPlotItemList items = itemList(QwtPlotItem::Rtti_PlotHistogram); + for ( int i = 0; i < items.size(); i++ ) + { + if ( i == 0 ) + { + QwtLegendItem *legendItem = (QwtLegendItem *)legend->find(items[i]); + if ( legendItem ) + legendItem->setChecked(true); + items[i]->setVisible(true); + } + else + items[i]->setVisible(false); + } + + setAutoReplot(true); +} + +void TVPlot::populate() +{ + QwtPlotGrid *grid = new QwtPlotGrid; + grid->enableX(false); + grid->enableY(true); + grid->enableXMin(false); + grid->enableYMin(false); + grid->setMajPen(QPen(Qt::black, 0, Qt::DotLine)); + grid->attach(this); + + const double juneValues[] = { 7, 19, 24, 32, 10, 5, 3 }; + const double novemberValues[] = { 4, 15, 22, 34, 13, 8, 4 }; + + Histogram *histogramJune = new Histogram("Summer", Qt::red); + histogramJune->setValues( + sizeof(juneValues) / sizeof(double), juneValues); + histogramJune->attach(this); + + Histogram *histogramNovember = new Histogram("Winter", Qt::blue); + histogramNovember->setValues( + sizeof(novemberValues) / sizeof(double), novemberValues); + histogramNovember->attach(this); +} + +void TVPlot::showItem(QwtPlotItem *item, bool on) +{ + item->setVisible(on); +} diff --git a/qwt/examples/tvplot/tvplot.h b/qwt/examples/tvplot/tvplot.h new file mode 100644 index 000000000..23128f271 --- /dev/null +++ b/qwt/examples/tvplot/tvplot.h @@ -0,0 +1,19 @@ +#ifndef _TV_PLOT_H_ + +#include + +class TVPlot: public QwtPlot +{ + Q_OBJECT + +public: + TVPlot(QWidget * = NULL); + +private: + void populate(); + +private Q_SLOTS: + void showItem(QwtPlotItem *, bool on); +}; + +#endif diff --git a/qwt/examples/histogram/histogram.pro b/qwt/examples/tvplot/tvplot.pro similarity index 62% rename from qwt/examples/histogram/histogram.pro rename to qwt/examples/tvplot/tvplot.pro index 55a4751c9..f91401551 100644 --- a/qwt/examples/histogram/histogram.pro +++ b/qwt/examples/tvplot/tvplot.pro @@ -1,19 +1,19 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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( ../examples.pri ) +include( $${PWD}/../examples.pri ) -TARGET = histogram +TARGET = tvplot SOURCES = \ - main.cpp \ - histogram_item.cpp + tvplot.cpp \ + main.cpp -INCLUDES = \ - histogram_item.h +HEADERS = \ + tvplot.h diff --git a/qwt/qwt.prf b/qwt/qwt.prf index f91e65d98..a4ebb2e35 100644 --- a/qwt/qwt.prf +++ b/qwt/qwt.prf @@ -1,34 +1,44 @@ -# -*- mode: sh -*- ################################################ +################################################################ # 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 -################################################################### +################################################################ -QwtBuild = dll -QwtVersion = 5.2.0 +include ( ./qwtconfig.pri ) -unix { - QwtBase = /usr/local/qwt-$${QwtVersion}-svn - LIBS += -L$${QwtBase}/lib -lqwt -} -win32 { - QwtBase = C:/Qwt-$${QwtVersion}-svn +contains(QWT_CONFIG, QwtDll) { - contains(QwtBuild, dll) { - DEFINES += QWT_DLL - - msvc:LIBS += $${QwtBase}/lib/qwt5.lib - msvc.net:LIBS += $${QwtBase}/lib/qwt5.lib - msvc2005:LIBS += $${QwtBase}/lib/qwt5.lib - } else { - win32-msvc:LIBS += $${QwtBase}/lib/qwt.lib - win32-msvc.net:LIBS += $${QwtBase}/lib/qwt.lib - win32-msvc2005:LIBS += $${QwtBase}/lib/qwt.lib - } - g++:LIBS += -L$${QwtBase}/lib -lqwt + DEFINES *= QWT_DLL } -INCLUDEPATH += $${QwtBase}/include +contains(QWT_CONFIG, QwtSvg) { + + QT *= svg +} +else { + + DEFINES *= QWT_NO_SVG +} + +contains(QWT_CONFIG, QwtFramework) { + + INCLUDEPATH *= $${QWT_INSTALL_LIBS}/qwt.framework/Headers + LIBS *= -F$${QWT_INSTALL_LIBS} +} +else { + + INCLUDEPATH *= $${QWT_INSTALL_HEADERS} + LIBS *= -L$${QWT_INSTALL_LIBS} +} + +INCLUDEPATH_QWT = $${INCLUDEPATH} +qtAddLibrary(qwt) + +# we don't want qtAddLibrary to expand the +# include path, with directories, that might +# conflict with other installations of qwt + +INCLUDEPATH = $${INCLUDEPATH_QWT} diff --git a/qwt/qwt.pro b/qwt/qwt.pro index 20543ab37..17e088652 100644 --- a/qwt/qwt.pro +++ b/qwt/qwt.pro @@ -1,24 +1,30 @@ -# -*- mode: sh -*- ########################### +################################################################ # 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( qwtconfig.pri ) TEMPLATE = subdirs +CONFIG += ordered SUBDIRS = \ src \ textengines -contains(CONFIG, QwtDesigner ) { - SUBDIRS += designer +contains(QWT_CONFIG, QwtDesigner ) { + SUBDIRS += designer } -contains(CONFIG, QwtExamples ) { - SUBDIRS += examples +contains(QWT_CONFIG, QwtExamples ) { + SUBDIRS += examples } + +qwtspec.files = qwtconfig.pri qwt.prf +qwtspec.path = $${QWT_INSTALL_FEATURES} + +INSTALLS += qwtspec diff --git a/qwt/qwt.pro.user b/qwt/qwt.pro.user new file mode 100644 index 000000000..61f39f6b9 --- /dev/null +++ b/qwt/qwt.pro.user @@ -0,0 +1,2047 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + System + false + 4 + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Qt4ProjectManager.Target.DesktopTarget + 0 + 0 + 0 + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Desktop Qt 4.7.4 for GCC (Qt SDK) Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 12 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Desktop Qt 4.7.4 for GCC (Qt SDK) Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 12 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Qt dans le PATH Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 2 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Qt dans le PATH Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 2 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + 4.7.0 Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 8 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + 4.7.0 Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 8 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + 4.6.1 Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 4 + false + + + ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit./usr/bin/gdb + + + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + Make + + Qt4ProjectManager.MakeStep + false + + + + 2 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + Make + + Qt4ProjectManager.MakeStep + true + clean + + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + 4.6.1 Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /Users/grauser/Documents/DEV/Qt/qwt-6.0.1 + 4 + false + + 8 + + + 0 + Déploiement + + ProjectExplorer.BuildSteps.Deploy + + 1 + Pas de déploiement + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + dials + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/dials/dials.pro + false + false + + + 3768 + true + false + false + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + plotmatrix + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/plotmatrix/plotmatrix.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + spectrogram + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/spectrogram/spectrogram.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + navigation + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/navigation/navigation.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + refreshtest + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/refreshtest/refreshtest.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + bode + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/bode/bode.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + curvdemo2 + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/curvdemo2/curvdemo2.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + oscilloscope + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/oscilloscope/oscilloscope.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + rasterview + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/rasterview/rasterview.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + svgmap + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/svgmap/svgmap.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + radio + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/radio/radio.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + sysinfo + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/sysinfo/sysinfo.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + cpuplot + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/cpuplot/cpuplot.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + curvdemo1 + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/curvdemo1/curvdemo1.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + sinusplot + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/sinusplot/sinusplot.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + sliders + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/sliders/sliders.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + event_filter + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/event_filter/event_filter.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + realtime + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/realtime/realtime.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + friedberg + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/friedberg/friedberg.pro + false + false + + + 3768 + true + false + true + + + true + true + + + false + false + false + false + false + false + false + false + true + true + 0.01 + 0.01 + 10 + 10 + true + true + 25 + 25 + + + true + true + valgrind + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + tvplot + + Qt4ProjectManager.Qt4RunConfiguration + 2 + + examples/tvplot/tvplot.pro + false + false + + + 3768 + true + false + true + + 20 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {aacf4a18-beff-41d4-a574-373b7bf4e503} + + + ProjectExplorer.Project.Updater.FileVersion + 10 + + diff --git a/qwt/qwtbuild.pri b/qwt/qwtbuild.pri new file mode 100644 index 000000000..8777b51a1 --- /dev/null +++ b/qwt/qwtbuild.pri @@ -0,0 +1,69 @@ +################################################################ +# 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 +################################################################ + +###################################################################### +# qmake internal options +###################################################################### + +CONFIG += qt +CONFIG += warn_on +CONFIG += no_keywords +CONFIG += silent + +###################################################################### +# release/debug mode +###################################################################### + +win32 { + # On Windows you can't mix release and debug libraries. + # The designer is built in release mode. If you like to use it + # you need a release version. For your own application development you + # might need a debug version. + # Enable debug_and_release + build_all if you want to build both. + + CONFIG += debug_and_release + CONFIG += build_all +} +else { + + CONFIG += release + + VER_MAJ = $${QWT_VER_MAJ} + VER_MIN = $${QWT_VER_MIN} + VER_PAT = $${QWT_VER_PAT} + VERSION = $${QWT_VERSION} +} + +linux-g++ { + # CONFIG += separate_debug_info +} + +###################################################################### +# paths for building qwt +###################################################################### + +MOC_DIR = moc +RCC_DIR = resources +!debug_and_release { + OBJECTS_DIR = obj +} + +unix { + + exists( $${QMAKE_LIBDIR_QT}/libqwt.* ) { + + # On some Linux distributions the Qwt libraries are installed + # in the same directory as the Qt libraries. Unfortunately + # qmake always adds QMAKE_LIBDIR_QT at the beginning of the + # linker path, so that the installed libraries will be + # used instead of the local ones. + + error( "local build will conflict with $${QMAKE_LIBDIR_QT}/libqwt.*" ) + } +} diff --git a/qwt/qwtconfig.pri.in b/qwt/qwtconfig.pri.in index 64245bb74..d584ebfe4 100644 --- a/qwt/qwtconfig.pri.in +++ b/qwt/qwtconfig.pri.in @@ -1,73 +1,56 @@ +################################################################ +# 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 +################################################################ + +QWT_VER_MAJ = 6 +QWT_VER_MIN = 0 +QWT_VER_PAT = 1 +QWT_VERSION = $${QWT_VER_MAJ}.$${QWT_VER_MIN}.$${QWT_VER_PAT} + ###################################################################### # Install paths ###################################################################### -VER_MAJ = 5 -VER_MIN = 2 -VER_PAT = 1 -VERSION = $${VER_MAJ}.$${VER_MIN}.$${VER_PAT} +QWT_INSTALL_PREFIX = $$[QT_INSTALL_PREFIX] unix { - INSTALLBASE = /usr/local/qwt-$$VERSION-svn + QWT_INSTALL_PREFIX = /usr/local/qwt-$$QWT_VERSION } win32 { - INSTALLBASE = C:/Qwt-$$VERSION-svn + QWT_INSTALL_PREFIX = C:/Qwt-$$QWT_VERSION } -target.path = $$INSTALLBASE/lib -headers.path = $$INSTALLBASE/include -doc.path = $$INSTALLBASE/doc +QWT_INSTALL_DOCS = $${QWT_INSTALL_PREFIX}/doc +QWT_INSTALL_HEADERS = $${QWT_INSTALL_PREFIX}/include +QWT_INSTALL_LIBS = $${QWT_INSTALL_PREFIX}/lib ###################################################################### -# qmake internal options +# Designer plugin ###################################################################### -CONFIG += qt # Also for Qtopia Core! -CONFIG += warn_on -CONFIG += thread +QWT_INSTALL_PLUGINS = $${QWT_INSTALL_PREFIX}/plugins/designer +# QWT_INSTALL_PLUGINS = $${QT_INSTALL_PREFIX}/plugins/designer ###################################################################### -# release/debug mode -# If you want to build both DEBUG_SUFFIX and RELEASE_SUFFIX -# have to differ to avoid, that they overwrite each other. +# Features +# When building a Qwt application with qmake you might want to load +# the compiler/linker flags, that are required to build a Qwt application +# from qwt.prf. Therefore all you need to do is to add "CONFIG += qwt" +# to your project file and take care, that qwt.prf can be found by qmake. +# ( see http://doc.trolltech.com/4.7/qmake-advanced-usage.html#adding-new-configuration-features ) +# I recommend not to install the Qwt features together with the +# Qt features, because you will have to reinstall the Qwt features, +# with every Qt upgrade. ###################################################################### -VVERSION = $$[QT_VERSION] -isEmpty(VVERSION) { - - # Qt 3 - CONFIG += debug # release/debug -} -else { - # Qt 4 - win32 { - # On Windows you can't mix release and debug libraries. - # The designer is built in release mode. If you like to use it - # you need a release version. For your own application development you - # might need a debug version. - # Enable debug_and_release + build_all if you want to build both. - - CONFIG += debug # release/debug/debug_and_release - #CONFIG += debug_and_release - #CONFIG += build_all - } - else { - CONFIG += debug # release/debug - } -} - -###################################################################### -# If you want to have different names for the debug and release -# versions you can add a suffix rule below. -###################################################################### - -DEBUG_SUFFIX = -RELEASE_SUFFIX = - -win32 { - DEBUG_SUFFIX = d -} +QWT_INSTALL_FEATURES = $${QWT_INSTALL_PREFIX}/features +# QWT_INSTALL_FEATURES = $${QT_INSTALL_PREFIX}/features ###################################################################### # Build the static/shared libraries. @@ -75,38 +58,39 @@ win32 { # it will be a static library. ###################################################################### -#CONFIG += QwtDll +#QWT_CONFIG += QwtDll ###################################################################### # QwtPlot enables all classes, that are needed to use the QwtPlot # widget. ###################################################################### -CONFIG += QwtPlot +QWT_CONFIG += QwtPlot ###################################################################### # QwtWidgets enables all classes, that are needed to use the all other # widgets (sliders, dials, ...), beside QwtPlot. ###################################################################### -CONFIG += QwtWidgets +QWT_CONFIG += QwtWidgets ###################################################################### -# If you want to display svg imageson the plot canvas, enable the -# line below. Note that Qwt needs the svg+xml, when enabling -# QwtSVGItem. +# If you want to display svg images on the plot canvas, or +# export a plot to a SVG document ###################################################################### -#CONFIG += QwtSVGItem +QWT_CONFIG += QwtSvg ###################################################################### -# If you have a commercial license you can use the MathML renderer -# of the Qt solutions package to enable MathML support in Qwt. -# So if you want this, copy qtmmlwidget.h + qtmmlwidget.cpp to -# textengines/mathml and enable the line below. +# You can use the MathML renderer of the Qt solutions package to +# enable MathML support in Qwt. Because of license implications +# the ( modified ) code of the MML Widget solution is included and +# linked together with the QwtMathMLTextEngine into an own library. +# To use it you will have to add "CONFIG += qwtmathml" +# to your qmake project file. ###################################################################### -#CONFIG += QwtMathML +QWT_CONFIG += QwtMathML ###################################################################### # If you want to build the Qwt designer plugin, @@ -114,11 +98,27 @@ CONFIG += QwtWidgets # Otherwise you have to build it from the designer directory. ###################################################################### -#CONFIG += QwtDesigner +# QWT_CONFIG += QwtDesigner ###################################################################### # If you want to auto build the examples, enable the line below # Otherwise you have to build them from the examples directory. ###################################################################### -#CONFIG += QwtExamples +# QWT_CONFIG += QwtExamples + +###################################################################### +# Add GoldenCheetah patched plot +###################################################################### + +QWT_CONFIG += GoldenCheetahPatch + +###################################################################### +# When Qt has been built as framework qmake ( qtAddLibrary ) wants +# to link frameworks instead of regular libs +###################################################################### + +macx:CONFIG(qt_framework, qt_framework|qt_no_framework) { + + QWT_CONFIG += QwtFramework +} diff --git a/qwt/src/.gitignore b/qwt/src/.gitignore deleted file mode 100644 index b981566f7..000000000 --- a/qwt/src/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -moc -obj diff --git a/qwt/src/qwt.h b/qwt/src/qwt.h index 7d7634d1c..37494933e 100644 --- a/qwt/src/qwt.h +++ b/qwt/src/qwt.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -15,7 +15,7 @@ /*! Some constants for use within Qwt. */ -namespace Qwt +namespace Qwt { }; diff --git a/qwt/src/qwt_abstract_scale.cpp b/qwt/src/qwt_abstract_scale.cpp index 316a8fb3a..e44776e6e 100644 --- a/qwt/src/qwt_abstract_scale.cpp +++ b/qwt/src/qwt_abstract_scale.cpp @@ -2,26 +2,26 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ +#include "qwt_abstract_scale.h" #include "qwt_scale_engine.h" #include "qwt_scale_draw.h" #include "qwt_scale_div.h" #include "qwt_scale_map.h" -#include "qwt_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) + maxMajor( 5 ), + maxMinor( 3 ), + stepSize( 0.0 ), + autoScale( true ) { scaleEngine = new QwtLinearScaleEngine; scaleDraw = new QwtScaleDraw(); @@ -46,14 +46,14 @@ public: /*! Constructor - Creates a default QwtScaleDraw and a QwtLinearScaleEngine. + Creates a default QwtScaleDraw and a QwtLinearScaleEngine. Autoscaling is enabled, and the stepSize is initialized by 0.0. */ - + QwtAbstractScale::QwtAbstractScale() { d_data = new PrivateData; - rescale(0.0, 100.0); + rescale( 0.0, 100.0 ); } //! Destructor @@ -72,12 +72,12 @@ QwtAbstractScale::~QwtAbstractScale() \param stepSize major step size \sa setAutoScale() */ -void QwtAbstractScale::setScale(double vmin, double vmax, double stepSize) +void QwtAbstractScale::setScale( double vmin, double vmax, double stepSize ) { d_data->autoScale = false; d_data->stepSize = stepSize; - rescale(vmin, vmax, stepSize); + rescale( vmin, vmax, stepSize ); } /*! @@ -89,10 +89,9 @@ void QwtAbstractScale::setScale(double vmin, double vmax, double stepSize) \param stepSize major step size \sa setAutoScale() */ -void QwtAbstractScale::setScale(const QwtDoubleInterval &interval, - double stepSize) +void QwtAbstractScale::setScale( const QwtInterval &interval, double stepSize ) { - setScale(interval.minValue(), interval.maxValue(), stepSize); + setScale( interval.minValue(), interval.maxValue(), stepSize ); } @@ -104,13 +103,13 @@ void QwtAbstractScale::setScale(const QwtDoubleInterval &interval, \param scaleDiv Scale division \sa setAutoScale() */ -void QwtAbstractScale::setScale(const QwtScaleDiv &scaleDiv) +void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv ) { d_data->autoScale = false; - if (scaleDiv != d_data->scaleDraw->scaleDiv()) + if ( scaleDiv != d_data->scaleDraw->scaleDiv() ) { - d_data->scaleDraw->setScaleDiv(scaleDiv); + d_data->scaleDraw->setScaleDiv( scaleDiv ); scaleChange(); } } @@ -124,16 +123,16 @@ void QwtAbstractScale::setScale(const QwtScaleDiv &scaleDiv) \sa scaleChange() */ -void QwtAbstractScale::rescale(double vmin, double vmax, double stepSize) +void QwtAbstractScale::rescale( double vmin, double vmax, double stepSize ) { const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale( - vmin, vmax, d_data->maxMajor, d_data->maxMinor, stepSize); + 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); + d_data->scaleEngine->transformation() ); + d_data->scaleDraw->setScaleDiv( scaleDiv ); scaleChange(); } } @@ -141,12 +140,12 @@ void QwtAbstractScale::rescale(double vmin, double vmax, double stepSize) /*! \brief Advise the widget to control the scale range internally. - Autoscaling is on by default. + Autoscaling is on by default. \sa setScale(), autoScale() */ void QwtAbstractScale::setAutoScale() { - if (!d_data->autoScale) + if ( !d_data->autoScale ) { d_data->autoScale = true; scaleChange(); @@ -155,7 +154,7 @@ void QwtAbstractScale::setAutoScale() /*! \return \c true if autoscaling is enabled -*/ +*/ bool QwtAbstractScale::autoScale() const { return d_data->autoScale; @@ -170,9 +169,9 @@ bool QwtAbstractScale::autoScale() const \param ticks maximal number of major ticks. \sa QwtAbstractScaleDraw */ -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(); @@ -188,29 +187,29 @@ void QwtAbstractScale::setScaleMaxMajor(int ticks) \param ticks \sa QwtAbstractScaleDraw */ -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 +/*! + \return Max. number of minor tick intervals The default value is 3. */ -int QwtAbstractScale::scaleMaxMinor() const +int QwtAbstractScale::scaleMaxMinor() const { return d_data->maxMinor; } -/*! - \return Max. number of major tick intervals +/*! + \return Max. number of major tick intervals The default value is 5. */ -int QwtAbstractScale::scaleMaxMajor() const +int QwtAbstractScale::scaleMaxMajor() const { return d_data->maxMajor; } @@ -221,23 +220,23 @@ int QwtAbstractScale::scaleMaxMajor() const scaleDraw has to be created with new and will be deleted in ~QwtAbstractScale or the next call of setAbstractScaleDraw. */ -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; -} +} /*! \return Scale draw \sa setAbstractScaleDraw() */ -QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() +QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() { return d_data->scaleDraw; } @@ -253,8 +252,8 @@ const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const void QwtAbstractScale::updateScaleDraw() { - rescale( d_data->scaleDraw->scaleDiv().lowerBound(), - d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize); + rescale( d_data->scaleDraw->scaleDiv().lowerBound(), + d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize ); } /*! @@ -266,7 +265,7 @@ void QwtAbstractScale::updateScaleDraw() scaleEngine has to be created with new and will be deleted in ~QwtAbstractScale or the next call of setScaleEngine. */ -void QwtAbstractScale::setScaleEngine(QwtScaleEngine *scaleEngine) +void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine ) { if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine ) { diff --git a/qwt/src/qwt_abstract_scale.h b/qwt/src/qwt_abstract_scale.h index cc1cc538f..670d2281c 100644 --- a/qwt/src/qwt_abstract_scale.h +++ b/qwt/src/qwt_abstract_scale.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -16,13 +16,13 @@ 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 classes containing a scale - QwtAbstractScale is used to provide classes with a QwtScaleDraw, - and a QwtScaleDiv. The QwtScaleDiv might be set explicitely + QwtAbstractScale is used to provide classes with a QwtScaleDraw, + and a QwtScaleDiv. The QwtScaleDiv might be set explicitely or calculated by a QwtScaleEngine. */ @@ -31,30 +31,30 @@ class QWT_EXPORT QwtAbstractScale public: QwtAbstractScale(); 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 vmin, double vmax, double step = 0.0 ); + void setScale( const QwtInterval &, double step = 0.0 ); + void setScale( const QwtScaleDiv & ); void setAutoScale(); bool autoScale() const; - void setScaleMaxMajor( int ticks); + void setScaleMaxMajor( int ticks ); int scaleMaxMinor() const; - void setScaleMaxMinor( int ticks); - int scaleMaxMajor() const; + void setScaleMaxMinor( int ticks ); + int scaleMaxMajor() const; - void setScaleEngine(QwtScaleEngine *); + void setScaleEngine( QwtScaleEngine * ); const QwtScaleEngine *scaleEngine() const; QwtScaleEngine *scaleEngine(); const QwtScaleMap &scaleMap() const; - -protected: - void rescale(double vmin, double vmax, double step = 0.0); - void setAbstractScaleDraw(QwtAbstractScaleDraw *); +protected: + void rescale( double vmin, double vmax, double step = 0.0 ); + + void setAbstractScaleDraw( QwtAbstractScaleDraw * ); const QwtAbstractScaleDraw *abstractScaleDraw() const; QwtAbstractScaleDraw *abstractScaleDraw(); diff --git a/qwt/src/qwt_abstract_scale_draw.cpp b/qwt/src/qwt_abstract_scale_draw.cpp index 2c38b2505..72f664c03 100644 --- a/qwt/src/qwt_abstract_scale_draw.cpp +++ b/qwt/src/qwt_abstract_scale_draw.cpp @@ -2,45 +2,48 @@ * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ -// vim: expandtab - -#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) + spacing( 4.0 ), + penWidth( 0 ), + minExtent( 0.0 ) { - tickLength[QwtScaleDiv::MinorTick] = 4; - tickLength[QwtScaleDiv::MediumTick] = 6; - tickLength[QwtScaleDiv::MajorTick] = 8; + 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; - - int spacing; - int tickLength[QwtScaleDiv::NTickTypes]; - int minExtent; + double spacing; + double tickLength[QwtScaleDiv::NTickTypes]; + int penWidth; + + double minExtent; QMap labelCache; }; @@ -57,25 +60,13 @@ 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 \param component Scale component @@ -84,7 +75,7 @@ QwtAbstractScaleDraw &QwtAbstractScaleDraw::operator=(const QwtAbstractScaleDraw \sa hasComponent() */ void QwtAbstractScaleDraw::enableComponent( - ScaleComponent component, bool enable) + ScaleComponent component, bool enable ) { if ( enable ) d_data->components |= component; @@ -92,23 +83,23 @@ void QwtAbstractScaleDraw::enableComponent( d_data->components &= ~component; } -/*! - Check if a component is enabled +/*! + Check if a 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 */ -void QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &sd) +void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &sd ) { d_data->scldiv = sd; - d_data->map.setScaleInterval(sd.lowerBound(), sd.upperBound()); + d_data->map.setScaleInterval( sd.lowerBound(), sd.upperBound() ); d_data->labelCache.clear(); } @@ -117,121 +108,129 @@ void QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &sd) \param transformation New scale transformation */ void QwtAbstractScaleDraw::setTransformation( - QwtScaleTransformation *transformation) + QwtScaleTransformation *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; } //! \return Map how to translate between scale and pixel values -QwtScaleMap &QwtAbstractScaleDraw::scaleMap() +QwtScaleMap &QwtAbstractScaleDraw::scaleMap() { return d_data->map; } -//! \return scale division -const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const -{ - return d_data->scldiv; +//! \return scale division +const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const +{ + return d_data->scldiv; } -#if QT_VERSION < 0x040000 /*! - \brief Draw the scale - - \param painter The painter - - \param colorGroup Color group, text color is used for the labels, - foreground color for ticks and backbone + \brief Specify the width of the scale pen + \param width Pen width + \sa penWidth() */ -void QwtAbstractScaleDraw::draw(QPainter *painter, - const QColorGroup& colorGroup) const +void QwtAbstractScaleDraw::setPenWidth( int width ) +{ + if ( width < 0 ) + width = 0; -#else + if ( width != d_data->penWidth ) + d_data->penWidth = width; +} + +/*! + \return Scale pen width + \sa setPenWidth() +*/ +int QwtAbstractScaleDraw::penWidth() const +{ + return d_data->penWidth; +} /*! \brief Draw the scale \param painter The painter - \param palette Palette, text color is used for the labels, + \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(); + + QPen pen = painter->pen(); + pen.setWidth( d_data->penWidth ); + pen.setCosmetic( false ); + painter->setPen( pen ); + + if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) { painter->save(); + painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style -#if QT_VERSION < 0x040000 - painter->setPen(colorGroup.text()); // ignore pen style -#else - painter->setPen(palette.color(QPalette::Text)); // ignore pen style -#endif + const QList &majorTicks = + d_data->scldiv.ticks( QwtScaleDiv::MajorTick ); - const QwtValueList &majorTicks = - d_data->scldiv.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->scldiv.contains( v ) ) + drawLabel( painter, majorTicks[i] ); } 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 ); - for ( int tickType = QwtScaleDiv::MinorTick; + 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++) + const QList &ticks = d_data->scldiv.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->scldiv.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 ); - drawBackbone(painter); + painter->setPen( pen ); + + drawBackbone( painter ); painter->restore(); } + + painter->restore(); } /*! @@ -244,7 +243,7 @@ void QwtAbstractScaleDraw::draw(QPainter *painter, \sa spacing() */ -void QwtAbstractScaleDraw::setSpacing(int spacing) +void QwtAbstractScaleDraw::setSpacing( double spacing ) { if ( spacing < 0 ) spacing = 0; @@ -260,7 +259,7 @@ void QwtAbstractScaleDraw::setSpacing(int spacing) \sa setSpacing() */ -int QwtAbstractScaleDraw::spacing() const +double QwtAbstractScaleDraw::spacing() const { return d_data->spacing; } @@ -278,10 +277,10 @@ 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; } @@ -290,34 +289,34 @@ void QwtAbstractScaleDraw::setMinimumExtent(int minExtent) Get the minimum extent \sa extent(), setMinimumExtent() */ -int QwtAbstractScaleDraw::minimumExtent() const +double QwtAbstractScaleDraw::minimumExtent() const { return d_data->minExtent; } /*! Set the length of the ticks - + \param tickType Tick type \param length New length \warning the length is limited to [0..1000] */ void QwtAbstractScaleDraw::setTickLength( - QwtScaleDiv::TickType tickType, int length) + QwtScaleDiv::TickType tickType, double length ) { - if ( tickType < QwtScaleDiv::MinorTick || + if ( tickType < QwtScaleDiv::MinorTick || 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; } @@ -325,11 +324,11 @@ void QwtAbstractScaleDraw::setTickLength( /*! Return the length of the ticks - \sa setTickLength(), majTickLength() + \sa setTickLength(), maxTickLength() */ -int QwtAbstractScaleDraw::tickLength(QwtScaleDiv::TickType tickType) const +double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const { - if ( tickType < QwtScaleDiv::MinorTick || + if ( tickType < QwtScaleDiv::MinorTick || tickType > QwtScaleDiv::MajorTick ) { return 0; @@ -339,17 +338,24 @@ 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 + \brief Convert a value into its representing label - The value is converted to a plain text using + The value is converted to a plain text using QLocale::system().toString(value). This method is often overloaded by applications to have individual labels. @@ -357,9 +363,9 @@ int QwtAbstractScaleDraw::majTickLength() const \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,7 +374,7 @@ QwtText QwtAbstractScaleDraw::label(double value) const The conversion between value and label is called very often in the layout and painting code. Unfortunately the calculation of the label sizes might be slow (really slow - for rich text in Qt4), so it's necessary to cache the labels. + for rich text in Qt4), so it's necessary to cache the labels. \param font Font \param value Value @@ -376,21 +382,21 @@ 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); + 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); + 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 ); } /*! @@ -398,7 +404,7 @@ const QwtText &QwtAbstractScaleDraw::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/qwt/src/qwt_abstract_scale_draw.h b/qwt/src/qwt_abstract_scale_draw.h index bc3381990..1dd64c03b 100644 --- a/qwt/src/qwt_abstract_scale_draw.h +++ b/qwt/src/qwt_abstract_scale_draw.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -14,12 +14,7 @@ #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; @@ -38,80 +33,77 @@ class QWT_EXPORT QwtAbstractScaleDraw { public: - /*! - Components of a scale - - - Backbone - - Ticks - - Labels - - \sa enableComponent(), hasComponent + /*! + Components of a scale + \sa enableComponent(), hasComponent */ - enum ScaleComponent - { - Backbone = 1, - Ticks = 2, - Labels = 4 + { + //! Backbone = the line where the ticks are located + Backbone = 0x01, + + //! Ticks + Ticks = 0x02, + + //! 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( QwtScaleTransformation * ); + 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; - -#if QT_VERSION < 0x040000 - virtual void draw(QPainter *, const QColorGroup &) const; -#else - virtual void draw(QPainter *, const QPalette &) const; -#endif + void setSpacing( double margin ); + double spacing() const; - virtual QwtText label(double) const; + void setPenWidth( int width ); + int penWidth() const; - /*! - Calculate the extent + virtual void draw( QPainter *, const QPalette & ) const; + + virtual QwtText label( double ) const; + + /*! + Calculate the extent The extent is the distcance from the baseline to the outermost pixel of the scale draw in opposite to its orientation. It is at least minimumExtent() pixels. - + \sa setMinimumExtent(), minimumExtent() */ - virtual int extent(const QPen &, const QFont &) const = 0; + virtual double extent( const QFont & ) const = 0; - void setMinimumExtent(int); - int minimumExtent() const; - - QwtScaleMap &scaleMap(); + void setMinimumExtent( double ); + double minimumExtent() const; protected: /*! Draw a tick - + \param painter Painter \param value Value of the tick \param len Lenght 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,27 +111,29 @@ 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 - + \param painter Painter \param value Value - \sa drawTick, drawBackbone - */ - virtual void drawLabel(QPainter *painter, double value) const = 0; + \sa drawTick(), drawBackbone() + */ + 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/qwt/src/qwt_abstract_slider.cpp b/qwt/src/qwt_abstract_slider.cpp index f5ed74a4a..a2599af1b 100644 --- a/qwt/src/qwt_abstract_slider.cpp +++ b/qwt/src/qwt_abstract_slider.cpp @@ -2,35 +2,36 @@ * 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 -#include #include "qwt_abstract_slider.h" #include "qwt_math.h" +#include +#include -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 +#if QT_VERSION < 0x040601 +#define qFabs(x) ::fabs(x) +#define qExp(x) ::exp(x) #endif class QwtAbstractSlider::PrivateData { public: PrivateData(): - scrollMode(ScrNone), - mouseOffset(0.0), - tracking(true), - tmrID(0), - updTime(150), - mass(0.0), - readOnly(false) + scrollMode( QwtAbstractSlider::ScrNone ), + mouseOffset( 0.0 ), + tracking( true ), + tmrID( 0 ), + updTime( 150 ), + mass( 0.0 ), + readOnly( false ) { } - int scrollMode; + QwtAbstractSlider::ScrollMode scrollMode; double mouseOffset; int direction; int tracking; @@ -45,30 +46,27 @@ public: bool readOnly; }; -/*! +/*! \brief Constructor \param orientation Orientation \param parent Parent widget */ QwtAbstractSlider::QwtAbstractSlider( - Qt::Orientation orientation, QWidget *parent): - QWidget(parent, NULL) + Qt::Orientation orientation, QWidget *parent ): + QWidget( parent, NULL ) { d_data = new QwtAbstractSlider::PrivateData; d_data->orientation = orientation; -#if QT_VERSION >= 0x040000 - using namespace Qt; -#endif - setFocusPolicy(TabFocus); + setFocusPolicy( Qt::TabFocus ); } //! Destructor QwtAbstractSlider::~QwtAbstractSlider() { - if(d_data->tmrID) - killTimer(d_data->tmrID); + if ( d_data->tmrID ) + killTimer( d_data->tmrID ); delete d_data; } @@ -82,7 +80,7 @@ QwtAbstractSlider::~QwtAbstractSlider() \param readOnly Enables in case of true \sa isReadOnly() */ -void QwtAbstractSlider::setReadOnly(bool readOnly) +void QwtAbstractSlider::setReadOnly( bool readOnly ) { d_data->readOnly = readOnly; update(); @@ -105,12 +103,12 @@ bool QwtAbstractSlider::isReadOnly() const \param o Orientation. Allowed values are Qt::Horizontal and Qt::Vertical. */ -void QwtAbstractSlider::setOrientation(Qt::Orientation o) +void QwtAbstractSlider::setOrientation( Qt::Orientation o ) { d_data->orientation = o; } -/*! +/*! \return Orientation \sa setOrientation() */ @@ -121,11 +119,11 @@ Qt::Orientation QwtAbstractSlider::orientation() const //! Stop updating if automatic scrolling is active -void QwtAbstractSlider::stopMoving() +void QwtAbstractSlider::stopMoving() { - if(d_data->tmrID) + if ( d_data->tmrID ) { - killTimer(d_data->tmrID); + killTimer( d_data->tmrID ); d_data->tmrID = 0; } } @@ -135,19 +133,19 @@ void QwtAbstractSlider::stopMoving() \param t update interval in milliseconds \sa getScrollMode() */ -void QwtAbstractSlider::setUpdateTime(int t) +void QwtAbstractSlider::setUpdateTime( int t ) { - if (t < 50) + if ( t < 50 ) t = 50; d_data->updTime = t; } -/*! +/*! Mouse press event handler \param e Mouse event */ -void QwtAbstractSlider::mousePressEvent(QMouseEvent *e) +void QwtAbstractSlider::mousePressEvent( QMouseEvent *e ) { if ( isReadOnly() ) { @@ -161,24 +159,24 @@ void QwtAbstractSlider::mousePressEvent(QMouseEvent *e) d_data->timerTick = 0; - getScrollMode(p, d_data->scrollMode, d_data->direction); + getScrollMode( p, d_data->scrollMode, d_data->direction ); stopMoving(); - - switch(d_data->scrollMode) + + switch ( d_data->scrollMode ) { case ScrPage: case ScrTimer: d_data->mouseOffset = 0; - d_data->tmrID = startTimer(qwtMax(250, 2 * d_data->updTime)); + d_data->tmrID = startTimer( qMax( 250, 2 * d_data->updTime ) ); break; - + case ScrMouse: d_data->time.start(); d_data->speed = 0; - d_data->mouseOffset = getValue(p) - value(); - emit sliderPressed(); + d_data->mouseOffset = getValue( p ) - value(); + Q_EMIT sliderPressed(); break; - + default: d_data->mouseOffset = 0; d_data->direction = 0; @@ -190,16 +188,16 @@ void QwtAbstractSlider::mousePressEvent(QMouseEvent *e) //! Emits a valueChanged() signal if necessary void QwtAbstractSlider::buttonReleased() { - if ((!d_data->tracking) || (value() != prevValue())) - emit valueChanged(value()); + if ( ( !d_data->tracking ) || ( value() != prevValue() ) ) + Q_EMIT valueChanged( value() ); } -/*! +/*! Mouse Release Event handler \param e Mouse event */ -void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e) +void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *e ) { if ( isReadOnly() ) { @@ -210,33 +208,33 @@ void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e) return; const double inc = step(); - - switch(d_data->scrollMode) + + switch ( d_data->scrollMode ) { case ScrMouse: { - setPosition(e->pos()); + setPosition( e->pos() ); d_data->direction = 0; d_data->mouseOffset = 0; - if (d_data->mass > 0.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); + if ( ( qFabs( d_data->speed ) > 0.0 ) && ( ms < 50 ) ) + d_data->tmrID = startTimer( d_data->updTime ); } else { d_data->scrollMode = ScrNone; buttonReleased(); } - emit sliderReleased(); - + Q_EMIT sliderReleased(); + break; } case ScrDirect: { - setPosition(e->pos()); + setPosition( e->pos() ); d_data->direction = 0; d_data->mouseOffset = 0; d_data->scrollMode = ScrNone; @@ -247,8 +245,8 @@ void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e) case ScrPage: { stopMoving(); - if (!d_data->timerTick) - QwtDoubleRange::incPages(d_data->direction); + if ( !d_data->timerTick ) + QwtDoubleRange::incPages( d_data->direction ); d_data->timerTick = 0; buttonReleased(); d_data->scrollMode = ScrNone; @@ -258,8 +256,8 @@ void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e) case ScrTimer: { stopMoving(); - if (!d_data->timerTick) - QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc); + if ( !d_data->timerTick ) + QwtDoubleRange::fitValue( value() + double( d_data->direction ) * inc ); d_data->timerTick = 0; buttonReleased(); d_data->scrollMode = ScrNone; @@ -279,9 +277,9 @@ void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e) Move the slider to a specified point, adjust the value and emit signals if necessary. */ -void QwtAbstractSlider::setPosition(const QPoint &p) +void QwtAbstractSlider::setPosition( const QPoint &p ) { - QwtDoubleRange::fitValue(getValue(p) - d_data->mouseOffset); + QwtDoubleRange::fitValue( getValue( p ) - d_data->mouseOffset ); } @@ -299,16 +297,16 @@ void QwtAbstractSlider::setPosition(const QPoint &p) Tracking is enabled by default. \param enable \c true (enable) or \c false (disable) tracking. */ -void QwtAbstractSlider::setTracking(bool enable) +void QwtAbstractSlider::setTracking( bool enable ) { d_data->tracking = enable; } -/*! +/*! Mouse Move Event handler \param e Mouse event */ -void QwtAbstractSlider::mouseMoveEvent(QMouseEvent *e) +void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *e ) { if ( isReadOnly() ) { @@ -319,27 +317,27 @@ void QwtAbstractSlider::mouseMoveEvent(QMouseEvent *e) if ( !isValid() ) return; - if (d_data->scrollMode == ScrMouse ) + if ( d_data->scrollMode == ScrMouse ) { - setPosition(e->pos()); - if (d_data->mass > 0.0) + setPosition( e->pos() ); + if ( d_data->mass > 0.0 ) { - double ms = double(d_data->time.elapsed()); - if (ms < 1.0) + double ms = double( d_data->time.elapsed() ); + if ( ms < 1.0 ) ms = 1.0; - d_data->speed = (exactValue() - exactPrevValue()) / ms; + d_data->speed = ( exactValue() - exactPrevValue() ) / ms; d_data->time.start(); } - if (value() != prevValue()) - emit sliderMoved(value()); + if ( value() != prevValue() ) + Q_EMIT sliderMoved( value() ); } } -/*! +/*! Wheel Event handler \param e Whell event */ -void QwtAbstractSlider::wheelEvent(QWheelEvent *e) +void QwtAbstractSlider::wheelEvent( QWheelEvent *e ) { if ( isReadOnly() ) { @@ -350,16 +348,20 @@ void QwtAbstractSlider::wheelEvent(QWheelEvent *e) if ( !isValid() ) return; - int mode = ScrNone, direction = 0; + QwtAbstractSlider::ScrollMode mode = ScrNone; + int direction = 0; // Give derived classes a chance to say ScrNone - getScrollMode(e->pos(), mode, direction); - if ( mode != ScrNone ) + getScrollMode( e->pos(), mode, direction ); + if ( mode != QwtAbstractSlider::ScrNone ) { - const int inc = e->delta() / WHEEL_DELTA; - QwtDoubleRange::incPages(inc); - if (value() != prevValue()) - emit sliderMoved(value()); + // Most mouse types work in steps of 15 degrees, in which case + // the delta value is a multiple of 120 + + const int inc = e->delta() / 120; + QwtDoubleRange::incPages( inc ); + if ( value() != prevValue() ) + Q_EMIT sliderMoved( value() ); } } @@ -374,7 +376,7 @@ void QwtAbstractSlider::wheelEvent(QWheelEvent *e) \param e Key event \sa isReadOnly() */ -void QwtAbstractSlider::keyPressEvent(QKeyEvent *e) +void QwtAbstractSlider::keyPressEvent( QKeyEvent *e ) { if ( isReadOnly() ) { @@ -386,7 +388,7 @@ void QwtAbstractSlider::keyPressEvent(QKeyEvent *e) return; int increment = 0; - switch ( e->key() ) + switch ( e->key() ) { case Qt::Key_Down: if ( orientation() == Qt::Vertical ) @@ -410,32 +412,32 @@ void QwtAbstractSlider::keyPressEvent(QKeyEvent *e) if ( increment != 0 ) { - QwtDoubleRange::incValue(increment); - if (value() != prevValue()) - emit sliderMoved(value()); + QwtDoubleRange::incValue( increment ); + if ( value() != prevValue() ) + Q_EMIT sliderMoved( value() ); } } -/*! +/*! Qt timer event \param e Timer event */ -void QwtAbstractSlider::timerEvent(QTimerEvent *) +void QwtAbstractSlider::timerEvent( QTimerEvent * ) { const double inc = step(); - switch (d_data->scrollMode) + switch ( d_data->scrollMode ) { case ScrMouse: { - if (d_data->mass > 0.0) + 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); + d_data->speed *= qExp( - 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())) + if ( qFabs( d_data->speed ) < 0.001 * qFabs( step() ) ) { d_data->speed = 0; stopMoving(); @@ -444,27 +446,27 @@ void QwtAbstractSlider::timerEvent(QTimerEvent *) } else - stopMoving(); + stopMoving(); break; } case ScrPage: { - QwtDoubleRange::incPages(d_data->direction); - if (!d_data->timerTick) + QwtDoubleRange::incPages( d_data->direction ); + if ( !d_data->timerTick ) { - killTimer(d_data->tmrID); - d_data->tmrID = startTimer(d_data->updTime); + killTimer( d_data->tmrID ); + d_data->tmrID = startTimer( d_data->updTime ); } break; } case ScrTimer: { - QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc); - if (!d_data->timerTick) + QwtDoubleRange::fitValue( value() + double( d_data->direction ) * inc ); + if ( !d_data->timerTick ) { - killTimer(d_data->tmrID); - d_data->tmrID = startTimer(d_data->updTime); + killTimer( d_data->tmrID ); + d_data->tmrID = startTimer( d_data->updTime ); } break; } @@ -487,10 +489,10 @@ void QwtAbstractSlider::timerEvent(QTimerEvent *) The default implementation emits a valueChanged() signal if tracking is enabled. */ -void QwtAbstractSlider::valueChange() +void QwtAbstractSlider::valueChange() { - if (d_data->tracking) - emit valueChanged(value()); + if ( d_data->tracking ) + Q_EMIT valueChanged( value() ); } /*! @@ -510,14 +512,14 @@ void QwtAbstractSlider::valueChange() The maximal mass is limited to 100kg. \sa mass() */ -void QwtAbstractSlider::setMass(double val) +void QwtAbstractSlider::setMass( double val ) { - if (val < 0.001) - d_data->mass = 0.0; - else if (val > 100.0) - d_data->mass = 100.0; + if ( val < 0.001 ) + d_data->mass = 0.0; + else if ( val > 100.0 ) + d_data->mass = 100.0; else - d_data->mass = val; + d_data->mass = val; } /*! @@ -525,8 +527,8 @@ void QwtAbstractSlider::setMass(double val) \sa setMass() */ double QwtAbstractSlider::mass() const -{ - return d_data->mass; +{ + return d_data->mass; } @@ -538,11 +540,11 @@ double QwtAbstractSlider::mass() const \param val new value \sa fitValue() */ -void QwtAbstractSlider::setValue(double val) +void QwtAbstractSlider::setValue( double val ) { - if (d_data->scrollMode == ScrMouse) + if ( d_data->scrollMode == ScrMouse ) stopMoving(); - QwtDoubleRange::setValue(val); + QwtDoubleRange::setValue( val ); } @@ -553,11 +555,11 @@ void QwtAbstractSlider::setValue(double val) \param value Value \sa setValue(), incValue() */ -void QwtAbstractSlider::fitValue(double value) +void QwtAbstractSlider::fitValue( double value ) { - if (d_data->scrollMode == ScrMouse) + if ( d_data->scrollMode == ScrMouse ) stopMoving(); - QwtDoubleRange::fitValue(value); + QwtDoubleRange::fitValue( value ); } /*! @@ -565,23 +567,30 @@ void QwtAbstractSlider::fitValue(double value) \param steps number of steps \sa setValue() */ -void QwtAbstractSlider::incValue(int steps) +void QwtAbstractSlider::incValue( int steps ) { - if (d_data->scrollMode == ScrMouse) + if ( d_data->scrollMode == ScrMouse ) stopMoving(); - QwtDoubleRange::incValue(steps); + QwtDoubleRange::incValue( steps ); } -void QwtAbstractSlider::setMouseOffset(double offset) +/*! + \sa mouseOffset() +*/ +void QwtAbstractSlider::setMouseOffset( double offset ) { d_data->mouseOffset = offset; -} +} +/*! + \sa setMouseOffset() +*/ double QwtAbstractSlider::mouseOffset() const { return d_data->mouseOffset; } +//! sa ScrollMode int QwtAbstractSlider::scrollMode() const { return d_data->scrollMode; diff --git a/qwt/src/qwt_abstract_slider.h b/qwt/src/qwt_abstract_slider.h index c0fe7d462..3d7599080 100644 --- a/qwt/src/qwt_abstract_slider.h +++ b/qwt/src/qwt_abstract_slider.h @@ -2,7 +2,7 @@ * 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 *****************************************************************************/ @@ -10,9 +10,9 @@ #ifndef QWT_ABSTRACT_SLIDER_H #define QWT_ABSTRACT_SLIDER_H -#include #include "qwt_global.h" #include "qwt_double_range.h" +#include /*! \brief An abstract base class for slider widgets @@ -20,105 +20,112 @@ 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 + only have to implement the getValue() and getScrollMode() members, and should react to a - valueChange(), which normally requires repainting. + valueChange(), which normally requires repainting. */ class QWT_EXPORT QwtAbstractSlider : public QWidget, public QwtDoubleRange { - Q_OBJECT + Q_OBJECT 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( Qt::Orientation orientation + READ orientation WRITE setOrientation ) public: - /*! + /*! Scroll mode \sa getScrollMode() */ - enum ScrollMode - { - ScrNone, - ScrMouse, - ScrTimer, - ScrDirect, - ScrPage + enum ScrollMode + { + //! Scrolling switched off. Don't change the value. + ScrNone, + + /*! + Change the value while the user keeps the + button pressed and moves the mouse. + */ + ScrMouse, + + /*! + Automatic scrolling. Increment the value in the specified direction + as long as the user keeps the button pressed. + */ + ScrTimer, + + ScrDirect, + + //! Automatic scrolling. Same as ScrTimer, but increment by page size. + ScrPage }; - - explicit QwtAbstractSlider(Qt::Orientation, QWidget *parent = NULL); + + explicit QwtAbstractSlider( Qt::Orientation, QWidget *parent = NULL ); virtual ~QwtAbstractSlider(); - void setUpdateTime(int t); + void setUpdateTime( int t ); void stopMoving(); - void setTracking(bool enable); - - virtual void setMass(double val); + void setTracking( bool enable ); + + virtual void setMass( double val ); virtual double mass() const; -#if QT_VERSION >= 0x040000 - virtual void setOrientation(Qt::Orientation o); + virtual void setOrientation( Qt::Orientation o ); Qt::Orientation orientation() const; -#else - virtual void setOrientation(Orientation o); - Orientation orientation() const; -#endif bool isReadOnly() const; - /* + /* Wrappers for QwtDblRange::isValid/QwtDblRange::setValid made to be available as Q_PROPERTY in the designer. */ - /*! + /*! \sa QwtDblRange::isValid() */ - bool isValid() const { return QwtDoubleRange::isValid(); } + bool isValid() const + { + return QwtDoubleRange::isValid(); + } - /*! + /*! \param valid true/false \sa QwtDblRange::isValid() */ - void setValid(bool valid) { QwtDoubleRange::setValid(valid); } + void setValid( bool valid ) + { + QwtDoubleRange::setValid( valid ); + } -public slots: - virtual void setValue(double val); - virtual void fitValue(double val); - virtual void incValue(int steps); +public Q_SLOTS: + virtual void setValue( double val ); + virtual void fitValue( double val ); + virtual void incValue( int steps ); - virtual void setReadOnly(bool); + virtual void setReadOnly( bool ); -signals: +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() ). + In the default setting + (tracking enabled), this signal will be emitted every + time the value changes ( see setTracking() ). \param value new value */ - void valueChanged(double value); + void valueChanged( double value ); /*! - This signal is emitted when the user presses the + This signal is emitted when the user presses the movable part of the slider (start ScrMouse Mode). */ void sliderPressed(); /*! - This signal is emitted when the user releases the + This signal is emitted when the user releases the movable part of the slider. */ @@ -128,57 +135,45 @@ signals: slider with the mouse. \param value new value */ - void sliderMoved(double value); - + void sliderMoved( double value ); + protected: - virtual void setPosition(const QPoint &); + 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 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 ); - /*! - \brief Determine the value corresponding to a specified poind + /*! + \brief Determine the value corresponding to a specified poind - 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 - */ - virtual double getValue(const QPoint & p) = 0; - /*! - \brief Determine what to do when the user presses a mouse button. + 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 + */ + virtual double getValue( const QPoint & p ) = 0; - 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: