diff --git a/CMakeLists.txt b/CMakeLists.txt index 7046a712b20c3d814b0223aeb0ec0e848b560e6f..672209ef203929d8eedeca304ce675265df7bcb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,13 +6,13 @@ list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") set_property (GLOBAL PROPERTY USE_FOLDERS ON) set (CMAKE_CXX_VISIBILITY_PRESET hidden) set (CMAKE_VISIBILITY_INLINES_HIDDEN 1) -set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -fopenmp -lgomp") +set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11") set (CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "--expt-extended-lambda" "-lcublas" - "-lcublas_device" "-lcudadevrt" - #"-gencode=arch=compute_50,code=sm_50") - "-gencode=arch=compute_60,code=sm_60") + "-gencode=arch=compute_52,code=sm_52" + "-gencode=arch=compute_60,code=sm_60" + "-gencode=arch=compute_61,code=sm_61") ################################################## Options ################################################## option(BUILD_TESTS "Build tests." OFF) @@ -38,10 +38,6 @@ set(PROJECT_SOURCES include/pli_vis/cuda/sh/wigner.h include/pli_vis/cuda/utility/convert.h include/pli_vis/cuda/utility/vector_ops.h - include/pli_vis/cuda/zernike/disk.h - include/pli_vis/cuda/zernike/launch.h - include/pli_vis/cuda/zernike/zernike.h - include/pli_vis/cuda/global_tractography.h include/pli_vis/cuda/odf_field.h include/pli_vis/cuda/polar_plot.h include/pli_vis/cuda/spherical_histogram.h @@ -58,104 +54,7 @@ set(PROJECT_SOURCES include/pli_vis/opengl/texture.hpp include/pli_vis/opengl/vertex_array.hpp include/pli_vis/third_party/glew/GL/glew.h - include/pli_vis/third_party/qwt/qwt.h - include/pli_vis/third_party/qwt/qwt_abstract_legend.h - include/pli_vis/third_party/qwt/qwt_abstract_scale.h - include/pli_vis/third_party/qwt/qwt_abstract_scale_draw.h - include/pli_vis/third_party/qwt/qwt_abstract_slider.h - include/pli_vis/third_party/qwt/qwt_analog_clock.h - include/pli_vis/third_party/qwt/qwt_arrow_button.h - include/pli_vis/third_party/qwt/qwt_clipper.h - include/pli_vis/third_party/qwt/qwt_color_map.h - include/pli_vis/third_party/qwt/qwt_column_symbol.h - include/pli_vis/third_party/qwt/qwt_compass.h - include/pli_vis/third_party/qwt/qwt_compass_rose.h - include/pli_vis/third_party/qwt/qwt_compat.h - include/pli_vis/third_party/qwt/qwt_counter.h - include/pli_vis/third_party/qwt/qwt_curve_fitter.h - include/pli_vis/third_party/qwt/qwt_date.h - include/pli_vis/third_party/qwt/qwt_date_scale_draw.h - include/pli_vis/third_party/qwt/qwt_date_scale_engine.h - include/pli_vis/third_party/qwt/qwt_dial.h - include/pli_vis/third_party/qwt/qwt_dial_needle.h - include/pli_vis/third_party/qwt/qwt_dyngrid_layout.h - include/pli_vis/third_party/qwt/qwt_event_pattern.h - include/pli_vis/third_party/qwt/qwt_global.h - include/pli_vis/third_party/qwt/qwt_graphic.h - include/pli_vis/third_party/qwt/qwt_interval.h - include/pli_vis/third_party/qwt/qwt_interval_symbol.h - include/pli_vis/third_party/qwt/qwt_knob.h - include/pli_vis/third_party/qwt/qwt_legend.h - include/pli_vis/third_party/qwt/qwt_legend_data.h - include/pli_vis/third_party/qwt/qwt_legend_label.h - include/pli_vis/third_party/qwt/qwt_magnifier.h - include/pli_vis/third_party/qwt/qwt_math.h - include/pli_vis/third_party/qwt/qwt_matrix_raster_data.h - include/pli_vis/third_party/qwt/qwt_null_paintdevice.h - include/pli_vis/third_party/qwt/qwt_painter.h - include/pli_vis/third_party/qwt/qwt_painter_command.h - include/pli_vis/third_party/qwt/qwt_panner.h - include/pli_vis/third_party/qwt/qwt_picker.h - include/pli_vis/third_party/qwt/qwt_picker_machine.h - include/pli_vis/third_party/qwt/qwt_pixel_matrix.h - include/pli_vis/third_party/qwt/qwt_plot.h - include/pli_vis/third_party/qwt/qwt_plot_abstract_barchart.h - include/pli_vis/third_party/qwt/qwt_plot_barchart.h - include/pli_vis/third_party/qwt/qwt_plot_canvas.h - include/pli_vis/third_party/qwt/qwt_plot_curve.h - include/pli_vis/third_party/qwt/qwt_plot_dict.h - include/pli_vis/third_party/qwt/qwt_plot_directpainter.h - include/pli_vis/third_party/qwt/qwt_plot_glcanvas.h - include/pli_vis/third_party/qwt/qwt_plot_grid.h - include/pli_vis/third_party/qwt/qwt_plot_histogram.h - include/pli_vis/third_party/qwt/qwt_plot_intervalcurve.h - include/pli_vis/third_party/qwt/qwt_plot_item.h - include/pli_vis/third_party/qwt/qwt_plot_layout.h - include/pli_vis/third_party/qwt/qwt_plot_legenditem.h - include/pli_vis/third_party/qwt/qwt_plot_magnifier.h - include/pli_vis/third_party/qwt/qwt_plot_marker.h - include/pli_vis/third_party/qwt/qwt_plot_multi_barchart.h - include/pli_vis/third_party/qwt/qwt_plot_panner.h - include/pli_vis/third_party/qwt/qwt_plot_picker.h - include/pli_vis/third_party/qwt/qwt_plot_rasteritem.h - include/pli_vis/third_party/qwt/qwt_plot_renderer.h - include/pli_vis/third_party/qwt/qwt_plot_rescaler.h - include/pli_vis/third_party/qwt/qwt_plot_scaleitem.h - include/pli_vis/third_party/qwt/qwt_plot_seriesitem.h - include/pli_vis/third_party/qwt/qwt_plot_shapeitem.h - include/pli_vis/third_party/qwt/qwt_plot_spectrocurve.h - include/pli_vis/third_party/qwt/qwt_plot_spectrogram.h - include/pli_vis/third_party/qwt/qwt_plot_svgitem.h - include/pli_vis/third_party/qwt/qwt_plot_textlabel.h - include/pli_vis/third_party/qwt/qwt_plot_tradingcurve.h - include/pli_vis/third_party/qwt/qwt_plot_zoneitem.h - include/pli_vis/third_party/qwt/qwt_plot_zoomer.h - include/pli_vis/third_party/qwt/qwt_point_3d.h - include/pli_vis/third_party/qwt/qwt_point_data.h - include/pli_vis/third_party/qwt/qwt_point_mapper.h - include/pli_vis/third_party/qwt/qwt_point_polar.h - include/pli_vis/third_party/qwt/qwt_raster_data.h - include/pli_vis/third_party/qwt/qwt_round_scale_draw.h - include/pli_vis/third_party/qwt/qwt_samples.h - include/pli_vis/third_party/qwt/qwt_sampling_thread.h - include/pli_vis/third_party/qwt/qwt_scale_div.h - include/pli_vis/third_party/qwt/qwt_scale_draw.h - include/pli_vis/third_party/qwt/qwt_scale_engine.h - include/pli_vis/third_party/qwt/qwt_scale_map.h - include/pli_vis/third_party/qwt/qwt_scale_widget.h - include/pli_vis/third_party/qwt/qwt_series_data.h - include/pli_vis/third_party/qwt/qwt_series_store.h - include/pli_vis/third_party/qwt/qwt_slider.h - include/pli_vis/third_party/qwt/qwt_spline.h - include/pli_vis/third_party/qwt/qwt_symbol.h - include/pli_vis/third_party/qwt/qwt_system_clock.h - include/pli_vis/third_party/qwt/qwt_text.h - include/pli_vis/third_party/qwt/qwt_text_engine.h - include/pli_vis/third_party/qwt/qwt_text_label.h - include/pli_vis/third_party/qwt/qwt_thermo.h - include/pli_vis/third_party/qwt/qwt_transform.h - include/pli_vis/third_party/qwt/qwt_wheel.h - include/pli_vis/third_party/qwt/qwt_widget_overlay.h + include/pli_vis/third_party/json/json.hpp include/pli_vis/third_party/qxt/QxtGlobal.h include/pli_vis/third_party/qxt/QxtLetterBoxWidget.h include/pli_vis/third_party/qxt/QxtLetterBoxWidgetP.h @@ -176,40 +75,35 @@ set(PROJECT_SOURCES include/pli_vis/third_party/tangent-base/simple_tracer.hpp include/pli_vis/third_party/tangent-base/trace_recorder.hpp include/pli_vis/third_party/tangent-base/tracer_base.hpp - include/pli_vis/ui/plugins/color_plugin.hpp + include/pli_vis/ui/plugins/color_plugin.hpp include/pli_vis/ui/plugins/data_plugin.hpp + include/pli_vis/ui/plugins/demo_plugin.hpp include/pli_vis/ui/plugins/fom_plugin.hpp - include/pli_vis/ui/plugins/global_tractography_plugin.hpp include/pli_vis/ui/plugins/interactor_plugin.hpp include/pli_vis/ui/plugins/odf_plugin.hpp include/pli_vis/ui/plugins/polar_plot_plugin.hpp include/pli_vis/ui/plugins/scalar_plugin.hpp include/pli_vis/ui/plugins/local_tractography_plugin.hpp - include/pli_vis/ui/plugins/volume_rendering_plugin.hpp - include/pli_vis/ui/plugins/zernike_plugin.hpp include/pli_vis/ui/utility/line_edit.hpp - include/pli_vis/ui/utility/plot_interactor.hpp include/pli_vis/ui/utility/text_browser_sink.hpp + include/pli_vis/ui/widgets/remote_viewer.hpp include/pli_vis/ui/widgets/roi_rectangle.hpp include/pli_vis/ui/widgets/roi_selector.hpp - include/pli_vis/ui/widgets/transfer_function_editor.hpp include/pli_vis/ui/widgets/viewer.hpp include/pli_vis/ui/widgets/wait_spinner.hpp include/pli_vis/ui/application.hpp include/pli_vis/ui/plugin.hpp include/pli_vis/ui/plugin_base.hpp - include/pli_vis/utility/make_even.hpp + include/pli_vis/utility/make_even.hpp + include/pli_vis/visualization/algorithms/color_mapper.hpp include/pli_vis/visualization/algorithms/lineao_streamline_renderer.hpp include/pli_vis/visualization/algorithms/odf_field.hpp include/pli_vis/visualization/algorithms/polar_plot_field.hpp include/pli_vis/visualization/algorithms/scalar_field.hpp include/pli_vis/visualization/algorithms/streamline_renderer.hpp include/pli_vis/visualization/algorithms/vector_field.hpp - include/pli_vis/visualization/algorithms/volume_renderer.hpp - include/pli_vis/visualization/algorithms/zernike_field.hpp include/pli_vis/visualization/interactors/first_person_interactor.hpp include/pli_vis/visualization/interactors/interactor.hpp - include/pli_vis/visualization/interactors/orbit_interactor.hpp include/pli_vis/visualization/interactors/simple_interactor.hpp include/pli_vis/visualization/primitives/camera.hpp include/pli_vis/visualization/primitives/directional_light.hpp @@ -222,6 +116,8 @@ set(PROJECT_SOURCES shaders/depth_pass.frag.glsl shaders/depth_pass.vert.glsl + shaders/fullscreen_texture.frag.glsl + shaders/fullscreen_texture.vert.glsl shaders/lineao_color_pass.frag.glsl shaders/lineao_color_pass.vert.glsl shaders/lineao_main_pass.frag.glsl @@ -247,130 +143,25 @@ set(PROJECT_SOURCES shaders/view_dependent_vector_field.frag.glsl shaders/view_dependent_vector_field.geom.glsl shaders/view_dependent_vector_field.vert.glsl - shaders/volume_renderer_prepass.frag.glsl - shaders/volume_renderer_prepass.vert.glsl - shaders/volume_renderer.frag.glsl - shaders/volume_renderer.vert.glsl - shaders/zernike.frag.glsl - shaders/zernike.vert.glsl source/cuda/pt/tracer.cu - source/cuda/zernike/launch.cu source/cuda/odf_field.cu source/cuda/polar_plot.cu source/third_party/glew/glew.c - source/third_party/qwt/qwt_abstract_legend.cpp - source/third_party/qwt/qwt_abstract_scale.cpp - source/third_party/qwt/qwt_abstract_scale_draw.cpp - source/third_party/qwt/qwt_abstract_slider.cpp - source/third_party/qwt/qwt_analog_clock.cpp - source/third_party/qwt/qwt_arrow_button.cpp - source/third_party/qwt/qwt_clipper.cpp - source/third_party/qwt/qwt_color_map.cpp - source/third_party/qwt/qwt_column_symbol.cpp - source/third_party/qwt/qwt_compass.cpp - source/third_party/qwt/qwt_compass_rose.cpp - source/third_party/qwt/qwt_counter.cpp - source/third_party/qwt/qwt_curve_fitter.cpp - source/third_party/qwt/qwt_date.cpp - source/third_party/qwt/qwt_date_scale_draw.cpp - source/third_party/qwt/qwt_date_scale_engine.cpp - source/third_party/qwt/qwt_dial.cpp - source/third_party/qwt/qwt_dial_needle.cpp - source/third_party/qwt/qwt_dyngrid_layout.cpp - source/third_party/qwt/qwt_event_pattern.cpp - source/third_party/qwt/qwt_graphic.cpp - source/third_party/qwt/qwt_interval.cpp - source/third_party/qwt/qwt_interval_symbol.cpp - source/third_party/qwt/qwt_knob.cpp - source/third_party/qwt/qwt_legend.cpp - source/third_party/qwt/qwt_legend_data.cpp - source/third_party/qwt/qwt_legend_label.cpp - source/third_party/qwt/qwt_magnifier.cpp - source/third_party/qwt/qwt_math.cpp - source/third_party/qwt/qwt_matrix_raster_data.cpp - source/third_party/qwt/qwt_null_paintdevice.cpp - source/third_party/qwt/qwt_painter.cpp - source/third_party/qwt/qwt_painter_command.cpp - source/third_party/qwt/qwt_panner.cpp - source/third_party/qwt/qwt_picker.cpp - source/third_party/qwt/qwt_picker_machine.cpp - source/third_party/qwt/qwt_pixel_matrix.cpp - source/third_party/qwt/qwt_plot.cpp - source/third_party/qwt/qwt_plot_abstract_barchart.cpp - source/third_party/qwt/qwt_plot_axis.cpp - source/third_party/qwt/qwt_plot_barchart.cpp - source/third_party/qwt/qwt_plot_canvas.cpp - source/third_party/qwt/qwt_plot_curve.cpp - source/third_party/qwt/qwt_plot_dict.cpp - source/third_party/qwt/qwt_plot_directpainter.cpp - source/third_party/qwt/qwt_plot_glcanvas.cpp - source/third_party/qwt/qwt_plot_grid.cpp - source/third_party/qwt/qwt_plot_histogram.cpp - source/third_party/qwt/qwt_plot_intervalcurve.cpp - source/third_party/qwt/qwt_plot_item.cpp - source/third_party/qwt/qwt_plot_layout.cpp - source/third_party/qwt/qwt_plot_legenditem.cpp - source/third_party/qwt/qwt_plot_magnifier.cpp - source/third_party/qwt/qwt_plot_marker.cpp - source/third_party/qwt/qwt_plot_multi_barchart.cpp - source/third_party/qwt/qwt_plot_panner.cpp - source/third_party/qwt/qwt_plot_picker.cpp - source/third_party/qwt/qwt_plot_rasteritem.cpp - source/third_party/qwt/qwt_plot_renderer.cpp - source/third_party/qwt/qwt_plot_rescaler.cpp - source/third_party/qwt/qwt_plot_scaleitem.cpp - source/third_party/qwt/qwt_plot_seriesitem.cpp - source/third_party/qwt/qwt_plot_shapeitem.cpp - source/third_party/qwt/qwt_plot_spectrocurve.cpp - source/third_party/qwt/qwt_plot_spectrogram.cpp - source/third_party/qwt/qwt_plot_svgitem.cpp - source/third_party/qwt/qwt_plot_textlabel.cpp - source/third_party/qwt/qwt_plot_tradingcurve.cpp - source/third_party/qwt/qwt_plot_xml.cpp - source/third_party/qwt/qwt_plot_zoneitem.cpp - source/third_party/qwt/qwt_plot_zoomer.cpp - source/third_party/qwt/qwt_point_3d.cpp - source/third_party/qwt/qwt_point_data.cpp - source/third_party/qwt/qwt_point_mapper.cpp - source/third_party/qwt/qwt_point_polar.cpp - source/third_party/qwt/qwt_raster_data.cpp - source/third_party/qwt/qwt_round_scale_draw.cpp - source/third_party/qwt/qwt_sampling_thread.cpp - source/third_party/qwt/qwt_scale_div.cpp - source/third_party/qwt/qwt_scale_draw.cpp - source/third_party/qwt/qwt_scale_engine.cpp - source/third_party/qwt/qwt_scale_map.cpp - source/third_party/qwt/qwt_scale_widget.cpp - source/third_party/qwt/qwt_series_data.cpp - source/third_party/qwt/qwt_slider.cpp - source/third_party/qwt/qwt_spline.cpp - source/third_party/qwt/qwt_symbol.cpp - source/third_party/qwt/qwt_system_clock.cpp - source/third_party/qwt/qwt_text.cpp - source/third_party/qwt/qwt_text_engine.cpp - source/third_party/qwt/qwt_text_label.cpp - source/third_party/qwt/qwt_thermo.cpp - source/third_party/qwt/qwt_transform.cpp - source/third_party/qwt/qwt_wheel.cpp - source/third_party/qwt/qwt_widget_overlay.cpp source/third_party/qxt/QxtLetterBoxWidget.cpp source/third_party/qxt/QxtSpanSlider.cpp - source/ui/plugins/color_plugin.cpp + source/ui/plugins/color_plugin.cpp source/ui/plugins/data_plugin.cpp + source/ui/plugins/demo_plugin.cpp source/ui/plugins/fom_plugin.cpp - source/ui/plugins/global_tractography_plugin.cpp source/ui/plugins/interactor_plugin.cpp source/ui/plugins/odf_plugin.cpp source/ui/plugins/polar_plot_plugin.cpp source/ui/plugins/scalar_plugin.cpp source/ui/plugins/local_tractography_plugin.cpp - source/ui/plugins/volume_rendering_plugin.cpp - source/ui/plugins/zernike_plugin.cpp - source/ui/utility/plot_interactor.cpp + source/ui/widgets/remote_viewer.cpp source/ui/widgets/roi_rectangle.cpp source/ui/widgets/roi_selector.cpp - source/ui/widgets/transfer_function_editor.cpp source/ui/widgets/viewer.cpp source/ui/widgets/wait_spinner.cpp source/ui/application.cpp @@ -380,10 +171,7 @@ set(PROJECT_SOURCES source/visualization/algorithms/scalar_field.cpp source/visualization/algorithms/streamline_renderer.cpp source/visualization/algorithms/vector_field.cpp - source/visualization/algorithms/volume_renderer.cpp - source/visualization/algorithms/zernike_field.cpp source/visualization/interactors/first_person_interactor.cpp - source/visualization/interactors/orbit_interactor.cpp source/visualization/interactors/simple_interactor.cpp source/visualization/primitives/camera.cpp source/visualization/primitives/directional_light.cpp @@ -403,8 +191,9 @@ include(import_library) find_package (Boost REQUIRED) import_library(boost Boost_INCLUDE_DIR) -set (CUDA_SEPARABLE_COMPILATION ON) find_package (CUDA REQUIRED) +set (CUDA_SEPARABLE_COMPILATION ON) +set (CUDA_USE_STATIC_CUDA_RUNTIME OFF) list (APPEND PROJECT_LIBRARIES ${CUDA_CUBLAS_LIBRARIES} ${CUDA_cusolver_LIBRARY} @@ -420,18 +209,42 @@ else() import_library(hdf5 HDF5_INCLUDE_DIR HDF5_C_SHARED_LIBRARY) endif() -find_package (OpenMP) -list (APPEND CMAKE_CXX_FLAGS ${OpenMP_CXX_FLAGS}) - find_package (OpenGL REQUIRED) import_library(opengl OPENGL_INCLUDE_DIRS OPENGL_LIBRARIES) +find_package (Protobuf REQUIRED) +list (APPEND PROJECT_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS}) +list (APPEND PROJECT_LIBRARIES ${PROTOBUF_LIBRARIES} ) + +find_package (TBB REQUIRED) +import_library(tbb TBB_INCLUDE_DIRS TBB_LIBRARY_DEBUG TBB_LIBRARY_RELEASE) +import_library(tbb_malloc TBB_MALLOC_INCLUDE_DIRS TBB_MALLOC_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_RELEASE) +import_library(tbb_malloc_proxy TBB_MALLOC_PROXY_INCLUDE_DIRS TBB_MALLOC_PROXY_LIBRARY_DEBUG TBB_MALLOC_PROXY_LIBRARY_RELEASE) + +find_package (ZeroMQ REQUIRED) +list (APPEND PROJECT_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR}) +list (APPEND PROJECT_LIBRARIES ${ZeroMQ_LIBRARIES} ) + set (CMAKE_AUTOMOC ON) set (CMAKE_AUTOUIC ON) set (CMAKE_INCLUDE_CURRENT_DIR ON) find_package (Qt5Widgets REQUIRED) list (APPEND PROJECT_LIBRARIES Qt5::Widgets) +################################################## Prebuild ################################################## +set(PROJECT_PROTO_SOURCES + proto/camera.proto + proto/color_mapping.proto + proto/dataset_format.proto + proto/image.proto + proto/parameters.proto + proto/selection.proto + proto/vector_types.proto +) +protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROJECT_PROTO_SOURCES}) +list (APPEND PROJECT_SOURCES ${PROJECT_PROTO_SOURCES} ${PROTO_HDRS} ${PROTO_SRCS}) +assign_source_group (${PROJECT_SOURCES}) + ################################################## Targets ################################################## cuda_add_executable(${PROJECT_NAME} ${PROJECT_SOURCES}) target_include_directories(${PROJECT_NAME} PUBLIC @@ -441,8 +254,9 @@ target_include_directories(${PROJECT_NAME} PUBLIC $<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include/${PROJECT_NAME}/third_party> PRIVATE source) +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDE_DIRS}) target_link_libraries (${PROJECT_NAME} PUBLIC ${PROJECT_LIBRARIES}) -target_compile_definitions(${PROJECT_NAME} PUBLIC -DQWT_NO_SVG -DQT_NO_SVG -DQT_NO_PRINTER -DQT_NO_PRINTDIALOG) +target_compile_definitions(${PROJECT_NAME} PUBLIC -DH5_BUILT_AS_DYNAMIC_LIB -DQWT_NO_SVG -DQT_NO_SVG -DQT_NO_PRINTER -DQT_NO_PRINTDIALOG) set_target_properties (${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) ################################################## Testing ################################################## diff --git a/cmake/FindOSPRay.cmake b/cmake/FindOSPRay.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a68444ccc518ac10ae315bdacef2bbf3c3207717 --- /dev/null +++ b/cmake/FindOSPRay.cmake @@ -0,0 +1,79 @@ +## ======================================================================================= ## +## Copyright 2014-2015 Texas Advanced Computing Center, The University of Texas at Austin ## +## All rights reserved. ## +## ## +## Licensed under the BSD 3-Clause License, (the "License"); you may not use this file ## +## except in compliance with the License. ## +## A copy of the License is included with this software in the file LICENSE. ## +## If your copy does not contain the License, you may obtain a copy of the License at: ## +## ## +## http://opensource.org/licenses/BSD-3-Clause ## +## ## +## Unless required by applicable law or agreed to in writing, software distributed under ## +## the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## +## KIND, either express or implied. ## +## See the License for the specific language governing permissions and limitations under ## +## limitations under the License. ## +## ======================================================================================= ## + + +############################################################################### +# Find OSPRay +# defines: +# OSPRAY_FOUND +# OSPRAY_INCLUDE_DIRS +# OSPRAY_LIBRARIES + +set(OSPRAY_INSTALL_DIR "" CACHE PATH "install location of ospray") +mark_as_advanced(OSPRAY_INSTALL_DIR) +set(OSPRAY_BUILD_DIR "" CACHE PATH "build location of ospray") +mark_as_advanced(OSPRAY_BUILD_DIR) +if (OSPRAY_INSTALL_DIR AND OSPRAY_BUILD_DIR) + message("Ignoring the ospray build location in favor of the install location.") +endif() + +if (OSPRAY_INSTALL_DIR) + + find_package(ospray CONFIG REQUIRED HINTS ${OSPRAY_INSTALL_DIR}) + +else() + + if (OSPRAY_BUILD_DIR) + #find corresponding source directory + load_cache(${OSPRAY_BUILD_DIR} READ_WITH_PREFIX OSP_ + CMAKE_HOME_DIRECTORY + embree_DIR + ) + set(OSPRAY_SOURCE_DIR ${OSP_CMAKE_HOME_DIRECTORY}) + + set(OSPRAY_INCLUDE_DIRS + ${OSPRAY_BUILD_DIR} + ${OSPRAY_BUILD_DIR}/include + ${OSPRAY_SOURCE_DIR} + ${OSPRAY_SOURCE_DIR}/ospray/include + ${OSPRAY_SOURCE_DIR}/components + ) + + set(LIB_OSPRAY_EMBREE LIB_OSPRAY_EMBREE-NOTFOUND) + find_library(LIB_OSPRAY_EMBREE NAMES ospray_embree embree + PATHS ${OSPRAY_BUILD_DIR} ${OSP_embree_DIR} NO_DEFAULT_PATH) + mark_as_advanced(LIB_OSPRAY_EMBREE) + + set(LIB_OSPRAY_COMMON LIB_OSPRAY_COMMON-NOTFOUND) + find_library(LIB_OSPRAY_COMMON ospray_common + PATHS ${OSPRAY_BUILD_DIR} NO_DEFAULT_PATH) + mark_as_advanced(LIB_OSPRAY_COMMON) + + set(LIB_OSPRAY LIB_OSPRAY-NOTFOUND) + find_library(LIB_OSPRAY ospray PATHS ${OSPRAY_BUILD_DIR} NO_DEFAULT_PATH) + mark_as_advanced(LIB_OSPRAY) + + set(OSPRAY_LIBRARIES ${LIB_OSPRAY_EMBREE} ${LIB_OSPRAY_COMMON} ${LIB_OSPRAY}) + + else() + + message("Supply OSPRAY_INSTALL_DIR or OSPRAY_BUILD_DIR to find OSPRay") + + endif() + +endif() \ No newline at end of file diff --git a/cmake/FindTBB.cmake b/cmake/FindTBB.cmake new file mode 100644 index 0000000000000000000000000000000000000000..4469116f9cb692ff2a114524dbdd9ec7b0f22221 --- /dev/null +++ b/cmake/FindTBB.cmake @@ -0,0 +1,359 @@ +# - Find ThreadingBuildingBlocks include dirs and libraries +# Use this module by invoking find_package with the form: +# find_package(TBB +# [REQUIRED] # Fail with error if TBB is not found +# ) # +# Once done, this will define +# +# TBB_FOUND - system has TBB +# TBB_INCLUDE_DIRS - the TBB include directories +# TBB_LIBRARIES - TBB libraries to be lined, doesn't include malloc or +# malloc proxy +# +# TBB_VERSION_MAJOR - Major Product Version Number +# TBB_VERSION_MINOR - Minor Product Version Number +# TBB_INTERFACE_VERSION - Engineering Focused Version Number +# TBB_COMPATIBLE_INTERFACE_VERSION - The oldest major interface version +# still supported. This uses the engineering +# focused interface version numbers. +# +# TBB_MALLOC_FOUND - system has TBB malloc library +# TBB_MALLOC_INCLUDE_DIRS - the TBB malloc include directories +# TBB_MALLOC_LIBRARIES - The TBB malloc libraries to be lined +# +# TBB_MALLOC_PROXY_FOUND - system has TBB malloc proxy library +# TBB_MALLOC_PROXY_INCLUDE_DIRS = the TBB malloc proxy include directories +# TBB_MALLOC_PROXY_LIBRARIES - The TBB malloc proxy libraries to be lined +# +# +# This module reads hints about search locations from variables: +# ENV TBB_ARCH_PLATFORM - for eg. set it to "mic" for Xeon Phi builds +# ENV TBB_ROOT or just TBB_ROOT - root directory of tbb installation +# ENV TBB_BUILD_PREFIX - specifies the build prefix for user built tbb +# libraries. Should be specified with ENV TBB_ROOT +# and optionally... +# ENV TBB_BUILD_DIR - if build directory is different than ${TBB_ROOT}/build +# +# +# Modified by Robert Maynard from the original OGRE source +# +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- +# +#============================================================================= +# Copyright 2010-2012 Kitware, Inc. +# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +#============================================================================= +# FindTBB helper functions and macros +# + +#=============================================== +# Do the final processing for the package find. +#=============================================== +macro(findpkg_finish PREFIX) + # skip if already processed during this run + if (NOT ${PREFIX}_FOUND) + if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) + set(${PREFIX}_FOUND TRUE) + set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) + set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) + else () + if (${PREFIX}_FIND_REQUIRED AND NOT ${PREFIX}_FIND_QUIETLY) + message(FATAL_ERROR "Required library ${PREFIX} not found.") + endif () + endif () + + #mark the following variables as internal variables + mark_as_advanced(${PREFIX}_INCLUDE_DIR + ${PREFIX}_LIBRARY + ${PREFIX}_LIBRARY_DEBUG + ${PREFIX}_LIBRARY_RELEASE) + endif () +endmacro() + +#=============================================== +# Generate debug names from given release names +#=============================================== +macro(get_debug_names PREFIX) + foreach(i ${${PREFIX}}) + set(${PREFIX}_DEBUG ${${PREFIX}_DEBUG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) + endforeach() +endmacro() + +#=============================================== +# See if we have env vars to help us find tbb +#=============================================== +macro(getenv_path VAR) + set(ENV_${VAR} $ENV{${VAR}}) + # replace won't work if var is blank + if (ENV_${VAR}) + string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) + endif () +endmacro() + +#=============================================== +# Couple a set of release AND debug libraries +#=============================================== +macro(make_library_set PREFIX) + if (${PREFIX}_RELEASE AND ${PREFIX}_DEBUG) + set(${PREFIX} optimized ${${PREFIX}_RELEASE} debug ${${PREFIX}_DEBUG}) + elseif (${PREFIX}_RELEASE) + set(${PREFIX} ${${PREFIX}_RELEASE}) + elseif (${PREFIX}_DEBUG) + set(${PREFIX} ${${PREFIX}_DEBUG}) + endif () +endmacro() + + +#============================================================================= +# Now to actually find TBB +# + +# Get path, convert backslashes as ${ENV_${var}} +getenv_path(TBB_ROOT) + +# initialize search paths +set(TBB_PREFIX_PATH ${TBB_ROOT} ${ENV_TBB_ROOT}) +set(TBB_INC_SEARCH_PATH "") +set(TBB_LIB_SEARCH_PATH "") + + +# If user built from sources +set(TBB_BUILD_PREFIX $ENV{TBB_BUILD_PREFIX}) +if (TBB_BUILD_PREFIX AND ENV_TBB_ROOT) + getenv_path(TBB_BUILD_DIR) + if (NOT ENV_TBB_BUILD_DIR) + set(ENV_TBB_BUILD_DIR ${ENV_TBB_ROOT}/build) + endif () + + # include directory under ${ENV_TBB_ROOT}/include + list(APPEND TBB_LIB_SEARCH_PATH + ${ENV_TBB_BUILD_DIR}/${TBB_BUILD_PREFIX}_release + ${ENV_TBB_BUILD_DIR}/${TBB_BUILD_PREFIX}_debug) +endif () + + +# For Windows, let's assume that the user might be using the precompiled +# TBB packages from the main website. These use a rather awkward directory +# structure (at least for automatically finding the right files) depending +# on platform and compiler, but we'll do our best to accommodate it. +# Not adding the same effort for the precompiled linux builds, though. Those +# have different versions for CC compiler versions and linux kernels which +# will never adequately match the user's setup, so there is no feasible way +# to detect the "best" version to use. The user will have to manually +# select the right files. (Chances are the distributions are shipping their +# custom version of tbb, anyway, so the problem is probably nonexistent.) +if (WIN32 AND MSVC) + set(COMPILER_PREFIX "vc7.1") + if (MSVC_VERSION EQUAL 1400) + set(COMPILER_PREFIX "vc8") + elseif(MSVC_VERSION EQUAL 1500) + set(COMPILER_PREFIX "vc9") + elseif(MSVC_VERSION EQUAL 1600) + set(COMPILER_PREFIX "vc10") + elseif(MSVC_VERSION EQUAL 1700) + set(COMPILER_PREFIX "vc11") + elseif(MSVC_VERSION EQUAL 1800) + set(COMPILER_PREFIX "vc12") + elseif(MSVC_VERSION EQUAL 1900) + set(COMPILER_PREFIX "vc14") + endif () + + # for each prefix path, add ia32/64\${COMPILER_PREFIX}\lib to the lib search path + foreach (dir IN LISTS TBB_PREFIX_PATH) + if (CMAKE_CL_64) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia64/${COMPILER_PREFIX}/lib) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia64/${COMPILER_PREFIX}) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/intel64/${COMPILER_PREFIX}/lib) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/intel64/${COMPILER_PREFIX}) + else () + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia32/${COMPILER_PREFIX}/lib) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia32/${COMPILER_PREFIX}) + endif () + endforeach () +endif () + +# For OS X binary distribution, choose libc++ based libraries for Mavericks (10.9) +# and above and AppleClang +if (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND + NOT CMAKE_SYSTEM_VERSION VERSION_LESS 13.0) + set (USE_LIBCXX OFF) + cmake_policy(GET CMP0025 POLICY_VAR) + + if (POLICY_VAR STREQUAL "NEW") + if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set (USE_LIBCXX ON) + endif () + else () + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set (USE_LIBCXX ON) + endif () + endif () + + if (USE_LIBCXX) + foreach (dir IN LISTS TBB_PREFIX_PATH) + list (APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/libc++ ${dir}/libc++/lib) + endforeach () + endif () +endif () + +# check compiler ABI +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(COMPILER_PREFIX) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) + list(APPEND COMPILER_PREFIX "gcc4.7") + endif() + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) + list(APPEND COMPILER_PREFIX "gcc4.4") + endif() + list(APPEND COMPILER_PREFIX "gcc4.1") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(COMPILER_PREFIX) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6) + list(APPEND COMPILER_PREFIX "gcc4.7") + endif() + list(APPEND COMPILER_PREFIX "gcc4.4") +else() # Assume compatibility with 4.4 for other compilers + list(APPEND COMPILER_PREFIX "gcc4.4") +endif () + +# if platform architecture is explicitly specified +set(TBB_ARCH_PLATFORM $ENV{TBB_ARCH_PLATFORM}) +if (TBB_ARCH_PLATFORM) + foreach (dir IN LISTS TBB_PREFIX_PATH) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/${TBB_ARCH_PLATFORM}/lib) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/${TBB_ARCH_PLATFORM}) + endforeach () +endif () + +foreach (dir IN LISTS TBB_PREFIX_PATH) + foreach (prefix IN LISTS COMPILER_PREFIX) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/intel64) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/intel64/${prefix}) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/intel64/lib) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/intel64/${prefix}/lib) + else () + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia32) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia32/${prefix}) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia32/lib) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia32/${prefix}/lib) + endif () + endforeach() +endforeach () + +# add general search paths +foreach (dir IN LISTS TBB_PREFIX_PATH) + list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib ${dir}/Lib ${dir}/lib/tbb + ${dir}/Libs) + list(APPEND TBB_INC_SEARCH_PATH ${dir}/include ${dir}/Include + ${dir}/include/tbb) +endforeach () + +set(TBB_LIBRARY_NAMES tbb) +get_debug_names(TBB_LIBRARY_NAMES) + + +find_path(TBB_INCLUDE_DIR + NAMES tbb/tbb.h + PATHS ${TBB_INC_SEARCH_PATH}) + +find_library(TBB_LIBRARY_RELEASE + NAMES ${TBB_LIBRARY_NAMES} + PATHS ${TBB_LIB_SEARCH_PATH}) +find_library(TBB_LIBRARY_DEBUG + NAMES ${TBB_LIBRARY_NAMES_DEBUG} + PATHS ${TBB_LIB_SEARCH_PATH}) +make_library_set(TBB_LIBRARY) + +findpkg_finish(TBB) + +#if we haven't found TBB no point on going any further +if (NOT TBB_FOUND) + return() +endif () + +#============================================================================= +# Look for TBB's malloc package +set(TBB_MALLOC_LIBRARY_NAMES tbbmalloc) +get_debug_names(TBB_MALLOC_LIBRARY_NAMES) + +find_path(TBB_MALLOC_INCLUDE_DIR + NAMES tbb/tbb.h + PATHS ${TBB_INC_SEARCH_PATH}) + +find_library(TBB_MALLOC_LIBRARY_RELEASE + NAMES ${TBB_MALLOC_LIBRARY_NAMES} + PATHS ${TBB_LIB_SEARCH_PATH}) +find_library(TBB_MALLOC_LIBRARY_DEBUG + NAMES ${TBB_MALLOC_LIBRARY_NAMES_DEBUG} + PATHS ${TBB_LIB_SEARCH_PATH}) +make_library_set(TBB_MALLOC_LIBRARY) + +findpkg_finish(TBB_MALLOC) + +#============================================================================= +# Look for TBB's malloc proxy package +set(TBB_MALLOC_PROXY_LIBRARY_NAMES tbbmalloc_proxy) +get_debug_names(TBB_MALLOC_PROXY_LIBRARY_NAMES) + +find_path(TBB_MALLOC_PROXY_INCLUDE_DIR + NAMES tbb/tbbmalloc_proxy.h + PATHS ${TBB_INC_SEARCH_PATH}) + +find_library(TBB_MALLOC_PROXY_LIBRARY_RELEASE + NAMES ${TBB_MALLOC_PROXY_LIBRARY_NAMES} + PATHS ${TBB_LIB_SEARCH_PATH}) +find_library(TBB_MALLOC_PROXY_LIBRARY_DEBUG + NAMES ${TBB_MALLOC_PROXY_LIBRARY_NAMES_DEBUG} + PATHS ${TBB_LIB_SEARCH_PATH}) +make_library_set(TBB_MALLOC_PROXY_LIBRARY) + +findpkg_finish(TBB_MALLOC_PROXY) + + +#============================================================================= +#parse all the version numbers from tbb +if(NOT TBB_VERSION) + + #only read the start of the file + file(READ + "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" + TBB_VERSION_CONTENTS + LIMIT 2048) + + string(REGEX REPLACE + ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" + TBB_VERSION_MAJOR "${TBB_VERSION_CONTENTS}") + + string(REGEX REPLACE + ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" + TBB_VERSION_MINOR "${TBB_VERSION_CONTENTS}") + + string(REGEX REPLACE + ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" + TBB_INTERFACE_VERSION "${TBB_VERSION_CONTENTS}") + + string(REGEX REPLACE + ".*#define TBB_COMPATIBLE_INTERFACE_VERSION ([0-9]+).*" "\\1" + TBB_COMPATIBLE_INTERFACE_VERSION "${TBB_VERSION_CONTENTS}") + +endif() \ No newline at end of file diff --git a/cmake/FindZeroMQ.cmake b/cmake/FindZeroMQ.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f29a6e88dee205ac072cdb70c83135c7d4723239 --- /dev/null +++ b/cmake/FindZeroMQ.cmake @@ -0,0 +1,116 @@ +##============================================================================= +## +## Copyright (c) Kitware, Inc. +## All rights reserved. +## See LICENSE.txt for details. +## +## This software is distributed WITHOUT ANY WARRANTY; without even +## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the above copyright notice for more information. +## +##============================================================================= +# - Try to find ZeroMQ headers and libraries +# +# Usage of this module as follows: +# +# find_package(ZeroMQ) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# ZeroMQ_ROOT_DIR Set this variable to the root installation of +# ZeroMQ if the module has problems finding +# the proper installation path. +# +# Variables defined by this module: +# +# ZEROMQ_FOUND System has ZeroMQ libs/headers +# ZeroMQ_LIBRARIES The ZeroMQ libraries +# ZeroMQ_INCLUDE_DIR The location of ZeroMQ headers + +find_path(ZeroMQ_ROOT_DIR + NAMES include/zmq.h + ) + +if(MSVC) + #add in all the names it can have on windows + if(CMAKE_GENERATOR_TOOLSET MATCHES "v140" OR MSVC14) + set(_zmq_TOOLSET "-v140") + elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v120" OR MSVC12) + set(_zmq_TOOLSET "-v120") + elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110_xp") + set(_zmq_TOOLSET "-v110_xp") + elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110" OR MSVC11) + set(_zmq_TOOLSET "-v110") + elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v100" OR MSVC10) + set(_zmq_TOOLSET "-v100") + elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v90" OR MSVC90) + set(_zmq_TOOLSET "-v90") + endif() + + set(_zmq_versions + "4_1_4" "4_1_3" "4_1_2" "4_1_1" "4_1_0" + "4_0_8" "4_0_7" "4_0_6" "4_0_5" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0" + "3_2_5" "3_2_4" "3_2_3" "3_2_2" "3_2_1" "3_2_0" "3_1_0") + + set(_zmq_release_names) + set(_zmq_debug_names) + foreach( ver ${_zmq_versions}) + list(APPEND _zmq_release_names "libzmq${_zmq_TOOLSET}-mt-${ver}") + endforeach() + foreach( ver ${_zmq_versions}) + list(APPEND _zmq_debug_names "libzmq${_zmq_TOOLSET}-mt-gd-${ver}") + endforeach() + + #now try to find the release and debug version + find_library(ZeroMQ_LIBRARY_RELEASE + NAMES ${_zmq_release_names} zmq libzmq + HINTS ${ZeroMQ_ROOT_DIR}/bin + ${ZeroMQ_ROOT_DIR}/lib + ) + + find_library(ZeroMQ_LIBRARY_DEBUG + NAMES ${_zmq_debug_names} zmq libzmq + HINTS ${ZeroMQ_ROOT_DIR}/bin + ${ZeroMQ_ROOT_DIR}/lib + ) + + if(ZeroMQ_LIBRARY_RELEASE AND ZeroMQ_LIBRARY_DEBUG) + set(ZeroMQ_LIBRARY + debug ${ZeroMQ_LIBRARY_DEBUG} + optimized ${ZeroMQ_LIBRARY_RELEASE} + ) + elseif(ZeroMQ_LIBRARY_RELEASE) + set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_RELEASE}) + elseif(ZeroMQ_LIBRARY_DEBUG) + set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_DEBUG}) + endif() + +else() + find_library(ZeroMQ_LIBRARY + NAMES zmq libzmq + HINTS ${ZeroMQ_ROOT_DIR}/lib + ) +endif() + +find_path(ZeroMQ_INCLUDE_DIR + NAMES zmq.h + HINTS ${ZeroMQ_ROOT_DIR}/include + ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(ZeroMQ DEFAULT_MSG + ZeroMQ_LIBRARY + ZeroMQ_INCLUDE_DIR + ) + +set(ZeroMQ_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR}) +set(ZeroMQ_LIBRARIES ${ZeroMQ_LIBRARY}) + +mark_as_advanced( + ZeroMQ_ROOT_DIR + ZeroMQ_LIBRARY + ZeroMQ_LIBRARY_DEBUG + ZeroMQ_LIBRARY_RELEASE + ZeroMQ_INCLUDE_DIR + ) \ No newline at end of file diff --git a/docs/presets.json b/docs/presets.json new file mode 100644 index 0000000000000000000000000000000000000000..5ac028ea273f28a6e8ada3cffd85df2102bd3fb7 --- /dev/null +++ b/docs/presets.json @@ -0,0 +1,442 @@ +{ + "presets": [ + { + "color_plugin": { + "invert_p": false, + "k": 0.5, + "mode": 0 + }, + "data_plugin": { + "dataset": "D:/data/pli/MSA/MSA0309_s0536-0695.h5", + "offset": [ + 34, + 752, + 32 + ], + "size": [ + 768, + 768, + 32 + ], + "stride": [ + 1, + 1, + 1 + ] + }, + "demo_plugin": { + "description": "1- Scalar Maps:\n\nThe retardation map describes the quantity of change in the direction of light as it travels through the brain slice.\n\nDue to the optical properties (birefringence) of myelinated axons, the light deviates as it travels through them. Measuring this deviation for various polarization angles enable computation of the most likely direction for the axon (and hence the neuron). This is the major physical principle behind Polarized Light Imaging (PLI).\n\nMathematically, the retardation map is a 3D scalar map (see the Scalar Maps tab for modifying the slice)." + }, + "fom_plugin": { + "enabled": false, + "scale": 1.0 + }, + "interactor_plugin": { + "rotation": [ + -152.49996948242188, + -4.602674835041398e-06, + 1.057937515724916e-05 + ], + "translation": [ + 388.6102294921875, + 724.0062255859375, + -366.82843017578125 + ] + }, + "local_tractography_plugin": { + "enabled": false, + "integration_step": 1.0, + "iterations": 10, + "offset": [ + 0, + 0, + 0 + ], + "remote_address": "tcp://linuxihdc090.rz.rwth-aachen.de:14130", + "remote_folder": "/home/ad784563/data/", + "size": [ + 0, + 0, + 0 + ], + "streamline_radius": 0.10000000149011612, + "stride": [ + 1, + 1, + 1 + ] + }, + "odf_plugin": { + "enabled": false, + "hierarchical": false, + "histogram_bins": [ + 100, + 50 + ], + "maximum_sh_degree": 6, + "sampling_partitions": [ + 32, + 16 + ], + "supervoxel_extent": [ + 64, + 64, + 1 + ], + "symmetric": true, + "visible_layers": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "polar_plot_plugin": { + "angular_partitions": 360, + "enabled": false, + "superpixel_size": 16, + "symmetric": true + }, + "scalar_plugin": { + "enabled": true, + "mode": true + } + }, + { + "color_plugin": { + "invert_p": false, + "k": 0.5, + "mode": 0 + }, + "data_plugin": { + "dataset": "D:/data/pli/MSA/MSA0309_s0536-0695.h5", + "offset": [ + 34, + 752, + 32 + ], + "size": [ + 768, + 768, + 32 + ], + "stride": [ + 1, + 1, + 1 + ] + }, + "demo_plugin": { + "description": "2- Fiber Orientation Maps:\n\nThe Fiber Orientation Map is computed from the combination of Transmittance and Retardation maps. Each voxel is a single unit vector depicting the computed orientation of the axons at the given point.\n\nSince PLI data acquisition involves physical slicing, overlaying the slices naively results in significant discrepancies and prevent a full 3D reconstruction. Registration is almost always necessary to achieve 3D, which is researched by the collaborators of Jülich Forschungszentrum at University of Oxford.\n\nMathematically, the Fiber Orientation Map is a 3D unit vector field (see the Fiber Orientation Maps tab for modifying the scale)." + }, + "fom_plugin": { + "enabled": true, + "scale": 1.0 + }, + "interactor_plugin": { + "rotation": [ + -152.49996948242188, + -4.602674835041398e-06, + 1.057937515724916e-05 + ], + "translation": [ + 388.6102294921875, + 724.0062255859375, + -366.82843017578125 + ] + }, + "local_tractography_plugin": { + "enabled": false, + "integration_step": 1.0, + "iterations": 10, + "offset": [ + 0, + 0, + 0 + ], + "remote_address": "tcp://linuxihdc090.rz.rwth-aachen.de:14130", + "remote_folder": "/home/ad784563/data/", + "size": [ + 0, + 0, + 0 + ], + "streamline_radius": 0.10000000149011612, + "stride": [ + 1, + 1, + 1 + ] + }, + "odf_plugin": { + "enabled": false, + "hierarchical": false, + "histogram_bins": [ + 100, + 50 + ], + "maximum_sh_degree": 6, + "sampling_partitions": [ + 32, + 16 + ], + "supervoxel_extent": [ + 64, + 64, + 1 + ], + "symmetric": true, + "visible_layers": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "polar_plot_plugin": { + "angular_partitions": 360, + "enabled": false, + "superpixel_size": 16, + "symmetric": true + }, + "scalar_plugin": { + "enabled": true, + "mode": true + } + }, + { + "color_plugin": { + "invert_p": false, + "k": 0.5, + "mode": 0 + }, + "data_plugin": { + "dataset": "D:/data/pli/MSA/MSA0309_s0536-0695.h5", + "offset": [ + 34, + 752, + 32 + ], + "size": [ + 768, + 768, + 32 + ], + "stride": [ + 1, + 1, + 1 + ] + }, + "demo_plugin": { + "description": "3- Orientation Distribution Function (ODF) Maps:\n\nThe Fiber Orientation Map is convenient to analyze nerve fibers per slice, but visual clutter emerges when viewing multiple slices.\n\nGrouping the vectors into orientation distribution functions provide a workaround to the clutter without significantly distorting the data. These functions also enable comparison of 3D-PLI results with other approaches such as diffusion Magnetic Resonance Imaging.\n\nThe algorithm collects nearby vectors into spherical histograms and projects it to the spherical harmonics basis to create the visuals to the left.\n\nMathematically, the ODF map is a 3D (spherical) tensor field (see the Orientation Distribution Functions tab for customizing the parameters and re-run)." + }, + "fom_plugin": { + "enabled": false, + "scale": 1.0 + }, + "interactor_plugin": { + "rotation": [ + -152.49996948242188, + -4.602674835041398e-06, + 1.057937515724916e-05 + ], + "translation": [ + 388.6102294921875, + 724.0062255859375, + -366.82843017578125 + ] + }, + "local_tractography_plugin": { + "enabled": false, + "integration_step": 1.0, + "iterations": 10, + "offset": [ + 0, + 0, + 0 + ], + "remote_address": "tcp://linuxihdc090.rz.rwth-aachen.de:14130", + "remote_folder": "/home/ad784563/data/", + "size": [ + 0, + 0, + 0 + ], + "streamline_radius": 0.10000000149011612, + "stride": [ + 1, + 1, + 1 + ] + }, + "odf_plugin": { + "enabled": true, + "hierarchical": false, + "histogram_bins": [ + 64, + 32 + ], + "maximum_sh_degree": 6, + "sampling_partitions": [ + 64, + 32 + ], + "supervoxel_extent": [ + 8, + 8, + 32 + ], + "symmetric": false, + "visible_layers": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "polar_plot_plugin": { + "angular_partitions": 360, + "enabled": false, + "superpixel_size": 16, + "symmetric": true + }, + "scalar_plugin": { + "enabled": true, + "mode": true + } + }, + { + "color_plugin": { + "invert_p": false, + "k": 0.5, + "mode": 0 + }, + "data_plugin": { + "dataset": "D:/data/pli/MSA/MSA0309_s0536-0695.h5", + "offset": [ + 34, + 752, + 32 + ], + "size": [ + 768, + 768, + 32 + ], + "stride": [ + 1, + 1, + 1 + ] + }, + "demo_plugin": { + "description": "4- Computing Fiber Pathways via Particle Tracing\n\nThe voxel-wise visualization techniques certainly help the neuroscientists in comparison settings but they are a discrete depiction of continuous data such as the nerve fibers within the brain.\n\nParticle tracing enables computation of continuous pathways from the discrete Fiber Orientation Map using an integration scheme such as Runge-Kutta or Euler. This reveals structural details invisible to voxel-wise methods.\n\nIn order to be able to scale to the large datasets created through 3D-PLI, we utilize a larger server to back the application up remotely. The server runs Runge-Kutta integration in parallel using TBB and passes the results onto Ospray, which is a CPU raytracing framework by Intel.\n" + }, + "fom_plugin": { + "enabled": true, + "scale": 1.0 + }, + "interactor_plugin": { + "rotation": [ + -152.49996948242188, + -4.602674835041398e-06, + 1.057937515724916e-05 + ], + "translation": [ + 388.6102294921875, + 668.595703125, + -260.3866271972656 + ] + }, + "local_tractography_plugin": { + "enabled": true, + "integration_step": 0.5, + "iterations": 100, + "offset": [ + 0, + 0, + 0 + ], + "remote_address": "tcp://localhost:14130", + "remote_folder": "D:/data/pli/MSA/", + "size": [ + 768, + 768, + 32 + ], + "streamline_radius": 0.10000000149011612, + "stride": [ + 2, + 2, + 2 + ] + }, + "odf_plugin": { + "enabled": false, + "hierarchical": false, + "histogram_bins": [ + 64, + 32 + ], + "maximum_sh_degree": 6, + "sampling_partitions": [ + 64, + 32 + ], + "supervoxel_extent": [ + 8, + 8, + 32 + ], + "symmetric": false, + "visible_layers": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "polar_plot_plugin": { + "angular_partitions": 360, + "enabled": false, + "superpixel_size": 16, + "symmetric": true + }, + "scalar_plugin": { + "enabled": true, + "mode": true + } + }, + {}, + {}, + {}, + {}, + {}, + {} + ] +} diff --git a/docs/test_presets.json b/docs/test_presets.json new file mode 100644 index 0000000000000000000000000000000000000000..ff9adba9b2596468819cbf9b6e5f7b375d9c4570 --- /dev/null +++ b/docs/test_presets.json @@ -0,0 +1,65 @@ +{ + "presets" : + [ + { + "data_plugin" : + { + "dataset" : "msa", + "offset" : [300, 700, 0 ], + "size" : [512, 512, 32 ], + "stride" : [1 , 1 , 1 ] + }, + "interactor_plugin" : + { + "translation" : [10.0, 10.0, 10.0], + "rotation" : [30.0, 60.0, 10.0] + }, + "color_plugin" : + { + "mode" : "hsl-tkp", + "k" : 0.5, + "invert_p" : false + }, + "scalar_plugin" : + { + "enabled" : true, + "mode" : "retardation" + }, + "fom_plugin" : + { + "enabled" : true, + "scale" : 1.0 + }, + "polar_plot_plugin" : + { + "enabled" : true, + "symmetric" : true, + "superpixel_size" : 16, + "angular_partitions" : 180 + }, + "odf_plugin" : + { + "enabled" : true, + "symmetric" : true, + "supervoxel_extent" : [64 , 64, 1], + "histogram_bins" : [100, 50], + "maximum_sh_degree" : 6, + "sampling_partitions" : [32, 16], + "hierarchical" : false, + "visible_layers" : [false, false, false, false, false, false, false, false, false, false] + }, + "local_tractography_plugin": + { + "enabled" : true, + "offset" : [300, 700, 0 ], + "size" : [512, 512, 32 ], + "stride" : [1 , 1 , 1 ], + "integration_step" : 1.0, + "iterations" : 10, + "streamline_radius" : 0.1, + "remote_address" : "tcp://linuxihdc090.rz.rwth-aachen.de:14130", + "remote_folder" : "/home/ad784563/data/" + } + } + ] +} \ No newline at end of file diff --git a/include/pli_vis/cuda/global_tractography.h b/include/pli_vis/cuda/global_tractography.h deleted file mode 100644 index 5983d3d139b74f60651cbfe74bfb81eda9169883..0000000000000000000000000000000000000000 --- a/include/pli_vis/cuda/global_tractography.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef PLI_VIS_GLOBAL_TRACTOGRAPHY_H_ -#define PLI_VIS_GLOBAL_TRACTOGRAPHY_H_ - -#include <vector_types.h> - -#include <pli_vis/cuda/sh/spherical_harmonics.h> -#include <pli_vis/cuda/utility/vector_ops.h> - -namespace pli -{ -// Based on the following: -// - Global reconstruction of neuronal fibres (Reisert et al. 2009) -// - Global fiber reconstruction becomes practical (Reisert et al. 2011) -template< - typename scalar_precision = float , - typename vector_precision = float3> -__host__ __device__ scalar_precision interaction_potential( - const vector_precision& lhs_position , - const vector_precision& lhs_orientation , - const vector_precision& rhs_position , - const vector_precision& rhs_orientation , - const scalar_precision& bias , - const scalar_precision& length = 1) -{ - auto midpoint = (lhs_position + rhs_position) / 2; - auto lhs_sign = dot(lhs_orientation, midpoint - lhs_position) >= 0 ? 1 : -1; - auto rhs_sign = dot(rhs_orientation, midpoint - rhs_position) >= 0 ? 1 : -1; - auto lhs_segment = lhs_position + lhs_sign * length * lhs_orientation; - auto rhs_segment = rhs_position + rhs_sign * length * rhs_orientation; - auto lhs_diff = lhs_segment - midpoint; - auto rhs_diff = rhs_segment - midpoint; - auto lhs_sq_dist = pow(lhs_diff.x, 2) + pow(lhs_diff.y, 2) + pow(lhs_diff.z, 2); - auto rhs_sq_dist = pow(rhs_diff.x, 2) + pow(rhs_diff.y, 2) + pow(rhs_diff.z, 2); - return (1.0 / pow(length, 2)) * (lhs_sq_dist + rhs_sq_dist) - bias; -} - -template< - typename scalar_precision = float , - typename vector_precision = float3> -__host__ __device__ scalar_precision internal_energy( - const unsigned count , - const vector_precision* lhs_positions , - const vector_precision* lhs_orientations, - const vector_precision* rhs_positions , - const vector_precision* rhs_orientations, - const scalar_precision& bias , - const scalar_precision& length = 1) -{ - scalar_precision value(0); - for(auto i = 0; i < count; ++i) - value += interaction_potential( - lhs_positions [i], - lhs_orientations[i], - rhs_positions [i], - rhs_orientations[i], - bias, - length); - return value; -} - -template< - typename scalar_precision = float , - typename vector_precision = float3> -__host__ __device__ void energy_minimizing_configuration( - const vector_precision& position , - const vector_precision& direction , - vector_precision& out_position , - vector_precision& out_direction , - const scalar_precision& length = 1) -{ - out_position = position + 2 * length * direction; - out_direction = direction; -} - -template< - typename scalar_precision = float , - typename vector_precision = float3> -__host__ __device__ void energy_minimizing_configuration( - const vector_precision& lhs_position , - const vector_precision& lhs_direction , - const vector_precision& rhs_position , - const vector_precision& rhs_direction , - vector_precision& out_position , - vector_precision& out_direction , - const scalar_precision& length = 1) -{ - out_position = (lhs_position + length * lhs_direction + rhs_position + length * rhs_direction) / 2; - out_direction = normalize(rhs_position - lhs_position); -} - -template< - typename scalar_precision = float , - typename vector_precision = float3> -__host__ __device__ scalar_precision predicted_signal( - const vector_precision& position , - const vector_precision& direction , - const unsigned count , - const vector_precision* positions , - const vector_precision* directions , - const scalar_precision& weight , - const scalar_precision& c , - const scalar_precision& sigma ) -{ - scalar_precision sum(0); - for(auto i = 0; i < count; ++i) - { - scalar_precision dot_v = dot(direction, directions[i]); - vector_precision diff_x = position - positions[i]; - sum += exp(-c * pow(dot_v, 2)) * exp(-dot(diff_x, diff_x) / pow(sigma, 2)); - } - return weight * sum; -} - -template< - typename scalar_precision = float , - typename vector_precision = float3> -__host__ __device__ void predicted_signal( - const vector_precision& position , - const unsigned bin_count , - const vector_precision* bin_directions , - scalar_precision* bin_magnitudes , - const unsigned count , - const vector_precision* positions , - const vector_precision* directions , - const scalar_precision& weight , - const scalar_precision& c , - const scalar_precision& sigma ) -{ - for(auto i = 0; i < bin_count; ++i) - { - bin_magnitudes[i] = predicted_signal( - position , - bin_directions[i], - count , - positions , - directions , - weight , - c , - sigma ); - } -} - -template< - typename scalar_precision = float> -__host__ __device__ void external_energy( - const unsigned odf_count , - const unsigned odf_max_degree , - const scalar_precision* original_odfs , - const scalar_precision* predicted_odfs , - scalar_precision* out_energies ) -{ - auto odf_coefficient_count = coefficient_count(odf_max_degree); - for(auto i = 0; i < odf_count; ++i) - { - auto start_index = odf_coefficient_count * i; - out_energies[i] = l2_distance(odf_coefficient_count, original_odfs[start_index], predicted_odfs[start_index]); - } -} - -template< - typename scalar_precision = float> -__host__ __device__ scalar_precision posterior_probability( - const scalar_precision& internal_energy, - const scalar_precision& external_energy, - const scalar_precision& temperature ) -{ - return exp((- internal_energy - external_energy) / temperature); -} -} - -#endif diff --git a/include/pli_vis/cuda/odf_field.h b/include/pli_vis/cuda/odf_field.h index fb24818faafa5059fc0c6d0f8b7c0ff3bcaca9ca..feb9d46235fedf6ccd820ffa96bac39c3a57c4e8 100644 --- a/include/pli_vis/cuda/odf_field.h +++ b/include/pli_vis/cuda/odf_field.h @@ -35,15 +35,6 @@ void sample_odfs( bool clustering = false, float cluster_threshold = 0.0 , std::function<void(const std::string&)> status_callback = [](const std::string&){}); - -void extract_peaks( - const uint3& dimensions , - const unsigned maximum_degree, - const float* coefficients , - const uint2& tessellations , - const unsigned maxima_count , - float3* maxima , - std::function<void(const std::string&)> status_callback = [](const std::string&){}); } #endif \ No newline at end of file diff --git a/include/pli_vis/cuda/pt/cartesian_locator.h b/include/pli_vis/cuda/pt/cartesian_locator.h index aaeecbae2127ed6c22fd6204681d0856f9c240c8..8d90ecfbd30d602070fea97d5045e40591cbbbdb 100644 --- a/include/pli_vis/cuda/pt/cartesian_locator.h +++ b/include/pli_vis/cuda/pt/cartesian_locator.h @@ -10,7 +10,7 @@ namespace cupt { -template<class type = float3, class index_type = uint3> +template<class type, class index_type = uint3> class cartesian_locator { public: diff --git a/include/pli_vis/cuda/pt/runge_kutta_4_integrator.h b/include/pli_vis/cuda/pt/runge_kutta_4_integrator.h index cb1fc97984ec27a07f8e281383b6a57cb75c5d88..b4f85cc0fc1ab90d7f6904b6943e2a947e540fbc 100644 --- a/include/pli_vis/cuda/pt/runge_kutta_4_integrator.h +++ b/include/pli_vis/cuda/pt/runge_kutta_4_integrator.h @@ -44,7 +44,7 @@ public: char next_stage ; }; - __host__ __device__ explicit runge_kutta_4_integrator(const uint3& dimensions, const float3& spacing, const data_type* data) + __host__ __device__ explicit runge_kutta_4_integrator(const uint3& dimensions, const data_type& spacing, const data_type* data) : interpolator_ (dimensions, spacing, data) , stage_factors_ ({0.0f, 0.5f, 0.5f, 1.0f} ) , result_factors_({1.0f, 2.0f, 2.0f, 1.0f} ) @@ -52,7 +52,7 @@ public: } - __host__ __device__ void set_data (const uint3& dimensions, const float3& spacing, const data_type* data) + __host__ __device__ void set_data (const uint3& dimensions, const data_type& spacing, const data_type* data) { interpolator_ = interpolator_type(dimensions, spacing, data); } @@ -66,12 +66,12 @@ public: else if (stage == 2) { stage_factor = stage_factors_.z; result_factor = result_factors_.z; } else if (stage == 3) { stage_factor = stage_factors_.w; result_factor = result_factors_.w; } - float3 current_point = step_data.start_point + stage_factor * step_data.current_k; + auto current_point = step_data.start_point + stage_factor * step_data.current_k; if (!interpolator_.is_valid(current_point)) return; - float3 current_vector = interpolator_.interpolate(current_point); + auto current_vector = interpolator_.interpolate(current_point); step_data.current_k = step_data.time_step * current_vector; step_data.sum_k = step_data.sum_k + result_factor * step_data.current_k; step_data.next_stage = stage + 1; diff --git a/include/pli_vis/cuda/pt/tracer.h b/include/pli_vis/cuda/pt/tracer.h index 49e21d7b20248d2de7ff56cf18211f07cd2259a1..83ed420b600e7f21d184054053144303962233ee 100644 --- a/include/pli_vis/cuda/pt/tracer.h +++ b/include/pli_vis/cuda/pt/tracer.h @@ -8,13 +8,13 @@ namespace cupt { -std::vector<std::vector<float3>> trace( +std::vector<std::vector<float4>> trace( const std::size_t iteration_count, const float step_size , const uint3 data_dimensions, - const float3 data_spacing , - const std::vector<float3>& data , - const std::vector<float3>& seeds ); + const float4 data_spacing , + const std::vector<float4>& data , + const std::vector<float4>& seeds ); } #endif diff --git a/include/pli_vis/cuda/pt/trilinear_interpolator.h b/include/pli_vis/cuda/pt/trilinear_interpolator.h index bb871fcff10f9591d8cac7c68cce0c5e7a8b9265..9c0a5dfade7d2fe3889275ff90e1bc229103fe94 100644 --- a/include/pli_vis/cuda/pt/trilinear_interpolator.h +++ b/include/pli_vis/cuda/pt/trilinear_interpolator.h @@ -11,11 +11,11 @@ namespace cupt { -template<class type = float3> +template<class type> class trilinear_interpolator { public: - __host__ __device__ explicit trilinear_interpolator(const uint3& dimensions, const float3& spacing, const type* data) + __host__ __device__ explicit trilinear_interpolator(const uint3& dimensions, const type& spacing, const type* data) : data_ {data} , locator_{dimensions, spacing} { diff --git a/include/pli_vis/cuda/utility/convert.h b/include/pli_vis/cuda/utility/convert.h index df50fe1aff4e41f7d5b8466e1c9e3e285b535fe0..af15863406a1625e84ad4fc42bf09eaac38194f3 100644 --- a/include/pli_vis/cuda/utility/convert.h +++ b/include/pli_vis/cuda/utility/convert.h @@ -58,6 +58,19 @@ SPECIALIZE_CONVERT(float3 ) SPECIALIZE_CONVERT(longlong3 ) SPECIALIZE_CONVERT(ulonglong3) SPECIALIZE_CONVERT(double3 ) + +SPECIALIZE_CONVERT(char4 ) +SPECIALIZE_CONVERT(uchar4 ) +SPECIALIZE_CONVERT(short4 ) +SPECIALIZE_CONVERT(ushort4 ) +SPECIALIZE_CONVERT(int4 ) +SPECIALIZE_CONVERT(uint4 ) +SPECIALIZE_CONVERT(long4 ) +SPECIALIZE_CONVERT(ulong4 ) +SPECIALIZE_CONVERT(float4 ) +SPECIALIZE_CONVERT(longlong4 ) +SPECIALIZE_CONVERT(ulonglong4) +SPECIALIZE_CONVERT(double4 ) #undef SPECIALIZE_CONVERT } diff --git a/include/pli_vis/cuda/zernike/disk.h b/include/pli_vis/cuda/zernike/disk.h deleted file mode 100644 index bc18901c0bd391f2d915264b86887be35ad584c1..0000000000000000000000000000000000000000 --- a/include/pli_vis/cuda/zernike/disk.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DISK_H_ -#define DISK_H_ - -#define _USE_MATH_DEFINES - -#include <math.h> - -#include <device_launch_parameters.h> -#include <host_defines.h> -#include <vector_types.h> - -// References: -// - Weisstein, Disk Point Picking, MathWorld - A Wolfram Web Resource. -namespace zer -{ -// This kernel requires a dimensions.x x dimensions.y 2D grid. -template<typename precision> -__global__ void sample_disk(uint2 dimensions, precision* samples, bool uniform) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - if (x >= dimensions.x || y >= dimensions.y) - return; - - const auto rho = uniform ? sqrtf(static_cast<float>(x) / dimensions.x) : static_cast<float>(x) / dimensions.x; - const auto theta = 2.0f * M_PI * y / dimensions.y; - - const auto sample_index = y + dimensions.y * x; - samples[sample_index].x = rho * cos(theta); - samples[sample_index].y = rho * sin(theta); -} -} - -#endif \ No newline at end of file diff --git a/include/pli_vis/cuda/zernike/launch.h b/include/pli_vis/cuda/zernike/launch.h deleted file mode 100644 index 69363f2b0ef727961633cad5870bca4572f3c3f2..0000000000000000000000000000000000000000 --- a/include/pli_vis/cuda/zernike/launch.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef ZERNIKE_LAUNCH_H_ -#define ZERNIKE_LAUNCH_H_ - -#include <thrust/device_vector.h> -#include <vector_types.h> - -namespace zer -{ -thrust::device_vector<float> launch( - const thrust::device_vector<float3>& vectors , - const uint2& vectors_size , - const uint2& superpixel_size , - const uint2& disk_partitions = {100u, 360u}, - const unsigned maximum_degree = 10 , - bool symmetric = true , - bool normalize = true , - bool even_only = false , - bool edge_only = false ); - -std::vector<float> launch( - const std::vector<float3>& vectors , - const uint2& vectors_size , - const uint2& superpixel_size , - const uint2& disk_partitions = {100u, 360u}, - const unsigned maximum_degree = 10 , - bool symmetric = true , - bool normalize = true , - bool even_only = false , - bool edge_only = false ); -} - -#endif diff --git a/include/pli_vis/cuda/zernike/zernike.h b/include/pli_vis/cuda/zernike/zernike.h deleted file mode 100644 index 9544d3ad9fa13655cd24690a8689632f51b610a3..0000000000000000000000000000000000000000 --- a/include/pli_vis/cuda/zernike/zernike.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef ZERNIKE_H_ -#define ZERNIKE_H_ - -#include <math.h> - -#include <device_launch_parameters.h> -#include <host_defines.h> -#include <vector_types.h> - -// References: -// - Lakshminarayanan & Fleck, Zernike Polynomials: A Guide, Journal of Modern Optics 2011.7. -// Notes: -// - Rho is restricted to the unit circle. -// - Theta is measured clockwise from the vertical axis and is in radians. -namespace zer -{ -// Launch utility. -__forceinline__ __host__ __device__ unsigned block_size_1d() -{ - return 64; -} -__forceinline__ __host__ __device__ dim3 block_size_2d() -{ - return {32, 32, 1}; -} -__forceinline__ __host__ __device__ dim3 block_size_3d() -{ - return {16, 16, 4}; -} -__forceinline__ __host__ __device__ unsigned grid_size_1d (const unsigned& target_dimension ) -{ - const auto block_size = block_size_1d(); - return (target_dimension + block_size - 1u) / block_size; -} -__forceinline__ __host__ __device__ dim3 grid_size_2d (const dim3& target_dimensions) -{ - const auto block_size = block_size_2d(); - return - { - (target_dimensions.x + block_size.x - 1u) / block_size.x, - (target_dimensions.y + block_size.y - 1u) / block_size.y, - 1u - }; -} -__forceinline__ __host__ __device__ dim3 grid_size_3d (const dim3& target_dimensions) -{ - const auto block_size = block_size_3d(); - return - { - (target_dimensions.x + block_size.x - 1) / block_size.x, - (target_dimensions.y + block_size.y - 1) / block_size.y, - (target_dimensions.z + block_size.z - 1) / block_size.z - }; -} - -// Reflection utility. -template <class T, class M> -M member_type(M T:: *); - -// Factorial utility. -template<typename precision> -__host__ __device__ precision factorial(unsigned n) -{ - precision out(1); - for (auto i = 2; i <= n; i++) - out *= i; - return out; -} - -// Zernike moments implementation. -__forceinline__ __host__ __device__ unsigned maximum_degree(const unsigned& count) -{ - return round(sqrtf(2 * count) - 1); -} -__forceinline__ __host__ __device__ unsigned expansion_size(const unsigned& max_n) -{ - return (max_n + 1) * (max_n + 2) / 2; -} -__forceinline__ __host__ __device__ unsigned linear_index (const int2& nm ) -{ - return (nm.x * (nm.x + 2) + nm.y) / 2; -} -__forceinline__ __host__ __device__ int2 quantum_index (const unsigned& i ) -{ - int2 nm; - nm.x = ceil((-3 + sqrtf(9 + 8 * i)) / 2); - nm.y = 2 * i - nm.x * (nm.x + 2); - return nm; -} - -template<typename precision> -__host__ __device__ precision mode (const int2& nm, const precision& rho) -{ - precision out(0); - for(unsigned i = 0; i <= (nm.x - nm.y) / 2; i++) - out += pow(rho, nm.x - 2 * i) * - (pow(-1, i) * factorial<precision>(nm.x - i)) / - (factorial<precision>(i) * - factorial<precision>(0.5 * (nm.x + nm.y) - i) * - factorial<precision>(0.5 * (nm.x - nm.y) - i)); - return out; -} -template<typename precision> -__host__ __device__ decltype(member_type(&precision::x)) evaluate(const int2& nm, const precision& rt ) -{ - return (nm.y >= 0 ? 1.0f : -1.0f) * sqrtf((2.0f * nm.x + 2.0f) / (1.0f + (nm.y == 0 ? 1.0f : 0.0f))) * mode(int2{abs(nm.x), abs(nm.y)}, rt.x) * (nm.y >= 0 ? cos(abs(nm.y) * rt.y) : sin(abs(nm.y) * rt.y)); -} - -// This kernel requires a sample_count x expansion_size 2D grid. -template<typename precision, typename sample_type> -__global__ void compute_basis( - const unsigned sample_count , - const sample_type* samples , - const unsigned expansion_size , - precision* basis , - bool even_only = false, - bool edge_only = false) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - if (x >= sample_count || y >= expansion_size) - return; - - const auto index = quantum_index(y); - if(even_only && index.x % 2 != 0) - return; - if(edge_only && abs(index.x) != abs(index.y)) - return; - - atomicAdd(&basis[x + sample_count * y], evaluate(index, samples[x])); -} -// This kernel requires a dimensions.x x dimensions.y x dimensions.z 3D grid. -template<typename precision, typename sample_type> -__global__ void compute_bases( - const uint3 dimensions , - const unsigned samples_per_voxel, - const sample_type* samples , - const unsigned expansion_size , - precision* bases , - bool even_only = false, - bool edge_only = false) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - const auto z = blockIdx.z * blockDim.z + threadIdx.z; - if (x >= dimensions.x || y >= dimensions.y || z >= dimensions.z) - return; - - const auto samples_offset = samples_per_voxel * (z + dimensions.z * (y + dimensions.y * x)); - const auto bases_offset = samples_offset * expansion_size; - compute_basis<<<grid_size_2d(dim3(samples_per_voxel, expansion_size)), block_size_2d()>>>( - samples_per_voxel , - samples + samples_offset, - expansion_size , - bases + bases_offset , - even_only , - edge_only ); -} - -// This kernel requires a expansion_size x samples_per_voxel 2D grid. -template<typename precision, typename coefficient_type> -__global__ void reconstruct( - const unsigned expansion_size , - const coefficient_type* coefficients , - const unsigned samples_per_voxel, - const precision* samples , - precision* outputs ) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - if (x >= expansion_size || y >= samples_per_voxel) - return; - - atomicAdd(&outputs[y], coefficients[x] * evaluate(x, samples[y])); -} -// This kernel requires a dimensions.x x dimensions.y x dimensions.z 3D grid. -template<typename precision, typename coefficient_type> -__global__ void reconstruct( - const uint3 dimensions , - const unsigned expansion_size , - const coefficient_type* coefficients , - const unsigned samples_per_voxel, - const precision* samples , - precision* outputs ) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - const auto z = blockIdx.z * blockDim.z + threadIdx.z; - if (x >= dimensions.x || y >= dimensions.y || z >= dimensions.z) - return; - - const auto volume_index = z + dimensions.z * (y + dimensions.y * x); - const auto coefficients_offset = volume_index * expansion_size ; - const auto samples_offset = volume_index * samples_per_voxel; - reconstruct<<<grid_size_2d(dim3(expansion_size, samples_per_voxel)), block_size_2d()>>>( - expansion_size , - coefficients + coefficients_offset, - samples_per_voxel , - samples + samples_offset , - outputs + samples_offset ); - cudaDeviceSynchronize(); -} -} - -#endif diff --git a/include/pli_vis/third_party/cppzmq/zmq.hpp b/include/pli_vis/third_party/cppzmq/zmq.hpp new file mode 100644 index 0000000000000000000000000000000000000000..da0ffa1bf038a14d23e7d3b75cfe6f5115132c4b --- /dev/null +++ b/include/pli_vis/third_party/cppzmq/zmq.hpp @@ -0,0 +1,976 @@ +/* + Copyright (c) 2016-2017 ZeroMQ community + Copyright (c) 2009-2011 250bpm s.r.o. + Copyright (c) 2011 Botond Ballo + Copyright (c) 2007-2009 iMatix Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#ifndef __ZMQ_HPP_INCLUDED__ +#define __ZMQ_HPP_INCLUDED__ + +#if (__cplusplus >= 201103L) + #define ZMQ_CPP11 + #define ZMQ_NOTHROW noexcept + #define ZMQ_EXPLICIT explicit +#elif (defined(_MSC_VER) && (_MSC_VER >= 1900)) + #define ZMQ_CPP11 + #define ZMQ_NOTHROW noexcept + #define ZMQ_EXPLICIT explicit +#else + #define ZMQ_CPP03 + #define ZMQ_NOTHROW + #define ZMQ_EXPLICIT +#endif + +#include <zmq.h> + +#include <algorithm> +#include <cassert> +#include <cstring> +#include <string> +#include <exception> +#include <vector> +#include <iterator> + +#ifdef ZMQ_CPP11 +#include <chrono> +#include <tuple> +#include <functional> +#endif + +// Detect whether the compiler supports C++11 rvalue references. +#if (defined(__GNUC__) && (__GNUC__ > 4 || \ + (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \ + defined(__GXX_EXPERIMENTAL_CXX0X__)) + #define ZMQ_HAS_RVALUE_REFS + #define ZMQ_DELETED_FUNCTION = delete +#elif defined(__clang__) + #if __has_feature(cxx_rvalue_references) + #define ZMQ_HAS_RVALUE_REFS + #endif + + #if __has_feature(cxx_deleted_functions) + #define ZMQ_DELETED_FUNCTION = delete + #else + #define ZMQ_DELETED_FUNCTION + #endif +#elif defined(_MSC_VER) && (_MSC_VER >= 1900) + #define ZMQ_HAS_RVALUE_REFS + #define ZMQ_DELETED_FUNCTION = delete +#elif defined(_MSC_VER) && (_MSC_VER >= 1600) + #define ZMQ_HAS_RVALUE_REFS + #define ZMQ_DELETED_FUNCTION +#else + #define ZMQ_DELETED_FUNCTION +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0) +#define ZMQ_NEW_MONITOR_EVENT_LAYOUT +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) +#define ZMQ_HAS_PROXY_STEERABLE +/* Socket event data */ +typedef struct { + uint16_t event; // id of the event as bitfield + int32_t value ; // value is either error code, fd or reconnect interval +} zmq_event_t; +#endif + +// Avoid using deprecated message receive function when possible +#if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0) +# define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags) +#endif + + +// In order to prevent unused variable warnings when building in non-debug +// mode use this macro to make assertions. +#ifndef NDEBUG +# define ZMQ_ASSERT(expression) assert(expression) +#else +# define ZMQ_ASSERT(expression) (void)(expression) +#endif + +namespace zmq +{ + + typedef zmq_free_fn free_fn; + typedef zmq_pollitem_t pollitem_t; + + class error_t : public std::exception + { + public: + + error_t () : errnum (zmq_errno ()) {} +#ifdef ZMQ_CPP11 + virtual const char *what () const noexcept + { + return zmq_strerror (errnum); + } +#else + virtual const char *what() const throw () + { + return zmq_strerror(errnum); + } +#endif + int num () const + { + return errnum; + } + + private: + + int errnum; + }; + + inline int poll (zmq_pollitem_t const* items_, size_t nitems_, long timeout_ = -1) + { + int rc = zmq_poll (const_cast<zmq_pollitem_t*>(items_), static_cast<int>(nitems_), timeout_); + if (rc < 0) + throw error_t (); + return rc; + } + + inline int poll(zmq_pollitem_t const* items, size_t nitems) + { + return poll(items, nitems, -1); + } + + #ifdef ZMQ_CPP11 + inline int poll(zmq_pollitem_t const* items, size_t nitems, std::chrono::milliseconds timeout) + { + return poll(items, nitems, static_cast<long>(timeout.count())); + } + + inline int poll(std::vector<zmq_pollitem_t> const& items, std::chrono::milliseconds timeout) + { + return poll(items.data(), items.size(), static_cast<long>(timeout.count())); + } + + inline int poll(std::vector<zmq_pollitem_t> const& items, long timeout_ = -1) + { + return poll(items.data(), items.size(), timeout_); + } + #endif + + + + inline void proxy (void *frontend, void *backend, void *capture) + { + int rc = zmq_proxy (frontend, backend, capture); + if (rc != 0) + throw error_t (); + } + +#ifdef ZMQ_HAS_PROXY_STEERABLE + inline void proxy_steerable (void *frontend, void *backend, void *capture, void *control) + { + int rc = zmq_proxy_steerable (frontend, backend, capture, control); + if (rc != 0) + throw error_t (); + } +#endif + + inline void version (int *major_, int *minor_, int *patch_) + { + zmq_version (major_, minor_, patch_); + } + + #ifdef ZMQ_CPP11 + inline std::tuple<int, int, int> version() + { + std::tuple<int, int, int> v; + zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v) ); + return v; + } + #endif + + class message_t + { + friend class socket_t; + + public: + + inline message_t () + { + int rc = zmq_msg_init (&msg); + if (rc != 0) + throw error_t (); + } + + inline explicit message_t (size_t size_) + { + int rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + } + + template<typename I> message_t(I first, I last): + msg() + { + typedef typename std::iterator_traits<I>::difference_type size_type; + typedef typename std::iterator_traits<I>::value_type value_t; + + size_type const size_ = std::distance(first, last)*sizeof(value_t); + int const rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + value_t* dest = data<value_t>(); + while (first != last) + { + *dest = *first; + ++dest; ++first; + } + } + + inline message_t (const void *data_, size_t size_) + { + int rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + memcpy(data(), data_, size_); + } + + inline message_t (void *data_, size_t size_, free_fn *ffn_, + void *hint_ = NULL) + { + int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); + if (rc != 0) + throw error_t (); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + inline message_t (message_t &&rhs): msg (rhs.msg) + { + int rc = zmq_msg_init (&rhs.msg); + if (rc != 0) + throw error_t (); + } + + inline message_t &operator = (message_t &&rhs) ZMQ_NOTHROW + { + std::swap (msg, rhs.msg); + return *this; + } +#endif + + inline ~message_t () ZMQ_NOTHROW + { + int rc = zmq_msg_close (&msg); + ZMQ_ASSERT (rc == 0); + } + + inline void rebuild () + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init (&msg); + if (rc != 0) + throw error_t (); + } + + inline void rebuild (size_t size_) + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + } + + inline void rebuild (const void *data_, size_t size_) + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init_size (&msg, size_); + if (rc != 0) + throw error_t (); + memcpy(data(), data_, size_); + } + + inline void rebuild (void *data_, size_t size_, free_fn *ffn_, + void *hint_ = NULL) + { + int rc = zmq_msg_close (&msg); + if (rc != 0) + throw error_t (); + rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); + if (rc != 0) + throw error_t (); + } + + inline void move (message_t const *msg_) + { + int rc = zmq_msg_move (&msg, const_cast<zmq_msg_t*>(&(msg_->msg))); + if (rc != 0) + throw error_t (); + } + + inline void copy (message_t const *msg_) + { + int rc = zmq_msg_copy (&msg, const_cast<zmq_msg_t*>(&(msg_->msg))); + if (rc != 0) + throw error_t (); + } + + inline bool more () const ZMQ_NOTHROW + { + int rc = zmq_msg_more (const_cast<zmq_msg_t*>(&msg) ); + return rc != 0; + } + + inline void *data () ZMQ_NOTHROW + { + return zmq_msg_data (&msg); + } + + inline const void* data () const ZMQ_NOTHROW + { + return zmq_msg_data (const_cast<zmq_msg_t*>(&msg)); + } + + inline size_t size () const ZMQ_NOTHROW + { + return zmq_msg_size (const_cast<zmq_msg_t*>(&msg)); + } + + template<typename T> T* data() ZMQ_NOTHROW + { + return static_cast<T*>( data() ); + } + + template<typename T> T const* data() const ZMQ_NOTHROW + { + return static_cast<T const*>( data() ); + } + + inline bool equal(const message_t* other) const ZMQ_NOTHROW + { + if (size() != other->size()) + return false; + std::string a(data<char>(), size()); + std::string b(other->data<char>(), other->size()); + return a == b; + } + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) + inline const char* gets(const char *property_) + { + const char* value = zmq_msg_gets (&msg, property_); + if (value == NULL) + throw error_t (); + return value; + } +#endif + + private: + // The underlying message + zmq_msg_t msg; + + // Disable implicit message copying, so that users won't use shared + // messages (less efficient) without being aware of the fact. + message_t (const message_t&) ZMQ_DELETED_FUNCTION; + void operator = (const message_t&) ZMQ_DELETED_FUNCTION; + }; + + class context_t + { + friend class socket_t; + + public: + inline context_t () + { + ptr = zmq_ctx_new (); + if (ptr == NULL) + throw error_t (); + } + + + inline explicit context_t (int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT) + { + ptr = zmq_ctx_new (); + if (ptr == NULL) + throw error_t (); + + int rc = zmq_ctx_set (ptr, ZMQ_IO_THREADS, io_threads_); + ZMQ_ASSERT (rc == 0); + + rc = zmq_ctx_set (ptr, ZMQ_MAX_SOCKETS, max_sockets_); + ZMQ_ASSERT (rc == 0); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + inline context_t (context_t &&rhs) ZMQ_NOTHROW : ptr (rhs.ptr) + { + rhs.ptr = NULL; + } + inline context_t &operator = (context_t &&rhs) ZMQ_NOTHROW + { + std::swap (ptr, rhs.ptr); + return *this; + } +#endif + + inline ~context_t () ZMQ_NOTHROW + { + close(); + } + + inline void close() ZMQ_NOTHROW + { + if (ptr == NULL) + return; + + int rc = zmq_ctx_destroy (ptr); + ZMQ_ASSERT (rc == 0); + ptr = NULL; + } + + // Be careful with this, it's probably only useful for + // using the C api together with an existing C++ api. + // Normally you should never need to use this. + inline ZMQ_EXPLICIT operator void* () ZMQ_NOTHROW + { + return ptr; + } + + inline ZMQ_EXPLICIT operator void const* () const ZMQ_NOTHROW + { + return ptr; + } + private: + + void *ptr; + + context_t (const context_t&) ZMQ_DELETED_FUNCTION; + void operator = (const context_t&) ZMQ_DELETED_FUNCTION; + }; + + #ifdef ZMQ_CPP11 + enum class socket_type: int + { + req = ZMQ_REQ, + rep = ZMQ_REP, + dealer = ZMQ_DEALER, + router = ZMQ_ROUTER, + pub = ZMQ_PUB, + sub = ZMQ_SUB, + xpub = ZMQ_XPUB, + xsub = ZMQ_XSUB, + push = ZMQ_PUSH, + pull = ZMQ_PULL, +#if ZMQ_VERSION_MAJOR < 4 + pair = ZMQ_PAIR +#else + pair = ZMQ_PAIR, + stream = ZMQ_STREAM +#endif + }; + #endif + + class socket_t + { + friend class monitor_t; + friend class poller_t; + public: + inline socket_t(context_t& context_, int type_) + { + init(context_, type_); + } + + #ifdef ZMQ_CPP11 + inline socket_t(context_t& context_, socket_type type_) + { + init(context_, static_cast<int>(type_)); + } + #endif + +#ifdef ZMQ_HAS_RVALUE_REFS + inline socket_t(socket_t&& rhs) ZMQ_NOTHROW : + ptr(rhs.ptr), + ctxptr(rhs.ctxptr) + { + rhs.ptr = NULL; + rhs.ctxptr = NULL; + } + inline socket_t& operator=(socket_t&& rhs) ZMQ_NOTHROW + { + std::swap(ptr, rhs.ptr); + return *this; + } +#endif + + inline ~socket_t () ZMQ_NOTHROW + { + close(); + } + + inline operator void* () ZMQ_NOTHROW + { + return ptr; + } + + inline operator void const* () const ZMQ_NOTHROW + { + return ptr; + } + + inline void close() ZMQ_NOTHROW + { + if(ptr == NULL) + // already closed + return ; + int rc = zmq_close (ptr); + ZMQ_ASSERT (rc == 0); + ptr = 0 ; + } + + template<typename T> void setsockopt(int option_, T const& optval) + { + setsockopt(option_, &optval, sizeof(T) ); + } + + inline void setsockopt (int option_, const void *optval_, + size_t optvallen_) + { + int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_); + if (rc != 0) + throw error_t (); + } + + inline void getsockopt (int option_, void *optval_, + size_t *optvallen_) const + { + int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_); + if (rc != 0) + throw error_t (); + } + + template<typename T> T getsockopt(int option_) const + { + T optval; + size_t optlen = sizeof(T); + getsockopt(option_, &optval, &optlen ); + return optval; + } + + inline void bind(std::string const& addr) + { + bind(addr.c_str()); + } + + inline void bind (const char *addr_) + { + int rc = zmq_bind (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline void unbind(std::string const& addr) + { + unbind(addr.c_str()); + } + + inline void unbind (const char *addr_) + { + int rc = zmq_unbind (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline void connect(std::string const& addr) + { + connect(addr.c_str()); + } + + inline void connect (const char *addr_) + { + int rc = zmq_connect (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline void disconnect(std::string const& addr) + { + disconnect(addr.c_str()); + } + + inline void disconnect (const char *addr_) + { + int rc = zmq_disconnect (ptr, addr_); + if (rc != 0) + throw error_t (); + } + + inline bool connected() const ZMQ_NOTHROW + { + return(ptr != NULL); + } + + inline size_t send (const void *buf_, size_t len_, int flags_ = 0) + { + int nbytes = zmq_send (ptr, buf_, len_, flags_); + if (nbytes >= 0) + return (size_t) nbytes; + if (zmq_errno () == EAGAIN) + return 0; + if (zmq_errno () == EHOSTUNREACH) + return 0; + throw error_t (); + } + + inline bool send (message_t &msg_, int flags_ = 0) + { + int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno () == EAGAIN) + return false; + if (zmq_errno () == EHOSTUNREACH) + return false; + throw error_t (); + } + + template<typename I> bool send(I first, I last, int flags_=0) + { + zmq::message_t msg(first, last); + return send(msg, flags_); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + inline bool send (message_t &&msg_, int flags_ = 0) + { + return send(msg_, flags_); + } +#endif + + inline size_t recv (void *buf_, size_t len_, int flags_ = 0) + { + int nbytes = zmq_recv (ptr, buf_, len_, flags_); + if (nbytes >= 0) + return (size_t) nbytes; + if (zmq_errno () == EAGAIN) + return 0; + throw error_t (); + } + + inline bool recv (message_t *msg_, int flags_ = 0) + { + int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno () == EAGAIN) + return false; + throw error_t (); + } + + private: + inline void init(context_t& context_, int type_) + { + ctxptr = context_.ptr; + ptr = zmq_socket (context_.ptr, type_ ); + if (ptr == NULL) + throw error_t (); + } + + void *ptr; + void *ctxptr; + + socket_t (const socket_t&) ZMQ_DELETED_FUNCTION; + void operator = (const socket_t&) ZMQ_DELETED_FUNCTION; + }; + + class monitor_t + { + public: + monitor_t() : socketPtr(NULL), monitor_socket(NULL) {} + + virtual ~monitor_t() + { + if (socketPtr) + zmq_socket_monitor(socketPtr, NULL, 0); + + if (monitor_socket) + zmq_close (monitor_socket); + + } + + +#ifdef ZMQ_HAS_RVALUE_REFS + monitor_t(monitor_t&& rhs) ZMQ_NOTHROW : + socketPtr(rhs.socketPtr), + monitor_socket(rhs.monitor_socket) + { + rhs.socketPtr = NULL; + rhs.monitor_socket = NULL; + } + + socket_t& operator=(socket_t&& rhs) ZMQ_DELETED_FUNCTION ; +#endif + + + + void monitor(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) + { + monitor(socket, addr.c_str(), events); + } + + void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) + { + init (socket, addr_, events) ; + while(true) + { + check_event(-1) ; + } + } + + void init(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) + { + init(socket, addr.c_str(), events); + } + + void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) + { + int rc = zmq_socket_monitor(socket.ptr, addr_, events); + if (rc != 0) + throw error_t (); + + socketPtr = socket.ptr; + monitor_socket = zmq_socket (socket.ctxptr, ZMQ_PAIR); + assert (monitor_socket); + + rc = zmq_connect (monitor_socket, addr_); + assert (rc == 0); + + on_monitor_started(); + } + + bool check_event(int timeout = 0) + { + assert (monitor_socket); + + zmq_msg_t eventMsg; + zmq_msg_init (&eventMsg); + + zmq::pollitem_t items [] = { + { monitor_socket, 0, ZMQ_POLLIN, 0 }, + }; + + zmq::poll (&items [0], 1, timeout); + + if (items [0].revents & ZMQ_POLLIN) + { + int rc = zmq_msg_recv (&eventMsg, monitor_socket, 0); + if (rc == -1 && zmq_errno() == ETERM) + return false; + assert (rc != -1); + + } + else + { + zmq_msg_close (&eventMsg); + return false; + } + +#if ZMQ_VERSION_MAJOR >= 4 + const char* data = static_cast<const char*>(zmq_msg_data(&eventMsg)); + zmq_event_t msgEvent; + memcpy(&msgEvent.event, data, sizeof(uint16_t)); data += sizeof(uint16_t); + memcpy(&msgEvent.value, data, sizeof(int32_t)); + zmq_event_t* event = &msgEvent; +#else + zmq_event_t* event = static_cast<zmq_event_t*>(zmq_msg_data(&eventMsg)); +#endif + +#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT + zmq_msg_t addrMsg; + zmq_msg_init (&addrMsg); + int rc = zmq_msg_recv (&addrMsg, monitor_socket, 0); + if (rc == -1 && zmq_errno() == ETERM) + { + zmq_msg_close (&eventMsg); + return false; + } + + assert (rc != -1); + const char* str = static_cast<const char*>(zmq_msg_data (&addrMsg)); + std::string address(str, str + zmq_msg_size(&addrMsg)); + zmq_msg_close (&addrMsg); +#else + // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. + std::string address = event->data.connected.addr; +#endif + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + if (event->event == ZMQ_EVENT_MONITOR_STOPPED) + { + zmq_msg_close (&eventMsg); + return true; + } + +#endif + + switch (event->event) { + case ZMQ_EVENT_CONNECTED: + on_event_connected(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_DELAYED: + on_event_connect_delayed(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_RETRIED: + on_event_connect_retried(*event, address.c_str()); + break; + case ZMQ_EVENT_LISTENING: + on_event_listening(*event, address.c_str()); + break; + case ZMQ_EVENT_BIND_FAILED: + on_event_bind_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPTED: + on_event_accepted(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPT_FAILED: + on_event_accept_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSED: + on_event_closed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSE_FAILED: + on_event_close_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_DISCONNECTED: + on_event_disconnected(*event, address.c_str()); + break; +#ifdef ZMQ_BUILD_DRAFT_API + case ZMQ_EVENT_HANDSHAKE_FAILED: + on_event_handshake_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_SUCCEED: + on_event_handshake_succeed(*event, address.c_str()); + break; +#endif + default: + on_event_unknown(*event, address.c_str()); + break; + } + zmq_msg_close (&eventMsg); + + return true ; + } + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + void abort() + { + if (socketPtr) + zmq_socket_monitor(socketPtr, NULL, 0); + + if (monitor_socket) + zmq_close (monitor_socket); + + socketPtr = NULL; + monitor_socket = NULL; + } +#endif + virtual void on_monitor_started() {} + virtual void on_event_connected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_connect_delayed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_connect_retried(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_listening(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_bind_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_accepted(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_accept_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_closed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_close_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_disconnected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + virtual void on_event_handshake_failed(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } + virtual void on_event_handshake_succeed(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } + virtual void on_event_unknown(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } + private: + + monitor_t (const monitor_t&) ZMQ_DELETED_FUNCTION; + void operator = (const monitor_t&) ZMQ_DELETED_FUNCTION; + + void* socketPtr; + void *monitor_socket ; + }; + +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) + class poller_t + { + public: + poller_t () : poller_ptr (zmq_poller_new ()) + { + if (!poller_ptr) + throw error_t (); + } + + ~poller_t () + { + zmq_poller_destroy (&poller_ptr); + } + + bool add (zmq::socket_t &socket, short events, std::function<void(void)> &handler) + { + if (0 == zmq_poller_add (poller_ptr, socket.ptr, handler ? &handler : NULL, events)) { + poller_events.emplace_back (zmq_poller_event_t ()); + return true; + } + return false; + } + + bool remove (zmq::socket_t &socket) + { + if (0 == zmq_poller_remove (poller_ptr, socket.ptr)) { + poller_events.pop_back (); + return true; + } + return false; + } + + bool wait (std::chrono::milliseconds timeout) + { + int rc = zmq_poller_wait_all (poller_ptr, poller_events.data (), poller_events.size (), static_cast<long>(timeout.count ())); + if (rc >= 0) { + std::for_each (poller_events.begin (), poller_events.begin () + rc, [](zmq_poller_event_t& event) { + if (event.user_data != NULL) + (*reinterpret_cast<std::function<void(void)>*> (event.user_data)) (); + }); + return true; + } + + if (zmq_errno () == ETIMEDOUT) + return false; + + throw error_t (); + } + + private: + void *poller_ptr; + std::vector<zmq_poller_event_t> poller_events; + }; +#endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) + +} + +#endif diff --git a/include/pli_vis/third_party/cppzmq/zmq_addon.hpp b/include/pli_vis/third_party/cppzmq/zmq_addon.hpp new file mode 100644 index 0000000000000000000000000000000000000000..21accf0ce6c3b254c1b29e381b2920a68f4ea6e0 --- /dev/null +++ b/include/pli_vis/third_party/cppzmq/zmq_addon.hpp @@ -0,0 +1,590 @@ +/* + Copyright (c) 2016-2017 ZeroMQ community + Copyright (c) 2016 VOCA AS / Harald Nøkland + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#ifndef __ZMQ_ADDON_HPP_INCLUDED__ +#define __ZMQ_ADDON_HPP_INCLUDED__ + +#include <zmq.hpp> +#include <deque> +#include <iomanip> +#include <sstream> +#include <stdexcept> + +namespace zmq { + +#ifdef ZMQ_HAS_RVALUE_REFS + +/* + This class handles multipart messaging. It is the C++ equivalent of zmsg.h, + which is part of CZMQ (the high-level C binding). Furthermore, it is a major + improvement compared to zmsg.hpp, which is part of the examples in the ØMQ + Guide. Unnecessary copying is avoided by using move semantics to efficiently + add/remove parts. +*/ +class multipart_t +{ +private: + std::deque<message_t> m_parts; + +public: + + typedef std::deque<message_t>::iterator iterator; + typedef std::deque<message_t>::const_iterator const_iterator; + + typedef std::deque<message_t>::reverse_iterator reverse_iterator; + typedef std::deque<message_t>::const_reverse_iterator const_reverse_iterator; + + // Default constructor + multipart_t() + {} + + // Construct from socket receive + multipart_t(socket_t& socket) + { + recv(socket); + } + + // Construct from memory block + multipart_t(const void *src, size_t size) + { + addmem(src, size); + } + + // Construct from string + multipart_t(const std::string& string) + { + addstr(string); + } + + // Construct from message part + multipart_t(message_t&& message) + { + add(std::move(message)); + } + + // Move constructor + multipart_t(multipart_t&& other) + { + m_parts = std::move(other.m_parts); + } + + // Move assignment operator + multipart_t& operator=(multipart_t&& other) + { + m_parts = std::move(other.m_parts); + return *this; + } + + // Destructor + virtual ~multipart_t() + { + clear(); + } + + message_t& operator[] (size_t n) + { + return m_parts[n]; + } + + const message_t& operator[] (size_t n) const + { + return m_parts[n]; + } + + message_t& at (size_t n) + { + return m_parts.at(n); + } + + const message_t& at (size_t n) const + { + return m_parts.at(n); + } + + iterator begin() + { + return m_parts.begin(); + } + + const_iterator begin() const + { + return m_parts.begin(); + } + + const_iterator cbegin() const + { + return m_parts.cbegin(); + } + + reverse_iterator rbegin() + { + return m_parts.rbegin(); + } + + const_reverse_iterator rbegin() const + { + return m_parts.rbegin(); + } + + iterator end() + { + return m_parts.end(); + } + + const_iterator end() const + { + return m_parts.end(); + } + + const_iterator cend() const + { + return m_parts.cend(); + } + + reverse_iterator rend() + { + return m_parts.rend(); + } + + const_reverse_iterator rend() const + { + return m_parts.rend(); + } + + // Delete all parts + void clear() + { + m_parts.clear(); + } + + // Get number of parts + size_t size() const + { + return m_parts.size(); + } + + // Check if number of parts is zero + bool empty() const + { + return m_parts.empty(); + } + + // Receive multipart message from socket + bool recv(socket_t& socket, int flags = 0) + { + clear(); + bool more = true; + while (more) + { + message_t message; + if (!socket.recv(&message, flags)) + return false; + more = message.more(); + add(std::move(message)); + } + return true; + } + + // Send multipart message to socket + bool send(socket_t& socket, int flags = 0) + { + flags &= ~(ZMQ_SNDMORE); + bool more = size() > 0; + while (more) + { + message_t message = pop(); + more = size() > 0; + if (!socket.send(message, (more ? ZMQ_SNDMORE : 0) | flags)) + return false; + } + clear(); + return true; + } + + // Concatenate other multipart to front + void prepend(multipart_t&& other) + { + while (!other.empty()) + push(other.remove()); + } + + // Concatenate other multipart to back + void append(multipart_t&& other) + { + while (!other.empty()) + add(other.pop()); + } + + // Push memory block to front + void pushmem(const void *src, size_t size) + { + m_parts.push_front(message_t(src, size)); + } + + // Push memory block to back + void addmem(const void *src, size_t size) + { + m_parts.push_back(message_t(src, size)); + } + + // Push string to front + void pushstr(const std::string& string) + { + m_parts.push_front(message_t(string.data(), string.size())); + } + + // Push string to back + void addstr(const std::string& string) + { + m_parts.push_back(message_t(string.data(), string.size())); + } + + // Push type (fixed-size) to front + template<typename T> + void pushtyp(const T& type) + { + static_assert(!std::is_same<T, std::string>::value, "Use pushstr() instead of pushtyp<std::string>()"); + m_parts.push_front(message_t(&type, sizeof(type))); + } + + // Push type (fixed-size) to back + template<typename T> + void addtyp(const T& type) + { + static_assert(!std::is_same<T, std::string>::value, "Use addstr() instead of addtyp<std::string>()"); + m_parts.push_back(message_t(&type, sizeof(type))); + } + + // Push message part to front + void push(message_t&& message) + { + m_parts.push_front(std::move(message)); + } + + // Push message part to back + void add(message_t&& message) + { + m_parts.push_back(std::move(message)); + } + + // Pop string from front + std::string popstr() + { + std::string string(m_parts.front().data<char>(), m_parts.front().size()); + m_parts.pop_front(); + return string; + } + + // Pop type (fixed-size) from front + template<typename T> + T poptyp() + { + static_assert(!std::is_same<T, std::string>::value, "Use popstr() instead of poptyp<std::string>()"); + if (sizeof(T) != m_parts.front().size()) + throw std::runtime_error("Invalid type, size does not match the message size"); + T type = *m_parts.front().data<T>(); + m_parts.pop_front(); + return type; + } + + // Pop message part from front + message_t pop() + { + message_t message = std::move(m_parts.front()); + m_parts.pop_front(); + return message; + } + + // Pop message part from back + message_t remove() + { + message_t message = std::move(m_parts.back()); + m_parts.pop_back(); + return message; + } + + // Get pointer to a specific message part + const message_t* peek(size_t index) const + { + return &m_parts[index]; + } + + // Get a string copy of a specific message part + std::string peekstr(size_t index) const + { + std::string string(m_parts[index].data<char>(), m_parts[index].size()); + return string; + } + + // Peek type (fixed-size) from front + template<typename T> + T peektyp(size_t index) + { + static_assert(!std::is_same<T, std::string>::value, "Use peekstr() instead of peektyp<std::string>()"); + if(sizeof(T) != m_parts.front().size()) + throw std::runtime_error("Invalid type, size does not match the message size"); + T type = *m_parts[index].data<T>(); + } + + // Create multipart from type (fixed-size) + template<typename T> + static multipart_t create(const T& type) + { + multipart_t multipart; + multipart.addtyp(type); + return multipart; + } + + // Copy multipart + multipart_t clone() const + { + multipart_t multipart; + for (size_t i = 0; i < size(); i++) + multipart.addmem(m_parts[i].data(), m_parts[i].size()); + return multipart; + } + + // Dump content to string + std::string str() const + { + std::stringstream ss; + for (size_t i = 0; i < m_parts.size(); i++) + { + const unsigned char* data = m_parts[i].data<unsigned char>(); + size_t size = m_parts[i].size(); + + // Dump the message as text or binary + bool isText = true; + for (size_t j = 0; j < size; j++) + { + if (data[j] < 32 || data[j] > 127) + { + isText = false; + break; + } + } + ss << "\n[" << std::dec << std::setw(3) << std::setfill('0') << size << "] "; + if (size >= 1000) + { + ss << "... (to big to print)"; + continue; + } + for (size_t j = 0; j < size; j++) + { + if (isText) + ss << static_cast<char>(data[j]); + else + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<short>(data[j]); + } + } + return ss.str(); + } + + // Check if equal to other multipart + bool equal(const multipart_t* other) const + { + if (size() != other->size()) + return false; + for (size_t i = 0; i < size(); i++) + if (!peek(i)->equal(other->peek(i))) + return false; + return true; + } + + // Self test + static int test() + { + bool ok = true; (void) ok; + float num = 0; (void) num; + std::string str = ""; + message_t msg; + + // Create two PAIR sockets and connect over inproc + context_t context(1); + socket_t output(context, ZMQ_PAIR); + socket_t input(context, ZMQ_PAIR); + output.bind("inproc://multipart.test"); + input.connect("inproc://multipart.test"); + + // Test send and receive of single-frame message + multipart_t multipart; + assert(multipart.empty()); + + multipart.push(message_t("Hello", 5)); + assert(multipart.size() == 1); + + ok = multipart.send(output); + assert(multipart.empty()); + assert(ok); + + ok = multipart.recv(input); + assert(multipart.size() == 1); + assert(ok); + + msg = multipart.pop(); + assert(multipart.empty()); + assert(std::string(msg.data<char>(), msg.size()) == "Hello"); + + // Test send and receive of multi-frame message + multipart.addstr("A"); + multipart.addstr("BB"); + multipart.addstr("CCC"); + assert(multipart.size() == 3); + + multipart_t copy = multipart.clone(); + assert(copy.size() == 3); + + ok = copy.send(output); + assert(copy.empty()); + assert(ok); + + ok = copy.recv(input); + assert(copy.size() == 3); + assert(ok); + assert(copy.equal(&multipart)); + + multipart.clear(); + assert(multipart.empty()); + + // Test message frame manipulation + multipart.add(message_t("Frame5", 6)); + multipart.addstr("Frame6"); + multipart.addstr("Frame7"); + multipart.addtyp(8.0f); + multipart.addmem("Frame9", 6); + multipart.push(message_t("Frame4", 6)); + multipart.pushstr("Frame3"); + multipart.pushstr("Frame2"); + multipart.pushtyp(1.0f); + multipart.pushmem("Frame0", 6); + assert(multipart.size() == 10); + + msg = multipart.remove(); + assert(multipart.size() == 9); + assert(std::string(msg.data<char>(), msg.size()) == "Frame9"); + + msg = multipart.pop(); + assert(multipart.size() == 8); + assert(std::string(msg.data<char>(), msg.size()) == "Frame0"); + + num = multipart.poptyp<float>(); + assert(multipart.size() == 7); + assert(num == 1.0f); + + str = multipart.popstr(); + assert(multipart.size() == 6); + assert(str == "Frame2"); + + str = multipart.popstr(); + assert(multipart.size() == 5); + assert(str == "Frame3"); + + str = multipart.popstr(); + assert(multipart.size() == 4); + assert(str == "Frame4"); + + str = multipart.popstr(); + assert(multipart.size() == 3); + assert(str == "Frame5"); + + str = multipart.popstr(); + assert(multipart.size() == 2); + assert(str == "Frame6"); + + str = multipart.popstr(); + assert(multipart.size() == 1); + assert(str == "Frame7"); + + num = multipart.poptyp<float>(); + assert(multipart.empty()); + assert(num == 8.0f); + + // Test message constructors and concatenation + multipart_t head("One", 3); + head.addstr("Two"); + assert(head.size() == 2); + + multipart_t tail("One-hundred"); + tail.pushstr("Ninety-nine"); + assert(tail.size() == 2); + + multipart_t tmp(message_t("Fifty", 5)); + assert(tmp.size() == 1); + + multipart_t mid = multipart_t::create(49.0f); + mid.append(std::move(tmp)); + assert(mid.size() == 2); + assert(tmp.empty()); + + multipart_t merged(std::move(mid)); + merged.prepend(std::move(head)); + merged.append(std::move(tail)); + assert(merged.size() == 6); + assert(head.empty()); + assert(tail.empty()); + + ok = merged.send(output); + assert(merged.empty()); + assert(ok); + + multipart_t received(input); + assert(received.size() == 6); + + str = received.popstr(); + assert(received.size() == 5); + assert(str == "One"); + + str = received.popstr(); + assert(received.size() == 4); + assert(str == "Two"); + + num = received.poptyp<float>(); + assert(received.size() == 3); + assert(num == 49.0f); + + str = received.popstr(); + assert(received.size() == 2); + assert(str == "Fifty"); + + str = received.popstr(); + assert(received.size() == 1); + assert(str == "Ninety-nine"); + + str = received.popstr(); + assert(received.empty()); + assert(str == "One-hundred"); + + return 0; + } + +private: + // Disable implicit copying (moving is more efficient) + multipart_t(const multipart_t& other) ZMQ_DELETED_FUNCTION; + void operator=(const multipart_t& other) ZMQ_DELETED_FUNCTION; +}; + +#endif + +} + +#endif diff --git a/include/pli_vis/third_party/json/json.hpp b/include/pli_vis/third_party/json/json.hpp new file mode 100644 index 0000000000000000000000000000000000000000..729decf6109298faf61410ebe4efe130556ccc9f --- /dev/null +++ b/include/pli_vis/third_party/json/json.hpp @@ -0,0 +1,18490 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.1.2 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License <http://opensource.org/licenses/MIT>. +SPDX-License-Identifier: MIT +Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef NLOHMANN_JSON_HPP +#define NLOHMANN_JSON_HPP + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 1 +#define NLOHMANN_JSON_VERSION_PATCH 2 + +#include <algorithm> // all_of, find, for_each +#include <cassert> // assert +#include <ciso646> // and, not, or +#include <cstddef> // nullptr_t, ptrdiff_t, size_t +#include <functional> // hash, less +#include <initializer_list> // initializer_list +#include <iosfwd> // istream, ostream +#include <iterator> // iterator_traits, random_access_iterator_tag +#include <numeric> // accumulate +#include <string> // string, stoi, to_string +#include <utility> // declval, forward, move, pair, swap + +// #include <nlohmann/json_fwd.hpp> +#ifndef NLOHMANN_JSON_FWD_HPP +#define NLOHMANN_JSON_FWD_HPP + +#include <cstdint> // int64_t, uint64_t +#include <map> // map +#include <memory> // allocator +#include <string> // string +#include <vector> // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template<typename T = void, typename SFINAE = void> +struct adl_serializer; + +template<template<typename U, typename V, typename... Args> class ObjectType = + std::map, + template<typename U, typename... Args> class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template<typename U> class AllocatorType = std::allocator, + template<typename T, typename SFINAE = void> class JSONSerializer = + adl_serializer> +class basic_json; + +/*! +@brief JSON Pointer + +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + +@since version 2.0.0 +*/ +template<typename BasicJsonType> +class json_pointer; + +/*! +@brief default JSON class + +This type is the default specialization of the @ref basic_json class which +uses the standard template types. + +@since version 1.0.0 +*/ +using json = basic_json<>; +} + +#endif + +// #include <nlohmann/detail/macro_scope.hpp> + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif +#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow for portable deprecation warnings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define JSON_DEPRECATED __declspec(deprecated) +#else + #define JSON_DEPRECATED +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) +#else + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER +#endif + +// manual branch prediction +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_LIKELY(x) __builtin_expect(!!(x), 1) + #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + #define JSON_LIKELY(x) x + #define JSON_UNLIKELY(x) x +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template<template<typename, typename, typename...> class ObjectType, \ + template<typename, typename...> class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template<typename> class AllocatorType, \ + template<typename, typename = void> class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json<ObjectType, ArrayType, StringType, BooleanType, \ + NumberIntegerType, NumberUnsignedType, NumberFloatType, \ + AllocatorType, JSONSerializer> + +/*! +@brief Helper to determine whether there's a key_type for T. + +This helper is used to tell associative containers apart from other containers +such as sequence containers. For instance, `std::map` passes the test as it +contains a `mapped_type`, whereas `std::vector` fails the test. + +@sa http://stackoverflow.com/a/7728728/266378 +@since version 1.0.0, overworked in version 2.0.6 +*/ +#define NLOHMANN_JSON_HAS_HELPER(type) \ + template<typename T> struct has_##type { \ + private: \ + template<typename U, typename = typename U::type> \ + static int detect(U &&); \ + static void detect(...); \ + public: \ + static constexpr bool value = \ + std::is_integral<decltype(detect(std::declval<T>()))>::value; \ + } + +// #include <nlohmann/detail/meta.hpp> + + +#include <ciso646> // not +#include <cstddef> // size_t +#include <limits> // numeric_limits +#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include <utility> // declval + +// #include <nlohmann/json_fwd.hpp> + +// #include <nlohmann/detail/macro_scope.hpp> + + +namespace nlohmann +{ +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ +///////////// +// helpers // +///////////// + +template<typename> struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; + +// alias templates to reduce boilerplate +template<bool B, typename T = void> +using enable_if_t = typename std::enable_if<B, T>::type; + +template<typename T> +using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template<std::size_t... Ints> +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template<class Sequence1, class Sequence2> +struct merge_and_renumber; + +template<std::size_t... I1, std::size_t... I2> +struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template<std::size_t N> +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template<typename... Ts> +using index_sequence_for = make_index_sequence<sizeof...(Ts)>; + +/* +Implementation of two C++17 constructs: conjunction, negation. This is needed +to avoid evaluating all the traits in a condition + +For example: not std::is_same<void, T>::value and has_value_type<T>::value +will not compile when T = void (on MSVC at least). Whereas +conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will +stop evaluating if negation<...>::value == false + +Please note that those constructs must be used with caution, since symbols can +become very long quickly (which can slow down compilation and cause MSVC +internal compiler errors). Only use it when you have to (see example ahead). +*/ +template<class...> struct conjunction : std::true_type {}; +template<class B1> struct conjunction<B1> : B1 {}; +template<class B1, class... Bn> +struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {}; + +template<class B> struct negation : std::integral_constant<bool, not B::value> {}; + +// dispatch utility (taken from ranges-v3) +template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +//////////////////////// +// has_/is_ functions // +//////////////////////// + +// source: https://stackoverflow.com/a/37193089/4116453 + +template <typename T, typename = void> +struct is_complete_type : std::false_type {}; + +template <typename T> +struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {}; + +NLOHMANN_JSON_HAS_HELPER(mapped_type); +NLOHMANN_JSON_HAS_HELPER(key_type); +NLOHMANN_JSON_HAS_HELPER(value_type); +NLOHMANN_JSON_HAS_HELPER(iterator); + +template<bool B, class RealType, class CompatibleObjectType> +struct is_compatible_object_type_impl : std::false_type {}; + +template<class RealType, class CompatibleObjectType> +struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType> +{ + static constexpr auto value = + std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and + std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value; +}; + +template<class BasicJsonType, class CompatibleObjectType> +struct is_compatible_object_type +{ + static auto constexpr value = is_compatible_object_type_impl < + conjunction<negation<std::is_same<void, CompatibleObjectType>>, + has_mapped_type<CompatibleObjectType>, + has_key_type<CompatibleObjectType>>::value, + typename BasicJsonType::object_t, CompatibleObjectType >::value; +}; + +template<typename BasicJsonType, typename T> +struct is_basic_json_nested_type +{ + static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or + std::is_same<T, typename BasicJsonType::const_iterator>::value or + std::is_same<T, typename BasicJsonType::reverse_iterator>::value or + std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value; +}; + +template<class BasicJsonType, class CompatibleArrayType> +struct is_compatible_array_type +{ + static auto constexpr value = + conjunction<negation<std::is_same<void, CompatibleArrayType>>, + negation<is_compatible_object_type< + BasicJsonType, CompatibleArrayType>>, + negation<std::is_constructible<typename BasicJsonType::string_t, + CompatibleArrayType>>, + negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>, + has_value_type<CompatibleArrayType>, + has_iterator<CompatibleArrayType>>::value; +}; + +template<bool, typename, typename> +struct is_compatible_integer_type_impl : std::false_type {}; + +template<typename RealIntegerType, typename CompatibleNumberIntegerType> +struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits<RealIntegerType>; + using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; + + static constexpr auto value = + std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and + CompatibleLimits::is_integer and + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template<typename RealIntegerType, typename CompatibleNumberIntegerType> +struct is_compatible_integer_type +{ + static constexpr auto value = + is_compatible_integer_type_impl < + std::is_integral<CompatibleNumberIntegerType>::value and + not std::is_same<bool, CompatibleNumberIntegerType>::value, + RealIntegerType, CompatibleNumberIntegerType > ::value; +}; + +// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists +template<typename BasicJsonType, typename T> +struct has_from_json +{ + private: + // also check the return type of from_json + template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json( + std::declval<BasicJsonType>(), std::declval<T&>()))>::value>> + static int detect(U&&); + static void detect(...); + + public: + static constexpr bool value = std::is_integral<decltype( + detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value; +}; + +// This trait checks if JSONSerializer<T>::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template<typename BasicJsonType, typename T> +struct has_non_default_from_json +{ + private: + template < + typename U, + typename = enable_if_t<std::is_same< + T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >> + static int detect(U&&); + static void detect(...); + + public: + static constexpr bool value = std::is_integral<decltype(detect( + std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value; +}; + +// This trait checks if BasicJsonType::json_serializer<T>::to_json exists +template<typename BasicJsonType, typename T> +struct has_to_json +{ + private: + template<typename U, typename = decltype(uncvref_t<U>::to_json( + std::declval<BasicJsonType&>(), std::declval<T>()))> + static int detect(U&&); + static void detect(...); + + public: + static constexpr bool value = std::is_integral<decltype(detect( + std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value; +}; + +template <typename BasicJsonType, typename CompatibleCompleteType> +struct is_compatible_complete_type +{ + static constexpr bool value = + not std::is_base_of<std::istream, CompatibleCompleteType>::value and + not is_basic_json<CompatibleCompleteType>::value and + not is_basic_json_nested_type<BasicJsonType, CompatibleCompleteType>::value and + has_to_json<BasicJsonType, CompatibleCompleteType>::value; +}; + +template <typename BasicJsonType, typename CompatibleType> +struct is_compatible_type + : conjunction<is_complete_type<CompatibleType>, + is_compatible_complete_type<BasicJsonType, CompatibleType>> +{ +}; + +// taken from ranges-v3 +template<typename T> +struct static_const +{ + static constexpr T value{}; +}; + +template<typename T> +constexpr T static_const<T>::value; +} +} + +// #include <nlohmann/detail/exceptions.hpp> + + +#include <exception> // exception +#include <stdexcept> // runtime_error +#include <string> // to_string + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa @ref exception for the base class of the library exceptions +@sa @ref invalid_iterator for exceptions indicating errors with iterators +@sa @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa @ref out_of_range for exceptions indicating access out of the defined range +@sa @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] byte_ the byte index where the error occurred (or 0 if the + position cannot be determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa @ref exception for the base class of the library exceptions +@sa @ref parse_error for exceptions indicating a parse error +@sa @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa @ref out_of_range for exceptions indicating access out of the defined range +@sa @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa @ref exception for the base class of the library exceptions +@sa @ref parse_error for exceptions indicating a parse error +@sa @ref invalid_iterator for exceptions indicating errors with iterators +@sa @ref out_of_range for exceptions indicating access out of the defined range +@sa @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa @ref exception for the base class of the library exceptions +@sa @ref parse_error for exceptions indicating a parse error +@sa @ref invalid_iterator for exceptions indicating errors with iterators +@sa @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa @ref exception for the base class of the library exceptions +@sa @ref parse_error for exceptions indicating a parse error +@sa @ref invalid_iterator for exceptions indicating errors with iterators +@sa @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} +} + +// #include <nlohmann/detail/value_t.hpp> + + +#include <array> // array +#include <ciso646> // and +#include <cstddef> // size_t +#include <cstdint> // uint8_t + +namespace nlohmann +{ +namespace detail +{ +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + discarded ///< discarded by the the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string +- furthermore, each type is not smaller than itself +- discarded values are not comparable + +@since version 1.0.0 +*/ +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + static constexpr std::array<std::uint8_t, 8> order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */ + } + }; + + const auto l_index = static_cast<std::size_t>(lhs); + const auto r_index = static_cast<std::size_t>(rhs); + return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index]; +} +} +} + +// #include <nlohmann/detail/conversions/from_json.hpp> + + +#include <algorithm> // transform +#include <array> // array +#include <ciso646> // and, not +#include <forward_list> // forward_list +#include <iterator> // inserter, front_inserter, end +#include <map> // map +#include <string> // string +#include <tuple> // tuple, make_tuple +#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include <utility> // pair, declval +#include <valarray> // valarray + +// #include <nlohmann/detail/exceptions.hpp> + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/meta.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +// overloads for basic_json template parameters +template<typename BasicJsonType, typename ArithmeticType, + enable_if_t<std::is_arithmetic<ArithmeticType>::value and + not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, + int> = 0> +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast<value_t>(j)) + { + case value_t::number_unsigned: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); + break; + } + case value_t::number_integer: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); + break; + } + case value_t::number_float: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } +} + +template<typename BasicJsonType> +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_UNLIKELY(not j.is_boolean())) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); + } + b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); +} + +template<typename BasicJsonType> +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); +} + +template<typename BasicJsonType> +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template<typename BasicJsonType> +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template<typename BasicJsonType> +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +template<typename BasicJsonType, typename EnumType, + enable_if_t<std::is_enum<EnumType>::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type<EnumType>::type val; + get_arithmetic_value(j, val); + e = static_cast<EnumType>(val); +} + +template<typename BasicJsonType> +void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); +} + +// forward_list doesn't have an insert method +template<typename BasicJsonType, typename T, typename Allocator, + enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get<T>(); + }); +} + +// valarray doesn't have an insert method +template<typename BasicJsonType, typename T, + enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0> +void from_json(const BasicJsonType& j, std::valarray<T>& l) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + l.resize(j.size()); + std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); +} + +template<typename BasicJsonType, typename CompatibleArrayType> +void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) +{ + using std::end; + + std::transform(j.begin(), j.end(), + std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get<BasicJsonType>() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get<typename CompatibleArrayType::value_type>(); + }); +} + +template<typename BasicJsonType, typename CompatibleArrayType> +auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval<typename CompatibleArrayType::size_type>()), + void()) +{ + using std::end; + + arr.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(arr, end(arr)), [](const BasicJsonType & i) + { + // get<BasicJsonType>() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get<typename CompatibleArrayType::value_type>(); + }); +} + +template<typename BasicJsonType, typename T, std::size_t N> +void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get<T>(); + } +} + +template < + typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < + is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and + not std::is_same<typename BasicJsonType::array_t, + CompatibleArrayType>::value and + std::is_constructible < + BasicJsonType, typename CompatibleArrayType::value_type >::value, + int > = 0 > +void from_json(const BasicJsonType& j, CompatibleArrayType& arr) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + + std::string(j.type_name()))); + } + + from_json_array_impl(j, arr, priority_tag<2> {}); +} + +template<typename BasicJsonType, typename CompatibleObjectType, + enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0> +void from_json(const BasicJsonType& j, CompatibleObjectType& obj) +{ + if (JSON_UNLIKELY(not j.is_object())) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); + } + + auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); + using value_type = typename CompatibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(obj, obj.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>()); + }); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template<typename BasicJsonType, typename ArithmeticType, + enable_if_t < + std::is_arithmetic<ArithmeticType>::value and + not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and + not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and + not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and + not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, + int> = 0> +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast<value_t>(j)) + { + case value_t::number_unsigned: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); + break; + } + case value_t::number_integer: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); + break; + } + case value_t::number_float: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); + break; + } + case value_t::boolean: + { + val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } +} + +template<typename BasicJsonType, typename A1, typename A2> +void from_json(const BasicJsonType& j, std::pair<A1, A2>& p) +{ + p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()}; +} + +template<typename BasicJsonType, typename Tuple, std::size_t... Idx> +void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>) +{ + t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...); +} + +template<typename BasicJsonType, typename... Args> +void from_json(const BasicJsonType& j, std::tuple<Args...>& t) +{ + from_json_tuple_impl(j, t, index_sequence_for<Args...> {}); +} + +template <typename BasicJsonType, typename Key, typename Value, + typename = enable_if_t<not std::is_constructible< + typename BasicJsonType::string_t, Key>::value>> +void from_json(const BasicJsonType& j, std::map<Key, Value>& m) +{ + if (JSON_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + for (const auto& p : j) + { + if (JSON_UNLIKELY(not p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); + } +} + +struct from_json_fn +{ + private: + template<typename BasicJsonType, typename T> + auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const + noexcept(noexcept(from_json(j, val))) + -> decltype(from_json(j, val), void()) + { + return from_json(j, val); + } + + template<typename BasicJsonType, typename T> + void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept + { + static_assert(sizeof(BasicJsonType) == 0, + "could not find from_json() method in T's namespace"); +#ifdef _MSC_VER + // MSVC does not show a stacktrace for the above assert + using decayed = uncvref_t<T>; + static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, + "forcing MSVC stacktrace to show which T we're talking about."); +#endif + } + + public: + template<typename BasicJsonType, typename T> + void operator()(const BasicJsonType& j, T& val) const + noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {}))) + { + return call(j, val, priority_tag<1> {}); + } +}; +} + +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace +{ +constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; +} +} + +// #include <nlohmann/detail/conversions/to_json.hpp> + + +#include <ciso646> // or, and, not +#include <iterator> // begin, end +#include <tuple> // tuple, get +#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include <utility> // move, forward, declval, pair +#include <valarray> // valarray +#include <vector> // vector + +// #include <nlohmann/detail/meta.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +////////////////// +// constructors // +////////////////// + +template<value_t> struct external_constructor; + +template<> +struct external_constructor<value_t::boolean> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor<value_t::string> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } + + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor<value_t::number_float> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor<value_t::number_unsigned> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor<value_t::number_integer> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor<value_t::array> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_type = value_t::array; + j.m_value = arr; + j.assert_invariant(); + } + + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.assert_invariant(); + } + + template<typename BasicJsonType, typename CompatibleArrayType, + enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + j.m_type = value_t::array; + j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); + j.assert_invariant(); + } + + template<typename BasicJsonType> + static void construct(BasicJsonType& j, const std::vector<bool>& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } + + template<typename BasicJsonType, typename T, + enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray<T>& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor<value_t::object> +{ + template<typename BasicJsonType> + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_type = value_t::object; + j.m_value = obj; + j.assert_invariant(); + } + + template<typename BasicJsonType> + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.assert_invariant(); + } + + template<typename BasicJsonType, typename CompatibleObjectType, + enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0> + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_type = value_t::object; + j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template<typename BasicJsonType, typename T, + enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor<value_t::boolean>::construct(j, b); +} + +template<typename BasicJsonType, typename CompatibleString, + enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor<value_t::string>::construct(j, s); +} + +template<typename BasicJsonType> +void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor<value_t::string>::construct(j, std::move(s)); +} + +template<typename BasicJsonType, typename FloatType, + enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); +} + +template<typename BasicJsonType, typename CompatibleNumberUnsignedType, + enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); +} + +template<typename BasicJsonType, typename CompatibleNumberIntegerType, + enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); +} + +template<typename BasicJsonType, typename EnumType, + enable_if_t<std::is_enum<EnumType>::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type<EnumType>::type; + external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); +} + +template<typename BasicJsonType> +void to_json(BasicJsonType& j, const std::vector<bool>& e) +{ + external_constructor<value_t::array>::construct(j, e); +} + +template<typename BasicJsonType, typename CompatibleArrayType, + enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or + std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, + int> = 0> +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor<value_t::array>::construct(j, arr); +} + +template<typename BasicJsonType, typename T, + enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> +void to_json(BasicJsonType& j, std::valarray<T> arr) +{ + external_constructor<value_t::array>::construct(j, std::move(arr)); +} + +template<typename BasicJsonType> +void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor<value_t::array>::construct(j, std::move(arr)); +} + +template<typename BasicJsonType, typename CompatibleObjectType, + enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor<value_t::object>::construct(j, obj); +} + +template<typename BasicJsonType> +void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor<value_t::object>::construct(j, std::move(obj)); +} + +template<typename BasicJsonType, typename T, std::size_t N, + enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0> +void to_json(BasicJsonType& j, T (&arr)[N]) +{ + external_constructor<value_t::array>::construct(j, arr); +} + +template<typename BasicJsonType, typename... Args> +void to_json(BasicJsonType& j, const std::pair<Args...>& p) +{ + j = {p.first, p.second}; +} + +template<typename BasicJsonType, typename Tuple, std::size_t... Idx> +void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>) +{ + j = {std::get<Idx>(t)...}; +} + +template<typename BasicJsonType, typename... Args> +void to_json(BasicJsonType& j, const std::tuple<Args...>& t) +{ + to_json_tuple_impl(j, t, index_sequence_for<Args...> {}); +} + +struct to_json_fn +{ + private: + template<typename BasicJsonType, typename T> + auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) + -> decltype(to_json(j, std::forward<T>(val)), void()) + { + return to_json(j, std::forward<T>(val)); + } + + template<typename BasicJsonType, typename T> + void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept + { + static_assert(sizeof(BasicJsonType) == 0, + "could not find to_json() method in T's namespace"); + +#ifdef _MSC_VER + // MSVC does not show a stacktrace for the above assert + using decayed = uncvref_t<T>; + static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, + "forcing MSVC stacktrace to show which T we're talking about."); +#endif + } + + public: + template<typename BasicJsonType, typename T> + void operator()(BasicJsonType& j, T&& val) const + noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {}))) + { + return call(j, std::forward<T>(val), priority_tag<1> {}); + } +}; +} + +/// namespace to hold default `to_json` function +namespace +{ +constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; +} +} + +// #include <nlohmann/detail/input/input_adapters.hpp> + + +#include <cassert> // assert +#include <cstddef> // size_t +#include <cstring> // strlen +#include <istream> // istream +#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include <memory> // shared_ptr, make_shared, addressof +#include <numeric> // accumulate +#include <string> // string, char_traits +#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include <utility> // pair, declval + +// #include <nlohmann/detail/macro_scope.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson }; + +//////////////////// +// input adapters // +//////////////////// + +/*! +@brief abstract input adapter interface + +Produces a stream of std::char_traits<char>::int_type characters from a +std::istream, a buffer, or some other input type. Accepts the return of +exactly one non-EOF character for future input. The int_type characters +returned consist of all valid char values as positive values (typically +unsigned char), plus an EOF value outside that range, specified by the value +of the function std::char_traits<char>::eof(). This value is typically -1, but +could be any arbitrary value which is not a valid char value. +*/ +struct input_adapter_protocol +{ + /// get a character [0,255] or std::char_traits<char>::eof(). + virtual std::char_traits<char>::int_type get_character() = 0; + virtual ~input_adapter_protocol() = default; +}; + +/// a type to simplify interfaces +using input_adapter_t = std::shared_ptr<input_adapter_protocol>; + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter : public input_adapter_protocol +{ + public: + ~input_stream_adapter() override + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags + is.clear(); + } + + explicit input_stream_adapter(std::istream& i) + : is(i), sb(*i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + + // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to + // ensure that std::char_traits<char>::eof() and the character 0xFF do not + // end up as the same value, eg. 0xFFFFFFFF. + std::char_traits<char>::int_type get_character() override + { + return sb.sbumpc(); + } + + private: + /// the associated input stream + std::istream& is; + std::streambuf& sb; +}; + +/// input adapter for buffer input +class input_buffer_adapter : public input_adapter_protocol +{ + public: + input_buffer_adapter(const char* b, const std::size_t l) + : cursor(b), limit(b + l) + {} + + // delete because of pointer members + input_buffer_adapter(const input_buffer_adapter&) = delete; + input_buffer_adapter& operator=(input_buffer_adapter&) = delete; + + std::char_traits<char>::int_type get_character() noexcept override + { + if (JSON_LIKELY(cursor < limit)) + { + return std::char_traits<char>::to_int_type(*(cursor++)); + } + + return std::char_traits<char>::eof(); + } + + private: + /// pointer to the current character + const char* cursor; + /// pointer past the last character + const char* const limit; +}; + +template<typename WideStringType> +class wide_string_input_adapter : public input_adapter_protocol +{ + public: + wide_string_input_adapter(const WideStringType& w) : str(w) {} + + std::char_traits<char>::int_type get_character() noexcept override + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + if (sizeof(typename WideStringType::value_type) == 2) + { + fill_buffer_utf16(); + } + else + { + fill_buffer_utf32(); + } + + assert(utf8_bytes_filled > 0); + assert(utf8_bytes_index == 0); + } + + // use buffer + assert(utf8_bytes_filled > 0); + assert(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + void fill_buffer_utf16() + { + utf8_bytes_index = 0; + + if (current_wchar == str.size()) + { + utf8_bytes[0] = std::char_traits<char>::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const int wc = static_cast<int>(str[current_wchar++]); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = wc; + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = 0xC0 | ((wc >> 6)); + utf8_bytes[1] = 0x80 | (wc & 0x3F); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc or wc >= 0xE000) + { + utf8_bytes[0] = 0xE0 | ((wc >> 12)); + utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F); + utf8_bytes[2] = 0x80 | (wc & 0x3F); + utf8_bytes_filled = 3; + } + else + { + if (current_wchar < str.size()) + { + const int wc2 = static_cast<int>(str[current_wchar++]); + const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF)); + utf8_bytes[0] = 0xf0 | (charcode >> 18); + utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F); + utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F); + utf8_bytes[3] = 0x80 | (charcode & 0x3F); + utf8_bytes_filled = 4; + } + else + { + // unknown character + ++current_wchar; + utf8_bytes[0] = wc; + utf8_bytes_filled = 1; + } + } + } + } + + void fill_buffer_utf32() + { + utf8_bytes_index = 0; + + if (current_wchar == str.size()) + { + utf8_bytes[0] = std::char_traits<char>::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const int wc = static_cast<int>(str[current_wchar++]); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = wc; + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F); + utf8_bytes[1] = 0x80 | (wc & 0x3F); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F); + utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F); + utf8_bytes[2] = 0x80 | (wc & 0x3F); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07); + utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F); + utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F); + utf8_bytes[3] = 0x80 | (wc & 0x3F); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = wc; + utf8_bytes_filled = 1; + } + } + } + + private: + /// the wstring to process + const WideStringType& str; + + /// index of the current wchar in str + std::size_t current_wchar = 0; + + /// a buffer for UTF-8 bytes + std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + +class input_adapter +{ + public: + // native support + + /// input adapter for input stream + input_adapter(std::istream& i) + : ia(std::make_shared<input_stream_adapter>(i)) {} + + /// input adapter for input stream + input_adapter(std::istream&& i) + : ia(std::make_shared<input_stream_adapter>(i)) {} + + input_adapter(const std::wstring& ws) + : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {} + + input_adapter(const std::u16string& ws) + : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {} + + input_adapter(const std::u32string& ws) + : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {} + + /// input adapter for buffer + template<typename CharT, + typename std::enable_if< + std::is_pointer<CharT>::value and + std::is_integral<typename std::remove_pointer<CharT>::type>::value and + sizeof(typename std::remove_pointer<CharT>::type) == 1, + int>::type = 0> + input_adapter(CharT b, std::size_t l) + : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {} + + // derived support + + /// input adapter for string literal + template<typename CharT, + typename std::enable_if< + std::is_pointer<CharT>::value and + std::is_integral<typename std::remove_pointer<CharT>::type>::value and + sizeof(typename std::remove_pointer<CharT>::type) == 1, + int>::type = 0> + input_adapter(CharT b) + : input_adapter(reinterpret_cast<const char*>(b), + std::strlen(reinterpret_cast<const char*>(b))) {} + + /// input adapter for iterator range with contiguous storage + template<class IteratorType, + typename std::enable_if< + std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + input_adapter(IteratorType first, IteratorType last) + { + // assertion to check that the iterator range is indeed contiguous, + // see http://stackoverflow.com/a/35008842/266378 for more discussion + assert(std::accumulate( + first, last, std::pair<bool, int>(true, 0), + [&first](std::pair<bool, int> res, decltype(*first) val) + { + res.first &= (val == *(std::next(std::addressof(*first), res.second++))); + return res; + }).first); + + // assertion to check that each element is 1 byte long + static_assert( + sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1, + "each element in the iterator range must have the size of 1 byte"); + + const auto len = static_cast<size_t>(std::distance(first, last)); + if (JSON_LIKELY(len > 0)) + { + // there is at least one element: use the address of first + ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len); + } + else + { + // the address of first cannot be used: use nullptr + ia = std::make_shared<input_buffer_adapter>(nullptr, len); + } + } + + /// input adapter for array + template<class T, std::size_t N> + input_adapter(T (&array)[N]) + : input_adapter(std::begin(array), std::end(array)) {} + + /// input adapter for contiguous container + template<class ContiguousContainer, typename + std::enable_if<not std::is_pointer<ContiguousContainer>::value and + std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value, + int>::type = 0> + input_adapter(const ContiguousContainer& c) + : input_adapter(std::begin(c), std::end(c)) {} + + operator input_adapter_t() + { + return ia; + } + + private: + /// the actual adapter + input_adapter_t ia = nullptr; +}; +} +} + +// #include <nlohmann/detail/input/lexer.hpp> + + +#include <clocale> // localeconv +#include <cstddef> // size_t +#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull +#include <initializer_list> // initializer_list +#include <ios> // hex, uppercase +#include <iomanip> // setw, setfill +#include <sstream> // stringstream +#include <string> // char_traits, string +#include <vector> // vector + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/input/input_adapters.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/////////// +// lexer // +/////////// + +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template<typename BasicJsonType> +class lexer +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return "<uninitialized>"; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return "<parse error>"; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + default: // catch non-enum values + return "unknown token"; // LCOV_EXCL_LINE + } + } + + explicit lexer(detail::input_adapter_t&& adapter) + : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer& operator=(lexer&) = delete; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + static char get_decimal_point() noexcept + { + const auto loc = localeconv(); + assert(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + assert(current == 'u'); + int codepoint = 0; + + const auto factors = { 12, 8, 4, 0 }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' and current <= '9') + { + codepoint += ((current - 0x30) << factor); + } + else if (current >= 'A' and current <= 'F') + { + codepoint += ((current - 0x37) << factor); + } + else if (current >= 'a' and current <= 'f') + { + codepoint += ((current - 0x57) << factor); + } + else + { + return -1; + } + } + + assert(0x0000 <= codepoint and codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list<int> ranges) + { + assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_LIKELY(*range <= current and current <= *(++range))) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 7159. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + assert(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case std::char_traits<char>::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_LIKELY(get() == '\\' and get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = + // high surrogate occupies the most significant 22 bits + (codepoint1 << 10) + // low surrogate occupies the least significant 15 bits + + codepoint2 + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00; + } + else + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + assert(0x00 <= codepoint and codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(codepoint); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(0xC0 | (codepoint >> 6)); + add(0x80 | (codepoint & 0x3F)); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(0xE0 | (codepoint >> 12)); + add(0x80 | ((codepoint >> 6) & 0x3F)); + add(0x80 | (codepoint & 0x3F)); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(0xF0 | (codepoint >> 18)); + add(0x80 | ((codepoint >> 12) & 0x3F)); + add(0x80 | ((codepoint >> 6) & 0x3F)); + add(0x80 | (codepoint & 0x3F)); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + { + error_message = "invalid string: control character must be escaped"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 7159. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 7159. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + // all other characters are rejected outside scan_number() + assert(false); // LCOV_EXCL_LINE + } + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast<number_unsigned_t>(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast<number_integer_t>(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + token_type scan_literal(const char* literal_text, const std::size_t length, + token_type return_type) + { + assert(current == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_UNLIKELY(get() != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits<char>::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `std::char_traits<char>::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + std::char_traits<char>::int_type get() + { + ++chars_read; + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia->get_character(); + } + + if (JSON_LIKELY(current != std::char_traits<char>::eof())) + { + token_string.push_back(std::char_traits<char>::to_char_type(current)); + } + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read and + token_string. The next call to get() will behave as if the unget character + is read again. + */ + void unget() + { + next_unget = true; + --chars_read; + if (JSON_LIKELY(current != std::char_traits<char>::eof())) + { + assert(token_string.size() != 0); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(int c) + { + token_buffer.push_back(std::char_traits<char>::to_char_type(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr std::size_t get_position() const noexcept + { + return chars_read; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if ('\x00' <= c and c <= '\x1F') + { + // escape control characters + std::stringstream ss; + ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0') + << std::hex << static_cast<int>(c) << ">"; + result += ss.str(); + } + else + { + // add character as is + result.push_back(c); + } + } + + return result; + } + + /// return syntax error message + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + if (get() == 0xBB and get() == 0xBF) + { + // we completely parsed the BOM + return true; + } + else + { + // after reading 0xEF, an unexpected character followed + return false; + } + } + else + { + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + } + + token_type scan() + { + // initially, skip the BOM + if (chars_read == 0 and not skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + do + { + get(); + } + while (current == ' ' or current == '\t' or current == '\n' or current == '\r'); + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + return scan_literal("true", 4, token_type::literal_true); + case 'f': + return scan_literal("false", 5, token_type::literal_false); + case 'n': + return scan_literal("null", 4, token_type::literal_null); + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits<char>::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + detail::input_adapter_t ia = nullptr; + + /// the current character + std::char_traits<char>::int_type current = std::char_traits<char>::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the number of characters read + std::size_t chars_read = 0; + + /// raw input token string (for error messages) + std::vector<char> token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char decimal_point_char = '.'; +}; +} +} + +// #include <nlohmann/detail/input/parser.hpp> + + +#include <cassert> // assert +#include <cmath> // isfinite +#include <cstdint> // uint8_t +#include <functional> // function +#include <string> // string +#include <utility> // move + +// #include <nlohmann/detail/exceptions.hpp> + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/input/input_adapters.hpp> + +// #include <nlohmann/detail/input/json_sax.hpp> + + +#include <cstddef> +#include <string> +#include <vector> + +// #include <nlohmann/detail/input/parser.hpp> + +// #include <nlohmann/detail/exceptions.hpp> + + +namespace nlohmann +{ + +/*! +@brief SAX interface +*/ +template<typename BasicJsonType> +struct json_sax +{ + /// type for (signed) integers + using number_integer_t = typename BasicJsonType::number_integer_t; + /// type for unsigned integers + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + /// type for floating-point numbers + using number_float_t = typename BasicJsonType::number_float_t; + /// type for strings + using string_t = typename BasicJsonType::string_t; + + /// constant to indicate that no size limit is given for array or object + static constexpr auto no_limit = std::size_t(-1); + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief an floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string was read + @param[in] val string value + @return whether parsing should proceed + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or no_limit if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements = no_limit) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or no_limit if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements = no_limit) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] error_msg a detailed error message + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + virtual ~json_sax() = default; +}; + + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template<typename BasicJsonType> +class json_sax_dom_parser : public json_sax<BasicJsonType> +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + /*! + @param[in, out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + bool null() override + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) override + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) override + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) override + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t&) override + { + handle_value(val); + return true; + } + + bool string(string_t& val) override + { + handle_value(val); + return true; + } + + bool start_object(std::size_t len) override + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive object size: " + std::to_string(len))); + } + + return true; + } + + bool key(string_t& val) override + { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } + + bool end_object() override + { + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) override + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive array size: " + std::to_string(len))); + } + + return true; + } + + bool end_array() override + { + ref_stack.pop_back(); + return true; + } + + bool parse_error(std::size_t, const std::string&, + const detail::exception& ex) override + { + errored = true; + if (allow_exceptions) + { + // determine the proper exception type from the id + switch ((ex.id / 100) % 100) + { + case 1: + JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex)); + case 2: + JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex)); // LCOV_EXCL_LINE + case 3: + JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex)); // LCOV_EXCL_LINE + case 4: + JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex)); + case 5: + JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex)); // LCOV_EXCL_LINE + default: + assert(false); // LCOV_EXCL_LINE + } + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template<typename Value> + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward<Value>(v)); + return &root; + } + else + { + assert(ref_stack.back()->is_array() or ref_stack.back()->is_object()); + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v)); + return &(ref_stack.back()->m_value.array->back()); + } + else + { + assert(object_element); + *object_element = BasicJsonType(std::forward<Value>(v)); + return object_element; + } + } + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector<BasicJsonType*> ref_stack; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template<typename BasicJsonType> +class json_sax_dom_callback_parser : public json_sax<BasicJsonType> +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + bool null() override + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) override + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) override + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) override + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t&) override + { + handle_value(val); + return true; + } + + bool string(string_t& val) override + { + handle_value(val); + return true; + } + + bool start_object(std::size_t len) override + { + // check callback for object start + const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back()) + { + if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive object size: " + std::to_string(len))); + } + } + + return true; + } + + bool key(string_t& val) override + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep and ref_stack.back()) + { + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() override + { + bool keep = true; + if (ref_stack.back()) + { + keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()); + if (not keep) + { + // discard object + *ref_stack.back() = discarded; + } + } + + assert(not ref_stack.empty()); + assert(not keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (not ref_stack.empty() and ref_stack.back()) + { + // remove discarded value + if (ref_stack.back()->is_object()) + { + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + } + + return true; + } + + bool start_array(std::size_t len) override + { + const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back()) + { + if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive array size: " + std::to_string(len))); + } + } + + return true; + } + + bool end_array() override + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (not keep) + { + // discard array + *ref_stack.back() = discarded; + } + } + + assert(not ref_stack.empty()); + assert(not keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (not keep and not ref_stack.empty()) + { + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->pop_back(); + } + } + + return true; + } + + bool parse_error(std::size_t, const std::string&, + const detail::exception& ex) override + { + errored = true; + if (allow_exceptions) + { + // determine the proper exception type from the id + switch ((ex.id / 100) % 100) + { + case 1: + JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex)); + case 2: + JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex)); // LCOV_EXCL_LINE + case 3: + JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex)); // LCOV_EXCL_LINE + case 4: + JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex)); + case 5: + JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex)); // LCOV_EXCL_LINE + default: + assert(false); // LCOV_EXCL_LINE + } + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template<typename Value> + std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) + { + assert(not keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (not keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward<Value>(v)); + + // check callback + const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (not keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, &root}; + } + else + { + assert(ref_stack.back()->is_array() or ref_stack.back()->is_object()); + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->push_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } + else + { + // check if we should store an element for the current key + assert(not key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (not store_element) + { + return {false, nullptr}; + } + + assert(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + } + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector<BasicJsonType*> ref_stack; + /// stack to manage which values to keep + std::vector<bool> keep_stack; + /// stack to manage which object keys to keep + std::vector<bool> key_keep_stack; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template<typename BasicJsonType> +class json_sax_acceptor : public json_sax<BasicJsonType> +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + bool null() override + { + return true; + } + + bool boolean(bool) override + { + return true; + } + + bool number_integer(number_integer_t) override + { + return true; + } + + bool number_unsigned(number_unsigned_t) override + { + return true; + } + + bool number_float(number_float_t, const string_t&) override + { + return true; + } + + bool string(string_t&) override + { + return true; + } + + bool start_object(std::size_t) override + { + return true; + } + + bool key(string_t&) override + { + return true; + } + + bool end_object() override + { + return true; + } + + bool start_array(std::size_t) override + { + return true; + } + + bool end_array() override + { + return true; + } + + bool parse_error(std::size_t, const std::string&, const detail::exception&) override + { + return false; + } +}; +} + +} + +// #include <nlohmann/detail/input/lexer.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +//////////// +// parser // +//////////// + +/*! +@brief syntax analysis + +This class implements a recursive decent parser. +*/ +template<typename BasicJsonType> +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer<BasicJsonType>; + using token_type = typename lexer_t::token_type; + + public: + enum class parse_event_t : uint8_t + { + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value + }; + + using json_sax_t = json_sax<BasicJsonType>; + + using parser_callback_t = + std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>; + + /// a parser reading from an input adapter + explicit parser(detail::input_adapter_t&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true) + : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict and (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict and (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor<BasicJsonType> sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + bool sax_parse(json_sax_t* sax, const bool strict = true) + { + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result and strict and (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + } + + return result; + } + + private: + bool sax_parse_internal(json_sax_t* sax) + { + // stack to remember the hieararchy of structured values we are parsing + // true = array; false = object + std::vector<bool> states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (not skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_UNLIKELY(not sax->start_object())) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_UNLIKELY(not sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string))); + } + else + { + if (JSON_UNLIKELY(not sax->key(m_lexer.get_string()))) + { + return false; + } + } + + // parse separator (:) + if (JSON_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator))); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_UNLIKELY(not sax->start_array())) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_UNLIKELY(not sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_UNLIKELY(not std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); + } + else + { + if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + break; + } + } + + case token_type::literal_false: + { + if (JSON_UNLIKELY(not sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_UNLIKELY(not sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_UNLIKELY(not sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_UNLIKELY(not sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized))); + } + + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value))); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hieararchy: done + return true; + } + else + { + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_LIKELY(last_token == token_type::end_array)) + { + if (JSON_UNLIKELY(not sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + assert(not states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + else + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array))); + } + } + else // object + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string))); + } + else + { + if (JSON_UNLIKELY(not sax->key(m_lexer.get_string()))) + { + return false; + } + } + + // parse separator (:) + if (JSON_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator))); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_LIKELY(last_token == token_type::end_object)) + { + if (JSON_UNLIKELY(not sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + assert(not states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + else + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object))); + } + } + } + } + } + + /// get next token from lexer + token_type get_token() + { + return (last_token = m_lexer.scan()); + } + + std::string exception_message(const token_type expected) + { + std::string error_msg = "syntax error - "; + if (last_token == token_type::parse_error) + { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } + else + { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; +} +} + +// #include <nlohmann/detail/iterators/primitive_iterator.hpp> + + +#include <cstddef> // ptrdiff_t +#include <limits> // numeric_limits + +namespace nlohmann +{ +namespace detail +{ +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t const operator++(int) noexcept + { + auto result = *this; + m_it++; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t const operator--(int) noexcept + { + auto result = *this; + m_it--; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; +} +} + +// #include <nlohmann/detail/iterators/internal_iterator.hpp> + + +// #include <nlohmann/detail/iterators/primitive_iterator.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template<typename BasicJsonType> struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; +} +} + +// #include <nlohmann/detail/iterators/iter_impl.hpp> + + +#include <ciso646> // not +#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include <type_traits> // conditional, is_const, remove_const + +// #include <nlohmann/detail/exceptions.hpp> + +// #include <nlohmann/detail/iterators/internal_iterator.hpp> + +// #include <nlohmann/detail/iterators/primitive_iterator.hpp> + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/meta.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +// forward declare, to be able to friend it later on +template<typename IteratorType> class iteration_proxy; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class + +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. + +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). + +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template<typename BasicJsonType> +class iter_impl +{ + /// allow basic_json to access private members + friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; + friend BasicJsonType; + friend iteration_proxy<iter_impl>; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, + "iter_impl only accepts (const) basic_json"); + + public: + + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional<std::is_const<BasicJsonType>::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional<std::is_const<BasicJsonType>::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + /// default constructor + iter_impl() = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) {} + + /*! + @brief converting assignment + @param[in,out] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + private: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + assert(m_it.object_iterator != m_object->m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + assert(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + + default: + { + if (JSON_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + assert(m_it.object_iterator != m_object->m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + assert(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } + + default: + { + if (JSON_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator++(int) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator--(int) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator==(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } + + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator!=(const iter_impl& other) const + { + return not operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } + + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return not other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return not operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return not operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + + default: + { + if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + assert(m_object != nullptr); + + if (JSON_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + private: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it; +}; +} +} + +// #include <nlohmann/detail/iterators/iteration_proxy.hpp> + + +#include <cstddef> // size_t +#include <string> // string, to_string + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/// proxy class for the items() function +template<typename IteratorType> class iteration_proxy +{ + private: + /// helper class for iteration + class iteration_proxy_internal + { + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable std::string array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const std::string empty_str = ""; + + public: + explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} + + /// dereference operator (needed for range-based for) + iteration_proxy_internal& operator*() + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_internal& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_internal& o) const noexcept + { + return anchor != o.anchor; + } + + /// return key of the iterator + const std::string& key() const + { + assert(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + array_index_str = std::to_string(array_index); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } + }; + + /// the container to iterate + typename IteratorType::reference container; + + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} + + /// return iterator begin (needed for range-based for) + iteration_proxy_internal begin() noexcept + { + return iteration_proxy_internal(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_internal end() noexcept + { + return iteration_proxy_internal(container.end()); + } +}; +} +} + +// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> + + +#include <cstddef> // ptrdiff_t +#include <iterator> // reverse_iterator +#include <utility> // declval + +namespace nlohmann +{ +namespace detail +{ +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template<typename Base> +class json_reverse_iterator : public std::reverse_iterator<Base> +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator<Base>; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator const operator++(int) + { + return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast<json_reverse_iterator&>(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator const operator--(int) + { + return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast<json_reverse_iterator&>(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast<json_reverse_iterator>(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast<json_reverse_iterator>(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval<Base>().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; +} +} + +// #include <nlohmann/detail/output/output_adapters.hpp> + + +#include <algorithm> // copy +#include <cstddef> // size_t +#include <ios> // streamsize +#include <iterator> // back_inserter +#include <memory> // shared_ptr, make_shared +#include <ostream> // basic_ostream +#include <string> // basic_string +#include <vector> // vector + +namespace nlohmann +{ +namespace detail +{ +/// abstract output adapter interface +template<typename CharType> struct output_adapter_protocol +{ + virtual void write_character(CharType c) = 0; + virtual void write_characters(const CharType* s, std::size_t length) = 0; + virtual ~output_adapter_protocol() = default; +}; + +/// a type to simplify interfaces +template<typename CharType> +using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; + +/// output adapter for byte vectors +template<typename CharType> +class output_vector_adapter : public output_adapter_protocol<CharType> +{ + public: + explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {} + + void write_character(CharType c) override + { + v.push_back(c); + } + + void write_characters(const CharType* s, std::size_t length) override + { + std::copy(s, s + length, std::back_inserter(v)); + } + + private: + std::vector<CharType>& v; +}; + +/// output adapter for output streams +template<typename CharType> +class output_stream_adapter : public output_adapter_protocol<CharType> +{ + public: + explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {} + + void write_character(CharType c) override + { + stream.put(c); + } + + void write_characters(const CharType* s, std::size_t length) override + { + stream.write(s, static_cast<std::streamsize>(length)); + } + + private: + std::basic_ostream<CharType>& stream; +}; + +/// output adapter for basic_string +template<typename CharType, typename StringType = std::basic_string<CharType>> +class output_string_adapter : public output_adapter_protocol<CharType> +{ + public: + explicit output_string_adapter(StringType& s) : str(s) {} + + void write_character(CharType c) override + { + str.push_back(c); + } + + void write_characters(const CharType* s, std::size_t length) override + { + str.append(s, length); + } + + private: + StringType& str; +}; + +template<typename CharType, typename StringType = std::basic_string<CharType>> +class output_adapter +{ + public: + output_adapter(std::vector<CharType>& vec) + : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {} + + output_adapter(std::basic_ostream<CharType>& s) + : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} + + output_adapter(StringType& s) + : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} + + operator output_adapter_t<CharType>() + { + return oa; + } + + private: + output_adapter_t<CharType> oa = nullptr; +}; +} +} + +// #include <nlohmann/detail/input/binary_reader.hpp> + + +#include <algorithm> // generate_n +#include <array> // array +#include <cassert> // assert +#include <cmath> // ldexp +#include <cstddef> // size_t +#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t +#include <cstring> // memcpy +#include <iomanip> // setw, setfill +#include <ios> // hex +#include <iterator> // back_inserter +#include <limits> // numeric_limits +#include <sstream> // stringstream +#include <string> // char_traits, string +#include <utility> // make_pair, move + +// #include <nlohmann/detail/input/input_adapters.hpp> + +// #include <nlohmann/detail/input/json_sax.hpp> + +// #include <nlohmann/detail/exceptions.hpp> + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template<typename BasicJsonType> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using string_t = typename BasicJsonType::string_t; + using json_sax_t = json_sax<BasicJsonType>; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter)) + { + assert(ia); + } + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + + @return + */ + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true) + { + sax = sax_; + bool result; + + switch (format) + { + case input_format_t::cbor: + result = parse_cbor_internal(); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; + + default: + assert(false); // LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result and strict) + { + if (format == input_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_UNLIKELY(current != std::char_traits<char>::eof())) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); + } + } + + return result; + } + + /*! + @brief determine system byte order + + @return true if and only if system's byte order is little endian + + @note from http://stackoverflow.com/a/1001328/266378 + */ + static constexpr bool little_endianess(int num = 1) noexcept + { + return (*reinterpret_cast<char*>(&num) == 1); + } + + private: + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char = true) + { + switch (get_char ? get() : current) + { + // EOF + case std::char_traits<char>::eof(): + return unexpect_eof(); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast<number_unsigned_t>(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + uint8_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + uint16_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + uint32_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + uint64_t number; + return get_number(number) and sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + uint8_t number; + return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + uint16_t number; + return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + uint32_t number; + return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + uint64_t number; + return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) + - static_cast<number_integer_t>(number)); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) and sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast<std::size_t>(current & 0x1F)); + + case 0x98: // array (one-byte uint8_t for n follows) + { + uint8_t len; + return get_number(len) and get_cbor_array(static_cast<std::size_t>(len)); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + uint16_t len; + return get_number(len) and get_cbor_array(static_cast<std::size_t>(len)); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + uint32_t len; + return get_number(len) and get_cbor_array(static_cast<std::size_t>(len)); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + uint64_t len; + return get_number(len) and get_cbor_array(static_cast<std::size_t>(len)); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(json_sax_t::no_limit); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast<std::size_t>(current & 0x1F)); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + uint8_t len; + return get_number(len) and get_cbor_object(static_cast<std::size_t>(len)); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + uint16_t len; + return get_number(len) and get_cbor_object(static_cast<std::size_t>(len)); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + uint32_t len; + return get_number(len) and get_cbor_object(static_cast<std::size_t>(len)); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + uint64_t len; + return get_number(len) and get_cbor_object(static_cast<std::size_t>(len)); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(json_sax_t::no_limit); + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const int byte1 = get(); + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + const int byte2 = get(); + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const int half = (byte1 << 8) + byte2; + const int exp = (half >> 10) & 0x1F; + const int mant = half & 0x3FF; + double val; + if (exp == 0) + { + val = std::ldexp(mant, -24); + } + else if (exp != 31) + { + val = std::ldexp(mant + 1024, exp - 25); + } + else + { + val = (mant == 0) ? std::numeric_limits<double>::infinity() + : std::numeric_limits<double>::quiet_NaN(); + } + return sax->number_float((half & 0x8000) != 0 ? -val : val, ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number; + return get_number(number) and sax->number_float(static_cast<double>(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number; + return get_number(number) and sax->number_float(number, ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + last_token)); + } + } + } + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case std::char_traits<char>::eof(): + return unexpect_eof(); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast<number_unsigned_t>(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast<std::size_t>(current & 0x0F)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast<std::size_t>(current & 0x0F)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + string_t s; + return get_msgpack_string(s) and sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xCA: // float 32 + { + float number; + return get_number(number) and sax->number_float(static_cast<double>(number), ""); + } + + case 0xCB: // float 64 + { + double number; + return get_number(number) and sax->number_float(number, ""); + } + + case 0xCC: // uint 8 + { + uint8_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + uint16_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + uint32_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + uint64_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + int8_t number; + return get_number(number) and sax->number_integer(number); + } + + case 0xD1: // int 16 + { + int16_t number; + return get_number(number) and sax->number_integer(number); + } + + case 0xD2: // int 32 + { + int32_t number; + return get_number(number) and sax->number_integer(number); + } + + case 0xD3: // int 64 + { + int64_t number; + return get_number(number) and sax->number_integer(number); + } + + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) and sax->string(s); + } + + case 0xDC: // array 16 + { + uint16_t len; + return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len)); + } + + case 0xDD: // array 32 + { + uint32_t len; + return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len)); + } + + case 0xDE: // map 16 + { + uint16_t len; + return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len)); + } + + case 0xDF: // map 32 + { + uint32_t len; + return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast<int8_t>(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + last_token)); + } + } + } + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `std::char_traits<char>::eof()` in that case. + + @return character read from the input + */ + int get() + { + ++chars_read; + return (current = ia->get_character()); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + int get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianess, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + */ + template<typename NumberType> + bool get_number(NumberType& result) + { + // step 1: read input into array with system's byte order + std::array<uint8_t, sizeof(NumberType)> vec; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian) + { + vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current); + } + else + { + vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] len number of characters to read + @param[out] string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template<typename NumberType> + bool get_string(const NumberType len, string_t& result) + { + bool success = true; + std::generate_n(std::back_inserter(result), len, [this, &success]() + { + get(); + if (JSON_UNLIKELY(not unexpect_eof())) + { + success = false; + } + return static_cast<char>(current); + }); + return success; + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(current & 0x1F, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + uint8_t len; + return get_number(len) and get_string(len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + uint16_t len; + return get_number(len) and get_string(len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + uint32_t len; + return get_number(len) and get_string(len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + uint64_t len; + return get_number(len) and get_string(len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (not get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + last_token)); + } + } + } + + /*! + @param[in] len the length of the array or json_sax_t::no_limit for an + array of indefinite size + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_array(len))) + { + return false; + } + + if (len != json_sax_t::no_limit) + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + } + else + { + while (get() != 0xFF) + { + if (JSON_UNLIKELY(not parse_cbor_internal(false))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or json_sax_t::no_limit for an + object of indefinite size + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len) + { + if (not JSON_UNLIKELY(sax->start_object(len))) + { + return false; + } + + string_t key; + if (len != json_sax_t::no_limit) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + key.clear(); + } + } + + return sax->end_object(); + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(current & 0x1F, result); + } + + case 0xD9: // str 8 + { + uint8_t len; + return get_number(len) and get_string(len, result); + } + + case 0xDA: // str 16 + { + uint16_t len; + return get_number(len) and get_string(len, result); + } + + case 0xDB: // str 32 + { + uint32_t len; + return get_number(len) and get_string(len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + last_token)); + } + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_UNLIKELY(not parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_UNLIKELY(not sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_UNLIKELY(not parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO: may we ignore N here? + } + + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + + switch (current) + { + case 'U': + { + uint8_t len; + return get_number(len) and get_string(len, result); + } + + case 'i': + { + int8_t len; + return get_number(len) and get_string(len, result); + } + + case 'I': + { + int16_t len; + return get_number(len) and get_string(len, result); + } + + case 'l': + { + int32_t len; + return get_number(len) and get_string(len, result); + } + + case 'L': + { + int64_t len; + return get_number(len) and get_string(len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + last_token)); + } + } + + /*! + @param[out] result determined size + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result) + { + switch (get_ignore_noop()) + { + case 'U': + { + uint8_t number; + if (JSON_UNLIKELY(not get_number(number))) + { + return false; + } + result = static_cast<std::size_t>(number); + return true; + } + + case 'i': + { + int8_t number; + if (JSON_UNLIKELY(not get_number(number))) + { + return false; + } + result = static_cast<std::size_t>(number); + return true; + } + + case 'I': + { + int16_t number; + if (JSON_UNLIKELY(not get_number(number))) + { + return false; + } + result = static_cast<std::size_t>(number); + return true; + } + + case 'l': + { + int32_t number; + if (JSON_UNLIKELY(not get_number(number))) + { + return false; + } + result = static_cast<std::size_t>(number); + return true; + } + + case 'L': + { + int64_t number; + if (JSON_UNLIKELY(not get_number(number))) + { + return false; + } + result = static_cast<std::size_t>(number); + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after '#' must denote a number type; last byte: 0x" + last_token)); + } + } + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair<std::size_t, int>& result) + { + result.first = string_t::npos; // size + result.second = 0; // type + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + + get_ignore_noop(); + if (JSON_UNLIKELY(current != '#')) + { + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + last_token)); + } + + return get_ubjson_size_value(result.first); + } + else if (current == '#') + { + return get_ubjson_size_value(result.first); + } + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const int prefix) + { + switch (prefix) + { + case std::char_traits<char>::eof(): // EOF + return unexpect_eof(); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + uint8_t number; + return get_number(number) and sax->number_unsigned(number); + } + + case 'i': + { + int8_t number; + return get_number(number) and sax->number_integer(number); + } + + case 'I': + { + int16_t number; + return get_number(number) and sax->number_integer(number); + } + + case 'l': + { + int32_t number; + return get_number(number) and sax->number_integer(number); + } + + case 'L': + { + int64_t number; + return get_number(number) and sax->number_integer(number); + } + + case 'd': + { + float number; + return get_number(number) and sax->number_float(static_cast<double>(number), ""); + } + + case 'D': + { + double number; + return get_number(number) and sax->number_float(number, ""); + } + + case 'C': // char + { + get(); + if (JSON_UNLIKELY(not unexpect_eof())) + { + return false; + } + if (JSON_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token)); + } + string_t s(1, static_cast<char>(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) and sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + last_token)); + } + } + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair<std::size_t, int> size_and_type; + if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (JSON_UNLIKELY(not sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_UNLIKELY(not sax->start_array())) + { + return false; + } + + while (current != ']') + { + if (JSON_UNLIKELY(not parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair<std::size_t, int> size_and_type; + if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type))) + { + return false; + } + + string_t key; + if (size_and_type.first != string_t::npos) + { + if (JSON_UNLIKELY(not sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key))) + { + return false; + } + if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key))) + { + return false; + } + if (JSON_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_UNLIKELY(not sax->start_object())) + { + return false; + } + + while (current != '}') + { + if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key))) + { + return false; + } + if (JSON_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + /*! + @return whether the last read character is not EOF + */ + bool unexpect_eof() const + { + if (JSON_UNLIKELY(current == std::char_traits<char>::eof())) + { + return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input")); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::stringstream ss; + ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; + return ss.str(); + } + + private: + /// input adapter + input_adapter_t ia = nullptr; + + /// the current character + int current = std::char_traits<char>::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); + + /// the SAX parser + json_sax_t* sax = nullptr; +}; +} +} + +// #include <nlohmann/detail/output/binary_writer.hpp> + + +#include <algorithm> // reverse +#include <array> // array +#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t +#include <cstring> // memcpy +#include <limits> // numeric_limits + +// #include <nlohmann/detail/input/binary_reader.hpp> + +// #include <nlohmann/detail/output/output_adapters.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary writer // +/////////////////// + +/*! +@brief serialization to CBOR and MessagePack values +*/ +template<typename BasicJsonType, typename CharType> +class binary_writer +{ + public: + /*! + @brief create a binary writer + + @param[in] adapter output adapter to write to + */ + explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter) + { + assert(oa); + } + + /*! + @brief[in] j JSON value to serialize + */ + void write_cbor(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: + { + oa->write_character(static_cast<CharType>(0xF6)); + break; + } + + case value_t::boolean: + { + oa->write_character(j.m_value.boolean + ? static_cast<CharType>(0xF5) + : static_cast<CharType>(0xF4)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // CBOR does not differentiate between positive signed + // integers and unsigned integers. Therefore, we used the + // code from the value_t::number_unsigned case here. + if (j.m_value.number_integer <= 0x17) + { + write_number(static_cast<uint8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x18)); + write_number(static_cast<uint8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x19)); + write_number(static_cast<uint16_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x1A)); + write_number(static_cast<uint32_t>(j.m_value.number_integer)); + } + else + { + oa->write_character(static_cast<CharType>(0x1B)); + write_number(static_cast<uint64_t>(j.m_value.number_integer)); + } + } + else + { + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) + { + write_number(static_cast<uint8_t>(0x20 + positive_number)); + } + else if (positive_number <= (std::numeric_limits<uint8_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x38)); + write_number(static_cast<uint8_t>(positive_number)); + } + else if (positive_number <= (std::numeric_limits<uint16_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x39)); + write_number(static_cast<uint16_t>(positive_number)); + } + else if (positive_number <= (std::numeric_limits<uint32_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x3A)); + write_number(static_cast<uint32_t>(positive_number)); + } + else + { + oa->write_character(static_cast<CharType>(0x3B)); + write_number(static_cast<uint64_t>(positive_number)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= 0x17) + { + write_number(static_cast<uint8_t>(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x18)); + write_number(static_cast<uint8_t>(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x19)); + write_number(static_cast<uint16_t>(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x1A)); + write_number(static_cast<uint32_t>(j.m_value.number_unsigned)); + } + else + { + oa->write_character(static_cast<CharType>(0x1B)); + write_number(static_cast<uint64_t>(j.m_value.number_unsigned)); + } + break; + } + + case value_t::number_float: + { + oa->write_character(get_cbor_float_prefix(j.m_value.number_float)); + write_number(j.m_value.number_float); + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 0x17) + { + write_number(static_cast<uint8_t>(0x60 + N)); + } + else if (N <= (std::numeric_limits<uint8_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x78)); + write_number(static_cast<uint8_t>(N)); + } + else if (N <= (std::numeric_limits<uint16_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x79)); + write_number(static_cast<uint16_t>(N)); + } + else if (N <= (std::numeric_limits<uint32_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x7A)); + write_number(static_cast<uint32_t>(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits<uint64_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x7B)); + write_number(static_cast<uint64_t>(N)); + } + // LCOV_EXCL_STOP + + // step 2: write the string + oa->write_characters( + reinterpret_cast<const CharType*>(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 0x17) + { + write_number(static_cast<uint8_t>(0x80 + N)); + } + else if (N <= (std::numeric_limits<uint8_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x98)); + write_number(static_cast<uint8_t>(N)); + } + else if (N <= (std::numeric_limits<uint16_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x99)); + write_number(static_cast<uint16_t>(N)); + } + else if (N <= (std::numeric_limits<uint32_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x9A)); + write_number(static_cast<uint32_t>(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits<uint64_t>::max)()) + { + oa->write_character(static_cast<CharType>(0x9B)); + write_number(static_cast<uint64_t>(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_cbor(el); + } + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 0x17) + { + write_number(static_cast<uint8_t>(0xA0 + N)); + } + else if (N <= (std::numeric_limits<uint8_t>::max)()) + { + oa->write_character(static_cast<CharType>(0xB8)); + write_number(static_cast<uint8_t>(N)); + } + else if (N <= (std::numeric_limits<uint16_t>::max)()) + { + oa->write_character(static_cast<CharType>(0xB9)); + write_number(static_cast<uint16_t>(N)); + } + else if (N <= (std::numeric_limits<uint32_t>::max)()) + { + oa->write_character(static_cast<CharType>(0xBA)); + write_number(static_cast<uint32_t>(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits<uint64_t>::max)()) + { + oa->write_character(static_cast<CharType>(0xBB)); + write_number(static_cast<uint64_t>(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_cbor(el.first); + write_cbor(el.second); + } + break; + } + + default: + break; + } + } + + /*! + @brief[in] j JSON value to serialize + */ + void write_msgpack(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: // nil + { + oa->write_character(static_cast<CharType>(0xC0)); + break; + } + + case value_t::boolean: // true and false + { + oa->write_character(j.m_value.boolean + ? static_cast<CharType>(0xC3) + : static_cast<CharType>(0xC2)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // MessagePack does not differentiate between positive + // signed integers and unsigned integers. Therefore, we used + // the code from the value_t::number_unsigned case here. + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast<uint8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) + { + // uint 8 + oa->write_character(static_cast<CharType>(0xCC)); + write_number(static_cast<uint8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) + { + // uint 16 + oa->write_character(static_cast<CharType>(0xCD)); + write_number(static_cast<uint16_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) + { + // uint 32 + oa->write_character(static_cast<CharType>(0xCE)); + write_number(static_cast<uint32_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)()) + { + // uint 64 + oa->write_character(static_cast<CharType>(0xCF)); + write_number(static_cast<uint64_t>(j.m_value.number_integer)); + } + } + else + { + if (j.m_value.number_integer >= -32) + { + // negative fixnum + write_number(static_cast<int8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and + j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)()) + { + // int 8 + oa->write_character(static_cast<CharType>(0xD0)); + write_number(static_cast<int8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and + j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)()) + { + // int 16 + oa->write_character(static_cast<CharType>(0xD1)); + write_number(static_cast<int16_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and + j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)()) + { + // int 32 + oa->write_character(static_cast<CharType>(0xD2)); + write_number(static_cast<int32_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and + j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)()) + { + // int 64 + oa->write_character(static_cast<CharType>(0xD3)); + write_number(static_cast<int64_t>(j.m_value.number_integer)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast<uint8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) + { + // uint 8 + oa->write_character(static_cast<CharType>(0xCC)); + write_number(static_cast<uint8_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) + { + // uint 16 + oa->write_character(static_cast<CharType>(0xCD)); + write_number(static_cast<uint16_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) + { + // uint 32 + oa->write_character(static_cast<CharType>(0xCE)); + write_number(static_cast<uint32_t>(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)()) + { + // uint 64 + oa->write_character(static_cast<CharType>(0xCF)); + write_number(static_cast<uint64_t>(j.m_value.number_integer)); + } + break; + } + + case value_t::number_float: + { + oa->write_character(get_msgpack_float_prefix(j.m_value.number_float)); + write_number(j.m_value.number_float); + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 31) + { + // fixstr + write_number(static_cast<uint8_t>(0xA0 | N)); + } + else if (N <= (std::numeric_limits<uint8_t>::max)()) + { + // str 8 + oa->write_character(static_cast<CharType>(0xD9)); + write_number(static_cast<uint8_t>(N)); + } + else if (N <= (std::numeric_limits<uint16_t>::max)()) + { + // str 16 + oa->write_character(static_cast<CharType>(0xDA)); + write_number(static_cast<uint16_t>(N)); + } + else if (N <= (std::numeric_limits<uint32_t>::max)()) + { + // str 32 + oa->write_character(static_cast<CharType>(0xDB)); + write_number(static_cast<uint32_t>(N)); + } + + // step 2: write the string + oa->write_characters( + reinterpret_cast<const CharType*>(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 15) + { + // fixarray + write_number(static_cast<uint8_t>(0x90 | N)); + } + else if (N <= (std::numeric_limits<uint16_t>::max)()) + { + // array 16 + oa->write_character(static_cast<CharType>(0xDC)); + write_number(static_cast<uint16_t>(N)); + } + else if (N <= (std::numeric_limits<uint32_t>::max)()) + { + // array 32 + oa->write_character(static_cast<CharType>(0xDD)); + write_number(static_cast<uint32_t>(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_msgpack(el); + } + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 15) + { + // fixmap + write_number(static_cast<uint8_t>(0x80 | (N & 0xF))); + } + else if (N <= (std::numeric_limits<uint16_t>::max)()) + { + // map 16 + oa->write_character(static_cast<CharType>(0xDE)); + write_number(static_cast<uint16_t>(N)); + } + else if (N <= (std::numeric_limits<uint32_t>::max)()) + { + // map 32 + oa->write_character(static_cast<CharType>(0xDF)); + write_number(static_cast<uint32_t>(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_msgpack(el.first); + write_msgpack(el.second); + } + break; + } + + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + @param[in] use_count whether to use '#' prefixes (optimized format) + @param[in] use_type whether to use '$' prefixes (optimized format) + @param[in] add_prefix whether prefixes need to be used for this value + */ + void write_ubjson(const BasicJsonType& j, const bool use_count, + const bool use_type, const bool add_prefix = true) + { + switch (j.type()) + { + case value_t::null: + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('Z')); + } + break; + } + + case value_t::boolean: + { + if (add_prefix) + oa->write_character(j.m_value.boolean + ? static_cast<CharType>('T') + : static_cast<CharType>('F')); + break; + } + + case value_t::number_integer: + { + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); + break; + } + + case value_t::number_unsigned: + { + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); + break; + } + + case value_t::number_float: + { + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); + break; + } + + case value_t::string: + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('S')); + } + write_number_with_ubjson_prefix(j.m_value.string->size(), true); + oa->write_characters( + reinterpret_cast<const CharType*>(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('[')); + } + + bool prefix_required = true; + if (use_type and not j.m_value.array->empty()) + { + assert(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin() + 1, j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(static_cast<CharType>('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(static_cast<CharType>('#')); + write_number_with_ubjson_prefix(j.m_value.array->size(), true); + } + + for (const auto& el : *j.m_value.array) + { + write_ubjson(el, use_count, use_type, prefix_required); + } + + if (not use_count) + { + oa->write_character(static_cast<CharType>(']')); + } + + break; + } + + case value_t::object: + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('{')); + } + + bool prefix_required = true; + if (use_type and not j.m_value.object->empty()) + { + assert(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin(), j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(static_cast<CharType>('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(static_cast<CharType>('#')); + write_number_with_ubjson_prefix(j.m_value.object->size(), true); + } + + for (const auto& el : *j.m_value.object) + { + write_number_with_ubjson_prefix(el.first.size(), true); + oa->write_characters( + reinterpret_cast<const CharType*>(el.first.c_str()), + el.first.size()); + write_ubjson(el.second, use_count, use_type, prefix_required); + } + + if (not use_count) + { + oa->write_character(static_cast<CharType>('}')); + } + + break; + } + + default: + break; + } + } + + private: + /* + @brief write a number to output input + + @param[in] n number of type @a NumberType + @tparam NumberType the type of the number + + @note This function needs to respect the system's endianess, because bytes + in CBOR, MessagePack, and UBJSON are stored in network order (big + endian) and therefore need reordering on little endian systems. + */ + template<typename NumberType> + void write_number(const NumberType n) + { + // step 1: write number to array of length NumberType + std::array<CharType, sizeof(NumberType)> vec; + std::memcpy(vec.data(), &n, sizeof(NumberType)); + + // step 2: write array to output (with possible reordering) + if (is_little_endian) + { + // reverse byte order prior to conversion if necessary + std::reverse(vec.begin(), vec.end()); + } + + oa->write_characters(vec.data(), sizeof(NumberType)); + } + + // UBJSON: write number (floating point) + template<typename NumberType, typename std::enable_if< + std::is_floating_point<NumberType>::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (add_prefix) + { + oa->write_character(get_ubjson_float_prefix(n)); + } + write_number(n); + } + + // UBJSON: write number (unsigned integer) + template<typename NumberType, typename std::enable_if< + std::is_unsigned<NumberType>::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)())) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('i')); // int8 + } + write_number(static_cast<uint8_t>(n)); + } + else if (n <= (std::numeric_limits<uint8_t>::max)()) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('U')); // uint8 + } + write_number(static_cast<uint8_t>(n)); + } + else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)())) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('I')); // int16 + } + write_number(static_cast<int16_t>(n)); + } + else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)())) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('l')); // int32 + } + write_number(static_cast<int32_t>(n)); + } + else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)())) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('L')); // int64 + } + write_number(static_cast<int64_t>(n)); + } + else + { + JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n))); + } + } + + // UBJSON: write number (signed integer) + template<typename NumberType, typename std::enable_if< + std::is_signed<NumberType>::value and + not std::is_floating_point<NumberType>::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)()) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('i')); // int8 + } + write_number(static_cast<int8_t>(n)); + } + else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)())) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('U')); // uint8 + } + write_number(static_cast<uint8_t>(n)); + } + else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)()) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('I')); // int16 + } + write_number(static_cast<int16_t>(n)); + } + else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)()) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('l')); // int32 + } + write_number(static_cast<int32_t>(n)); + } + else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)()) + { + if (add_prefix) + { + oa->write_character(static_cast<CharType>('L')); // int64 + } + write_number(static_cast<int64_t>(n)); + } + // LCOV_EXCL_START + else + { + JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n))); + } + // LCOV_EXCL_STOP + } + + /*! + @brief determine the type prefix of container values + + @note This function does not need to be 100% accurate when it comes to + integer limits. In case a number exceeds the limits of int64_t, + this will be detected by a later call to function + write_number_with_ubjson_prefix. Therefore, we return 'L' for any + value that does not fit the previous limits. + */ + CharType ubjson_prefix(const BasicJsonType& j) const noexcept + { + switch (j.type()) + { + case value_t::null: + return 'Z'; + + case value_t::boolean: + return j.m_value.boolean ? 'T' : 'F'; + + case value_t::number_integer: + { + if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)()) + { + return 'i'; + } + else if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)()) + { + return 'U'; + } + else if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)()) + { + return 'I'; + } + else if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)()) + { + return 'l'; + } + else // no check and assume int64_t (see note above) + { + return 'L'; + } + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)()) + { + return 'i'; + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) + { + return 'U'; + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)()) + { + return 'I'; + } + else if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)()) + { + return 'l'; + } + else // no check and assume int64_t (see note above) + { + return 'L'; + } + } + + case value_t::number_float: + return get_ubjson_float_prefix(j.m_value.number_float); + + case value_t::string: + return 'S'; + + case value_t::array: + return '['; + + case value_t::object: + return '{'; + + default: // discarded values + return 'N'; + } + } + + static constexpr CharType get_cbor_float_prefix(float) + { + return static_cast<CharType>(0xFA); // Single-Precision Float + } + + static constexpr CharType get_cbor_float_prefix(double) + { + return static_cast<CharType>(0xFB); // Double-Precision Float + } + + static constexpr CharType get_msgpack_float_prefix(float) + { + return static_cast<CharType>(0xCA); // float 32 + } + + static constexpr CharType get_msgpack_float_prefix(double) + { + return static_cast<CharType>(0xCB); // float 64 + } + + static constexpr CharType get_ubjson_float_prefix(float) + { + return 'd'; // float 32 + } + + static constexpr CharType get_ubjson_float_prefix(double) + { + return 'D'; // float 64 + } + + private: + /// whether we can assume little endianess + const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess(); + + /// the output + output_adapter_t<CharType> oa = nullptr; +}; +} +} + +// #include <nlohmann/detail/output/serializer.hpp> + + +#include <algorithm> // reverse, remove, fill, find, none_of +#include <array> // array +#include <cassert> // assert +#include <ciso646> // and, or +#include <clocale> // localeconv, lconv +#include <cmath> // labs, isfinite, isnan, signbit +#include <cstddef> // size_t, ptrdiff_t +#include <cstdint> // uint8_t +#include <cstdio> // snprintf +#include <iomanip> // setfill +#include <iterator> // next +#include <limits> // numeric_limits +#include <string> // string +#include <sstream> // stringstream +#include <type_traits> // is_same + +// #include <nlohmann/detail/exceptions.hpp> + +// #include <nlohmann/detail/conversions/to_chars.hpp> + + +#include <cassert> // assert +#include <ciso646> // or, and, not +#include <cmath> // signbit, isfinite +#include <cstdint> // intN_t, uintN_t +#include <cstring> // memcpy, memmove + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template <typename Target, typename Source> +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + uint64_t f; + int e; + + constexpr diyfp() noexcept : f(0), e(0) {} + constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + assert(x.e == y.e); + assert(x.f >= y.f); + + return diyfp(x.f - y.f, x.e); + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const uint64_t u_lo = x.f & 0xFFFFFFFF; + const uint64_t u_hi = x.f >> 32; + const uint64_t v_lo = y.f & 0xFFFFFFFF; + const uint64_t v_hi = y.f >> 32; + + const uint64_t p0 = u_lo * v_lo; + const uint64_t p1 = u_lo * v_hi; + const uint64_t p2 = u_hi * v_lo; + const uint64_t p3 = u_hi * v_hi; + + const uint64_t p0_hi = p0 >> 32; + const uint64_t p1_lo = p1 & 0xFFFFFFFF; + const uint64_t p1_hi = p1 >> 32; + const uint64_t p2_lo = p2 & 0xFFFFFFFF; + const uint64_t p2_hi = p2 >> 32; + + uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += uint64_t{1} << (64 - 32 - 1); // round, ties up + + const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32); + + return diyfp(h, x.e + y.e + 64); + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + assert(x.f != 0); + + while ((x.f >> 63) == 0) + { + x.f <<= 1; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + assert(delta >= 0); + assert(((x.f << delta) >> delta) == x.f); + + return diyfp(x.f << delta, target_exponent); + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template <typename FloatType> +boundaries compute_boundaries(FloatType value) +{ + assert(std::isfinite(value)); + assert(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits<FloatType>::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type; + + const uint64_t bits = reinterpret_bits<bits_type>(value); + const uint64_t E = bits >> (kPrecision - 1); + const uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = (E == 0); + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = (F == 0 and E > 1); + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersSize = 79; + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr cached_power kCachedPowers[] = + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + assert(e >= -1500); + assert(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + (f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + assert(index >= 0); + assert(index < kCachedPowersSize); + static_cast<void>(kCachedPowersSize); // Fix warning. + + const cached_power cached = kCachedPowers[index]; + assert(kAlpha <= cached.e + e + 64); + assert(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const uint32_t n, uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + else if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + else if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + else if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + else if (n >= 100000) + { + pow10 = 100000; + return 6; + } + else if (n >= 10000) + { + pow10 = 10000; + return 5; + } + else if (n >= 1000) + { + pow10 = 1000; + return 4; + } + else if (n >= 100) + { + pow10 = 100; + return 3; + } + else if (n >= 10) + { + pow10 = 10; + return 2; + } + else + { + pow10 = 1; + return 1; + } +} + +inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta, + uint64_t rest, uint64_t ten_k) +{ + assert(len >= 1); + assert(dist <= delta); + assert(rest <= delta); + assert(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + and delta - rest >= ten_k + and (rest + ten_k < dist or dist - rest > rest + ten_k - dist)) + { + assert(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + assert(M_plus.e >= kAlpha); + assert(M_plus.e <= kGamma); + + uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e); + + uint32_t p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + assert(p1 > 0); + + uint32_t pow10; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + assert(d <= 9); + buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const uint64_t rest = (uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const uint64_t ten_n = uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + assert(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + assert(p2 <= UINT64_MAX / 10); + p2 *= 10; + const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + assert(d <= 9); + buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + assert(m_plus.e == m_minus.e); + assert(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template <typename FloatType> +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, + "internal error: not enough precision"); + + assert(std::isfinite(value)); + assert(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 + const boundaries w = compute_boundaries(static_cast<double>(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +inline char* append_exponent(char* buf, int e) +{ + assert(e > -1000); + assert(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + uint32_t k = static_cast<uint32_t>(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast<char>('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast<char>('0' + k / 10); + k %= 10; + *buf++ = static_cast<char>('0' + k); + } + else + { + *buf++ = static_cast<char>('0' + k / 100); + k %= 100; + *buf++ = static_cast<char>('0' + k / 10); + k %= 10; + *buf++ = static_cast<char>('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + assert(min_exp < 0); + assert(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n and n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast<size_t>(n - k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (n + 2); + } + + if (0 < n and n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + assert(k > n); + + std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n)); + buf[n] = '.'; + return buf + (k + 1); + } + + if (min_exp < n and n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast<size_t>(-n)); + return buf + (2 + (-n) + k); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1)); + buf[1] = '.'; + buf += 1 + k; + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template <typename FloatType> +char* to_chars(char* first, char* last, FloatType value) +{ + static_cast<void>(last); // maybe unused - fix warning + assert(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } + + assert(last - first >= std::numeric_limits<FloatType>::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + assert(len <= std::numeric_limits<FloatType>::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10; + + assert(last - first >= kMaxExp + 2); + assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10); + assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +} // namespace nlohmann + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/meta.hpp> + +// #include <nlohmann/detail/output/output_adapters.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// serialization // +/////////////////// + +template<typename BasicJsonType> +class serializer +{ + using string_t = typename BasicJsonType::string_t; + using number_float_t = typename BasicJsonType::number_float_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + static constexpr uint8_t UTF8_ACCEPT = 0; + static constexpr uint8_t UTF8_REJECT = 1; + + public: + /*! + @param[in] s output stream to serialize to + @param[in] ichar indentation character to use + */ + serializer(output_adapter_t<char> s, const char ichar) + : o(std::move(s)), loc(std::localeconv()), + thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep)), + decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point)), + indent_char(ichar), indent_string(512, indent_char) + {} + + // delete because of pointer members + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; + + /*! + @brief internal implementation of the serialization function + + This function is called by the public member function dump and organizes + the serialization internally. The indentation level is propagated as + additional parameter. In case of arrays and objects, the function is + called recursively. + + - strings and object keys are escaped using `escape_string()` + - integer numbers are converted implicitly via `operator<<` + - floating-point numbers are converted to a string using `"%g"` format + + @param[in] val value to serialize + @param[in] pretty_print whether the output shall be pretty-printed + @param[in] indent_step the indent level + @param[in] current_indent the current indent level (only used internally) + */ + void dump(const BasicJsonType& val, const bool pretty_print, + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent = 0) + { + switch (val.m_type) + { + case value_t::object: + { + if (val.m_value.object->empty()) + { + o->write_characters("{}", 2); + return; + } + + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + assert(i != val.m_value.object->cend()); + assert(std::next(i) == val.m_value.object->cend()); + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_character('{'); + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + assert(i != val.m_value.object->cend()); + assert(std::next(i) == val.m_value.object->cend()); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + + o->write_character('}'); + } + + return; + } + + case value_t::array: + { + if (val.m_value.array->empty()) + { + o->write_characters("[]", 2); + return; + } + + if (pretty_print) + { + o->write_characters("[\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + dump(*i, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + assert(not val.m_value.array->empty()); + o->write_characters(indent_string.c_str(), new_indent); + dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character(']'); + } + else + { + o->write_character('['); + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + dump(*i, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + assert(not val.m_value.array->empty()); + dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + + o->write_character(']'); + } + + return; + } + + case value_t::string: + { + o->write_character('\"'); + dump_escaped(*val.m_value.string, ensure_ascii); + o->write_character('\"'); + return; + } + + case value_t::boolean: + { + if (val.m_value.boolean) + { + o->write_characters("true", 4); + } + else + { + o->write_characters("false", 5); + } + return; + } + + case value_t::number_integer: + { + dump_integer(val.m_value.number_integer); + return; + } + + case value_t::number_unsigned: + { + dump_integer(val.m_value.number_unsigned); + return; + } + + case value_t::number_float: + { + dump_float(val.m_value.number_float); + return; + } + + case value_t::discarded: + { + o->write_characters("<discarded>", 11); + return; + } + + case value_t::null: + { + o->write_characters("null", 4); + return; + } + } + } + + private: + /*! + @brief dump escaped string + + Escape a string by replacing certain special characters by a sequence of an + escape character (backslash) and another character and other control + characters by a sequence of "\u" followed by a four-digit hex + representation. The escaped string is written to output stream @a o. + + @param[in] s the string to escape + @param[in] ensure_ascii whether to escape non-ASCII characters with + \uXXXX sequences + + @complexity Linear in the length of string @a s. + */ + void dump_escaped(const string_t& s, const bool ensure_ascii) + { + uint32_t codepoint; + uint8_t state = UTF8_ACCEPT; + std::size_t bytes = 0; // number of bytes written to string_buffer + + for (std::size_t i = 0; i < s.size(); ++i) + { + const auto byte = static_cast<uint8_t>(s[i]); + + switch (decode(state, codepoint, byte)) + { + case UTF8_ACCEPT: // decode found a new code point + { + switch (codepoint) + { + case 0x08: // backspace + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'b'; + break; + } + + case 0x09: // horizontal tab + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 't'; + break; + } + + case 0x0A: // newline + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'n'; + break; + } + + case 0x0C: // formfeed + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'f'; + break; + } + + case 0x0D: // carriage return + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'r'; + break; + } + + case 0x22: // quotation mark + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\"'; + break; + } + + case 0x5C: // reverse solidus + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\\'; + break; + } + + default: + { + // escape control characters (0x00..0x1F) or, if + // ensure_ascii parameter is used, non-ASCII characters + if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F))) + { + if (codepoint <= 0xFFFF) + { + std::snprintf(string_buffer.data() + bytes, 7, "\\u%04x", + static_cast<uint16_t>(codepoint)); + bytes += 6; + } + else + { + std::snprintf(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", + static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)), + static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF))); + bytes += 12; + } + } + else + { + // copy byte to buffer (all previous bytes + // been copied have in default case above) + string_buffer[bytes++] = s[i]; + } + break; + } + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + break; + } + + case UTF8_REJECT: // decode found invalid UTF-8 byte + { + std::stringstream ss; + ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(byte); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str())); + } + + default: // decode found yet incomplete multi-byte code point + { + if (not ensure_ascii) + { + // code point will not be escaped - copy byte to buffer + string_buffer[bytes++] = s[i]; + } + break; + } + } + } + + if (JSON_LIKELY(state == UTF8_ACCEPT)) + { + // write buffer + if (bytes > 0) + { + o->write_characters(string_buffer.data(), bytes); + } + } + else + { + // we finish reading, but do not accept: string was incomplete + std::stringstream ss; + ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(static_cast<uint8_t>(s.back())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str())); + } + } + + /*! + @brief dump an integer + + Dump a given integer to output stream @a o. Works internally with + @a number_buffer. + + @param[in] x integer number (signed or unsigned) to dump + @tparam NumberType either @a number_integer_t or @a number_unsigned_t + */ + template<typename NumberType, detail::enable_if_t< + std::is_same<NumberType, number_unsigned_t>::value or + std::is_same<NumberType, number_integer_t>::value, + int> = 0> + void dump_integer(NumberType x) + { + // special case for "0" + if (x == 0) + { + o->write_character('0'); + return; + } + + const bool is_negative = (x <= 0) and (x != 0); // see issue #755 + std::size_t i = 0; + + while (x != 0) + { + // spare 1 byte for '\0' + assert(i < number_buffer.size() - 1); + + const auto digit = std::labs(static_cast<long>(x % 10)); + number_buffer[i++] = static_cast<char>('0' + digit); + x /= 10; + } + + if (is_negative) + { + // make sure there is capacity for the '-' + assert(i < number_buffer.size() - 2); + number_buffer[i++] = '-'; + } + + std::reverse(number_buffer.begin(), number_buffer.begin() + i); + o->write_characters(number_buffer.data(), i); + } + + /*! + @brief dump a floating-point number + + Dump a given floating-point number to output stream @a o. Works internally + with @a number_buffer. + + @param[in] x floating-point number to dump + */ + void dump_float(number_float_t x) + { + // NaN / inf + if (not std::isfinite(x)) + { + o->write_characters("null", 4); + return; + } + + // If number_float_t is an IEEE-754 single or double precision number, + // use the Grisu2 algorithm to produce short numbers which are + // guaranteed to round-trip, using strtof and strtod, resp. + // + // NB: The test below works if <long double> == <double>. + static constexpr bool is_ieee_single_or_double + = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or + (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024); + + dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); + } + + void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) + { + char* begin = number_buffer.data(); + char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); + + o->write_characters(begin, static_cast<size_t>(end - begin)); + } + + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) + { + // get number of digits for a float -> text -> float round-trip + static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; + + // the actual conversion + std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + + // negative value indicates an error + assert(len > 0); + // check if buffer was large enough + assert(static_cast<std::size_t>(len) < number_buffer.size()); + + // erase thousands separator + if (thousands_sep != '\0') + { + const auto end = std::remove(number_buffer.begin(), + number_buffer.begin() + len, thousands_sep); + std::fill(end, number_buffer.end(), '\0'); + assert((end - number_buffer.begin()) <= len); + len = (end - number_buffer.begin()); + } + + // convert decimal point to '.' + if (decimal_point != '\0' and decimal_point != '.') + { + const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); + if (dec_pos != number_buffer.end()) + { + *dec_pos = '.'; + } + } + + o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); + + // determine if need to append ".0" + const bool value_is_int_like = + std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, + [](char c) + { + return (c == '.' or c == 'e'); + }); + + if (value_is_int_like) + { + o->write_characters(".0", 2); + } + } + + /*! + @brief check whether a string is UTF-8 encoded + + The function checks each byte of a string whether it is UTF-8 encoded. The + result of the check is stored in the @a state parameter. The function must + be called initially with state 0 (accept). State 1 means the string must + be rejected, because the current byte is not allowed. If the string is + completely processed, but the state is non-zero, the string ended + prematurely; that is, the last byte indicated more bytes should have + followed. + + @param[in,out] state the state of the decoding + @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) + @param[in] byte next byte to decode + @return new state + + @note The function has been edited: a std::array is used. + + @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> + @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + */ + static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept + { + static const std::array<uint8_t, 400> utf8d = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF + 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF + 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 + } + }; + + const uint8_t type = utf8d[byte]; + + codep = (state != UTF8_ACCEPT) + ? (byte & 0x3fu) | (codep << 6) + : static_cast<uint32_t>(0xff >> type) & (byte); + + state = utf8d[256u + state * 16u + type]; + return state; + } + + private: + /// the output of the serializer + output_adapter_t<char> o = nullptr; + + /// a (hopefully) large enough character buffer + std::array<char, 64> number_buffer{{}}; + + /// the locale + const std::lconv* loc = nullptr; + /// the locale's thousand separator character + const char thousands_sep = '\0'; + /// the locale's decimal point character + const char decimal_point = '\0'; + + /// string buffer + std::array<char, 512> string_buffer{{}}; + + /// the indentation character + const char indent_char; + /// the indentation string + string_t indent_string; +}; +} +} + +// #include <nlohmann/detail/json_ref.hpp> + + +#include <initializer_list> +#include <utility> + +namespace nlohmann +{ +namespace detail +{ +template<typename BasicJsonType> +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true) + {} + + json_ref(const value_type& value) + : value_ref(const_cast<value_type*>(&value)), is_rvalue(false) + {} + + json_ref(std::initializer_list<json_ref> init) + : owned_value(init), value_ref(&owned_value), is_rvalue(true) + {} + + template<class... Args> + json_ref(Args&& ... args) + : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true) + {} + + // class should be movable only + json_ref(json_ref&&) = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + + value_type moved_or_copied() const + { + if (is_rvalue) + { + return std::move(*value_ref); + } + return *value_ref; + } + + value_type const& operator*() const + { + return *static_cast<value_type const*>(value_ref); + } + + value_type const* operator->() const + { + return static_cast<value_type const*>(value_ref); + } + + private: + mutable value_type owned_value = nullptr; + value_type* value_ref = nullptr; + const bool is_rvalue; +}; +} +} + +// #include <nlohmann/detail/json_pointer.hpp> + + +#include <cassert> // assert +#include <numeric> // accumulate +#include <string> // string +#include <vector> // vector + +// #include <nlohmann/detail/macro_scope.hpp> + +// #include <nlohmann/detail/exceptions.hpp> + +// #include <nlohmann/detail/value_t.hpp> + + +namespace nlohmann +{ +template<typename BasicJsonType> +class json_pointer +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + public: + /*! + @brief create JSON pointer + + Create a JSON pointer according to the syntax described in + [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). + + @param[in] s string representing the JSON pointer; if omitted, the empty + string is assumed which references the whole JSON value + + @throw parse_error.107 if the given JSON pointer @a s is nonempty and does + not begin with a slash (`/`); see example below + + @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is + not followed by `0` (representing `~`) or `1` (representing `/`); see + example below + + @liveexample{The example shows the construction several valid JSON pointers + as well as the exceptional behavior.,json_pointer} + + @since version 2.0.0 + */ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`., + json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const noexcept + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + escape(b); + }); + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); + } + + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw out_of_range.404 if string @a s could not be converted to an integer + */ + static int array_index(const std::string& s) + { + std::size_t processed_chars = 0; + const int res = std::stoi(s, &processed_chars); + + // check if the string was completely read + if (JSON_UNLIKELY(processed_chars != s.size())) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); + } + + return res; + } + + private: + /*! + @brief remove and return last reference pointer + @throw out_of_range.405 if JSON pointer has no parent + */ + std::string pop_back() + { + if (JSON_UNLIKELY(is_root())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + auto last = reference_tokens.back(); + reference_tokens.pop_back(); + return last; + } + + /// return whether pointer points to the root document + bool is_root() const + { + return reference_tokens.empty(); + } + + json_pointer top() const + { + if (JSON_UNLIKELY(is_root())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + BasicJsonType& get_and_create(BasicJsonType& j) const + { + using size_type = typename BasicJsonType::size_type; + auto result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->m_type) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + JSON_TRY + { + result = &result->operator[](static_cast<size_type>(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->m_type == detail::value_t::null) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const char x) + { + return (x >= '0' and x <= '9'); + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums or reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->m_type) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + JSON_TRY + { + ptr = &ptr->operator[]( + static_cast<size_type>(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast<size_type>(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // use unchecked array access + JSON_TRY + { + ptr = &ptr->operator[]( + static_cast<size_type>(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->m_type) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast<size_type>(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector<std::string> split(const std::string& reference_string) + { + std::vector<std::string> result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == string::npos+1 = 0 + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + assert(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_UNLIKELY(pos == reference_token.size() - 1 or + (reference_token[pos + 1] != '0' and + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); + } + } + + // finally, store the reference token + unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + /*! + @brief replace all occurrences of a substring by another string + + @param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t + @param[in] f the substring to replace with @a t + @param[in] t the string to replace @a f + + @pre The search string @a f must not be empty. **This precondition is + enforced with an assertion.** + + @since version 2.0.0 + */ + static void replace_substring(std::string& s, const std::string& f, + const std::string& t) + { + assert(not f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} + } + + /// escape "~"" to "~0" and "/" to "~1" + static std::string escape(std::string s) + { + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; + } + + /// unescape "~1" to tilde and "~0" to slash (order is important!) + static void unescape(std::string& s) + { + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); + } + + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + static void flatten(const std::string& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.m_type) + { + case detail::value_t::array: + { + if (value.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_value.object) + { + flatten(reference_string + "/" + escape(element.first), element.second, result); + } + } + break; + } + + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_UNLIKELY(not value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (JSON_UNLIKELY(not element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return (lhs.reference_tokens == rhs.reference_tokens); + } + + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return not (lhs == rhs); + } + + /// the reference tokens + std::vector<std::string> reference_tokens; +}; +} + +// #include <nlohmann/adl_serializer.hpp> + + +#include <utility> + +// #include <nlohmann/detail/conversions/from_json.hpp> + +// #include <nlohmann/detail/conversions/to_json.hpp> + + +namespace nlohmann +{ +template<typename, typename> +struct adl_serializer +{ + /*! + @brief convert a JSON value to any value type + + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). + + @param[in] j JSON value to read from + @param[in,out] val value to write to + */ + template<typename BasicJsonType, typename ValueType> + static void from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) + { + ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); + } + + /*! + @brief convert any value type to a JSON value + + This function is usually called by the constructors of the @ref basic_json + class. + + @param[in,out] j JSON value to write to + @param[in] val value to read from + */ + template<typename BasicJsonType, typename ValueType> + static void to_json(BasicJsonType& j, ValueType&& val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val)))) + { + ::nlohmann::to_json(j, std::forward<ValueType>(val)); + } +}; +} + + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ + +/*! +@brief a class to store JSON values + +@tparam ObjectType type for JSON objects (`std::map` by default; will be used +in @ref object_t) +@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used +in @ref array_t) +@tparam StringType type for JSON strings and object keys (`std::string` by +default; will be used in @ref string_t) +@tparam BooleanType type for JSON booleans (`bool` by default; will be used +in @ref boolean_t) +@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by +default; will be used in @ref number_integer_t) +@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c +`uint64_t` by default; will be used in @ref number_unsigned_t) +@tparam NumberFloatType type for JSON floating-point numbers (`double` by +default; will be used in @ref number_float_t) +@tparam AllocatorType type of the allocator to use (`std::allocator` by +default) +@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` +and `from_json()` (@ref adl_serializer by default) + +@requirement The class satisfies the following concept requirements: +- Basic + - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): + JSON values can be default constructed. The result will be a JSON null + value. + - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): + A JSON value can be constructed from an rvalue argument. + - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): + A JSON value can be copy-constructed from an lvalue expression. + - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): + A JSON value van be assigned from an rvalue argument. + - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): + A JSON value can be copy-assigned from an lvalue expression. + - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): + JSON values can be destructed. +- Layout + - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): + JSON values have + [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): + All non-static data members are private and standard layout types, the + class has no virtual functions or (virtual) base classes. +- Library-wide + - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): + JSON values can be compared with `==`, see @ref + operator==(const_reference,const_reference). + - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): + JSON values can be compared with `<`, see @ref + operator<(const_reference,const_reference). + - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): + Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of + other compatible types, using unqualified function call @ref swap(). + - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): + JSON values can be compared against `std::nullptr_t` objects which are used + to model the `null` value. +- Container + - [Container](http://en.cppreference.com/w/cpp/concept/Container): + JSON values can be used like STL containers and provide iterator access. + - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); + JSON values can be used like STL containers and provide reverse iterator + access. + +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + +@internal +@note ObjectType trick from http://stackoverflow.com/a/9860911 +@endinternal + +@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange +Format](http://rfc7159.net/rfc7159) + +@since version 1.0.0 + +@nosubgrouping +*/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +class basic_json +{ + private: + template<detail::value_t> friend struct detail::external_constructor; + friend ::nlohmann::json_pointer<basic_json>; + friend ::nlohmann::detail::parser<basic_json>; + friend ::nlohmann::detail::serializer<basic_json>; + template<typename BasicJsonType> + friend class ::nlohmann::detail::iter_impl; + template<typename BasicJsonType, typename CharType> + friend class ::nlohmann::detail::binary_writer; + template<typename BasicJsonType> + friend class ::nlohmann::detail::binary_reader; + template<typename BasicJsonType> + friend class ::nlohmann::detail::json_sax_dom_parser; + template<typename BasicJsonType> + friend class ::nlohmann::detail::json_sax_dom_callback_parser; + + /// workaround type for MSVC + using basic_json_t = NLOHMANN_BASIC_JSON_TPL; + + // convenience aliases for types residing in namespace detail; + using lexer = ::nlohmann::detail::lexer<basic_json>; + using parser = ::nlohmann::detail::parser<basic_json>; + + using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; + template<typename BasicJsonType> + using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; + template<typename BasicJsonType> + using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; + template<typename Iterator> + using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; + template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; + + template<typename CharType> + using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; + + using binary_reader = ::nlohmann::detail::binary_reader<basic_json>; + template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; + + using serializer = ::nlohmann::detail::serializer<basic_json>; + + public: + using value_t = detail::value_t; + /// @copydoc nlohmann::json_pointer + using json_pointer = ::nlohmann::json_pointer<basic_json>; + template<typename T, typename SFINAE> + using json_serializer = JSONSerializer<T, SFINAE>; + /// helper type for initializer lists of basic_json values + using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; + + using input_format_t = detail::input_format_t; + + //////////////// + // exceptions // + //////////////// + + /// @name exceptions + /// Classes to implement user-defined exceptions. + /// @{ + + /// @copydoc detail::exception + using exception = detail::exception; + /// @copydoc detail::parse_error + using parse_error = detail::parse_error; + /// @copydoc detail::invalid_iterator + using invalid_iterator = detail::invalid_iterator; + /// @copydoc detail::type_error + using type_error = detail::type_error; + /// @copydoc detail::out_of_range + using out_of_range = detail::out_of_range; + /// @copydoc detail::other_error + using other_error = detail::other_error; + + /// @} + + + ///////////////////// + // container types // + ///////////////////// + + /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. + /// @{ + + /// the type of elements in a basic_json container + using value_type = basic_json; + + /// the type of an element reference + using reference = value_type&; + /// the type of an element const reference + using const_reference = const value_type&; + + /// a type to represent differences between iterators + using difference_type = std::ptrdiff_t; + /// a type to represent container sizes + using size_type = std::size_t; + + /// the allocator type + using allocator_type = AllocatorType<basic_json>; + + /// the type of an element pointer + using pointer = typename std::allocator_traits<allocator_type>::pointer; + /// the type of an element const pointer + using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; + + /// an iterator for a basic_json container + using iterator = iter_impl<basic_json>; + /// a const iterator for a basic_json container + using const_iterator = iter_impl<const basic_json>; + /// a reverse iterator for a basic_json container + using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; + /// a const reverse iterator for a basic_json container + using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; + + /// @} + + + /*! + @brief returns the allocator associated with the container + */ + static allocator_type get_allocator() + { + return allocator_type(); + } + + /*! + @brief returns version information on the library + + This function returns a JSON object with information about the library, + including the version number and information on the platform and compiler. + + @return JSON object holding version information + key | description + ----------- | --------------- + `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). + `copyright` | The copyright line for the library as string. + `name` | The name of the library as string. + `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. + `url` | The URL of the project as string. + `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). + + @liveexample{The following code shows an example output of the `meta()` + function.,meta} + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @complexity Constant. + + @since 2.1.0 + */ + static basic_json meta() + { + basic_json result; + + result["copyright"] = "(C) 2013-2017 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"]["string"] = + std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_PATCH); + result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; + result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; + result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; + +#ifdef _WIN32 + result["platform"] = "win32"; +#elif defined __linux__ + result["platform"] = "linux"; +#elif defined __APPLE__ + result["platform"] = "apple"; +#elif defined __unix__ + result["platform"] = "unix"; +#else + result["platform"] = "unknown"; +#endif + +#if defined(__ICC) || defined(__INTEL_COMPILER) + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; +#elif defined(__clang__) + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; +#elif defined(__GNUC__) || defined(__GNUG__) + result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; +#elif defined(__HP_cc) || defined(__HP_aCC) + result["compiler"] = "hp" +#elif defined(__IBMCPP__) + result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; +#elif defined(_MSC_VER) + result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; +#elif defined(__PGI) + result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; +#elif defined(__SUNPRO_CC) + result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; +#else + result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; +#endif + +#ifdef __cplusplus + result["compiler"]["c++"] = std::to_string(__cplusplus); +#else + result["compiler"]["c++"] = "unknown"; +#endif + return result; + } + + + /////////////////////////// + // JSON value data types // + /////////////////////////// + + /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. + /// @{ + +#if defined(JSON_HAS_CPP_14) + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; +#else + using object_comparator_t = std::less<StringType>; +#endif + + /*! + @brief a type for an object + + [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: + > An object is an unordered collection of zero or more name/value pairs, + > where a name is a string and a value is a string, number, boolean, null, + > object, or array. + + To store objects in C++, a type is defined by the template parameters + described below. + + @tparam ObjectType the container to store objects (e.g., `std::map` or + `std::unordered_map`) + @tparam StringType the type of the keys or names (e.g., `std::string`). + The comparison function `std::less<StringType>` is used to order elements + inside the container. + @tparam AllocatorType the allocator to use for objects (e.g., + `std::allocator`) + + #### Default type + + With the default values for @a ObjectType (`std::map`), @a StringType + (`std::string`), and @a AllocatorType (`std::allocator`), the default + value for @a object_t is: + + @code {.cpp} + std::map< + std::string, // key_type + basic_json, // value_type + std::less<std::string>, // key_compare + std::allocator<std::pair<const std::string, basic_json>> // allocator_type + > + @endcode + + #### Behavior + + The choice of @a object_t influences the behavior of the JSON class. With + the default type, objects have the following behavior: + + - When all names are unique, objects will be interoperable in the sense + that all software implementations receiving that object will agree on + the name-value mappings. + - When the names within an object are not unique, it is unspecified which + one of the values for a given key will be chosen. For instance, + `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or + `{"key": 2}`. + - Internally, name/value pairs are stored in lexicographical order of the + names. Objects will also be serialized (see @ref dump) in this order. + For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored + and serialized as `{"a": 2, "b": 1}`. + - When comparing objects, the order of the name/value pairs is irrelevant. + This makes objects interoperable in the sense that they will not be + affected by these differences. For instance, `{"b": 1, "a": 2}` and + `{"a": 2, "b": 1}` will be treated as equal. + + #### Limits + + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the maximum depth of nesting. + + In this class, the object's limit of nesting is not explicitly constrained. + However, a maximum depth of nesting may be introduced by the compiler or + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON object. + + #### Storage + + Objects are stored as pointers in a @ref basic_json type. That is, for any + access to object values, a pointer of type `object_t*` must be + dereferenced. + + @sa @ref array_t -- type for an array value + + @since version 1.0.0 + + @note The order name/value pairs are added to the object is *not* + preserved by the library. Therefore, iterating an object may return + name/value pairs in a different order than they were originally stored. In + fact, keys will be traversed in alphabetical order as `std::map` with + `std::less` is used by default. Please note this behavior conforms to [RFC + 7159](http://rfc7159.net/rfc7159), because any order implements the + specified "unordered" nature of JSON objects. + */ + using object_t = ObjectType<StringType, + basic_json, + object_comparator_t, + AllocatorType<std::pair<const StringType, + basic_json>>>; + + /*! + @brief a type for an array + + [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: + > An array is an ordered sequence of zero or more values. + + To store objects in C++, a type is defined by the template parameters + explained below. + + @tparam ArrayType container type to store arrays (e.g., `std::vector` or + `std::list`) + @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) + + #### Default type + + With the default values for @a ArrayType (`std::vector`) and @a + AllocatorType (`std::allocator`), the default value for @a array_t is: + + @code {.cpp} + std::vector< + basic_json, // value_type + std::allocator<basic_json> // allocator_type + > + @endcode + + #### Limits + + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the maximum depth of nesting. + + In this class, the array's limit of nesting is not explicitly constrained. + However, a maximum depth of nesting may be introduced by the compiler or + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON array. + + #### Storage + + Arrays are stored as pointers in a @ref basic_json type. That is, for any + access to array values, a pointer of type `array_t*` must be dereferenced. + + @sa @ref object_t -- type for an object value + + @since version 1.0.0 + */ + using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; + + /*! + @brief a type for a string + + [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: + > A string is a sequence of zero or more Unicode characters. + + To store objects in C++, a type is defined by the template parameter + described below. Unicode values are split by the JSON class into + byte-sized characters during deserialization. + + @tparam StringType the container to store strings (e.g., `std::string`). + Note this container is used for keys/names in objects, see @ref object_t. + + #### Default type + + With the default values for @a StringType (`std::string`), the default + value for @a string_t is: + + @code {.cpp} + std::string + @endcode + + #### Encoding + + Strings are stored in UTF-8 encoding. Therefore, functions like + `std::string::size()` or `std::string::length()` return the number of + bytes in the string rather than the number of characters or glyphs. + + #### String comparison + + [RFC 7159](http://rfc7159.net/rfc7159) states: + > Software implementations are typically required to test names of object + > members for equality. Implementations that transform the textual + > representation into sequences of Unicode code units and then perform the + > comparison numerically, code unit by code unit, are interoperable in the + > sense that implementations will agree in all cases on equality or + > inequality of two strings. For example, implementations that compare + > strings with escaped characters unconverted may incorrectly find that + > `"a\\b"` and `"a\u005Cb"` are not equal. + + This implementation is interoperable as it does compare strings code unit + by code unit. + + #### Storage + + String values are stored as pointers in a @ref basic_json type. That is, + for any access to string values, a pointer of type `string_t*` must be + dereferenced. + + @since version 1.0.0 + */ + using string_t = StringType; + + /*! + @brief a type for a boolean + + [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a + type which differentiates the two literals `true` and `false`. + + To store objects in C++, a type is defined by the template parameter @a + BooleanType which chooses the type to use. + + #### Default type + + With the default values for @a BooleanType (`bool`), the default value for + @a boolean_t is: + + @code {.cpp} + bool + @endcode + + #### Storage + + Boolean values are stored directly inside a @ref basic_json type. + + @since version 1.0.0 + */ + using boolean_t = BooleanType; + + /*! + @brief a type for a number (integer) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store integer numbers in C++, a type is defined by the template + parameter @a NumberIntegerType which chooses the type to use. + + #### Default type + + With the default values for @a NumberIntegerType (`int64_t`), the default + value for @a number_integer_t is: + + @code {.cpp} + int64_t + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the range and precision of numbers. + + When the default type is used, the maximal integer number that can be + stored is `9223372036854775807` (INT64_MAX) and the minimal integer number + that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers + that are out of range will yield over/underflow when used in a + constructor. During deserialization, too large or small integer numbers + will be automatically be stored as @ref number_unsigned_t or @ref + number_float_t. + + [RFC 7159](http://rfc7159.net/rfc7159) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. + + As this range is a subrange of the exactly supported range [INT64_MIN, + INT64_MAX], this class's integer type is interoperable. + + #### Storage + + Integer number values are stored directly inside a @ref basic_json type. + + @sa @ref number_float_t -- type for number values (floating-point) + + @sa @ref number_unsigned_t -- type for number values (unsigned integer) + + @since version 1.0.0 + */ + using number_integer_t = NumberIntegerType; + + /*! + @brief a type for a number (unsigned) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store unsigned integer numbers in C++, a type is defined by the + template parameter @a NumberUnsignedType which chooses the type to use. + + #### Default type + + With the default values for @a NumberUnsignedType (`uint64_t`), the + default value for @a number_unsigned_t is: + + @code {.cpp} + uint64_t + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 7159](http://rfc7159.net/rfc7159) specifies: + > An implementation may set limits on the range and precision of numbers. + + When the default type is used, the maximal integer number that can be + stored is `18446744073709551615` (UINT64_MAX) and the minimal integer + number that can be stored is `0`. Integer numbers that are out of range + will yield over/underflow when used in a constructor. During + deserialization, too large or small integer numbers will be automatically + be stored as @ref number_integer_t or @ref number_float_t. + + [RFC 7159](http://rfc7159.net/rfc7159) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. + + As this range is a subrange (when considered in conjunction with the + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. + + #### Storage + + Integer number values are stored directly inside a @ref basic_json type. + + @sa @ref number_float_t -- type for number values (floating-point) + @sa @ref number_integer_t -- type for number values (integer) + + @since version 2.0.0 + */ + using number_unsigned_t = NumberUnsignedType; + + /*! + @brief a type for a number (floating-point) + + [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store floating-point numbers in C++, a type is defined by the template + parameter @a NumberFloatType which chooses the type to use. + + #### Default type + + With the default values for @a NumberFloatType (`double`), the default + value for @a number_float_t is: + + @code {.cpp} + double + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in floating-point literals will be ignored. Internally, + the value will be stored as decimal number. For instance, the C++ + floating-point literal `01.2` will be serialized to `1.2`. During + deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 7159](http://rfc7159.net/rfc7159) states: + > This specification allows implementations to set limits on the range and + > precision of numbers accepted. Since software that implements IEEE + > 754-2008 binary64 (double precision) numbers is generally available and + > widely used, good interoperability can be achieved by implementations + > that expect no more precision or range than these provide, in the sense + > that implementations will approximate JSON numbers within the expected + > precision. + + This implementation does exactly follow this approach, as it uses double + precision floating-point numbers. Note values smaller than + `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` + will be stored as NaN internally and be serialized to `null`. + + #### Storage + + Floating-point number values are stored directly inside a @ref basic_json + type. + + @sa @ref number_integer_t -- type for number values (integer) + + @sa @ref number_unsigned_t -- type for number values (unsigned integer) + + @since version 1.0.0 + */ + using number_float_t = NumberFloatType; + + /// @} + + private: + + /// helper for exception-safe object creation + template<typename T, typename... Args> + static T* create(Args&& ... args) + { + AllocatorType<T> alloc; + using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; + + auto deleter = [&](T * object) + { + AllocatorTraits::deallocate(alloc, object, 1); + }; + std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter); + AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...); + assert(object != nullptr); + return object.release(); + } + + //////////////////////// + // JSON value storage // + //////////////////////// + + /*! + @brief a JSON value + + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. + + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + null | null | *no value is stored* + + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. + + @since version 1.0.0 + */ + union json_value + { + /// object (stored with pointer to save storage) + object_t* object; + /// array (stored with pointer to save storage) + array_t* array; + /// string (stored with pointer to save storage) + string_t* string; + /// boolean + boolean_t boolean; + /// number (integer) + number_integer_t number_integer; + /// number (unsigned integer) + number_unsigned_t number_unsigned; + /// number (floating-point) + number_float_t number_float; + + /// default constructor (for null values) + json_value() = default; + /// constructor for booleans + json_value(boolean_t v) noexcept : boolean(v) {} + /// constructor for numbers (integer) + json_value(number_integer_t v) noexcept : number_integer(v) {} + /// constructor for numbers (unsigned) + json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} + /// constructor for numbers (floating-point) + json_value(number_float_t v) noexcept : number_float(v) {} + /// constructor for empty values of a given type + json_value(value_t t) + { + switch (t) + { + case value_t::object: + { + object = create<object_t>(); + break; + } + + case value_t::array: + { + array = create<array_t>(); + break; + } + + case value_t::string: + { + string = create<string_t>(""); + break; + } + + case value_t::boolean: + { + boolean = boolean_t(false); + break; + } + + case value_t::number_integer: + { + number_integer = number_integer_t(0); + break; + } + + case value_t::number_unsigned: + { + number_unsigned = number_unsigned_t(0); + break; + } + + case value_t::number_float: + { + number_float = number_float_t(0.0); + break; + } + + case value_t::null: + { + object = nullptr; // silence warning, see #821 + break; + } + + default: + { + object = nullptr; // silence warning, see #821 + if (JSON_UNLIKELY(t == value_t::null)) + { + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.1.2")); // LCOV_EXCL_LINE + } + break; + } + } + } + + /// constructor for strings + json_value(const string_t& value) + { + string = create<string_t>(value); + } + + /// constructor for rvalue strings + json_value(string_t&& value) + { + string = create<string_t>(std::move(value)); + } + + /// constructor for objects + json_value(const object_t& value) + { + object = create<object_t>(value); + } + + /// constructor for rvalue objects + json_value(object_t&& value) + { + object = create<object_t>(std::move(value)); + } + + /// constructor for arrays + json_value(const array_t& value) + { + array = create<array_t>(value); + } + + /// constructor for rvalue arrays + json_value(array_t&& value) + { + array = create<array_t>(std::move(value)); + } + + void destroy(value_t t) noexcept + { + switch (t) + { + case value_t::object: + { + AllocatorType<object_t> alloc; + std::allocator_traits<decltype(alloc)>::destroy(alloc, object); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); + break; + } + + case value_t::array: + { + AllocatorType<array_t> alloc; + std::allocator_traits<decltype(alloc)>::destroy(alloc, array); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); + break; + } + + case value_t::string: + { + AllocatorType<string_t> alloc; + std::allocator_traits<decltype(alloc)>::destroy(alloc, string); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); + break; + } + + default: + { + break; + } + } + } + }; + + /*! + @brief checks the class invariants + + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. + */ + void assert_invariant() const noexcept + { + assert(m_type != value_t::object or m_value.object != nullptr); + assert(m_type != value_t::array or m_value.array != nullptr); + assert(m_type != value_t::string or m_value.string != nullptr); + } + + public: + ////////////////////////// + // JSON parser callback // + ////////////////////////// + + /*! + @brief parser event types + + The parser callback distinguishes the following events: + - `object_start`: the parser read `{` and started to process a JSON object + - `key`: the parser read a key of a value in an object + - `object_end`: the parser read `}` and finished processing a JSON object + - `array_start`: the parser read `[` and started to process a JSON array + - `array_end`: the parser read `]` and finished processing a JSON array + - `value`: the parser finished reading a JSON value + + @image html callback_events.png "Example when certain parse events are triggered" + + @sa @ref parser_callback_t for more information and examples + */ + using parse_event_t = typename parser::parse_event_t; + + /*! + @brief per-element parser callback type + + With a parser callback function, the result of parsing a JSON text can be + influenced. When passed to @ref parse, it is called on certain events + (passed as @ref parse_event_t via parameter @a event) with a set recursion + depth @a depth and context JSON value @a parsed. The return value of the + callback function is a boolean indicating whether the element that emitted + the callback shall be kept or not. + + We distinguish six scenarios (determined by the event type) in which the + callback function can be called. The following table describes the values + of the parameters @a depth, @a event, and @a parsed. + + parameter @a event | description | parameter @a depth | parameter @a parsed + ------------------ | ----------- | ------------------ | ------------------- + parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded + parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key + parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object + parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded + parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array + parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value + + @image html callback_events.png "Example when certain parse events are triggered" + + Discarding a value (i.e., returning `false`) has different effects + depending on the context in which function was called: + + - Discarded values in structured types are skipped. That is, the parser + will behave as if the discarded value was never read. + - In case a value outside a structured type is skipped, it is replaced + with `null`. This case happens if the top-level element is skipped. + + @param[in] depth the depth of the recursion during parsing + + @param[in] event an event of type parse_event_t indicating the context in + the callback function has been called + + @param[in,out] parsed the current intermediate parse result; note that + writing to this value has no effect for parse_event_t::key events + + @return Whether the JSON value which called the function during parsing + should be kept (`true`) or not (`false`). In the latter case, it is either + skipped completely or replaced by an empty discarded object. + + @sa @ref parse for examples + + @since version 1.0.0 + */ + using parser_callback_t = typename parser::parser_callback_t; + + using json_sax_t = typename parser::json_sax_t; + + ////////////////// + // constructors // + ////////////////// + + /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. + /// @{ + + /*! + @brief create an empty value with a given type + + Create an empty JSON value with a given type. The value will be default + initialized with an empty value which depends on the type: + + Value type | initial value + ----------- | ------------- + null | `null` + boolean | `false` + string | `""` + number | `0` + object | `{}` + array | `[]` + + @param[in] v the type of the value to create + + @complexity Constant. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows the constructor for different @ref + value_t values,basic_json__value_t} + + @sa @ref clear() -- restores the postcondition of this constructor + + @since version 1.0.0 + */ + basic_json(const value_t v) + : m_type(v), m_value(v) + { + assert_invariant(); + } + + /*! + @brief create a null object + + Create a `null` JSON value. It either takes a null pointer as parameter + (explicitly creating `null`) or no parameter (implicitly creating `null`). + The passed null pointer itself is not read -- it is only used to choose + the right constructor. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this constructor never throws + exceptions. + + @liveexample{The following code shows the constructor with and without a + null pointer parameter.,basic_json__nullptr_t} + + @since version 1.0.0 + */ + basic_json(std::nullptr_t = nullptr) noexcept + : basic_json(value_t::null) + { + assert_invariant(); + } + + /*! + @brief create a JSON value + + This is a "catch all" constructor for all compatible JSON types; that is, + types for which a `to_json()` method exists. The constructor forwards the + parameter @a val to that method (to `json_serializer<U>::to_json` method + with `U = uncvref_t<CompatibleType>`, to be exact). + + Template type @a CompatibleType includes, but is not limited to, the + following types: + - **arrays**: @ref array_t and all kinds of compatible containers such as + `std::vector`, `std::deque`, `std::list`, `std::forward_list`, + `std::array`, `std::valarray`, `std::set`, `std::unordered_set`, + `std::multiset`, and `std::unordered_multiset` with a `value_type` from + which a @ref basic_json value can be constructed. + - **objects**: @ref object_t and all kinds of compatible associative + containers such as `std::map`, `std::unordered_map`, `std::multimap`, + and `std::unordered_multimap` with a `key_type` compatible to + @ref string_t and a `value_type` from which a @ref basic_json value can + be constructed. + - **strings**: @ref string_t, string literals, and all compatible string + containers can be used. + - **numbers**: @ref number_integer_t, @ref number_unsigned_t, + @ref number_float_t, and all convertible number types such as `int`, + `size_t`, `int64_t`, `float` or `double` can be used. + - **boolean**: @ref boolean_t / `bool` can be used. + + See the examples below. + + @tparam CompatibleType a type such that: + - @a CompatibleType is not derived from `std::istream`, + - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move + constructors), + - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments) + - @a CompatibleType is not a @ref basic_json nested type (e.g., + @ref json_pointer, @ref iterator, etc ...) + - @ref @ref json_serializer<U> has a + `to_json(basic_json_t&, CompatibleType&&)` method + + @tparam U = `uncvref_t<CompatibleType>` + + @param[in] val the value to be forwarded to the respective constructor + + @complexity Usually linear in the size of the passed @a val, also + depending on the implementation of the called `to_json()` + method. + + @exceptionsafety Depends on the called constructor. For types directly + supported by the library (i.e., all types for which no `to_json()` function + was provided), strong guarantee holds: if an exception is thrown, there are + no changes to any JSON value. + + @liveexample{The following code shows the constructor with several + compatible types.,basic_json__CompatibleType} + + @since version 2.1.0 + */ + template <typename CompatibleType, + typename U = detail::uncvref_t<CompatibleType>, + detail::enable_if_t< + detail::is_compatible_type<basic_json_t, U>::value, int> = 0> + basic_json(CompatibleType && val) noexcept(noexcept( + JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), + std::forward<CompatibleType>(val)))) + { + JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); + assert_invariant(); + } + + /*! + @brief create a JSON value from an existing one + + This is a constructor for existing @ref basic_json types. + It does not hijack copy/move constructors, since the parameter has different + template arguments than the current ones. + + The constructor tries to convert the internal @ref m_value of the parameter. + + @tparam BasicJsonType a type such that: + - @a BasicJsonType is a @ref basic_json type. + - @a BasicJsonType has different template arguments than @ref basic_json_t. + + @param[in] val the @ref basic_json value to be converted. + + @complexity Usually linear in the size of the passed @a val, also + depending on the implementation of the called `to_json()` + method. + + @exceptionsafety Depends on the called constructor. For types directly + supported by the library (i.e., all types for which no `to_json()` function + was provided), strong guarantee holds: if an exception is thrown, there are + no changes to any JSON value. + + @since version 3.1.2 + */ + template <typename BasicJsonType, + detail::enable_if_t< + detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0> + basic_json(const BasicJsonType& val) + { + using other_boolean_t = typename BasicJsonType::boolean_t; + using other_number_float_t = typename BasicJsonType::number_float_t; + using other_number_integer_t = typename BasicJsonType::number_integer_t; + using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using other_string_t = typename BasicJsonType::string_t; + using other_object_t = typename BasicJsonType::object_t; + using other_array_t = typename BasicJsonType::array_t; + + switch (val.type()) + { + case value_t::boolean: + JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); + break; + case value_t::number_float: + JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); + break; + case value_t::number_integer: + JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); + break; + case value_t::number_unsigned: + JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); + break; + case value_t::string: + JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); + break; + case value_t::object: + JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); + break; + case value_t::array: + JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); + break; + case value_t::null: + *this = nullptr; + break; + case value_t::discarded: + m_type = value_t::discarded; + break; + } + assert_invariant(); + } + + /*! + @brief create a container (array or object) from an initializer list + + Creates a JSON value of type array or object from the passed initializer + list @a init. In case @a type_deduction is `true` (default), the type of + the JSON value to be created is deducted from the initializer list @a init + according to the following rules: + + 1. If the list is empty, an empty JSON object value `{}` is created. + 2. If the list consists of pairs whose first element is a string, a JSON + object value is created where the first elements of the pairs are + treated as keys and the second elements are as values. + 3. In all other cases, an array is created. + + The rules aim to create the best fit between a C++ initializer list and + JSON values. The rationale is as follows: + + 1. The empty initializer list is written as `{}` which is exactly an empty + JSON object. + 2. C++ has no way of describing mapped types other than to list a list of + pairs. As JSON requires that keys must be of type string, rule 2 is the + weakest constraint one can pose on initializer lists to interpret them + as an object. + 3. In all other cases, the initializer list could not be interpreted as + JSON object type, so interpreting it as JSON array type is safe. + + With the rules described above, the following JSON values cannot be + expressed by an initializer list: + + - the empty array (`[]`): use @ref array(initializer_list_t) + with an empty initializer list in this case + - arrays whose elements satisfy rule 2: use @ref + array(initializer_list_t) with the same initializer list + in this case + + @note When used without parentheses around an empty initializer list, @ref + basic_json() is called instead of this function, yielding the JSON null + value. + + @param[in] init initializer list with JSON values + + @param[in] type_deduction internal parameter; when set to `true`, the type + of the JSON value is deducted from the initializer list @a init; when set + to `false`, the type provided via @a manual_type is forced. This mode is + used by the functions @ref array(initializer_list_t) and + @ref object(initializer_list_t). + + @param[in] manual_type internal parameter; when @a type_deduction is set + to `false`, the created JSON value will use the provided type (only @ref + value_t::array and @ref value_t::object are valid); when @a type_deduction + is set to `true`, this parameter has no effect + + @throw type_error.301 if @a type_deduction is `false`, @a manual_type is + `value_t::object`, but @a init contains an element which is not a pair + whose first element is a string. In this case, the constructor could not + create an object. If @a type_deduction would have be `true`, an array + would have been created. See @ref object(initializer_list_t) + for an example. + + @complexity Linear in the size of the initializer list @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The example below shows how JSON values are created from + initializer lists.,basic_json__list_init_t} + + @sa @ref array(initializer_list_t) -- create a JSON array + value from an initializer list + @sa @ref object(initializer_list_t) -- create a JSON object + value from an initializer list + + @since version 1.0.0 + */ + basic_json(initializer_list_t init, + bool type_deduction = true, + value_t manual_type = value_t::array) + { + // check if each element is an array with two elements whose first + // element is a string + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const detail::json_ref<basic_json>& element_ref) + { + return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string()); + }); + + // adjust type if type deduction is not wanted + if (not type_deduction) + { + // if array is wanted, do not create an object though possible + if (manual_type == value_t::array) + { + is_an_object = false; + } + + // if object is wanted but impossible, throw an exception + if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object)) + { + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); + } + } + + if (is_an_object) + { + // the initializer list is a list of pairs -> create object + m_type = value_t::object; + m_value = value_t::object; + + std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref) + { + auto element = element_ref.moved_or_copied(); + m_value.object->emplace( + std::move(*((*element.m_value.array)[0].m_value.string)), + std::move((*element.m_value.array)[1])); + }); + } + else + { + // the initializer list describes an array -> create array + m_type = value_t::array; + m_value.array = create<array_t>(init.begin(), init.end()); + } + + assert_invariant(); + } + + /*! + @brief explicitly create an array from an initializer list + + Creates a JSON array value from a given initializer list. That is, given a + list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the + initializer list is empty, the empty array `[]` is created. + + @note This function is only needed to express two edge cases that cannot + be realized with the initializer list constructor (@ref + basic_json(initializer_list_t, bool, value_t)). These cases + are: + 1. creating an array whose elements are all pairs whose first element is a + string -- in this case, the initializer list constructor would create an + object, taking the first elements as keys + 2. creating an empty array -- passing the empty initializer list to the + initializer list constructor yields an empty object + + @param[in] init initializer list with JSON values to create an array from + (optional) + + @return JSON array value + + @complexity Linear in the size of @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows an example for the `array` + function.,array} + + @sa @ref basic_json(initializer_list_t, bool, value_t) -- + create a JSON value from an initializer list + @sa @ref object(initializer_list_t) -- create a JSON object + value from an initializer list + + @since version 1.0.0 + */ + static basic_json array(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::array); + } + + /*! + @brief explicitly create an object from an initializer list + + Creates a JSON object value from a given initializer list. The initializer + lists elements must be pairs, and their first elements must be strings. If + the initializer list is empty, the empty object `{}` is created. + + @note This function is only added for symmetry reasons. In contrast to the + related function @ref array(initializer_list_t), there are + no cases which can only be expressed by this function. That is, any + initializer list @a init can also be passed to the initializer list + constructor @ref basic_json(initializer_list_t, bool, value_t). + + @param[in] init initializer list to create an object from (optional) + + @return JSON object value + + @throw type_error.301 if @a init is not a list of pairs whose first + elements are strings. In this case, no object can be created. When such a + value is passed to @ref basic_json(initializer_list_t, bool, value_t), + an array would have been created from the passed initializer list @a init. + See example below. + + @complexity Linear in the size of @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows an example for the `object` + function.,object} + + @sa @ref basic_json(initializer_list_t, bool, value_t) -- + create a JSON value from an initializer list + @sa @ref array(initializer_list_t) -- create a JSON array + value from an initializer list + + @since version 1.0.0 + */ + static basic_json object(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::object); + } + + /*! + @brief construct an array with count copies of given value + + Constructs a JSON array value by creating @a cnt copies of a passed value. + In case @a cnt is `0`, an empty array is created. + + @param[in] cnt the number of JSON copies of @a val to create + @param[in] val the JSON value to copy + + @post `std::distance(begin(),end()) == cnt` holds. + + @complexity Linear in @a cnt. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows examples for the @ref + basic_json(size_type\, const basic_json&) + constructor.,basic_json__size_type_basic_json} + + @since version 1.0.0 + */ + basic_json(size_type cnt, const basic_json& val) + : m_type(value_t::array) + { + m_value.array = create<array_t>(cnt, val); + assert_invariant(); + } + + /*! + @brief construct a JSON container given an iterator range + + Constructs the JSON value with the contents of the range `[first, last)`. + The semantics depends on the different types a JSON value can have: + - In case of a null type, invalid_iterator.206 is thrown. + - In case of other primitive types (number, boolean, or string), @a first + must be `begin()` and @a last must be `end()`. In this case, the value is + copied. Otherwise, invalid_iterator.204 is thrown. + - In case of structured types (array, object), the constructor behaves as + similar versions for `std::vector` or `std::map`; that is, a JSON array + or object is constructed from the values in the range. + + @tparam InputIT an input iterator type (@ref iterator or @ref + const_iterator) + + @param[in] first begin of the range to copy from (included) + @param[in] last end of the range to copy from (excluded) + + @pre Iterators @a first and @a last must be initialized. **This + precondition is enforced with an assertion (see warning).** If + assertions are switched off, a violation of this precondition yields + undefined behavior. + + @pre Range `[first, last)` is valid. Usually, this precondition cannot be + checked efficiently. Only certain edge cases are detected; see the + description of the exceptions below. A violation of this precondition + yields undefined behavior. + + @warning A precondition is enforced with a runtime assertion that will + result in calling `std::abort` if this precondition is not met. + Assertions can be disabled by defining `NDEBUG` at compile time. + See http://en.cppreference.com/w/cpp/error/assert for more + information. + + @throw invalid_iterator.201 if iterators @a first and @a last are not + compatible (i.e., do not belong to the same JSON value). In this case, + the range `[first, last)` is undefined. + @throw invalid_iterator.204 if iterators @a first and @a last belong to a + primitive type (number, boolean, or string), but @a first does not point + to the first element any more. In this case, the range `[first, last)` is + undefined. See example code below. + @throw invalid_iterator.206 if iterators @a first and @a last belong to a + null value. In this case, the range `[first, last)` is undefined. + + @complexity Linear in distance between @a first and @a last. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The example below shows several ways to create JSON values by + specifying a subrange with iterators.,basic_json__InputIt_InputIt} + + @since version 1.0.0 + */ + template<class InputIT, typename std::enable_if< + std::is_same<InputIT, typename basic_json_t::iterator>::value or + std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0> + basic_json(InputIT first, InputIT last) + { + assert(first.m_object != nullptr); + assert(last.m_object != nullptr); + + // make sure iterator fits the current value + if (JSON_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); + } + + // copy type from first iterator + m_type = first.m_object->m_type; + + // check if iterator range is complete for primitive values + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + { + if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin() + or not last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + } + break; + } + + default: + break; + } + + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = first.m_object->m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = first.m_object->m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value.number_float = first.m_object->m_value.number_float; + break; + } + + case value_t::boolean: + { + m_value.boolean = first.m_object->m_value.boolean; + break; + } + + case value_t::string: + { + m_value = *first.m_object->m_value.string; + break; + } + + case value_t::object: + { + m_value.object = create<object_t>(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + m_value.array = create<array_t>(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + default: + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + + std::string(first.m_object->type_name()))); + } + + assert_invariant(); + } + + + /////////////////////////////////////// + // other constructors and destructor // + /////////////////////////////////////// + + /// @private + basic_json(const detail::json_ref<basic_json>& ref) + : basic_json(ref.moved_or_copied()) + {} + + /*! + @brief copy constructor + + Creates a copy of a given JSON value. + + @param[in] other the JSON value to copy + + @post `*this == other` + + @complexity Linear in the size of @a other. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is linear. + - As postcondition, it holds: `other == basic_json(other)`. + + @liveexample{The following code shows an example for the copy + constructor.,basic_json__basic_json} + + @since version 1.0.0 + */ + basic_json(const basic_json& other) + : m_type(other.m_type) + { + // check of passed value is valid + other.assert_invariant(); + + switch (m_type) + { + case value_t::object: + { + m_value = *other.m_value.object; + break; + } + + case value_t::array: + { + m_value = *other.m_value.array; + break; + } + + case value_t::string: + { + m_value = *other.m_value.string; + break; + } + + case value_t::boolean: + { + m_value = other.m_value.boolean; + break; + } + + case value_t::number_integer: + { + m_value = other.m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value = other.m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value = other.m_value.number_float; + break; + } + + default: + break; + } + + assert_invariant(); + } + + /*! + @brief move constructor + + Move constructor. Constructs a JSON value with the contents of the given + value @a other using move semantics. It "steals" the resources from @a + other and leaves it as JSON null value. + + @param[in,out] other value to move to this object + + @post `*this` has the same value as @a other before the call. + @post @a other is a JSON null value. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this constructor never throws + exceptions. + + @requirement This function helps `basic_json` satisfying the + [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible) + requirements. + + @liveexample{The code below shows the move constructor explicitly called + via std::move.,basic_json__moveconstructor} + + @since version 1.0.0 + */ + basic_json(basic_json&& other) noexcept + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) + { + // check that passed value is valid + other.assert_invariant(); + + // invalidate payload + other.m_type = value_t::null; + other.m_value = {}; + + assert_invariant(); + } + + /*! + @brief copy assignment + + Copy assignment operator. Copies a JSON value via the "copy and swap" + strategy: It is expressed in terms of the copy constructor, destructor, + and the `swap()` member function. + + @param[in] other value to copy from + + @complexity Linear. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is linear. + + @liveexample{The code below shows and example for the copy assignment. It + creates a copy of value `a` which is then swapped with `b`. Finally\, the + copy of `a` (which is the null value after the swap) is + destroyed.,basic_json__copyassignment} + + @since version 1.0.0 + */ + reference& operator=(basic_json other) noexcept ( + std::is_nothrow_move_constructible<value_t>::value and + std::is_nothrow_move_assignable<value_t>::value and + std::is_nothrow_move_constructible<json_value>::value and + std::is_nothrow_move_assignable<json_value>::value + ) + { + // check that passed value is valid + other.assert_invariant(); + + using std::swap; + swap(m_type, other.m_type); + swap(m_value, other.m_value); + + assert_invariant(); + return *this; + } + + /*! + @brief destructor + + Destroys the JSON value and frees all allocated memory. + + @complexity Linear. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is linear. + - All stored elements are destroyed and all memory is freed. + + @since version 1.0.0 + */ + ~basic_json() noexcept + { + assert_invariant(); + m_value.destroy(m_type); + } + + /// @} + + public: + /////////////////////// + // object inspection // + /////////////////////// + + /// @name object inspection + /// Functions to inspect the type of a JSON value. + /// @{ + + /*! + @brief serialization + + Serialization function for JSON values. The function tries to mimic + Python's `json.dumps()` function, and currently supports its @a indent + and @a ensure_ascii parameters. + + @param[in] indent If indent is nonnegative, then array elements and object + members will be pretty-printed with that indent level. An indent level of + `0` will only insert newlines. `-1` (the default) selects the most compact + representation. + @param[in] indent_char The character to use for indentation if @a indent is + greater than `0`. The default is ` ` (space). + @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters + in the output are escaped with `\uXXXX` sequences, and the result consists + of ASCII characters only. + + @return string containing the serialization of the JSON value + + @throw type_error.316 if a string stored inside the JSON value is not + UTF-8 encoded + + @complexity Linear. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @liveexample{The following example shows the effect of different @a indent\, + @a indent_char\, and @a ensure_ascii parameters to the result of the + serialization.,dump} + + @see https://docs.python.org/2/library/json.html#json.dump + + @since version 1.0.0; indentation character @a indent_char, option + @a ensure_ascii and exceptions added in version 3.0.0 + */ + string_t dump(const int indent = -1, const char indent_char = ' ', + const bool ensure_ascii = false) const + { + string_t result; + serializer s(detail::output_adapter<char, string_t>(result), indent_char); + + if (indent >= 0) + { + s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); + } + else + { + s.dump(*this, false, ensure_ascii, 0); + } + + return result; + } + + /*! + @brief return the type of the JSON value (explicit) + + Return the type of the JSON value as a value from the @ref value_t + enumeration. + + @return the type of the JSON value + Value type | return value + ------------------------- | ------------------------- + null | value_t::null + boolean | value_t::boolean + string | value_t::string + number (integer) | value_t::number_integer + number (unsigned integer) | value_t::number_unsigned + number (floating-point) | value_t::number_float + object | value_t::object + array | value_t::array + discarded | value_t::discarded + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `type()` for all JSON + types.,type} + + @sa @ref operator value_t() -- return the type of the JSON value (implicit) + @sa @ref type_name() -- return the type as string + + @since version 1.0.0 + */ + constexpr value_t type() const noexcept + { + return m_type; + } + + /*! + @brief return whether type is primitive + + This function returns true if and only if the JSON type is primitive + (string, number, boolean, or null). + + @return `true` if type is primitive (string, number, boolean, or null), + `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_primitive()` for all JSON + types.,is_primitive} + + @sa @ref is_structured() -- returns whether JSON value is structured + @sa @ref is_null() -- returns whether JSON value is `null` + @sa @ref is_string() -- returns whether JSON value is a string + @sa @ref is_boolean() -- returns whether JSON value is a boolean + @sa @ref is_number() -- returns whether JSON value is a number + + @since version 1.0.0 + */ + constexpr bool is_primitive() const noexcept + { + return is_null() or is_string() or is_boolean() or is_number(); + } + + /*! + @brief return whether type is structured + + This function returns true if and only if the JSON type is structured + (array or object). + + @return `true` if type is structured (array or object), `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_structured()` for all JSON + types.,is_structured} + + @sa @ref is_primitive() -- returns whether value is primitive + @sa @ref is_array() -- returns whether value is an array + @sa @ref is_object() -- returns whether value is an object + + @since version 1.0.0 + */ + constexpr bool is_structured() const noexcept + { + return is_array() or is_object(); + } + + /*! + @brief return whether value is null + + This function returns true if and only if the JSON value is null. + + @return `true` if type is null, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_null()` for all JSON + types.,is_null} + + @since version 1.0.0 + */ + constexpr bool is_null() const noexcept + { + return (m_type == value_t::null); + } + + /*! + @brief return whether value is a boolean + + This function returns true if and only if the JSON value is a boolean. + + @return `true` if type is boolean, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_boolean()` for all JSON + types.,is_boolean} + + @since version 1.0.0 + */ + constexpr bool is_boolean() const noexcept + { + return (m_type == value_t::boolean); + } + + /*! + @brief return whether value is a number + + This function returns true if and only if the JSON value is a number. This + includes both integer (signed and unsigned) and floating-point values. + + @return `true` if type is number (regardless whether integer, unsigned + integer or floating-type), `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number()` for all JSON + types.,is_number} + + @sa @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa @ref is_number_unsigned() -- check if value is an unsigned integer + number + @sa @ref is_number_float() -- check if value is a floating-point number + + @since version 1.0.0 + */ + constexpr bool is_number() const noexcept + { + return is_number_integer() or is_number_float(); + } + + /*! + @brief return whether value is an integer number + + This function returns true if and only if the JSON value is a signed or + unsigned integer number. This excludes floating-point values. + + @return `true` if type is an integer or unsigned integer number, `false` + otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_integer()` for all + JSON types.,is_number_integer} + + @sa @ref is_number() -- check if value is a number + @sa @ref is_number_unsigned() -- check if value is an unsigned integer + number + @sa @ref is_number_float() -- check if value is a floating-point number + + @since version 1.0.0 + */ + constexpr bool is_number_integer() const noexcept + { + return (m_type == value_t::number_integer or m_type == value_t::number_unsigned); + } + + /*! + @brief return whether value is an unsigned integer number + + This function returns true if and only if the JSON value is an unsigned + integer number. This excludes floating-point and signed integer values. + + @return `true` if type is an unsigned integer number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_unsigned()` for all + JSON types.,is_number_unsigned} + + @sa @ref is_number() -- check if value is a number + @sa @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa @ref is_number_float() -- check if value is a floating-point number + + @since version 2.0.0 + */ + constexpr bool is_number_unsigned() const noexcept + { + return (m_type == value_t::number_unsigned); + } + + /*! + @brief return whether value is a floating-point number + + This function returns true if and only if the JSON value is a + floating-point number. This excludes signed and unsigned integer values. + + @return `true` if type is a floating-point number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_float()` for all + JSON types.,is_number_float} + + @sa @ref is_number() -- check if value is number + @sa @ref is_number_integer() -- check if value is an integer number + @sa @ref is_number_unsigned() -- check if value is an unsigned integer + number + + @since version 1.0.0 + */ + constexpr bool is_number_float() const noexcept + { + return (m_type == value_t::number_float); + } + + /*! + @brief return whether value is an object + + This function returns true if and only if the JSON value is an object. + + @return `true` if type is object, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_object()` for all JSON + types.,is_object} + + @since version 1.0.0 + */ + constexpr bool is_object() const noexcept + { + return (m_type == value_t::object); + } + + /*! + @brief return whether value is an array + + This function returns true if and only if the JSON value is an array. + + @return `true` if type is array, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_array()` for all JSON + types.,is_array} + + @since version 1.0.0 + */ + constexpr bool is_array() const noexcept + { + return (m_type == value_t::array); + } + + /*! + @brief return whether value is a string + + This function returns true if and only if the JSON value is a string. + + @return `true` if type is string, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_string()` for all JSON + types.,is_string} + + @since version 1.0.0 + */ + constexpr bool is_string() const noexcept + { + return (m_type == value_t::string); + } + + /*! + @brief return whether value is discarded + + This function returns true if and only if the JSON value was discarded + during parsing with a callback function (see @ref parser_callback_t). + + @note This function will always be `false` for JSON values after parsing. + That is, discarded values can only occur during parsing, but will be + removed when inside a structured value or replaced by null in other cases. + + @return `true` if type is discarded, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_discarded()` for all JSON + types.,is_discarded} + + @since version 1.0.0 + */ + constexpr bool is_discarded() const noexcept + { + return (m_type == value_t::discarded); + } + + /*! + @brief return the type of the JSON value (implicit) + + Implicitly return the type of the JSON value as a value from the @ref + value_t enumeration. + + @return the type of the JSON value + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies the @ref value_t operator for + all JSON types.,operator__value_t} + + @sa @ref type() -- return the type of the JSON value (explicit) + @sa @ref type_name() -- return the type as string + + @since version 1.0.0 + */ + constexpr operator value_t() const noexcept + { + return m_type; + } + + /// @} + + private: + ////////////////// + // value access // + ////////////////// + + /// get a boolean (explicit) + boolean_t get_impl(boolean_t* /*unused*/) const + { + if (JSON_LIKELY(is_boolean())) + { + return m_value.boolean; + } + + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); + } + + /// get a pointer to the value (object) + object_t* get_impl_ptr(object_t* /*unused*/) noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (object) + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (array) + array_t* get_impl_ptr(array_t* /*unused*/) noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (array) + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (string) + string_t* get_impl_ptr(string_t* /*unused*/) noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (string) + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (boolean) + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (boolean) + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (integer number) + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (integer number) + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (unsigned number) + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (unsigned number) + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (floating-point number) + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (floating-point number) + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /*! + @brief helper function to implement get_ref() + + This function helps to implement get_ref() without code duplication for + const and non-const overloads + + @tparam ThisType will be deduced as `basic_json` or `const basic_json` + + @throw type_error.303 if ReferenceType does not match underlying value + type of the current JSON + */ + template<typename ReferenceType, typename ThisType> + static ReferenceType get_ref_impl(ThisType& obj) + { + // delegate the call to get_ptr<>() + auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); + + if (JSON_LIKELY(ptr != nullptr)) + { + return *ptr; + } + + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); + } + + public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ + + /*! + @brief get special-case overload + + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this + + @complexity Constant. + + @since version 2.1.0 + */ + template<typename BasicJsonType, detail::enable_if_t< + std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value, + int> = 0> + basic_json get() const + { + return *this; + } + + /*! + @brief get special-case overload + + This overloads converts the current @ref basic_json in a different + @ref basic_json type + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this, converted into @tparam BasicJsonType + + @complexity Depending on the implementation of the called `from_json()` + method. + + @since version 3.1.2 + */ + template<typename BasicJsonType, detail::enable_if_t< + not std::is_same<BasicJsonType, basic_json>::value and + detail::is_basic_json<BasicJsonType>::value, int> = 0> + BasicJsonType get() const + { + return *this; + } + + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer<ValueType> + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer<ValueType>::from_json(*this, ret); + return ret; + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer<ValueType> has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + - @ref json_serializer<ValueType> does not have a `from_json()` method of + the form `ValueType from_json(const basic_json&)` + + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer<ValueType> `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector<short>`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map<std::string\, + json>`.,get__ValueType_const} + + @since version 2.1.0 + */ + template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>, + detail::enable_if_t < + not detail::is_basic_json<ValueType>::value and + detail::has_from_json<basic_json_t, ValueType>::value and + not detail::has_non_default_from_json<basic_json_t, ValueType>::value, + int> = 0> + ValueType get() const noexcept(noexcept( + JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) + { + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get<const basic_json_t>(), which is why we + // still need the uncvref + static_assert(not std::is_reference<ValueTypeCV>::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + static_assert(std::is_default_constructible<ValueType>::value, + "types must be DefaultConstructible when used with get()"); + + ValueType ret; + JSONSerializer<ValueType>::from_json(*this, ret); + return ret; + } + + /*! + @brief get a value (explicit); special case + + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer<ValueType> + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer<ValueTypeCV>::from_json(*this); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json and + - @ref json_serializer<ValueType> has a `from_json()` method of the form + `ValueType from_json(const basic_json&)` + + @note If @ref json_serializer<ValueType> has both overloads of + `from_json()`, this one is chosen. + + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer<ValueType> `from_json()` method throws + + @since version 2.1.0 + */ + template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>, + detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and + detail::has_non_default_from_json<basic_json_t, ValueType>::value, + int> = 0> + ValueType get() const noexcept(noexcept( + JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>()))) + { + static_assert(not std::is_reference<ValueTypeCV>::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return JSONSerializer<ValueTypeCV>::from_json(*this); + } + + /*! + @brief get a pointer value (explicit) + + Explicit pointer access to the internally stored JSON value. No copies are + made. + + @warning The pointer becomes invalid if the underlying JSON object + changes. + + @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. + + @return pointer to the internally stored JSON value if the requested + pointer type @a PointerType fits to the JSON value; `nullptr` otherwise + + @complexity Constant. + + @liveexample{The example below shows how pointers to internal values of a + JSON value can be requested. Note that no type conversions are made and a + `nullptr` is returned if the value and the requested pointer type does not + match.,get__PointerType} + + @sa @ref get_ptr() for explicit pointer-member access + + @since version 1.0.0 + */ + template<typename PointerType, typename std::enable_if< + std::is_pointer<PointerType>::value, int>::type = 0> + PointerType get() noexcept + { + // delegate the call to get_ptr + return get_ptr<PointerType>(); + } + + /*! + @brief get a pointer value (explicit) + @copydoc get() + */ + template<typename PointerType, typename std::enable_if< + std::is_pointer<PointerType>::value, int>::type = 0> + constexpr const PointerType get() const noexcept + { + // delegate the call to get_ptr + return get_ptr<PointerType>(); + } + + /*! + @brief get a pointer value (implicit) + + Implicit pointer access to the internally stored JSON value. No copies are + made. + + @warning Writing data to the pointee of the result yields an undefined + state. + + @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. Enforced by a static + assertion. + + @return pointer to the internally stored JSON value if the requested + pointer type @a PointerType fits to the JSON value; `nullptr` otherwise + + @complexity Constant. + + @liveexample{The example below shows how pointers to internal values of a + JSON value can be requested. Note that no type conversions are made and a + `nullptr` is returned if the value and the requested pointer type does not + match.,get_ptr} + + @since version 1.0.0 + */ + template<typename PointerType, typename std::enable_if< + std::is_pointer<PointerType>::value, int>::type = 0> + PointerType get_ptr() noexcept + { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const<typename + std::remove_pointer<typename + std::remove_const<PointerType>::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same<object_t, pointee_t>::value + or std::is_same<array_t, pointee_t>::value + or std::is_same<string_t, pointee_t>::value + or std::is_same<boolean_t, pointee_t>::value + or std::is_same<number_integer_t, pointee_t>::value + or std::is_same<number_unsigned_t, pointee_t>::value + or std::is_same<number_float_t, pointee_t>::value + , "incompatible pointer type"); + + // delegate the call to get_impl_ptr<>() + return get_impl_ptr(static_cast<PointerType>(nullptr)); + } + + /*! + @brief get a pointer value (implicit) + @copydoc get_ptr() + */ + template<typename PointerType, typename std::enable_if< + std::is_pointer<PointerType>::value and + std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0> + constexpr const PointerType get_ptr() const noexcept + { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const<typename + std::remove_pointer<typename + std::remove_const<PointerType>::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same<object_t, pointee_t>::value + or std::is_same<array_t, pointee_t>::value + or std::is_same<string_t, pointee_t>::value + or std::is_same<boolean_t, pointee_t>::value + or std::is_same<number_integer_t, pointee_t>::value + or std::is_same<number_unsigned_t, pointee_t>::value + or std::is_same<number_float_t, pointee_t>::value + , "incompatible pointer type"); + + // delegate the call to get_impl_ptr<>() const + return get_impl_ptr(static_cast<PointerType>(nullptr)); + } + + /*! + @brief get a reference value (implicit) + + Implicit reference access to the internally stored JSON value. No copies + are made. + + @warning Writing data to the referee of the result yields an undefined + state. + + @tparam ReferenceType reference type; must be a reference to @ref array_t, + @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or + @ref number_float_t. Enforced by static assertion. + + @return reference to the internally stored JSON value if the requested + reference type @a ReferenceType fits to the JSON value; throws + type_error.303 otherwise + + @throw type_error.303 in case passed type @a ReferenceType is incompatible + with the stored JSON value; see example below + + @complexity Constant. + + @liveexample{The example shows several calls to `get_ref()`.,get_ref} + + @since version 1.1.0 + */ + template<typename ReferenceType, typename std::enable_if< + std::is_reference<ReferenceType>::value, int>::type = 0> + ReferenceType get_ref() + { + // delegate call to get_ref_impl + return get_ref_impl<ReferenceType>(*this); + } + + /*! + @brief get a reference value (implicit) + @copydoc get_ref() + */ + template<typename ReferenceType, typename std::enable_if< + std::is_reference<ReferenceType>::value and + std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0> + ReferenceType get_ref() const + { + // delegate call to get_ref_impl + return get_ref_impl<ReferenceType>(*this); + } + + /*! + @brief get a value (implicit) + + Implicit type conversion between the JSON value and a compatible value. + The call is realized by calling @ref get() const. + + @tparam ValueType non-pointer type compatible to the JSON value, for + instance `int` for JSON integer numbers, `bool` for JSON booleans, or + `std::vector` types for JSON arrays. The character type of @ref string_t + as well as an initializer list of this type is excluded to avoid + ambiguities as these types implicitly convert to `std::string`. + + @return copy of the JSON value, converted to type @a ValueType + + @throw type_error.302 in case passed type @a ValueType is incompatible + to the JSON value type (e.g., the JSON value is of type boolean, but a + string is requested); see example below + + @complexity Linear in the size of the JSON value. + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector<short>`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map<std::string\, + json>`.,operator__ValueType} + + @since version 1.0.0 + */ + template < typename ValueType, typename std::enable_if < + not std::is_pointer<ValueType>::value and + not std::is_same<ValueType, detail::json_ref<basic_json>>::value and + not std::is_same<ValueType, typename string_t::value_type>::value and + not detail::is_basic_json<ValueType>::value +#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 + and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value +#endif +#if defined(JSON_HAS_CPP_17) + and not std::is_same<ValueType, typename std::string_view>::value +#endif + , int >::type = 0 > + operator ValueType() const + { + // delegate the call to get<>() const + return get<ValueType>(); + } + + /// @} + + + //////////////////// + // element access // + //////////////////// + + /// @name element access + /// Access to the JSON value. + /// @{ + + /*! + @brief access specified array element with bounds checking + + Returns a reference to the element at specified location @a idx, with + bounds checking. + + @param[in] idx index of the element to access + + @return reference to the element at index @a idx + + @throw type_error.304 if the JSON value is not an array; in this case, + calling `at` with an index makes no sense. See example below. + @throw out_of_range.401 if the index @a idx is out of range of the array; + that is, `idx >= size()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 1.0.0 + + @liveexample{The example below shows how array elements can be read and + written using `at()`. It also demonstrates the different exceptions that + can be thrown.,at__size_type} + */ + reference at(size_type idx) + { + // at only works for arrays + if (JSON_LIKELY(is_array())) + { + JSON_TRY + { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + } + } + + /*! + @brief access specified array element with bounds checking + + Returns a const reference to the element at specified location @a idx, + with bounds checking. + + @param[in] idx index of the element to access + + @return const reference to the element at index @a idx + + @throw type_error.304 if the JSON value is not an array; in this case, + calling `at` with an index makes no sense. See example below. + @throw out_of_range.401 if the index @a idx is out of range of the array; + that is, `idx >= size()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 1.0.0 + + @liveexample{The example below shows how array elements can be read using + `at()`. It also demonstrates the different exceptions that can be thrown., + at__size_type_const} + */ + const_reference at(size_type idx) const + { + // at only works for arrays + if (JSON_LIKELY(is_array())) + { + JSON_TRY + { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + } + } + + /*! + @brief access specified object element with bounds checking + + Returns a reference to the element at with specified key @a key, with + bounds checking. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.304 if the JSON value is not an object; in this case, + calling `at` with a key makes no sense. See example below. + @throw out_of_range.403 if the key @a key is is not stored in the object; + that is, `find(key) == end()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Logarithmic in the size of the container. + + @sa @ref operator[](const typename object_t::key_type&) for unchecked + access by reference + @sa @ref value() for access by value with a default value + + @since version 1.0.0 + + @liveexample{The example below shows how object elements can be read and + written using `at()`. It also demonstrates the different exceptions that + can be thrown.,at__object_t_key_type} + */ + reference at(const typename object_t::key_type& key) + { + // at only works for objects + if (JSON_LIKELY(is_object())) + { + JSON_TRY + { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + } + } + + /*! + @brief access specified object element with bounds checking + + Returns a const reference to the element at with specified key @a key, + with bounds checking. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @throw type_error.304 if the JSON value is not an object; in this case, + calling `at` with a key makes no sense. See example below. + @throw out_of_range.403 if the key @a key is is not stored in the object; + that is, `find(key) == end()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Logarithmic in the size of the container. + + @sa @ref operator[](const typename object_t::key_type&) for unchecked + access by reference + @sa @ref value() for access by value with a default value + + @since version 1.0.0 + + @liveexample{The example below shows how object elements can be read using + `at()`. It also demonstrates the different exceptions that can be thrown., + at__object_t_key_type_const} + */ + const_reference at(const typename object_t::key_type& key) const + { + // at only works for objects + if (JSON_LIKELY(is_object())) + { + JSON_TRY + { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + } + } + + /*! + @brief access specified array element + + Returns a reference to the element at specified location @a idx. + + @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), + then the array is silently filled up with `null` values to make `idx` a + valid reference to the last stored element. + + @param[in] idx index of the element to access + + @return reference to the element at index @a idx + + @throw type_error.305 if the JSON value is not an array or null; in that + cases, using the [] operator with an index makes no sense. + + @complexity Constant if @a idx is in the range of the array. Otherwise + linear in `idx - size()`. + + @liveexample{The example below shows how array elements can be read and + written using `[]` operator. Note the addition of `null` + values.,operatorarray__size_type} + + @since version 1.0.0 + */ + reference operator[](size_type idx) + { + // implicitly convert null value to an empty array + if (is_null()) + { + m_type = value_t::array; + m_value.array = create<array_t>(); + assert_invariant(); + } + + // operator[] only works for arrays + if (JSON_LIKELY(is_array())) + { + // fill up array with null values if given idx is outside range + if (idx >= m_value.array->size()) + { + m_value.array->insert(m_value.array->end(), + idx - m_value.array->size() + 1, + basic_json()); + } + + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + } + + /*! + @brief access specified array element + + Returns a const reference to the element at specified location @a idx. + + @param[in] idx index of the element to access + + @return const reference to the element at index @a idx + + @throw type_error.305 if the JSON value is not an array; in that case, + using the [] operator with an index makes no sense. + + @complexity Constant. + + @liveexample{The example below shows how array elements can be read using + the `[]` operator.,operatorarray__size_type_const} + + @since version 1.0.0 + */ + const_reference operator[](size_type idx) const + { + // const operator[] only works for arrays + if (JSON_LIKELY(is_array())) + { + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + } + + /*! + @brief access specified object element + + Returns a reference to the element at with specified key @a key. + + @note If @a key is not found in the object, then it is silently added to + the object and filled with a `null` value to make `key` a valid reference. + In case the value was `null` before, it is converted to an object. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read and + written using the `[]` operator.,operatorarray__key_type} + + @sa @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa @ref value() for access by value with a default value + + @since version 1.0.0 + */ + reference operator[](const typename object_t::key_type& key) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create<object_t>(); + assert_invariant(); + } + + // operator[] only works for objects + if (JSON_LIKELY(is_object())) + { + return m_value.object->operator[](key); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + } + + /*! + @brief read-only access specified object element + + Returns a const reference to the element at with specified key @a key. No + bounds checking is performed. + + @warning If the element with key @a key does not exist, the behavior is + undefined. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + + @throw type_error.305 if the JSON value is not an object; in that case, + using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read using + the `[]` operator.,operatorarray__key_type_const} + + @sa @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa @ref value() for access by value with a default value + + @since version 1.0.0 + */ + const_reference operator[](const typename object_t::key_type& key) const + { + // const operator[] only works for objects + if (JSON_LIKELY(is_object())) + { + assert(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + } + + /*! + @brief access specified object element + + Returns a reference to the element at with specified key @a key. + + @note If @a key is not found in the object, then it is silently added to + the object and filled with a `null` value to make `key` a valid reference. + In case the value was `null` before, it is converted to an object. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read and + written using the `[]` operator.,operatorarray__key_type} + + @sa @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa @ref value() for access by value with a default value + + @since version 1.1.0 + */ + template<typename T> + reference operator[](T* key) + { + // implicitly convert null to object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // at only works for objects + if (JSON_LIKELY(is_object())) + { + return m_value.object->operator[](key); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + } + + /*! + @brief read-only access specified object element + + Returns a const reference to the element at with specified key @a key. No + bounds checking is performed. + + @warning If the element with key @a key does not exist, the behavior is + undefined. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + + @throw type_error.305 if the JSON value is not an object; in that case, + using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read using + the `[]` operator.,operatorarray__key_type_const} + + @sa @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa @ref value() for access by value with a default value + + @since version 1.1.0 + */ + template<typename T> + const_reference operator[](T* key) const + { + // at only works for objects + if (JSON_LIKELY(is_object())) + { + assert(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + } + + /*! + @brief access specified object element with default value + + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(key); + } catch(out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const typename object_t::key_type&), this function + does not throw if the given key @a key was not found. + + @note Unlike @ref operator[](const typename object_t::key_type& key), this + function does not implicitly add an element to the position defined by @a + key. This function is furthermore also applicable to const objects. + + @param[in] key key of the element to access + @param[in] default_value the value to return if @a key is not found + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw type_error.306 if the JSON value is not an object; in that case, + using `value()` with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value} + + @sa @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa @ref operator[](const typename object_t::key_type&) for unchecked + access by reference + + @since version 1.0.0 + */ + template<class ValueType, typename std::enable_if< + std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0> + ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + { + // at only works for objects + if (JSON_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return *it; + } + + return default_value; + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const + */ + string_t value(const typename object_t::key_type& key, const char* default_value) const + { + return value(key, string_t(default_value)); + } + + /*! + @brief access specified object element via JSON Pointer with default value + + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(ptr); + } catch(out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const json_pointer&), this function does not throw + if the given key @a key was not found. + + @param[in] ptr a JSON pointer to the element to access + @param[in] default_value the value to return if @a ptr found no value + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw type_error.306 if the JSON value is not an object; in that case, + using `value()` with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value_ptr} + + @sa @ref operator[](const json_pointer&) for unchecked access by reference + + @since version 2.0.2 + */ + template<class ValueType, typename std::enable_if< + std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0> + ValueType value(const json_pointer& ptr, const ValueType& default_value) const + { + // at only works for objects + if (JSON_LIKELY(is_object())) + { + // if pointer resolves a value, return it or use default value + JSON_TRY + { + return ptr.get_checked(this); + } + JSON_CATCH (out_of_range&) + { + return default_value; + } + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const json_pointer&, ValueType) const + */ + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + + /*! + @brief access the first element + + Returns a reference to the first element in the container. For a JSON + container `c`, the expression `c.front()` is equivalent to `*c.begin()`. + + @return In case of a structured type (array or object), a reference to the + first element is returned. In case of number, string, or boolean values, a + reference to the value is returned. + + @complexity Constant. + + @pre The JSON value must not be `null` (would throw `std::out_of_range`) + or an empty array or object (undefined behavior, **guarded by + assertions**). + @post The JSON value remains unchanged. + + @throw invalid_iterator.214 when called on `null` value + + @liveexample{The following code shows an example for `front()`.,front} + + @sa @ref back() -- access the last element + + @since version 1.0.0 + */ + reference front() + { + return *begin(); + } + + /*! + @copydoc basic_json::front() + */ + const_reference front() const + { + return *cbegin(); + } + + /*! + @brief access the last element + + Returns a reference to the last element in the container. For a JSON + container `c`, the expression `c.back()` is equivalent to + @code {.cpp} + auto tmp = c.end(); + --tmp; + return *tmp; + @endcode + + @return In case of a structured type (array or object), a reference to the + last element is returned. In case of number, string, or boolean values, a + reference to the value is returned. + + @complexity Constant. + + @pre The JSON value must not be `null` (would throw `std::out_of_range`) + or an empty array or object (undefined behavior, **guarded by + assertions**). + @post The JSON value remains unchanged. + + @throw invalid_iterator.214 when called on a `null` value. See example + below. + + @liveexample{The following code shows an example for `back()`.,back} + + @sa @ref front() -- access the first element + + @since version 1.0.0 + */ + reference back() + { + auto tmp = end(); + --tmp; + return *tmp; + } + + /*! + @copydoc basic_json::back() + */ + const_reference back() const + { + auto tmp = cend(); + --tmp; + return *tmp; + } + + /*! + @brief remove element given an iterator + + Removes the element specified by iterator @a pos. The iterator @a pos must + be valid and dereferenceable. Thus the `end()` iterator (which is valid, + but is not dereferenceable) cannot be used as a value for @a pos. + + If called on a primitive type other than `null`, the resulting JSON value + will be `null`. + + @param[in] pos iterator to the element to remove + @return Iterator following the last removed element. If the iterator @a + pos refers to the last element, the `end()` iterator is returned. + + @tparam IteratorType an @ref iterator or @ref const_iterator + + @post Invalidates iterators and references at or after the point of the + erase, including the `end()` iterator. + + @throw type_error.307 if called on a `null` value; example: `"cannot use + erase() with null"` + @throw invalid_iterator.202 if called on an iterator which does not belong + to the current JSON value; example: `"iterator does not fit current + value"` + @throw invalid_iterator.205 if called on a primitive type with invalid + iterator (i.e., any iterator which is not `begin()`); example: `"iterator + out of range"` + + @complexity The complexity depends on the type: + - objects: amortized constant + - arrays: linear in distance between @a pos and the end of the container + - strings: linear in the length of the string + - other types: constant + + @liveexample{The example shows the result of `erase()` for different JSON + types.,erase__IteratorType} + + @sa @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa @ref erase(const typename object_t::key_type&) -- removes the element + from an object at the given key + @sa @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 1.0.0 + */ + template<class IteratorType, typename std::enable_if< + std::is_same<IteratorType, typename basic_json_t::iterator>::value or + std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type + = 0> + IteratorType erase(IteratorType pos) + { + // make sure iterator fits the current value + if (JSON_UNLIKELY(this != pos.m_object)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + { + if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin())) + { + JSON_THROW(invalid_iterator::create(205, "iterator out of range")); + } + + if (is_string()) + { + AllocatorType<string_t> alloc; + std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + break; + } + + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + } + + return result; + } + + /*! + @brief remove elements given an iterator range + + Removes the element specified by the range `[first; last)`. The iterator + @a first does not need to be dereferenceable if `first == last`: erasing + an empty range is a no-op. + + If called on a primitive type other than `null`, the resulting JSON value + will be `null`. + + @param[in] first iterator to the beginning of the range to remove + @param[in] last iterator past the end of the range to remove + @return Iterator following the last removed element. If the iterator @a + second refers to the last element, the `end()` iterator is returned. + + @tparam IteratorType an @ref iterator or @ref const_iterator + + @post Invalidates iterators and references at or after the point of the + erase, including the `end()` iterator. + + @throw type_error.307 if called on a `null` value; example: `"cannot use + erase() with null"` + @throw invalid_iterator.203 if called on iterators which does not belong + to the current JSON value; example: `"iterators do not fit current value"` + @throw invalid_iterator.204 if called on a primitive type with invalid + iterators (i.e., if `first != begin()` and `last != end()`); example: + `"iterators out of range"` + + @complexity The complexity depends on the type: + - objects: `log(size()) + std::distance(first, last)` + - arrays: linear in the distance between @a first and @a last, plus linear + in the distance between @a last and end of the container + - strings: linear in the length of the string + - other types: constant + + @liveexample{The example shows the result of `erase()` for different JSON + types.,erase__IteratorType_IteratorType} + + @sa @ref erase(IteratorType) -- removes the element at a given position + @sa @ref erase(const typename object_t::key_type&) -- removes the element + from an object at the given key + @sa @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 1.0.0 + */ + template<class IteratorType, typename std::enable_if< + std::is_same<IteratorType, typename basic_json_t::iterator>::value or + std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type + = 0> + IteratorType erase(IteratorType first, IteratorType last) + { + // make sure iterator fits the current value + if (JSON_UNLIKELY(this != first.m_object or this != last.m_object)) + { + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + { + if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin() + or not last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + } + + if (is_string()) + { + AllocatorType<string_t> alloc; + std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + } + + return result; + } + + /*! + @brief remove element from a JSON object given a key + + Removes elements from a JSON object with the key value @a key. + + @param[in] key value of the elements to remove + + @return Number of elements removed. If @a ObjectType is the default + `std::map` type, the return value will always be `0` (@a key was not + found) or `1` (@a key was found). + + @post References and iterators to the erased elements are invalidated. + Other references and iterators are not affected. + + @throw type_error.307 when called on a type other than JSON object; + example: `"cannot use erase() with null"` + + @complexity `log(size()) + count(key)` + + @liveexample{The example shows the effect of `erase()`.,erase__key_type} + + @sa @ref erase(IteratorType) -- removes the element at a given position + @sa @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 1.0.0 + */ + size_type erase(const typename object_t::key_type& key) + { + // this erase only works for objects + if (JSON_LIKELY(is_object())) + { + return m_value.object->erase(key); + } + + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + } + + /*! + @brief remove element from a JSON array given an index + + Removes element from a JSON array at the index @a idx. + + @param[in] idx index of the element to remove + + @throw type_error.307 when called on a type other than JSON object; + example: `"cannot use erase() with null"` + @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 + is out of range"` + + @complexity Linear in distance between @a idx and the end of the container. + + @liveexample{The example shows the effect of `erase()`.,erase__size_type} + + @sa @ref erase(IteratorType) -- removes the element at a given position + @sa @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa @ref erase(const typename object_t::key_type&) -- removes the element + from an object at the given key + + @since version 1.0.0 + */ + void erase(const size_type idx) + { + // this erase only works for arrays + if (JSON_LIKELY(is_array())) + { + if (JSON_UNLIKELY(idx >= size())) + { + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + + m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx)); + } + else + { + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + } + } + + /// @} + + + //////////// + // lookup // + //////////// + + /// @name lookup + /// @{ + + /*! + @brief find an element in a JSON object + + Finds an element in a JSON object with key equivalent to @a key. If the + element is not found or the JSON value is not an object, end() is + returned. + + @note This method always returns @ref end() when executed on a JSON type + that is not an object. + + @param[in] key key value of the element to search for. + + @return Iterator to an element with key equivalent to @a key. If no such + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. + + @complexity Logarithmic in the size of the JSON object. + + @liveexample{The example shows how `find()` is used.,find__key_type} + + @since version 1.0.0 + */ + template<typename KeyT> + iterator find(KeyT&& key) + { + auto result = end(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key)); + } + + return result; + } + + /*! + @brief find an element in a JSON object + @copydoc find(KeyT&&) + */ + template<typename KeyT> + const_iterator find(KeyT&& key) const + { + auto result = cend(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key)); + } + + return result; + } + + /*! + @brief returns the number of occurrences of a key in a JSON object + + Returns the number of elements with key @a key. If ObjectType is the + default `std::map` type, the return value will always be `0` (@a key was + not found) or `1` (@a key was found). + + @note This method always returns `0` when executed on a JSON type that is + not an object. + + @param[in] key key value of the element to count + + @return Number of elements with key @a key. If the JSON value is not an + object, the return value will be `0`. + + @complexity Logarithmic in the size of the JSON object. + + @liveexample{The example shows how `count()` is used.,count} + + @since version 1.0.0 + */ + template<typename KeyT> + size_type count(KeyT&& key) const + { + // return 0 for all nonobject types + return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0; + } + + /// @} + + + /////////////// + // iterators // + /////////////// + + /// @name iterators + /// @{ + + /*! + @brief returns an iterator to the first element + + Returns an iterator to the first element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return iterator to the first element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + + @liveexample{The following code shows an example for `begin()`.,begin} + + @sa @ref cbegin() -- returns a const iterator to the beginning + @sa @ref end() -- returns an iterator to the end + @sa @ref cend() -- returns a const iterator to the end + + @since version 1.0.0 + */ + iterator begin() noexcept + { + iterator result(this); + result.set_begin(); + return result; + } + + /*! + @copydoc basic_json::cbegin() + */ + const_iterator begin() const noexcept + { + return cbegin(); + } + + /*! + @brief returns a const iterator to the first element + + Returns a const iterator to the first element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return const iterator to the first element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast<const basic_json&>(*this).begin()`. + + @liveexample{The following code shows an example for `cbegin()`.,cbegin} + + @sa @ref begin() -- returns an iterator to the beginning + @sa @ref end() -- returns an iterator to the end + @sa @ref cend() -- returns a const iterator to the end + + @since version 1.0.0 + */ + const_iterator cbegin() const noexcept + { + const_iterator result(this); + result.set_begin(); + return result; + } + + /*! + @brief returns an iterator to one past the last element + + Returns an iterator to one past the last element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return iterator one past the last element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + + @liveexample{The following code shows an example for `end()`.,end} + + @sa @ref cend() -- returns a const iterator to the end + @sa @ref begin() -- returns an iterator to the beginning + @sa @ref cbegin() -- returns a const iterator to the beginning + + @since version 1.0.0 + */ + iterator end() noexcept + { + iterator result(this); + result.set_end(); + return result; + } + + /*! + @copydoc basic_json::cend() + */ + const_iterator end() const noexcept + { + return cend(); + } + + /*! + @brief returns a const iterator to one past the last element + + Returns a const iterator to one past the last element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return const iterator one past the last element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast<const basic_json&>(*this).end()`. + + @liveexample{The following code shows an example for `cend()`.,cend} + + @sa @ref end() -- returns an iterator to the end + @sa @ref begin() -- returns an iterator to the beginning + @sa @ref cbegin() -- returns a const iterator to the beginning + + @since version 1.0.0 + */ + const_iterator cend() const noexcept + { + const_iterator result(this); + result.set_end(); + return result; + } + + /*! + @brief returns an iterator to the reverse-beginning + + Returns an iterator to the reverse-beginning; that is, the last element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `reverse_iterator(end())`. + + @liveexample{The following code shows an example for `rbegin()`.,rbegin} + + @sa @ref crbegin() -- returns a const reverse iterator to the beginning + @sa @ref rend() -- returns a reverse iterator to the end + @sa @ref crend() -- returns a const reverse iterator to the end + + @since version 1.0.0 + */ + reverse_iterator rbegin() noexcept + { + return reverse_iterator(end()); + } + + /*! + @copydoc basic_json::crbegin() + */ + const_reverse_iterator rbegin() const noexcept + { + return crbegin(); + } + + /*! + @brief returns an iterator to the reverse-end + + Returns an iterator to the reverse-end; that is, one before the first + element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `reverse_iterator(begin())`. + + @liveexample{The following code shows an example for `rend()`.,rend} + + @sa @ref crend() -- returns a const reverse iterator to the end + @sa @ref rbegin() -- returns a reverse iterator to the beginning + @sa @ref crbegin() -- returns a const reverse iterator to the beginning + + @since version 1.0.0 + */ + reverse_iterator rend() noexcept + { + return reverse_iterator(begin()); + } + + /*! + @copydoc basic_json::crend() + */ + const_reverse_iterator rend() const noexcept + { + return crend(); + } + + /*! + @brief returns a const reverse iterator to the last element + + Returns a const iterator to the reverse-beginning; that is, the last + element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`. + + @liveexample{The following code shows an example for `crbegin()`.,crbegin} + + @sa @ref rbegin() -- returns a reverse iterator to the beginning + @sa @ref rend() -- returns a reverse iterator to the end + @sa @ref crend() -- returns a const reverse iterator to the end + + @since version 1.0.0 + */ + const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(cend()); + } + + /*! + @brief returns a const reverse iterator to one before the first + + Returns a const reverse iterator to the reverse-end; that is, one before + the first element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast<const basic_json&>(*this).rend()`. + + @liveexample{The following code shows an example for `crend()`.,crend} + + @sa @ref rend() -- returns a reverse iterator to the end + @sa @ref rbegin() -- returns a reverse iterator to the beginning + @sa @ref crbegin() -- returns a const reverse iterator to the beginning + + @since version 1.0.0 + */ + const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(cbegin()); + } + + public: + /*! + @brief wrapper to access iterator member functions in range-based for + + This function allows to access @ref iterator::key() and @ref + iterator::value() during range-based for loops. In these loops, a + reference to the JSON values is returned, so there is no access to the + underlying iterator. + + For loop without iterator_wrapper: + + @code{cpp} + for (auto it = j_object.begin(); it != j_object.end(); ++it) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + Range-based for loop without iterator proxy: + + @code{cpp} + for (auto it : j_object) + { + // "it" is of type json::reference and has no key() member + std::cout << "value: " << it << '\n'; + } + @endcode + + Range-based for loop with iterator proxy: + + @code{cpp} + for (auto it : json::iterator_wrapper(j_object)) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + @note When iterating over an array, `key()` will return the index of the + element as string (see example). + + @param[in] ref reference to a JSON value + @return iteration proxy object wrapping @a ref with an interface to use in + range-based for loops + + @liveexample{The following code shows how the wrapper is used,iterator_wrapper} + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @note The name of this function is not yet final and may change in the + future. + + @deprecated This stream operator is deprecated and will be removed in + future 4.0.0 of the library. Please use @ref items() instead; + that is, replace `json::iterator_wrapper(j)` with `j.items()`. + */ + JSON_DEPRECATED + static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept + { + return ref.items(); + } + + /*! + @copydoc iterator_wrapper(reference) + */ + JSON_DEPRECATED + static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept + { + return ref.items(); + } + + /*! + @brief helper to access iterator member functions in range-based for + + This function allows to access @ref iterator::key() and @ref + iterator::value() during range-based for loops. In these loops, a + reference to the JSON values is returned, so there is no access to the + underlying iterator. + + For loop without `items()` function: + + @code{cpp} + for (auto it = j_object.begin(); it != j_object.end(); ++it) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + Range-based for loop without `items()` function: + + @code{cpp} + for (auto it : j_object) + { + // "it" is of type json::reference and has no key() member + std::cout << "value: " << it << '\n'; + } + @endcode + + Range-based for loop with `items()` function: + + @code{cpp} + for (auto it : j_object.items()) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + @note When iterating over an array, `key()` will return the index of the + element as string (see example). For primitive types (e.g., numbers), + `key()` returns an empty string. + + @return iteration proxy object wrapping @a ref with an interface to use in + range-based for loops + + @liveexample{The following code shows how the function is used.,items} + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 3.x.x. + */ + iteration_proxy<iterator> items() noexcept + { + return iteration_proxy<iterator>(*this); + } + + /*! + @copydoc items() + */ + iteration_proxy<const_iterator> items() const noexcept + { + return iteration_proxy<const_iterator>(*this); + } + + /// @} + + + ////////////// + // capacity // + ////////////// + + /// @name capacity + /// @{ + + /*! + @brief checks whether the container is empty. + + Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). + + @return The return value depends on the different types and is + defined as follows: + Value type | return value + ----------- | ------------- + null | `true` + boolean | `false` + string | `false` + number | `false` + object | result of function `object_t::empty()` + array | result of function `array_t::empty()` + + @liveexample{The following code uses `empty()` to check if a JSON + object contains any elements.,empty} + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their `empty()` functions have constant + complexity. + + @iterators No changes. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + - Has the semantics of `begin() == end()`. + + @sa @ref size() -- returns the number of elements + + @since version 1.0.0 + */ + bool empty() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return true; + } + + case value_t::array: + { + // delegate call to array_t::empty() + return m_value.array->empty(); + } + + case value_t::object: + { + // delegate call to object_t::empty() + return m_value.object->empty(); + } + + default: + { + // all other types are nonempty + return false; + } + } + } + + /*! + @brief returns the number of elements + + Returns the number of elements in a JSON value. + + @return The return value depends on the different types and is + defined as follows: + Value type | return value + ----------- | ------------- + null | `0` + boolean | `1` + string | `1` + number | `1` + object | result of function object_t::size() + array | result of function array_t::size() + + @liveexample{The following code calls `size()` on the different value + types.,size} + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their size() functions have constant + complexity. + + @iterators No changes. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + - Has the semantics of `std::distance(begin(), end())`. + + @sa @ref empty() -- checks whether the container is empty + @sa @ref max_size() -- returns the maximal number of elements + + @since version 1.0.0 + */ + size_type size() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return 0; + } + + case value_t::array: + { + // delegate call to array_t::size() + return m_value.array->size(); + } + + case value_t::object: + { + // delegate call to object_t::size() + return m_value.object->size(); + } + + default: + { + // all other types have size 1 + return 1; + } + } + } + + /*! + @brief returns the maximum possible number of elements + + Returns the maximum number of elements a JSON value is able to hold due to + system or library implementation limitations, i.e. `std::distance(begin(), + end())` for the JSON value. + + @return The return value depends on the different types and is + defined as follows: + Value type | return value + ----------- | ------------- + null | `0` (same as `size()`) + boolean | `1` (same as `size()`) + string | `1` (same as `size()`) + number | `1` (same as `size()`) + object | result of function `object_t::max_size()` + array | result of function `array_t::max_size()` + + @liveexample{The following code calls `max_size()` on the different value + types. Note the output is implementation specific.,max_size} + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their `max_size()` functions have constant + complexity. + + @iterators No changes. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @requirement This function helps `basic_json` satisfying the + [Container](http://en.cppreference.com/w/cpp/concept/Container) + requirements: + - The complexity is constant. + - Has the semantics of returning `b.size()` where `b` is the largest + possible JSON value. + + @sa @ref size() -- returns the number of elements + + @since version 1.0.0 + */ + size_type max_size() const noexcept + { + switch (m_type) + { + case value_t::array: + { + // delegate call to array_t::max_size() + return m_value.array->max_size(); + } + + case value_t::object: + { + // delegate call to object_t::max_size() + return m_value.object->max_size(); + } + + default: + { + // all other types have max_size() == size() + return size(); + } + } + } + + /// @} + + + /////////////// + // modifiers // + /////////////// + + /// @name modifiers + /// @{ + + /*! + @brief clears the contents + + Clears the content of a JSON value and resets it to the default value as + if @ref basic_json(value_t) would have been called with the current value + type from @ref type(): + + Value type | initial value + ----------- | ------------- + null | `null` + boolean | `false` + string | `""` + number | `0` + object | `{}` + array | `[]` + + @post Has the same effect as calling + @code {.cpp} + *this = basic_json(type()); + @endcode + + @liveexample{The example below shows the effect of `clear()` to different + JSON types.,clear} + + @complexity Linear in the size of the JSON value. + + @iterators All iterators, pointers and references related to this container + are invalidated. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @sa @ref basic_json(value_t) -- constructor that creates an object with the + same value than calling `clear()` + + @since version 1.0.0 + */ + void clear() noexcept + { + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = 0; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = 0; + break; + } + + case value_t::number_float: + { + m_value.number_float = 0.0; + break; + } + + case value_t::boolean: + { + m_value.boolean = false; + break; + } + + case value_t::string: + { + m_value.string->clear(); + break; + } + + case value_t::array: + { + m_value.array->clear(); + break; + } + + case value_t::object: + { + m_value.object->clear(); + break; + } + + default: + break; + } + } + + /*! + @brief add an object to an array + + Appends the given element @a val to the end of the JSON value. If the + function is called on a JSON null value, an empty array is created before + appending @a val. + + @param[in] val the value to add to the JSON array + + @throw type_error.308 when called on a type other than JSON array or + null; example: `"cannot use push_back() with number"` + + @complexity Amortized constant. + + @liveexample{The example shows how `push_back()` and `+=` can be used to + add elements to a JSON array. Note how the `null` value was silently + converted to a JSON array.,push_back} + + @since version 1.0.0 + */ + void push_back(basic_json&& val) + { + // push_back only works for null objects or arrays + if (JSON_UNLIKELY(not(is_null() or is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (move semantics) + m_value.array->push_back(std::move(val)); + // invalidate object + val.m_type = value_t::null; + } + + /*! + @brief add an object to an array + @copydoc push_back(basic_json&&) + */ + reference operator+=(basic_json&& val) + { + push_back(std::move(val)); + return *this; + } + + /*! + @brief add an object to an array + @copydoc push_back(basic_json&&) + */ + void push_back(const basic_json& val) + { + // push_back only works for null objects or arrays + if (JSON_UNLIKELY(not(is_null() or is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array + m_value.array->push_back(val); + } + + /*! + @brief add an object to an array + @copydoc push_back(basic_json&&) + */ + reference operator+=(const basic_json& val) + { + push_back(val); + return *this; + } + + /*! + @brief add an object to an object + + Inserts the given element @a val to the JSON object. If the function is + called on a JSON null value, an empty object is created before inserting + @a val. + + @param[in] val the value to add to the JSON object + + @throw type_error.308 when called on a type other than JSON object or + null; example: `"cannot use push_back() with number"` + + @complexity Logarithmic in the size of the container, O(log(`size()`)). + + @liveexample{The example shows how `push_back()` and `+=` can be used to + add elements to a JSON object. Note how the `null` value was silently + converted to a JSON object.,push_back__object_t__value} + + @since version 1.0.0 + */ + void push_back(const typename object_t::value_type& val) + { + // push_back only works for null objects or objects + if (JSON_UNLIKELY(not(is_null() or is_object()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array + m_value.object->insert(val); + } + + /*! + @brief add an object to an object + @copydoc push_back(const typename object_t::value_type&) + */ + reference operator+=(const typename object_t::value_type& val) + { + push_back(val); + return *this; + } + + /*! + @brief add an object to an object + + This function allows to use `push_back` with an initializer list. In case + + 1. the current value is an object, + 2. the initializer list @a init contains only two elements, and + 3. the first element of @a init is a string, + + @a init is converted into an object element and added using + @ref push_back(const typename object_t::value_type&). Otherwise, @a init + is converted to a JSON value and added using @ref push_back(basic_json&&). + + @param[in] init an initializer list + + @complexity Linear in the size of the initializer list @a init. + + @note This function is required to resolve an ambiguous overload error, + because pairs like `{"key", "value"}` can be both interpreted as + `object_t::value_type` or `std::initializer_list<basic_json>`, see + https://github.com/nlohmann/json/issues/235 for more information. + + @liveexample{The example shows how initializer lists are treated as + objects when possible.,push_back__initializer_list} + */ + void push_back(initializer_list_t init) + { + if (is_object() and init.size() == 2 and (*init.begin())->is_string()) + { + basic_json&& key = init.begin()->moved_or_copied(); + push_back(typename object_t::value_type( + std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); + } + else + { + push_back(basic_json(init)); + } + } + + /*! + @brief add an object to an object + @copydoc push_back(initializer_list_t) + */ + reference operator+=(initializer_list_t init) + { + push_back(init); + return *this; + } + + /*! + @brief add an object to an array + + Creates a JSON value from the passed parameters @a args to the end of the + JSON value. If the function is called on a JSON null value, an empty array + is created before appending the value created from @a args. + + @param[in] args arguments to forward to a constructor of @ref basic_json + @tparam Args compatible types to create a @ref basic_json object + + @throw type_error.311 when called on a type other than JSON array or + null; example: `"cannot use emplace_back() with number"` + + @complexity Amortized constant. + + @liveexample{The example shows how `push_back()` can be used to add + elements to a JSON array. Note how the `null` value was silently converted + to a JSON array.,emplace_back} + + @since version 2.0.8 + */ + template<class... Args> + void emplace_back(Args&& ... args) + { + // emplace_back only works for null objects or arrays + if (JSON_UNLIKELY(not(is_null() or is_array()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (perfect forwarding) + m_value.array->emplace_back(std::forward<Args>(args)...); + } + + /*! + @brief add an object to an object if key does not exist + + Inserts a new element into a JSON object constructed in-place with the + given @a args if there is no element with the key in the container. If the + function is called on a JSON null value, an empty object is created before + appending the value created from @a args. + + @param[in] args arguments to forward to a constructor of @ref basic_json + @tparam Args compatible types to create a @ref basic_json object + + @return a pair consisting of an iterator to the inserted element, or the + already-existing element if no insertion happened, and a bool + denoting whether the insertion took place. + + @throw type_error.311 when called on a type other than JSON object or + null; example: `"cannot use emplace() with number"` + + @complexity Logarithmic in the size of the container, O(log(`size()`)). + + @liveexample{The example shows how `emplace()` can be used to add elements + to a JSON object. Note how the `null` value was silently converted to a + JSON object. Further note how no value is added if there was already one + value stored with the same key.,emplace} + + @since version 2.0.8 + */ + template<class... Args> + std::pair<iterator, bool> emplace(Args&& ... args) + { + // emplace only works for null objects or arrays + if (JSON_UNLIKELY(not(is_null() or is_object()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array (perfect forwarding) + auto res = m_value.object->emplace(std::forward<Args>(args)...); + // create result iterator and set iterator to the result of emplace + auto it = begin(); + it.m_it.object_iterator = res.first; + + // return pair of iterator and boolean + return {it, res.second}; + } + + /*! + @brief inserts element + + Inserts element @a val before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] val element to insert + @return iterator pointing to the inserted @a val. + + @throw type_error.309 if called on JSON values other than arrays; + example: `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + + @complexity Constant plus linear in the distance between @a pos and end of + the container. + + @liveexample{The example shows how `insert()` is used.,insert} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, const basic_json& val) + { + // insert only works for arrays + if (JSON_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // insert to array and return iterator + iterator result(this); + result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); + return result; + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + /*! + @brief inserts element + @copydoc insert(const_iterator, const basic_json&) + */ + iterator insert(const_iterator pos, basic_json&& val) + { + return insert(pos, val); + } + + /*! + @brief inserts elements + + Inserts @a cnt copies of @a val before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] cnt number of copies of @a val to insert + @param[in] val element to insert + @return iterator pointing to the first element inserted, or @a pos if + `cnt==0` + + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + + @complexity Linear in @a cnt plus linear in the distance between @a pos + and end of the container. + + @liveexample{The example shows how `insert()` is used.,insert__count} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + { + // insert only works for arrays + if (JSON_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // insert to array and return iterator + iterator result(this); + result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + return result; + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + /*! + @brief inserts elements + + Inserts elements from range `[first, last)` before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + @throw invalid_iterator.211 if @a first or @a last are iterators into + container for which insert is called; example: `"passed iterators may not + belong to container"` + + @return iterator pointing to the first element inserted, or @a pos if + `first==last` + + @complexity Linear in `std::distance(first, last)` plus linear in the + distance between @a pos and end of the container. + + @liveexample{The example shows how `insert()` is used.,insert__range} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, const_iterator first, const_iterator last) + { + // insert only works for arrays + if (JSON_UNLIKELY(not is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + // check if iterator pos fits to this JSON value + if (JSON_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // check if range iterators belong to the same JSON object + if (JSON_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + if (JSON_UNLIKELY(first.m_object == this)) + { + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); + } + + // insert to array and return iterator + iterator result(this); + result.m_it.array_iterator = m_value.array->insert( + pos.m_it.array_iterator, + first.m_it.array_iterator, + last.m_it.array_iterator); + return result; + } + + /*! + @brief inserts elements + + Inserts elements from initializer list @a ilist before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] ilist initializer list to insert the values from + + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + + @return iterator pointing to the first element inserted, or @a pos if + `ilist` is empty + + @complexity Linear in `ilist.size()` plus linear in the distance between + @a pos and end of the container. + + @liveexample{The example shows how `insert()` is used.,insert__ilist} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, initializer_list_t ilist) + { + // insert only works for arrays + if (JSON_UNLIKELY(not is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + // check if iterator pos fits to this JSON value + if (JSON_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // insert to array and return iterator + iterator result(this); + result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end()); + return result; + } + + /*! + @brief inserts elements + + Inserts elements from range `[first, last)`. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than objects; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number + of elements to insert. + + @liveexample{The example shows how `insert()` is used.,insert__range_object} + + @since version 3.0.0 + */ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (JSON_UNLIKELY(not is_object())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + // check if range iterators belong to the same JSON object + if (JSON_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (JSON_UNLIKELY(not first.m_object->is_object())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + + /*! + @brief updates a JSON object from another object, overwriting existing keys + + Inserts all values from JSON object @a j and overwrites existing keys. + + @param[in] j JSON object to read values from + + @throw type_error.312 if called on JSON values other than objects; example: + `"cannot use update() with string"` + + @complexity O(N*log(size() + N)), where N is the number of elements to + insert. + + @liveexample{The example shows how `update()` is used.,update} + + @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update + + @since version 3.0.0 + */ + void update(const_reference j) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create<object_t>(); + assert_invariant(); + } + + if (JSON_UNLIKELY(not is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); + } + if (JSON_UNLIKELY(not j.is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); + } + + for (auto it = j.cbegin(); it != j.cend(); ++it) + { + m_value.object->operator[](it.key()) = it.value(); + } + } + + /*! + @brief updates a JSON object from another object, overwriting existing keys + + Inserts all values from from range `[first, last)` and overwrites existing + keys. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.312 if called on JSON values other than objects; example: + `"cannot use update() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity O(N*log(size() + N)), where N is the number of elements to + insert. + + @liveexample{The example shows how `update()` is used__range.,update} + + @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update + + @since version 3.0.0 + */ + void update(const_iterator first, const_iterator last) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create<object_t>(); + assert_invariant(); + } + + if (JSON_UNLIKELY(not is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); + } + + // check if range iterators belong to the same JSON object + if (JSON_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (JSON_UNLIKELY(not first.m_object->is_object() + or not last.m_object->is_object())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + for (auto it = first; it != last; ++it) + { + m_value.object->operator[](it.key()) = it.value(); + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of the JSON value with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other JSON value to exchange the contents with + + @complexity Constant. + + @liveexample{The example below shows how JSON values can be swapped with + `swap()`.,swap__reference} + + @since version 1.0.0 + */ + void swap(reference other) noexcept ( + std::is_nothrow_move_constructible<value_t>::value and + std::is_nothrow_move_assignable<value_t>::value and + std::is_nothrow_move_constructible<json_value>::value and + std::is_nothrow_move_assignable<json_value>::value + ) + { + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); + assert_invariant(); + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON array with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other array to exchange the contents with + + @throw type_error.310 when JSON value is not an array; example: `"cannot + use swap() with string"` + + @complexity Constant. + + @liveexample{The example below shows how arrays can be swapped with + `swap()`.,swap__array_t} + + @since version 1.0.0 + */ + void swap(array_t& other) + { + // swap only works for arrays + if (JSON_LIKELY(is_array())) + { + std::swap(*(m_value.array), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON object with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other object to exchange the contents with + + @throw type_error.310 when JSON value is not an object; example: + `"cannot use swap() with string"` + + @complexity Constant. + + @liveexample{The example below shows how objects can be swapped with + `swap()`.,swap__object_t} + + @since version 1.0.0 + */ + void swap(object_t& other) + { + // swap only works for objects + if (JSON_LIKELY(is_object())) + { + std::swap(*(m_value.object), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON string with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other string to exchange the contents with + + @throw type_error.310 when JSON value is not a string; example: `"cannot + use swap() with boolean"` + + @complexity Constant. + + @liveexample{The example below shows how strings can be swapped with + `swap()`.,swap__string_t} + + @since version 1.0.0 + */ + void swap(string_t& other) + { + // swap only works for strings + if (JSON_LIKELY(is_string())) + { + std::swap(*(m_value.string), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } + } + + /// @} + + public: + ////////////////////////////////////////// + // lexicographical comparison operators // + ////////////////////////////////////////// + + /// @name lexicographical comparison operators + /// @{ + + /*! + @brief comparison: equal + + Compares two JSON values for equality according to the following rules: + - Two JSON values are equal if (1) they are from the same type and (2) + their stored values are the same according to their respective + `operator==`. + - Integer and floating-point numbers are automatically converted before + comparison. Note than two NaN values are always treated as unequal. + - Two JSON null values are equal. + + @note Floating-point inside JSON values numbers are compared with + `json::number_float_t::operator==` which is `double::operator==` by + default. To compare floating-point while respecting an epsilon, an alternative + [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39) + could be used, for instance + @code {.cpp} + template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type> + inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept + { + return std::abs(a - b) <= epsilon; + } + @endcode + + @note NaN values never compare equal to themselves or to other NaN values. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether the values @a lhs and @a rhs are equal + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @complexity Linear. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__equal} + + @since version 1.0.0 + */ + friend bool operator==(const_reference lhs, const_reference rhs) noexcept + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + return (*lhs.m_value.array == *rhs.m_value.array); + + case value_t::object: + return (*lhs.m_value.object == *rhs.m_value.object); + + case value_t::null: + return true; + + case value_t::string: + return (*lhs.m_value.string == *rhs.m_value.string); + + case value_t::boolean: + return (lhs.m_value.boolean == rhs.m_value.boolean); + + case value_t::number_integer: + return (lhs.m_value.number_integer == rhs.m_value.number_integer); + + case value_t::number_unsigned: + return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned); + + case value_t::number_float: + return (lhs.m_value.number_float == rhs.m_value.number_float); + + default: + return false; + } + } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float); + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer)); + } + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) + { + return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float); + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) + { + return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned)); + } + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) + { + return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) + { + return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned)); + } + + return false; + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs == basic_json(rhs)); + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) == rhs); + } + + /*! + @brief comparison: not equal + + Compares two JSON values for inequality by calculating `not (lhs == rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether the values @a lhs and @a rhs are not equal + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__notequal} + + @since version 1.0.0 + */ + friend bool operator!=(const_reference lhs, const_reference rhs) noexcept + { + return not (lhs == rhs); + } + + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs != basic_json(rhs)); + } + + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) != rhs); + } + + /*! + @brief comparison: less than + + Compares whether one JSON value @a lhs is less than another JSON value @a + rhs according to the following rules: + - If @a lhs and @a rhs have the same type, the values are compared using + the default `<` operator. + - Integer and floating-point numbers are automatically converted before + comparison + - In case @a lhs and @a rhs have different types, the values are ignored + and the order of the types is considered, see + @ref operator<(const value_t, const value_t). + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is less than @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__less} + + @since version 1.0.0 + */ + friend bool operator<(const_reference lhs, const_reference rhs) noexcept + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + return (*lhs.m_value.array) < (*rhs.m_value.array); + + case value_t::object: + return *lhs.m_value.object < *rhs.m_value.object; + + case value_t::null: + return false; + + case value_t::string: + return *lhs.m_value.string < *rhs.m_value.string; + + case value_t::boolean: + return lhs.m_value.boolean < rhs.m_value.boolean; + + case value_t::number_integer: + return lhs.m_value.number_integer < rhs.m_value.number_integer; + + case value_t::number_unsigned: + return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; + + case value_t::number_float: + return lhs.m_value.number_float < rhs.m_value.number_float; + + default: + return false; + } + } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) + { + return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) + { + return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; + } + + // We only reach this line if we cannot compare values. In that case, + // we compare types. Note we have to call the operator explicitly, + // because MSVC has problems otherwise. + return operator<(lhs_type, rhs_type); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs < basic_json(rhs)); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) < rhs); + } + + /*! + @brief comparison: less than or equal + + Compares whether one JSON value @a lhs is less than or equal to another + JSON value by calculating `not (rhs < lhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is less than or equal to @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__greater} + + @since version 1.0.0 + */ + friend bool operator<=(const_reference lhs, const_reference rhs) noexcept + { + return not (rhs < lhs); + } + + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs <= basic_json(rhs)); + } + + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) <= rhs); + } + + /*! + @brief comparison: greater than + + Compares whether one JSON value @a lhs is greater than another + JSON value by calculating `not (lhs <= rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is greater than to @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__lessequal} + + @since version 1.0.0 + */ + friend bool operator>(const_reference lhs, const_reference rhs) noexcept + { + return not (lhs <= rhs); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs > basic_json(rhs)); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) > rhs); + } + + /*! + @brief comparison: greater than or equal + + Compares whether one JSON value @a lhs is greater than or equal to another + JSON value by calculating `not (lhs < rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is greater than or equal to @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__greaterequal} + + @since version 1.0.0 + */ + friend bool operator>=(const_reference lhs, const_reference rhs) noexcept + { + return not (lhs < rhs); + } + + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs >= basic_json(rhs)); + } + + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template<typename ScalarType, typename std::enable_if< + std::is_scalar<ScalarType>::value, int>::type = 0> + friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) >= rhs); + } + + /// @} + + /////////////////// + // serialization // + /////////////////// + + /// @name serialization + /// @{ + + /*! + @brief serialize to stream + + Serialize the given JSON value @a j to the output stream @a o. The JSON + value will be serialized using the @ref dump member function. + + - The indentation of the output can be controlled with the member variable + `width` of the output stream @a o. For instance, using the manipulator + `std::setw(4)` on @a o sets the indentation level to `4` and the + serialization result is the same as calling `dump(4)`. + + - The indentation character can be controlled with the member variable + `fill` of the output stream @a o. For instance, the manipulator + `std::setfill('\\t')` sets indentation to use a tab character rather than + the default space character. + + @param[in,out] o stream to serialize to + @param[in] j JSON value to serialize + + @return the stream @a o + + @throw type_error.316 if a string stored inside the JSON value is not + UTF-8 encoded + + @complexity Linear. + + @liveexample{The example below shows the serialization with different + parameters to `width` to adjust the indentation level.,operator_serialize} + + @since version 1.0.0; indentation character added in version 3.0.0 + */ + friend std::ostream& operator<<(std::ostream& o, const basic_json& j) + { + // read width member and use it as indentation parameter if nonzero + const bool pretty_print = (o.width() > 0); + const auto indentation = (pretty_print ? o.width() : 0); + + // reset width to 0 for subsequent calls to this stream + o.width(0); + + // do the actual serialization + serializer s(detail::output_adapter<char>(o), o.fill()); + s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); + return o; + } + + /*! + @brief serialize to stream + @deprecated This stream operator is deprecated and will be removed in + future 4.0.0 of the library. Please use + @ref operator<<(std::ostream&, const basic_json&) + instead; that is, replace calls like `j >> o;` with `o << j;`. + @since version 1.0.0; deprecated since version 3.0.0 + */ + JSON_DEPRECATED + friend std::ostream& operator>>(const basic_json& j, std::ostream& o) + { + return o << j; + } + + /// @} + + + ///////////////////// + // deserialization // + ///////////////////// + + /// @name deserialization + /// @{ + + /*! + @brief deserialize from a compatible input + + This function reads from a compatible input. Examples are: + - an array of 1-byte values + - strings with character/literal type with size of 1 byte + - input streams + - container with contiguous storage of 1-byte values. Compatible container + types include `std::vector`, `std::string`, `std::array`, + `std::valarray`, and `std::initializer_list`. Furthermore, C-style + arrays can be used with `std::begin()`/`std::end()`. User-defined + containers can be used as long as they implement random-access iterators + and a contiguous storage. + + @pre Each element of the container has a size of 1 byte. Violating this + precondition yields undefined behavior. **This precondition is enforced + with a static assertion.** + + @pre The container storage is contiguous. Violating this precondition + yields undefined behavior. **This precondition is enforced with an + assertion.** + @pre Each element of the container has a size of 1 byte. Violating this + precondition yields undefined behavior. **This precondition is enforced + with a static assertion.** + + @warning There is no way to enforce all preconditions at compile-time. If + the function is called with a noncompliant container and with + assertions switched off, the behavior is undefined and will most + likely yield segmentation violation. + + @param[in] i input to read from + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + + @return result of the deserialization + + @throw parse_error.101 if a parse error occurs; example: `""unexpected end + of input; expected string literal""` + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `parse()` function reading + from an array.,parse__array__parser_callback_t} + + @liveexample{The example below demonstrates the `parse()` function with + and without callback function.,parse__string__parser_callback_t} + + @liveexample{The example below demonstrates the `parse()` function with + and without callback function.,parse__istream__parser_callback_t} + + @liveexample{The example below demonstrates the `parse()` function reading + from a contiguous container.,parse__contiguouscontainer__parser_callback_t} + + @since version 2.0.3 (contiguous containers) + */ + static basic_json parse(detail::input_adapter&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true) + { + basic_json result; + parser(i, cb, allow_exceptions).parse(true, result); + return result; + } + + static bool accept(detail::input_adapter&& i) + { + return parser(i).accept(true); + } + + static bool sax_parse(detail::input_adapter&& i, json_sax_t* sax, + input_format_t format = input_format_t::json, + const bool strict = true) + { + assert(sax); + switch (format) + { + case input_format_t::json: + return parser(std::move(i)).sax_parse(sax, strict); + default: + return binary_reader(std::move(i)).sax_parse(format, sax, strict); + } + } + + /*! + @brief deserialize from an iterator range with contiguous storage + + This function reads from an iterator range of a container with contiguous + storage of 1-byte values. Compatible container types include + `std::vector`, `std::string`, `std::array`, `std::valarray`, and + `std::initializer_list`. Furthermore, C-style arrays can be used with + `std::begin()`/`std::end()`. User-defined containers can be used as long + as they implement random-access iterators and a contiguous storage. + + @pre The iterator range is contiguous. Violating this precondition yields + undefined behavior. **This precondition is enforced with an assertion.** + @pre Each element in the range has a size of 1 byte. Violating this + precondition yields undefined behavior. **This precondition is enforced + with a static assertion.** + + @warning There is no way to enforce all preconditions at compile-time. If + the function is called with noncompliant iterators and with + assertions switched off, the behavior is undefined and will most + likely yield segmentation violation. + + @tparam IteratorType iterator of container with contiguous storage + @param[in] first begin of the range to parse (included) + @param[in] last end of the range to parse (excluded) + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return result of the deserialization + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `parse()` function reading + from an iterator range.,parse__iteratortype__parser_callback_t} + + @since version 2.0.3 + */ + template<class IteratorType, typename std::enable_if< + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0> + static basic_json parse(IteratorType first, IteratorType last, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true) + { + basic_json result; + parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result); + return result; + } + + template<class IteratorType, typename std::enable_if< + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0> + static bool accept(IteratorType first, IteratorType last) + { + return parser(detail::input_adapter(first, last)).accept(true); + } + + template<class IteratorType, typename std::enable_if< + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0> + static bool sax_parse(IteratorType first, IteratorType last, json_sax_t* sax) + { + return parser(detail::input_adapter(first, last)).sax_parse(sax); + } + + /*! + @brief deserialize from stream + @deprecated This stream operator is deprecated and will be removed in + version 4.0.0 of the library. Please use + @ref operator>>(std::istream&, basic_json&) + instead; that is, replace calls like `j << i;` with `i >> j;`. + @since version 1.0.0; deprecated since version 3.0.0 + */ + JSON_DEPRECATED + friend std::istream& operator<<(basic_json& j, std::istream& i) + { + return operator>>(i, j); + } + + /*! + @brief deserialize from stream + + Deserializes an input stream to a JSON value. + + @param[in,out] i input stream to read a serialized JSON value from + @param[in,out] j JSON value to write the deserialized input to + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below shows how a JSON value is constructed by + reading a serialization from a stream.,operator_deserialize} + + @sa parse(std::istream&, const parser_callback_t) for a variant with a + parser callback function to filter values while parsing + + @since version 1.0.0 + */ + friend std::istream& operator>>(std::istream& i, basic_json& j) + { + parser(detail::input_adapter(i)).parse(false, j); + return i; + } + + /// @} + + /////////////////////////// + // convenience functions // + /////////////////////////// + + /*! + @brief return the type as string + + Returns the type name as string to be used in error messages - usually to + indicate that a function was called on a wrong JSON type. + + @return a string representation of a the @a m_type member: + Value type | return value + ----------- | ------------- + null | `"null"` + boolean | `"boolean"` + string | `"string"` + number | `"number"` (for all number types) + object | `"object"` + array | `"array"` + discarded | `"discarded"` + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @complexity Constant. + + @liveexample{The following code exemplifies `type_name()` for all JSON + types.,type_name} + + @sa @ref type() -- return the type of the JSON value + @sa @ref operator value_t() -- return the type of the JSON value (implicit) + + @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` + since 3.0.0 + */ + const char* type_name() const noexcept + { + { + switch (m_type) + { + case value_t::null: + return "null"; + case value_t::object: + return "object"; + case value_t::array: + return "array"; + case value_t::string: + return "string"; + case value_t::boolean: + return "boolean"; + case value_t::discarded: + return "discarded"; + default: + return "number"; + } + } + } + + + private: + ////////////////////// + // member variables // + ////////////////////// + + /// the type of the current element + value_t m_type = value_t::null; + + /// the value of the current element + json_value m_value = {}; + + ////////////////////////////////////////// + // binary serialization/deserialization // + ////////////////////////////////////////// + + /// @name binary serialization/deserialization support + /// @{ + + public: + /*! + @brief create a CBOR serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the CBOR (Concise + Binary Object Representation) serialization format. CBOR is a binary + serialization format which aims to be more compact than JSON itself, yet + more efficient to parse. + + The library uses the following mapping from JSON values types to + CBOR types according to the CBOR specification (RFC 7049): + + JSON value type | value/range | CBOR type | first byte + --------------- | ------------------------------------------ | ---------------------------------- | --------------- + null | `null` | Null | 0xF6 + boolean | `true` | True | 0xF5 + boolean | `false` | False | 0xF4 + number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B + number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A + number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 + number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 + number_integer | -24..-1 | Negative integer | 0x20..0x37 + number_integer | 0..23 | Integer | 0x00..0x17 + number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 + number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 + number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A + number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B + number_unsigned | 0..23 | Integer | 0x00..0x17 + number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 + number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 + number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A + number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B + number_float | *any value* | Double-Precision Float | 0xFB + string | *length*: 0..23 | UTF-8 string | 0x60..0x77 + string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 + string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 + string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A + string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B + array | *size*: 0..23 | array | 0x80..0x97 + array | *size*: 23..255 | array (1 byte follow) | 0x98 + array | *size*: 256..65535 | array (2 bytes follow) | 0x99 + array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A + array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B + object | *size*: 0..23 | map | 0xA0..0xB7 + object | *size*: 23..255 | map (1 byte follow) | 0xB8 + object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 + object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA + object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a CBOR value. + + @note If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the @ref dump() + function which serializes NaN or Infinity to `null`. + + @note The following CBOR types are not used in the conversion: + - byte strings (0x40..0x5F) + - UTF-8 strings terminated by "break" (0x7F) + - arrays terminated by "break" (0x9F) + - maps terminated by "break" (0xBF) + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - tagged items (0xC6..0xD4, 0xD8..0xDB) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + - half and single-precision floats (0xF9-0xFA) + - break (0xFF) + + @param[in] j JSON value to serialize + @return MessagePack serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in CBOR format.,to_cbor} + + @sa http://cbor.io + @sa @ref from_cbor(detail::input_adapter, const bool strict) for the + analogous deserialization + @sa @ref to_msgpack(const basic_json&) for the related MessagePack format + @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the + related UBJSON format + + @since version 2.0.9 + */ + static std::vector<uint8_t> to_cbor(const basic_json& j) + { + std::vector<uint8_t> result; + to_cbor(j, result); + return result; + } + + static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o) + { + binary_writer<uint8_t>(o).write_cbor(j); + } + + static void to_cbor(const basic_json& j, detail::output_adapter<char> o) + { + binary_writer<char>(o).write_cbor(j); + } + + /*! + @brief create a MessagePack serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the MessagePack + serialization format. MessagePack is a binary serialization format which + aims to be more compact than JSON itself, yet more efficient to parse. + + The library uses the following mapping from JSON values types to + MessagePack types according to the MessagePack specification: + + JSON value type | value/range | MessagePack type | first byte + --------------- | --------------------------------- | ---------------- | ---------- + null | `null` | nil | 0xC0 + boolean | `true` | true | 0xC3 + boolean | `false` | false | 0xC2 + number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 + number_integer | -2147483648..-32769 | int32 | 0xD2 + number_integer | -32768..-129 | int16 | 0xD1 + number_integer | -128..-33 | int8 | 0xD0 + number_integer | -32..-1 | negative fixint | 0xE0..0xFF + number_integer | 0..127 | positive fixint | 0x00..0x7F + number_integer | 128..255 | uint 8 | 0xCC + number_integer | 256..65535 | uint 16 | 0xCD + number_integer | 65536..4294967295 | uint 32 | 0xCE + number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF + number_unsigned | 0..127 | positive fixint | 0x00..0x7F + number_unsigned | 128..255 | uint 8 | 0xCC + number_unsigned | 256..65535 | uint 16 | 0xCD + number_unsigned | 65536..4294967295 | uint 32 | 0xCE + number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF + number_float | *any value* | float 64 | 0xCB + string | *length*: 0..31 | fixstr | 0xA0..0xBF + string | *length*: 32..255 | str 8 | 0xD9 + string | *length*: 256..65535 | str 16 | 0xDA + string | *length*: 65536..4294967295 | str 32 | 0xDB + array | *size*: 0..15 | fixarray | 0x90..0x9F + array | *size*: 16..65535 | array 16 | 0xDC + array | *size*: 65536..4294967295 | array 32 | 0xDD + object | *size*: 0..15 | fix map | 0x80..0x8F + object | *size*: 16..65535 | map 16 | 0xDE + object | *size*: 65536..4294967295 | map 32 | 0xDF + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a MessagePack value. + + @note The following values can **not** be converted to a MessagePack value: + - strings with more than 4294967295 bytes + - arrays with more than 4294967295 elements + - objects with more than 4294967295 elements + + @note The following MessagePack types are not used in the conversion: + - bin 8 - bin 32 (0xC4..0xC6) + - ext 8 - ext 32 (0xC7..0xC9) + - float 32 (0xCA) + - fixext 1 - fixext 16 (0xD4..0xD8) + + @note Any MessagePack output created @ref to_msgpack can be successfully + parsed by @ref from_msgpack. + + @note If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the @ref dump() + function which serializes NaN or Infinity to `null`. + + @param[in] j JSON value to serialize + @return MessagePack serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in MessagePack format.,to_msgpack} + + @sa http://msgpack.org + @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the + analogous deserialization + @sa @ref to_cbor(const basic_json& for the related CBOR format + @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the + related UBJSON format + + @since version 2.0.9 + */ + static std::vector<uint8_t> to_msgpack(const basic_json& j) + { + std::vector<uint8_t> result; + to_msgpack(j, result); + return result; + } + + static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o) + { + binary_writer<uint8_t>(o).write_msgpack(j); + } + + static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) + { + binary_writer<char>(o).write_msgpack(j); + } + + /*! + @brief create a UBJSON serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the UBJSON + (Universal Binary JSON) serialization format. UBJSON aims to be more compact + than JSON itself, yet more efficient to parse. + + The library uses the following mapping from JSON values types to + UBJSON types according to the UBJSON specification: + + JSON value type | value/range | UBJSON type | marker + --------------- | --------------------------------- | ----------- | ------ + null | `null` | null | `Z` + boolean | `true` | true | `T` + boolean | `false` | false | `F` + number_integer | -9223372036854775808..-2147483649 | int64 | `L` + number_integer | -2147483648..-32769 | int32 | `l` + number_integer | -32768..-129 | int16 | `I` + number_integer | -128..127 | int8 | `i` + number_integer | 128..255 | uint8 | `U` + number_integer | 256..32767 | int16 | `I` + number_integer | 32768..2147483647 | int32 | `l` + number_integer | 2147483648..9223372036854775807 | int64 | `L` + number_unsigned | 0..127 | int8 | `i` + number_unsigned | 128..255 | uint8 | `U` + number_unsigned | 256..32767 | int16 | `I` + number_unsigned | 32768..2147483647 | int32 | `l` + number_unsigned | 2147483648..9223372036854775807 | int64 | `L` + number_float | *any value* | float64 | `D` + string | *with shortest length indicator* | string | `S` + array | *see notes on optimized format* | array | `[` + object | *see notes on optimized format* | map | `{` + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a UBJSON value. + + @note The following values can **not** be converted to a UBJSON value: + - strings with more than 9223372036854775807 bytes (theoretical) + - unsigned integer numbers above 9223372036854775807 + + @note The following markers are not used in the conversion: + - `Z`: no-op values are not created. + - `C`: single-byte strings are serialized with `S` markers. + + @note Any UBJSON output created @ref to_ubjson can be successfully parsed + by @ref from_ubjson. + + @note If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the @ref dump() + function which serializes NaN or Infinity to `null`. + + @note The optimized formats for containers are supported: Parameter + @a use_size adds size information to the beginning of a container and + removes the closing marker. Parameter @a use_type further checks + whether all elements of a container have the same type and adds the + type marker to the beginning of the container. The @a use_type + parameter must only be used together with @a use_size = true. Note + that @a use_size = true alone may result in larger representations - + the benefit of this parameter is that the receiving side is + immediately informed on the number of elements of the container. + + @param[in] j JSON value to serialize + @param[in] use_size whether to add size annotations to container types + @param[in] use_type whether to add type annotations to container types + (must be combined with @a use_size = true) + @return UBJSON serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in UBJSON format.,to_ubjson} + + @sa http://ubjson.org + @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the + analogous deserialization + @sa @ref to_cbor(const basic_json& for the related CBOR format + @sa @ref to_msgpack(const basic_json&) for the related MessagePack format + + @since version 3.1.0 + */ + static std::vector<uint8_t> to_ubjson(const basic_json& j, + const bool use_size = false, + const bool use_type = false) + { + std::vector<uint8_t> result; + to_ubjson(j, result, use_size, use_type); + return result; + } + + static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o, + const bool use_size = false, const bool use_type = false) + { + binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type); + } + + static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, + const bool use_size = false, const bool use_type = false) + { + binary_writer<char>(o).write_ubjson(j, use_size, use_type); + } + + /*! + @brief create a JSON value from an input in CBOR format + + Deserializes a given input @a i to a JSON value using the CBOR (Concise + Binary Object Representation) serialization format. + + The library maps CBOR types to JSON value types as follows: + + CBOR type | JSON value type | first byte + ---------------------- | --------------- | ---------- + Integer | number_unsigned | 0x00..0x17 + Unsigned integer | number_unsigned | 0x18 + Unsigned integer | number_unsigned | 0x19 + Unsigned integer | number_unsigned | 0x1A + Unsigned integer | number_unsigned | 0x1B + Negative integer | number_integer | 0x20..0x37 + Negative integer | number_integer | 0x38 + Negative integer | number_integer | 0x39 + Negative integer | number_integer | 0x3A + Negative integer | number_integer | 0x3B + Negative integer | number_integer | 0x40..0x57 + UTF-8 string | string | 0x60..0x77 + UTF-8 string | string | 0x78 + UTF-8 string | string | 0x79 + UTF-8 string | string | 0x7A + UTF-8 string | string | 0x7B + UTF-8 string | string | 0x7F + array | array | 0x80..0x97 + array | array | 0x98 + array | array | 0x99 + array | array | 0x9A + array | array | 0x9B + array | array | 0x9F + map | object | 0xA0..0xB7 + map | object | 0xB8 + map | object | 0xB9 + map | object | 0xBA + map | object | 0xBB + map | object | 0xBF + False | `false` | 0xF4 + True | `true` | 0xF5 + Nill | `null` | 0xF6 + Half-Precision Float | number_float | 0xF9 + Single-Precision Float | number_float | 0xFA + Double-Precision Float | number_float | 0xFB + + @warning The mapping is **incomplete** in the sense that not all CBOR + types can be converted to a JSON value. The following CBOR types + are not supported and will yield parse errors (parse_error.112): + - byte strings (0x40..0x5F) + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - tagged items (0xC6..0xD4, 0xD8..0xDB) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + + @warning CBOR allows map keys of any type, whereas JSON only allows + strings as keys in object values. Therefore, CBOR maps with keys + other than UTF-8 strings are rejected (parse_error.113). + + @note Any CBOR output created @ref to_cbor can be successfully parsed by + @ref from_cbor. + + @param[in] i an input in CBOR format convertible to an input adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value + + @throw parse_error.110 if the given input ends prematurely or the end of + file was not reached when @a strict was set to true + @throw parse_error.112 if unsupported features from CBOR were + used in the given input @a v or if the input is not valid CBOR + @throw parse_error.113 if a string was expected as map key, but not found + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in CBOR + format to a JSON value.,from_cbor} + + @sa http://cbor.io + @sa @ref to_cbor(const basic_json&) for the analogous serialization + @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the + related MessagePack format + @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the + related UBJSON format + + @since version 2.0.9; parameter @a start_index since 2.1.1; changed to + consume input adapters, removed start_index parameter, and added + @a strict parameter since 3.0.0; added @allow_exceptions parameter + since 3.2.0 + */ + static basic_json from_cbor(detail::input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_cbor(detail::input_adapter, const bool, const bool) + */ + template<typename A1, typename A2, + detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> + static basic_json from_cbor(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @brief create a JSON value from an input in MessagePack format + + Deserializes a given input @a i to a JSON value using the MessagePack + serialization format. + + The library maps MessagePack types to JSON value types as follows: + + MessagePack type | JSON value type | first byte + ---------------- | --------------- | ---------- + positive fixint | number_unsigned | 0x00..0x7F + fixmap | object | 0x80..0x8F + fixarray | array | 0x90..0x9F + fixstr | string | 0xA0..0xBF + nil | `null` | 0xC0 + false | `false` | 0xC2 + true | `true` | 0xC3 + float 32 | number_float | 0xCA + float 64 | number_float | 0xCB + uint 8 | number_unsigned | 0xCC + uint 16 | number_unsigned | 0xCD + uint 32 | number_unsigned | 0xCE + uint 64 | number_unsigned | 0xCF + int 8 | number_integer | 0xD0 + int 16 | number_integer | 0xD1 + int 32 | number_integer | 0xD2 + int 64 | number_integer | 0xD3 + str 8 | string | 0xD9 + str 16 | string | 0xDA + str 32 | string | 0xDB + array 16 | array | 0xDC + array 32 | array | 0xDD + map 16 | object | 0xDE + map 32 | object | 0xDF + negative fixint | number_integer | 0xE0-0xFF + + @warning The mapping is **incomplete** in the sense that not all + MessagePack types can be converted to a JSON value. The following + MessagePack types are not supported and will yield parse errors: + - bin 8 - bin 32 (0xC4..0xC6) + - ext 8 - ext 32 (0xC7..0xC9) + - fixext 1 - fixext 16 (0xD4..0xD8) + + @note Any MessagePack output created @ref to_msgpack can be successfully + parsed by @ref from_msgpack. + + @param[in] i an input in MessagePack format convertible to an input + adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value + + @throw parse_error.110 if the given input ends prematurely or the end of + file was not reached when @a strict was set to true + @throw parse_error.112 if unsupported features from MessagePack were + used in the given input @a i or if the input is not valid MessagePack + @throw parse_error.113 if a string was expected as map key, but not found + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in + MessagePack format to a JSON value.,from_msgpack} + + @sa http://msgpack.org + @sa @ref to_msgpack(const basic_json&) for the analogous serialization + @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the + related CBOR format + @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for + the related UBJSON format + + @since version 2.0.9; parameter @a start_index since 2.1.1; changed to + consume input adapters, removed start_index parameter, and added + @a strict parameter since 3.0.0; added @allow_exceptions parameter + since 3.2.0 + */ + static basic_json from_msgpack(detail::input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_msgpack(detail::input_adapter, const bool, const bool) + */ + template<typename A1, typename A2, + detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> + static basic_json from_msgpack(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @brief create a JSON value from an input in UBJSON format + + Deserializes a given input @a i to a JSON value using the UBJSON (Universal + Binary JSON) serialization format. + + The library maps UBJSON types to JSON value types as follows: + + UBJSON type | JSON value type | marker + ----------- | --------------------------------------- | ------ + no-op | *no value, next value is read* | `N` + null | `null` | `Z` + false | `false` | `F` + true | `true` | `T` + float32 | number_float | `d` + float64 | number_float | `D` + uint8 | number_unsigned | `U` + int8 | number_integer | `i` + int16 | number_integer | `I` + int32 | number_integer | `l` + int64 | number_integer | `L` + string | string | `S` + char | string | `C` + array | array (optimized values are supported) | `[` + object | object (optimized values are supported) | `{` + + @note The mapping is **complete** in the sense that any UBJSON value can + be converted to a JSON value. + + @param[in] i an input in UBJSON format convertible to an input adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value + + @throw parse_error.110 if the given input ends prematurely or the end of + file was not reached when @a strict was set to true + @throw parse_error.112 if a parse error occurs + @throw parse_error.113 if a string could not be parsed successfully + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in + UBJSON format to a JSON value.,from_ubjson} + + @sa http://ubjson.org + @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the + analogous serialization + @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the + related CBOR format + @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for + the related MessagePack format + + @since version 3.1.0; added @allow_exceptions parameter since 3.2.0 + */ + static basic_json from_ubjson(detail::input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_ubjson(detail::input_adapter, const bool, const bool) + */ + template<typename A1, typename A2, + detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> + static basic_json from_ubjson(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /// @} + + ////////////////////////// + // JSON Pointer support // + ////////////////////////// + + /// @name JSON Pointer functions + /// @{ + + /*! + @brief access specified element via JSON Pointer + + Uses a JSON pointer to retrieve a reference to the respective JSON value. + No bound checking is performed. Similar to @ref operator[](const typename + object_t::key_type&), `null` values are created in arrays and objects if + necessary. + + In particular: + - If the JSON pointer points to an object key that does not exist, it + is created an filled with a `null` value before a reference to it + is returned. + - If the JSON pointer points to an array index that does not exist, it + is created an filled with a `null` value before a reference to it + is returned. All indices between the current maximum and the given + index are also filled with `null`. + - The special value `-` is treated as a synonym for the index past the + end. + + @param[in] ptr a JSON pointer + + @return reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + + @liveexample{The behavior is shown in the example.,operatorjson_pointer} + + @since version 2.0.0 + */ + reference operator[](const json_pointer& ptr) + { + return ptr.get_unchecked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Uses a JSON pointer to retrieve a reference to the respective JSON value. + No bound checking is performed. The function does not change the JSON + value; no `null` values are created. In particular, the the special value + `-` yields an exception. + + @param[in] ptr JSON pointer to the desired element + + @return const reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + + @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} + + @since version 2.0.0 + */ + const_reference operator[](const json_pointer& ptr) const + { + return ptr.get_unchecked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Returns a reference to the element at with specified JSON pointer @a ptr, + with bounds checking. + + @param[in] ptr JSON pointer to the desired element + + @return reference to the element pointed to by @a ptr + + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. + + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. + + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.403 if the JSON pointer describes a key of an object + which cannot be found. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 2.0.0 + + @liveexample{The behavior is shown in the example.,at_json_pointer} + */ + reference at(const json_pointer& ptr) + { + return ptr.get_checked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Returns a const reference to the element at with specified JSON pointer @a + ptr, with bounds checking. + + @param[in] ptr JSON pointer to the desired element + + @return reference to the element pointed to by @a ptr + + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. + + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. + + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.403 if the JSON pointer describes a key of an object + which cannot be found. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 2.0.0 + + @liveexample{The behavior is shown in the example.,at_json_pointer_const} + */ + const_reference at(const json_pointer& ptr) const + { + return ptr.get_checked(this); + } + + /*! + @brief return flattened JSON value + + The function creates a JSON object whose keys are JSON pointers (see [RFC + 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all + primitive. The original JSON value can be restored using the @ref + unflatten() function. + + @return an object that maps JSON pointers to primitive values + + @note Empty objects and arrays are flattened to `null` and will not be + reconstructed correctly by the @ref unflatten() function. + + @complexity Linear in the size the JSON value. + + @liveexample{The following code shows how a JSON object is flattened to an + object whose keys consist of JSON pointers.,flatten} + + @sa @ref unflatten() for the reverse function + + @since version 2.0.0 + */ + basic_json flatten() const + { + basic_json result(value_t::object); + json_pointer::flatten("", *this, result); + return result; + } + + /*! + @brief unflatten a previously flattened JSON value + + The function restores the arbitrary nesting of a JSON value that has been + flattened before using the @ref flatten() function. The JSON value must + meet certain constraints: + 1. The value must be an object. + 2. The keys must be JSON pointers (see + [RFC 6901](https://tools.ietf.org/html/rfc6901)) + 3. The mapped values must be primitive JSON types. + + @return the original JSON from a flattened version + + @note Empty objects and arrays are flattened by @ref flatten() to `null` + values and can not unflattened to their original type. Apart from + this example, for a JSON value `j`, the following is always true: + `j == j.flatten().unflatten()`. + + @complexity Linear in the size the JSON value. + + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + + @liveexample{The following code shows how a flattened JSON object is + unflattened into the original nested JSON object.,unflatten} + + @sa @ref flatten() for the reverse function + + @since version 2.0.0 + */ + basic_json unflatten() const + { + return json_pointer::unflatten(*this); + } + + /// @} + + ////////////////////////// + // JSON Patch functions // + ////////////////////////// + + /// @name JSON Patch functions + /// @{ + + /*! + @brief applies a JSON patch + + [JSON Patch](http://jsonpatch.com) defines a JSON document structure for + expressing a sequence of operations to apply to a JSON) document. With + this function, a JSON Patch is applied to the current JSON value by + executing all operations from the patch. + + @param[in] json_patch JSON patch document + @return patched document + + @note The application of a patch is atomic: Either all operations succeed + and the patched document is returned or an exception is thrown. In + any case, the original value is not changed: the patch is applied + to a copy of the value. + + @throw parse_error.104 if the JSON patch does not consist of an array of + objects + + @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory + attributes are missing); example: `"operation add must have member path"` + + @throw out_of_range.401 if an array index is out of range. + + @throw out_of_range.403 if a JSON pointer inside the patch could not be + resolved successfully in the current JSON value; example: `"key baz not + found"` + + @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", + "move") + + @throw other_error.501 if "test" operation was unsuccessful + + @complexity Linear in the size of the JSON value and the length of the + JSON patch. As usually only a fraction of the JSON value is affected by + the patch, the complexity can usually be neglected. + + @liveexample{The following code shows how a JSON patch is applied to a + value.,patch} + + @sa @ref diff -- create a JSON patch by comparing two JSON values + + @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) + @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) + + @since version 2.0.0 + */ + basic_json patch(const basic_json& json_patch) const + { + // make a working copy to apply the patch to + basic_json result = *this; + + // the valid JSON Patch operations + enum class patch_operations {add, remove, replace, move, copy, test, invalid}; + + const auto get_op = [](const std::string & op) + { + if (op == "add") + { + return patch_operations::add; + } + if (op == "remove") + { + return patch_operations::remove; + } + if (op == "replace") + { + return patch_operations::replace; + } + if (op == "move") + { + return patch_operations::move; + } + if (op == "copy") + { + return patch_operations::copy; + } + if (op == "test") + { + return patch_operations::test; + } + + return patch_operations::invalid; + }; + + // wrapper for "add" operation; add value at ptr + const auto operation_add = [&result](json_pointer & ptr, basic_json val) + { + // adding to the root of the target document means replacing it + if (ptr.is_root()) + { + result = val; + } + else + { + // make sure the top element of the pointer exists + json_pointer top_pointer = ptr.top(); + if (top_pointer != ptr) + { + result.at(top_pointer); + } + + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.pop_back(); + basic_json& parent = result[ptr]; + + switch (parent.m_type) + { + case value_t::null: + case value_t::object: + { + // use operator[] to add value + parent[last_path] = val; + break; + } + + case value_t::array: + { + if (last_path == "-") + { + // special case: append to back + parent.push_back(val); + } + else + { + const auto idx = json_pointer::array_index(last_path); + if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size())) + { + // avoid undefined behavior + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + else + { + // default case: insert add offset + parent.insert(parent.begin() + static_cast<difference_type>(idx), val); + } + } + break; + } + + default: + { + // if there exists a parent it cannot be primitive + assert(false); // LCOV_EXCL_LINE + } + } + } + }; + + // wrapper for "remove" operation; remove value at ptr + const auto operation_remove = [&result](json_pointer & ptr) + { + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.pop_back(); + basic_json& parent = result.at(ptr); + + // remove child + if (parent.is_object()) + { + // perform range check + auto it = parent.find(last_path); + if (JSON_LIKELY(it != parent.end())) + { + parent.erase(it); + } + else + { + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); + } + } + else if (parent.is_array()) + { + // note erase performs range check + parent.erase(static_cast<size_type>(json_pointer::array_index(last_path))); + } + }; + + // type check: top level value must be an array + if (JSON_UNLIKELY(not json_patch.is_array())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); + } + + // iterate and apply the operations + for (const auto& val : json_patch) + { + // wrapper to get a value for an operation + const auto get_value = [&val](const std::string & op, + const std::string & member, + bool string_type) -> basic_json & + { + // find value + auto it = val.m_value.object->find(member); + + // context-sensitive error message + const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; + + // check if desired value is present + if (JSON_UNLIKELY(it == val.m_value.object->end())) + { + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); + } + + // check if result is of type string + if (JSON_UNLIKELY(string_type and not it->second.is_string())) + { + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); + } + + // no error: return value + return it->second; + }; + + // type check: every element of the array must be an object + if (JSON_UNLIKELY(not val.is_object())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); + } + + // collect mandatory members + const std::string op = get_value("op", "op", true); + const std::string path = get_value(op, "path", true); + json_pointer ptr(path); + + switch (get_op(op)) + { + case patch_operations::add: + { + operation_add(ptr, get_value("add", "value", false)); + break; + } + + case patch_operations::remove: + { + operation_remove(ptr); + break; + } + + case patch_operations::replace: + { + // the "path" location must exist - use at() + result.at(ptr) = get_value("replace", "value", false); + break; + } + + case patch_operations::move: + { + const std::string from_path = get_value("move", "from", true); + json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The move operation is functionally identical to a + // "remove" operation on the "from" location, followed + // immediately by an "add" operation at the target + // location with the value that was just removed. + operation_remove(from_ptr); + operation_add(ptr, v); + break; + } + + case patch_operations::copy: + { + const std::string from_path = get_value("copy", "from", true); + const json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The copy is functionally identical to an "add" + // operation at the target location using the value + // specified in the "from" member. + operation_add(ptr, v); + break; + } + + case patch_operations::test: + { + bool success = false; + JSON_TRY + { + // check if "value" matches the one at "path" + // the "path" location must exist - use at() + success = (result.at(ptr) == get_value("test", "value", false)); + } + JSON_CATCH (out_of_range&) + { + // ignore out of range errors: success remains false + } + + // throw an exception if test fails + if (JSON_UNLIKELY(not success)) + { + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); + } + + break; + } + + case patch_operations::invalid: + { + // op must be "add", "remove", "replace", "move", "copy", or + // "test" + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); + } + } + } + + return result; + } + + /*! + @brief creates a diff as a JSON patch + + Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can + be changed into the value @a target by calling @ref patch function. + + @invariant For two JSON values @a source and @a target, the following code + yields always `true`: + @code {.cpp} + source.patch(diff(source, target)) == target; + @endcode + + @note Currently, only `remove`, `add`, and `replace` operations are + generated. + + @param[in] source JSON value to compare from + @param[in] target JSON value to compare against + @param[in] path helper value to create JSON pointers + + @return a JSON patch to convert the @a source to @a target + + @complexity Linear in the lengths of @a source and @a target. + + @liveexample{The following code shows how a JSON patch is created as a + diff for two JSON values.,diff} + + @sa @ref patch -- apply a JSON patch + @sa @ref merge_patch -- apply a JSON Merge Patch + + @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) + + @since version 2.0.0 + */ + static basic_json diff(const basic_json& source, const basic_json& target, + const std::string& path = "") + { + // the patch + basic_json result(value_t::array); + + // if the values are the same, return empty patch + if (source == target) + { + return result; + } + + if (source.type() != target.type()) + { + // different types: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + } + else + { + switch (source.type()) + { + case value_t::array: + { + // first pass: traverse common elements + std::size_t i = 0; + while (i < source.size() and i < target.size()) + { + // recursive call to compare array values at index i + auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + ++i; + } + + // i now reached the end of at least one array + // in a second pass, traverse the remaining elements + + // remove my remaining elements + const auto end_index = static_cast<difference_type>(result.size()); + while (i < source.size()) + { + // add operations in reverse order to avoid invalid + // indices + result.insert(result.begin() + end_index, object( + { + {"op", "remove"}, + {"path", path + "/" + std::to_string(i)} + })); + ++i; + } + + // add other remaining elements + while (i < target.size()) + { + result.push_back( + { + {"op", "add"}, + {"path", path + "/" + std::to_string(i)}, + {"value", target[i]} + }); + ++i; + } + + break; + } + + case value_t::object: + { + // first pass: traverse this object's elements + for (auto it = source.cbegin(); it != source.cend(); ++it) + { + // escape the key name to be used in a JSON patch + const auto key = json_pointer::escape(it.key()); + + if (target.find(it.key()) != target.end()) + { + // recursive call to compare object values at key it + auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + } + else + { + // found a key that is not in o -> remove it + result.push_back(object( + { + {"op", "remove"}, {"path", path + "/" + key} + })); + } + } + + // second pass: traverse other object's elements + for (auto it = target.cbegin(); it != target.cend(); ++it) + { + if (source.find(it.key()) == source.end()) + { + // found a key that is not in this -> add it + const auto key = json_pointer::escape(it.key()); + result.push_back( + { + {"op", "add"}, {"path", path + "/" + key}, + {"value", it.value()} + }); + } + } + + break; + } + + default: + { + // both primitive type: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + break; + } + } + } + + return result; + } + + /// @} + + //////////////////////////////// + // JSON Merge Patch functions // + //////////////////////////////// + + /// @name JSON Merge Patch functions + /// @{ + + /*! + @brief applies a JSON Merge Patch + + The merge patch format is primarily intended for use with the HTTP PATCH + method as a means of describing a set of modifications to a target + resource's content. This function applies a merge patch to the current + JSON value. + + The function implements the following algorithm from Section 2 of + [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396): + + ``` + define MergePatch(Target, Patch): + if Patch is an Object: + if Target is not an Object: + Target = {} // Ignore the contents and set it to an empty Object + for each Name/Value pair in Patch: + if Value is null: + if Name exists in Target: + remove the Name/Value pair from Target + else: + Target[Name] = MergePatch(Target[Name], Value) + return Target + else: + return Patch + ``` + + Thereby, `Target` is the current object; that is, the patch is applied to + the current value. + + @param[in] patch the patch to apply + + @complexity Linear in the lengths of @a patch. + + @liveexample{The following code shows how a JSON Merge Patch is applied to + a JSON document.,merge_patch} + + @sa @ref patch -- apply a JSON patch + @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) + + @since version 3.0.0 + */ + void merge_patch(const basic_json& patch) + { + if (patch.is_object()) + { + if (not is_object()) + { + *this = object(); + } + for (auto it = patch.begin(); it != patch.end(); ++it) + { + if (it.value().is_null()) + { + erase(it.key()); + } + else + { + operator[](it.key()).merge_patch(it.value()); + } + } + } + else + { + *this = patch; + } + } + + /// @} +}; +} // namespace nlohmann + +/////////////////////// +// nonmember support // +/////////////////////// + +// specialization of std::swap, and std::hash +namespace std +{ +/*! +@brief exchanges the values of two JSON objects + +@since version 1.0.0 +*/ +template<> +inline void swap(nlohmann::json& j1, + nlohmann::json& j2) noexcept( + is_nothrow_move_constructible<nlohmann::json>::value and + is_nothrow_move_assignable<nlohmann::json>::value + ) +{ + j1.swap(j2); +} + +/// hash value for JSON objects +template<> +struct hash<nlohmann::json> +{ + /*! + @brief return a hash value for a JSON object + + @since version 1.0.0 + */ + std::size_t operator()(const nlohmann::json& j) const + { + // a naive hashing via the string representation + const auto& h = hash<nlohmann::json::string_t>(); + return h(j.dump()); + } +}; + +/// specialization for std::less<value_t> +/// @note: do not remove the space after '<', +/// see https://github.com/nlohmann/json/pull/679 +template<> +struct less< ::nlohmann::detail::value_t> +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + +} // namespace std + +/*! +@brief user-defined string literal for JSON values + +This operator implements a user-defined string literal for JSON objects. It +can be used by adding `"_json"` to a string literal and returns a JSON object +if no parse error occurred. + +@param[in] s a string representation of a JSON object +@param[in] n the length of string @a s +@return a JSON object + +@since version 1.0.0 +*/ +inline nlohmann::json operator "" _json(const char* s, std::size_t n) +{ + return nlohmann::json::parse(s, s + n); +} + +/*! +@brief user-defined string literal for JSON pointer + +This operator implements a user-defined string literal for JSON Pointers. It +can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer +object if no parse error occurred. + +@param[in] s a string representation of a JSON Pointer +@param[in] n the length of string @a s +@return a JSON pointer object + +@since version 2.0.0 +*/ +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(s, n)); +} + +// #include <nlohmann/detail/macro_unscope.hpp> + + +// restore GCC/clang diagnostic settings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic pop +#endif +#if defined(__clang__) + #pragma GCC diagnostic pop +#endif + +// clean up +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_LIKELY +#undef JSON_UNLIKELY +#undef JSON_DEPRECATED +#undef JSON_HAS_CPP_14 +#undef JSON_HAS_CPP_17 +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL +#undef NLOHMANN_JSON_HAS_HELPER + + +#endif \ No newline at end of file diff --git a/include/pli_vis/third_party/qwt/qwt.h b/include/pli_vis/third_party/qwt/qwt.h deleted file mode 100644 index e363dd57aacf37546267078013b6740aa2e9879b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt.h +++ /dev/null @@ -1,22 +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_H -#define QWT_H - -#include "qwt/qwt_global.h" - -/*! - Some constants for use within Qwt. -*/ -namespace Qwt -{ -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_abstract_legend.h b/include/pli_vis/third_party/qwt/qwt_abstract_legend.h deleted file mode 100644 index 642065845825e48c3fa54c334179e744e4153531..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_abstract_legend.h +++ /dev/null @@ -1,71 +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_ABSTRACT_LEGEND_H -#define QWT_ABSTRACT_LEGEND_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_legend_data.h" -#include <qframe.h> -#include <qlist.h> - -class QVariant; - -/*! - \brief Abstract base class for legend widgets - - Legends, that need to be under control of the QwtPlot layout system - need to be derived from QwtAbstractLegend. - - \note Other type of legends can be implemented by connecting to - the QwtPlot::legendDataChanged() signal. But as these legends - are unknown to the plot layout system the layout code - ( on screen and for QwtPlotRenderer ) need to be organized - in application code. - - \sa QwtLegend - */ -class QWT_EXPORT QwtAbstractLegend : public QFrame -{ - Q_OBJECT - -public: - explicit QwtAbstractLegend( QWidget *parent = NULL ); - virtual ~QwtAbstractLegend(); - - /*! - Render the legend into a given rectangle. - - \param painter Painter - \param rect Bounding rectangle - \param fillBackground When true, fill rect with the widget background - - \sa renderLegend() is used by QwtPlotRenderer - */ - virtual void renderLegend( QPainter *painter, - const QRectF &rect, bool fillBackground ) const = 0; - - //! \return True, when no plot item is inserted - virtual bool isEmpty() const = 0; - - virtual int scrollExtent( Qt::Orientation ) const; - -public Q_SLOTS: - - /*! - \brief Update the entries for a plot item - - \param itemInfo Info about an item - \param data List of legend entry attributes for the item - */ - virtual void updateLegend( const QVariant &itemInfo, - const QList<QwtLegendData> &data ) = 0; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_abstract_scale.h b/include/pli_vis/third_party/qwt/qwt_abstract_scale.h deleted file mode 100644 index 75175cc8d82d1771715538ec67ff35c425fe695e..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_abstract_scale.h +++ /dev/null @@ -1,105 +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_ABSTRACT_SCALE_H -#define QWT_ABSTRACT_SCALE_H - -#include "qwt/qwt_global.h" -#include <qwidget.h> - -class QwtScaleEngine; -class QwtAbstractScaleDraw; -class QwtScaleDiv; -class QwtScaleMap; -class QwtInterval; - -/*! - \brief An abstract base class for widgets having a scale - - The scale of an QwtAbstractScale is determined by a QwtScaleDiv - definition, that contains the boundaries and the ticks of the scale. - The scale is painted using a QwtScaleDraw object. - - The scale division might be assigned explicitly - but usually - it is calculated from the boundaries using a QwtScaleEngine. - - The scale engine also decides the type of transformation of the scale - ( linear, logarithmic ... ). -*/ - -class QWT_EXPORT QwtAbstractScale: public QWidget -{ - Q_OBJECT - - Q_PROPERTY( double lowerBound READ lowerBound WRITE setLowerBound ) - Q_PROPERTY( double upperBound READ upperBound WRITE setUpperBound ) - - Q_PROPERTY( int scaleMaxMajor READ scaleMaxMajor WRITE setScaleMaxMajor ) - Q_PROPERTY( int scaleMaxMinor READ scaleMaxMinor WRITE setScaleMaxMinor ) - - Q_PROPERTY( double scaleStepSize READ scaleStepSize WRITE setScaleStepSize ) - -public: - QwtAbstractScale( QWidget *parent = NULL ); - virtual ~QwtAbstractScale(); - - void setScale( double lowerBound, double upperBound ); - void setScale( const QwtInterval & ); - void setScale( const QwtScaleDiv & ); - - const QwtScaleDiv& scaleDiv() const; - - void setLowerBound( double value ); - double lowerBound() const; - - void setUpperBound( double value ); - double upperBound() const; - - void setScaleStepSize( double stepSize ); - double scaleStepSize() const; - - void setScaleMaxMajor( int ticks ); - int scaleMaxMinor() const; - - void setScaleMaxMinor( int ticks ); - int scaleMaxMajor() const; - - void setScaleEngine( QwtScaleEngine * ); - const QwtScaleEngine *scaleEngine() const; - QwtScaleEngine *scaleEngine(); - - int transform( double ) const; - double invTransform( int ) const; - - bool isInverted() const; - - double minimum() const; - double maximum() const; - - const QwtScaleMap &scaleMap() const; - -protected: - void rescale( double lowerBound, - double upperBound, double stepSize ); - - void setAbstractScaleDraw( QwtAbstractScaleDraw * ); - - const QwtAbstractScaleDraw *abstractScaleDraw() const; - QwtAbstractScaleDraw *abstractScaleDraw(); - - virtual void scaleChange(); - -private: - void updateScaleDraw(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_abstract_scale_draw.h b/include/pli_vis/third_party/qwt/qwt_abstract_scale_draw.h deleted file mode 100644 index 4ddbdf33781ae3538f5eaed59414399ec2de7a0a..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_abstract_scale_draw.h +++ /dev/null @@ -1,141 +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_ABSTRACT_SCALE_DRAW_H -#define QWT_ABSTRACT_SCALE_DRAW_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_text.h" - -class QPalette; -class QPainter; -class QFont; -class QwtTransform; -class QwtScaleMap; - -/*! - \brief A abstract base class for drawing scales - - QwtAbstractScaleDraw can be used to draw linear or logarithmic scales. - - After a scale division has been specified as a QwtScaleDiv object - using setScaleDiv(), the scale can be drawn with the draw() member. -*/ -class QWT_EXPORT QwtAbstractScaleDraw -{ -public: - - /*! - Components of a scale - \sa enableComponent(), hasComponent - */ - enum ScaleComponent - { - //! Backbone = the line where the ticks are located - Backbone = 0x01, - - //! Ticks - Ticks = 0x02, - - //! Labels - Labels = 0x04 - }; - - //! Scale components - typedef QFlags<ScaleComponent> ScaleComponents; - - QwtAbstractScaleDraw(); - virtual ~QwtAbstractScaleDraw(); - - void setScaleDiv( const QwtScaleDiv &s ); - const QwtScaleDiv& scaleDiv() const; - - void setTransformation( QwtTransform * ); - const QwtScaleMap &scaleMap() const; - QwtScaleMap &scaleMap(); - - void enableComponent( ScaleComponent, bool enable = true ); - bool hasComponent( ScaleComponent ) const; - - void setTickLength( QwtScaleDiv::TickType, double length ); - double tickLength( QwtScaleDiv::TickType ) const; - double maxTickLength() const; - - void setSpacing( double margin ); - double spacing() const; - - void setPenWidth( int width ); - int penWidth() const; - - virtual void draw( QPainter *, const QPalette & ) const; - - virtual QwtText label( double ) const; - - /*! - Calculate the extent - - The extent is the distance from the baseline to the outermost - pixel of the scale draw in opposite to its orientation. - It is at least minimumExtent() pixels. - - \param font Font used for drawing the tick labels - \return Number of pixels - - \sa setMinimumExtent(), minimumExtent() - */ - virtual double extent( const QFont &font ) const = 0; - - void setMinimumExtent( double ); - double minimumExtent() const; - -protected: - /*! - Draw a tick - - \param painter Painter - \param value Value of the tick - \param len Length of the tick - - \sa drawBackbone(), drawLabel() - */ - virtual void drawTick( QPainter *painter, double value, double len ) const = 0; - - /*! - Draws the baseline of the scale - \param painter Painter - - \sa drawTick(), drawLabel() - */ - virtual void drawBackbone( QPainter *painter ) const = 0; - - /*! - Draws the label for a major scale tick - - \param painter Painter - \param value Value - - \sa drawTick(), drawBackbone() - */ - virtual void drawLabel( QPainter *painter, double value ) const = 0; - - void invalidateCache(); - const QwtText &tickLabel( const QFont &, double value ) const; - -private: - QwtAbstractScaleDraw( const QwtAbstractScaleDraw & ); - QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & ); - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtAbstractScaleDraw::ScaleComponents ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_abstract_slider.h b/include/pli_vis/third_party/qwt/qwt_abstract_slider.h deleted file mode 100644 index fa97bc54958517b93e2e49110021f40987d157e2..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_abstract_slider.h +++ /dev/null @@ -1,167 +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_ABSTRACT_SLIDER_H -#define QWT_ABSTRACT_SLIDER_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_scale.h" - -/*! - \brief An abstract base class for slider widgets with a scale - - A slider widget displays a value according to a scale. - The class is designed as a common super class for widgets like - QwtKnob, QwtDial and QwtSlider. - - When the slider is nor readOnly() its value can be modified - by keyboard, mouse and wheel inputs. - - The range of the slider is divided into a number of steps from - which the value increments according to user inputs depend. - Only for linear scales the number of steps correspond with - a fixed step size. -*/ - -class QWT_EXPORT QwtAbstractSlider: public QwtAbstractScale -{ - Q_OBJECT - - Q_PROPERTY( double value READ value WRITE setValue ) - - Q_PROPERTY( uint totalSteps READ totalSteps WRITE setTotalSteps ) - Q_PROPERTY( uint singleSteps READ singleSteps WRITE setSingleSteps ) - Q_PROPERTY( uint pageSteps READ pageSteps WRITE setPageSteps ) - Q_PROPERTY( bool stepAlignment READ stepAlignment WRITE setStepAlignment ) - - Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) - Q_PROPERTY( bool tracking READ isTracking WRITE setTracking ) - Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) - - Q_PROPERTY( bool invertedControls READ invertedControls WRITE setInvertedControls ) - -public: - explicit QwtAbstractSlider( QWidget *parent = NULL ); - virtual ~QwtAbstractSlider(); - - void setValid( bool ); - bool isValid() const; - - double value() const; - - void setWrapping( bool ); - bool wrapping() const; - - void setTotalSteps( uint ); - uint totalSteps() const; - - void setSingleSteps( uint ); - uint singleSteps() const; - - void setPageSteps( uint ); - uint pageSteps() const; - - void setStepAlignment( bool ); - bool stepAlignment() const; - - void setTracking( bool ); - bool isTracking() const; - - void setReadOnly( bool ); - bool isReadOnly() const; - - void setInvertedControls( bool ); - bool invertedControls() const; - -public Q_SLOTS: - void setValue( double val ); - -Q_SIGNALS: - - /*! - \brief Notify a change of value. - - When tracking is enabled (default setting), - this signal will be emitted every time the value changes. - - \param value New value - - \sa setTracking(), sliderMoved() - */ - void valueChanged( double value ); - - /*! - This signal is emitted when the user presses the - movable part of the slider. - */ - void sliderPressed(); - - /*! - This signal is emitted when the user releases the - movable part of the slider. - */ - void sliderReleased(); - - /*! - This signal is emitted when the user moves the - slider with the mouse. - - \param value New value - - \sa valueChanged() - */ - void sliderMoved( double value ); - -protected: - virtual void mousePressEvent( QMouseEvent * ); - virtual void mouseReleaseEvent( QMouseEvent * ); - virtual void mouseMoveEvent( QMouseEvent * ); - virtual void keyPressEvent( QKeyEvent * ); - virtual void wheelEvent( QWheelEvent * ); - - /*! - \brief Determine what to do when the user presses a mouse button. - - \param pos Mouse position - - \retval True, when pos is a valid scroll position - \sa scrolledTo() - */ - virtual bool isScrollPosition( const QPoint &pos ) const = 0; - - /*! - \brief Determine the value for a new position of the - movable part of the slider - - \param pos Mouse position - - \return Value for the mouse position - \sa isScrollPosition() - */ - virtual double scrolledTo( const QPoint &pos ) const = 0; - - void incrementValue( int numSteps ); - - virtual void scaleChange(); - -protected: - virtual void sliderChange(); - - double incrementedValue( - double value, int stepCount ) const; - -private: - double alignedValue( double ) const; - double boundedValue( double ) const; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_analog_clock.h b/include/pli_vis/third_party/qwt/qwt_analog_clock.h deleted file mode 100644 index 2808d6981f9bde3f203d22fe0d36d4862899178f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_analog_clock.h +++ /dev/null @@ -1,93 +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_ANALOG_CLOCK_H -#define QWT_ANALOG_CLOCK_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_dial.h" -#include "qwt/qwt_dial_needle.h" -#include <qdatetime.h> - -/*! - \brief An analog clock - - \image html analogclock.png - - \par Example - \code - #include <qwt_analog_clock.h> - - QwtAnalogClock *clock = new QwtAnalogClock(...); - clock->scaleDraw()->setPenWidth(3); - clock->setLineWidth(6); - clock->setFrameShadow(QwtDial::Sunken); - clock->setTime(); - - // update the clock every second - QTimer *timer = new QTimer(clock); - timer->connect(timer, SIGNAL(timeout()), clock, SLOT(setCurrentTime())); - timer->start(1000); - - \endcode - - \note The examples/dials example shows how to use QwtAnalogClock. -*/ - -class QWT_EXPORT QwtAnalogClock: public QwtDial -{ - Q_OBJECT - -public: - /*! - Hand type - \sa setHand(), hand() - */ - enum Hand - { - //! Needle displaying the seconds - SecondHand, - - //! Needle displaying the minutes - MinuteHand, - - //! Needle displaying the hours - HourHand, - - //! Number of needles - NHands - }; - - explicit QwtAnalogClock( QWidget* parent = NULL ); - virtual ~QwtAnalogClock(); - - void setHand( Hand, QwtDialNeedle * ); - - const QwtDialNeedle *hand( Hand ) const; - QwtDialNeedle *hand( Hand ); - -public Q_SLOTS: - void setCurrentTime(); - void setTime( const QTime & ); - -protected: - virtual void drawNeedle( QPainter *, const QPointF &, - double radius, double direction, QPalette::ColorGroup ) const; - - virtual void drawHand( QPainter *, Hand, const QPointF &, - double radius, double direction, QPalette::ColorGroup ) const; - -private: - // use setHand instead - void setNeedle( QwtDialNeedle * ); - - QwtDialNeedle *d_hand[NHands]; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_arrow_button.h b/include/pli_vis/third_party/qwt/qwt_arrow_button.h deleted file mode 100644 index f380d9df148647676aecf6712cd24549ab4e82dd..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_arrow_button.h +++ /dev/null @@ -1,52 +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_ARROW_BUTTON_H -#define QWT_ARROW_BUTTON_H - -#include "qwt/qwt_global.h" -#include <qpushbutton.h> - -/*! - \brief Arrow Button - - A push button with one or more filled triangles on its front. - An Arrow button can have 1 to 3 arrows in a row, pointing - up, down, left or right. -*/ -class QWT_EXPORT QwtArrowButton : public QPushButton -{ -public: - explicit QwtArrowButton ( int num, Qt::ArrowType, QWidget *parent = NULL ); - virtual ~QwtArrowButton(); - - Qt::ArrowType arrowType() const; - int num() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - -protected: - virtual void paintEvent( QPaintEvent *event ); - - virtual void drawButtonLabel( QPainter *p ); - virtual void drawArrow( QPainter *, - const QRect &, Qt::ArrowType ) const; - virtual QRect labelRect() const; - virtual QSize arrowSize( Qt::ArrowType, - const QSize &boundingSize ) const; - - virtual void keyPressEvent( QKeyEvent * ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_clipper.h b/include/pli_vis/third_party/qwt/qwt_clipper.h deleted file mode 100644 index 2d9b1ebfb1cf52063755ec77c0541d2cae06ed32..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_clipper.h +++ /dev/null @@ -1,40 +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_CLIPPER_H -#define QWT_CLIPPER_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include <qpolygon.h> -#include <qvector.h> - -class QRect; -class QRectF; - -/*! - \brief Some clipping algorithms -*/ - -class QWT_EXPORT QwtClipper -{ -public: - static QPolygon clipPolygon( const QRect &, - const QPolygon &, bool closePolygon = false ); - static QPolygon clipPolygon( const QRectF &, - const QPolygon &, bool closePolygon = false ); - - static QPolygonF clipPolygonF( const QRectF &, - const QPolygonF &, bool closePolygon = false ); - - static QVector<QwtInterval> clipCircle( - const QRectF &, const QPointF &, double radius ); -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_color_map.h b/include/pli_vis/third_party/qwt/qwt_color_map.h deleted file mode 100644 index f467ffb55f0f0261412acc54b3d7f7b0c1332d13..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_color_map.h +++ /dev/null @@ -1,200 +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_COLOR_MAP_H -#define QWT_COLOR_MAP_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include <qcolor.h> -#include <qvector.h> - -/*! - \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. - - Each color map is optimized to return colors for only one of the - following image formats: - - - QImage::Format_Indexed8\n - - QImage::Format_ARGB32\n - - \sa QwtPlotSpectrogram, QwtScaleWidget -*/ - -class QWT_EXPORT QwtColorMap -{ -public: - /*! - Format for color mapping - \sa rgb(), colorIndex(), colorTable() - */ - - enum Format - { - //! The map is intended to map into RGB values. - RGB, - - /*! - The map is intended to map into 8 bit values, that - are indices into the color table. - */ - Indexed - }; - - QwtColorMap( Format = QwtColorMap::RGB ); - virtual ~QwtColorMap(); - - Format format() const; - - /*! - 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 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 QwtInterval &interval, double value ) const = 0; - - QColor color( const QwtInterval &, double value ) const; - virtual QVector<QRgb> 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 according to mode(). -*/ -class QWT_EXPORT QwtLinearColorMap: public QwtColorMap -{ -public: - /*! - Mode of color map - \sa setMode(), mode() - */ - enum Mode - { - //! Return the color from the next lower color stop - FixedColors, - - //! Interpolating the colors of the adjacent stops. - ScaledColors - }; - - QwtLinearColorMap( QwtColorMap::Format = QwtColorMap::RGB ); - QwtLinearColorMap( const QColor &from, const QColor &to, - QwtColorMap::Format = QwtColorMap::RGB ); - - virtual ~QwtLinearColorMap(); - - void setMode( Mode ); - Mode mode() const; - - void setColorInterval( const QColor &color1, const QColor &color2 ); - void addColorStop( double value, const QColor& ); - QVector<double> colorStops() const; - - QColor color1() const; - QColor color2() const; - - virtual QRgb rgb( const QwtInterval &, double value ) const; - virtual unsigned char colorIndex( - const QwtInterval &, double value ) const; - - class ColorStops; - -private: - // Disabled copy constructor and operator= - QwtLinearColorMap( const QwtLinearColorMap & ); - QwtLinearColorMap &operator=( const QwtLinearColorMap & ); - - class PrivateData; - PrivateData *d_data; -}; - -/*! - \brief QwtAlphaColorMap varies the alpha value of a color -*/ -class QWT_EXPORT QwtAlphaColorMap: public QwtColorMap -{ -public: - QwtAlphaColorMap( const QColor & = QColor( Qt::gray ) ); - virtual ~QwtAlphaColorMap(); - - void setColor( const QColor & ); - QColor color() const; - - virtual QRgb rgb( const QwtInterval &, double value ) const; - -private: - QwtAlphaColorMap( const QwtAlphaColorMap & ); - QwtAlphaColorMap &operator=( const QwtAlphaColorMap & ); - - virtual unsigned char colorIndex( - const QwtInterval &, double value ) const; - - class PrivateData; - PrivateData *d_data; -}; - - -/*! - Map a value into a color - - \param interval Valid interval for values - \param value Value - - \return Color corresponding to value - - \warning This method is slow for Indexed color maps. If it is - necessary to map many values, its better to get the - color table once and find the color using colorIndex(). -*/ -inline QColor QwtColorMap::color( - const QwtInterval &interval, double value ) const -{ - if ( d_format == RGB ) - { - return QColor::fromRgba( rgb( interval, value ) ); - } - else - { - const unsigned int index = colorIndex( interval, value ); - return colorTable( interval )[index]; // slow - } -} - -/*! - \return Intended format of the color map - \sa Format -*/ -inline QwtColorMap::Format QwtColorMap::format() const -{ - return d_format; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_column_symbol.h b/include/pli_vis/third_party/qwt/qwt_column_symbol.h deleted file mode 100644 index 7a04b1161229d0ce8ea55462941a16ac3aed1fd1..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_column_symbol.h +++ /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 - *****************************************************************************/ - -#ifndef QWT_COLUMN_SYMBOL_H -#define QWT_COLUMN_SYMBOL_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include <qpen.h> -#include <qsize.h> -#include <qrect.h> - -class QPainter; -class QPalette; -class QRect; -class QwtText; - -/*! - \brief Directed rectangle representing bounding rectangle and orientation - of a column. -*/ -class QWT_EXPORT QwtColumnRect -{ -public: - //! Direction of the column - enum Direction - { - //! From left to right - LeftToRight, - - //! From right to left - RightToLeft, - - //! From bottom to top - BottomToTop, - - //! From top to bottom - TopToBottom - }; - - //! Build an rectangle with invalid intervals directed BottomToTop. - QwtColumnRect(): - direction( BottomToTop ) - { - } - - //! \return A normalized QRect built from the intervals - QRectF toRect() const - { - QRectF r( hInterval.minValue(), vInterval.minValue(), - hInterval.maxValue() - hInterval.minValue(), - vInterval.maxValue() - vInterval.minValue() ); - r = r.normalized(); - - if ( hInterval.borderFlags() & QwtInterval::ExcludeMinimum ) - r.adjust( 1, 0, 0, 0 ); - if ( hInterval.borderFlags() & QwtInterval::ExcludeMaximum ) - r.adjust( 0, 0, -1, 0 ); - if ( vInterval.borderFlags() & QwtInterval::ExcludeMinimum ) - r.adjust( 0, 1, 0, 0 ); - if ( vInterval.borderFlags() & QwtInterval::ExcludeMaximum ) - r.adjust( 0, 0, 0, -1 ); - - return r; - } - - //! \return Orientation - Qt::Orientation orientation() const - { - if ( direction == LeftToRight || direction == RightToLeft ) - return Qt::Horizontal; - - return Qt::Vertical; - } - - //! Interval for the horizontal coordinates - QwtInterval hInterval; - - //! Interval for the vertical coordinates - QwtInterval vInterval; - - //! Direction - Direction direction; -}; - -//! A drawing primitive for columns -class QWT_EXPORT QwtColumnSymbol -{ -public: - /*! - Style - \sa setStyle(), style() - */ - enum Style - { - //! No Style, the symbol draws nothing - NoStyle = -1, - - /*! - The column is painted with a frame depending on the frameStyle() - and lineWidth() using the palette(). - */ - Box, - - /*! - Styles >= QwtColumnSymbol::UserStyle are reserved for derived - classes of QwtColumnSymbol that overload draw() with - additional application specific symbol types. - */ - UserStyle = 1000 - }; - - /*! - Frame Style used in Box style(). - \sa Style, setFrameStyle(), frameStyle(), setStyle(), setPalette() - */ - enum FrameStyle - { - //! No frame - NoFrame, - - //! A plain frame style - Plain, - - //! A raised frame style - Raised - }; - -public: - QwtColumnSymbol( Style = NoStyle ); - virtual ~QwtColumnSymbol(); - - void setFrameStyle( FrameStyle style ); - FrameStyle frameStyle() const; - - void setLineWidth( int width ); - int lineWidth() const; - - void setPalette( const QPalette & ); - const QPalette &palette() const; - - void setStyle( Style ); - Style style() const; - - virtual void draw( QPainter *, const QwtColumnRect & ) const; - -protected: - void drawBox( QPainter *, const QwtColumnRect & ) const; - -private: - class PrivateData; - PrivateData* d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_compass.h b/include/pli_vis/third_party/qwt/qwt_compass.h deleted file mode 100644 index 3a1c185c11a48b5cb6bf562b4838179fc1e99b29..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_compass.h +++ /dev/null @@ -1,83 +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_COMPASS_H -#define QWT_COMPASS_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_dial.h" -#include "qwt/qwt_round_scale_draw.h" -#include <qstring.h> -#include <qmap.h> - -class QwtCompassRose; - -/*! - \brief A special scale draw made for QwtCompass - - QwtCompassScaleDraw maps values to strings using - a special map, that can be modified by the application - - The default map consists of the labels N, NE, E, SE, S, SW, W, NW. - - \sa QwtCompass -*/ -class QWT_EXPORT QwtCompassScaleDraw: public QwtRoundScaleDraw -{ -public: - explicit QwtCompassScaleDraw(); - explicit QwtCompassScaleDraw( const QMap<double, QString> &map ); - - void setLabelMap( const QMap<double, QString> &map ); - QMap<double, QString> labelMap() const; - - virtual QwtText label( double value ) const; - -private: - QMap<double, QString> d_labelMap; -}; - -/*! - \brief A Compass Widget - - QwtCompass is a widget to display and enter directions. It consists - of a scale, an optional needle and rose. - - \image html dials1.png - - \note The examples/dials example shows how to use QwtCompass. -*/ - -class QWT_EXPORT QwtCompass: public QwtDial -{ - Q_OBJECT - -public: - explicit QwtCompass( QWidget* parent = NULL ); - virtual ~QwtCompass(); - - void setRose( QwtCompassRose *rose ); - const QwtCompassRose *rose() const; - QwtCompassRose *rose(); - -protected: - virtual void drawRose( QPainter *, const QPointF ¢er, - double radius, double north, QPalette::ColorGroup ) const; - - virtual void drawScaleContents( QPainter *, - const QPointF ¢er, double radius ) const; - - virtual void keyPressEvent( QKeyEvent * ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_compass_rose.h b/include/pli_vis/third_party/qwt/qwt_compass_rose.h deleted file mode 100644 index b023d8478a43e2b54d00e8cb8eb6ba19b2e242ef..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_compass_rose.h +++ /dev/null @@ -1,89 +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_COMPASS_ROSE_H -#define QWT_COMPASS_ROSE_H 1 - -#include "qwt/qwt_global.h" -#include <qpalette.h> - -class QPainter; - -/*! - \brief Abstract base class for a compass rose -*/ -class QWT_EXPORT QwtCompassRose -{ -public: - //! Destructor - virtual ~QwtCompassRose() {}; - - //! Assign a palette - virtual void setPalette( const QPalette &p ) - { - d_palette = p; - } - - //! \return Current palette - const QPalette &palette() const - { - return d_palette; - } - - /*! - Draw the rose - - \param painter Painter - \param center Center point - \param radius Radius of the rose - \param north Position - \param colorGroup Color group - */ - virtual void draw( QPainter *painter, - const QPointF ¢er, double radius, double north, - QPalette::ColorGroup colorGroup = QPalette::Active ) const = 0; - -private: - QPalette d_palette; -}; - -/*! - \brief A simple rose for QwtCompass -*/ -class QWT_EXPORT QwtSimpleCompassRose: public QwtCompassRose -{ -public: - QwtSimpleCompassRose( int numThorns = 8, int numThornLevels = -1 ); - virtual ~QwtSimpleCompassRose(); - - void setWidth( double w ); - double width() const; - - void setNumThorns( int count ); - int numThorns() const; - - void setNumThornLevels( int count ); - int numThornLevels() const; - - void setShrinkFactor( double factor ); - double shrinkFactor() const; - - virtual void draw( QPainter *, const QPointF ¢er, double radius, - double north, QPalette::ColorGroup = QPalette::Active ) const; - - static void drawRose( QPainter *, const QPalette &, - const QPointF ¢er, double radius, double origin, double width, - int numThorns, int numThornLevels, double shrinkFactor ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_compat.h b/include/pli_vis/third_party/qwt/qwt_compat.h deleted file mode 100644 index e3568436652f25e67ba40cb81dfb741fa251e5d5..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_compat.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_COMPAT_H_ -#define _QWT_COMPAT_H_ - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include "qwt/qwt_point_3d.h" -#include <qlist.h> -#include <qvector.h> -#include <qpoint.h> -#include <qsize.h> -#include <qrect.h> -#include <qpolygon.h> - -// A couple of definition for Qwt5 compatibility - -#define qwtMax qMax -#define qwtMin qMin -#define qwtAbs qAbs -#define qwtRound qRound - -#define QwtArray QVector - -typedef QList<double> 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/include/pli_vis/third_party/qwt/qwt_counter.h b/include/pli_vis/third_party/qwt/qwt_counter.h deleted file mode 100644 index 7b2530694171344875dd0702f4843f3ee07518f5..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_counter.h +++ /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 - *****************************************************************************/ - -#ifndef QWT_COUNTER_H -#define QWT_COUNTER_H - -#include "qwt/qwt_global.h" -#include <qwidget.h> - -/*! - \brief The Counter Widget - - A Counter consists of a label displaying a number and - one ore more (up to three) push buttons on each side - of the label which can be used to increment or decrement - the counter's value. - - A counter has a range from a minimum value to a maximum value - and a step size. When the wrapping property is set - the counter is circular. - - The number of steps by which a button increments or decrements the value - can be specified using setIncSteps(). The number of buttons can be - changed with setNumButtons(). - - Example: -\code -#include <qwt_counter.h> - -QwtCounter *counter = new QwtCounter(parent); - -counter->setRange(0.0, 100.0); // From 0.0 to 100 -counter->setSingleStep( 1.0 ); // Step size 1.0 -counter->setNumButtons(2); // Two buttons each side -counter->setIncSteps(QwtCounter::Button1, 1); // Button 1 increments 1 step -counter->setIncSteps(QwtCounter::Button2, 20); // Button 2 increments 20 steps - -connect(counter, SIGNAL(valueChanged(double)), myClass, SLOT(newValue(double))); -\endcode - */ - -class QWT_EXPORT QwtCounter : public QWidget -{ - Q_OBJECT - - Q_PROPERTY( double value READ value WRITE setValue ) - Q_PROPERTY( double minimum READ minimum WRITE setMinimum ) - Q_PROPERTY( double maximum READ maximum WRITE setMaximum ) - Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep ) - - Q_PROPERTY( int numButtons READ numButtons WRITE setNumButtons ) - Q_PROPERTY( int stepButton1 READ stepButton1 WRITE setStepButton1 ) - Q_PROPERTY( int stepButton2 READ stepButton2 WRITE setStepButton2 ) - Q_PROPERTY( int stepButton3 READ stepButton3 WRITE setStepButton3 ) - - Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) - Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) - -public: - //! Button index - enum Button - { - //! Button intended for minor steps - Button1, - - //! Button intended for medium steps - Button2, - - //! Button intended for large steps - Button3, - - //! Number of buttons - ButtonCnt - }; - - explicit QwtCounter( QWidget *parent = NULL ); - virtual ~QwtCounter(); - - void setValid( bool ); - bool isValid() const; - - void setWrapping( bool ); - bool wrapping() const; - - bool isReadOnly() const; - void setReadOnly( bool ); - - void setNumButtons( int n ); - int numButtons() const; - - void setIncSteps( QwtCounter::Button btn, int nSteps ); - int incSteps( QwtCounter::Button btn ) const; - - virtual QSize sizeHint() const; - - double singleStep() const; - void setSingleStep( double s ); - - void setRange( double min, double max ); - - double minimum() const; - void setMinimum( double min ); - - double maximum() const; - void setMaximum( double max ); - - void setStepButton1( int nSteps ); - int stepButton1() const; - - void setStepButton2( int nSteps ); - int stepButton2() const; - - void setStepButton3( int nSteps ); - int stepButton3() const; - - double value() const; - -public Q_SLOTS: - void setValue( double ); - - -Q_SIGNALS: - /*! - This signal is emitted when a button has been released - \param value The new value - */ - void buttonReleased ( double value ); - - /*! - This signal is emitted when the counter's value has changed - \param value The new value - */ - void valueChanged ( double value ); - -protected: - virtual bool event( QEvent * ); - virtual void wheelEvent( QWheelEvent * ); - virtual void keyPressEvent( QKeyEvent * ); - -private Q_SLOTS: - void btnReleased(); - void btnClicked(); - void textChanged(); - -private: - void incrementValue( int numSteps ); - void initCounter(); - void updateButtons(); - void showNumber( double ); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_curve_fitter.h b/include/pli_vis/third_party/qwt/qwt_curve_fitter.h deleted file mode 100644 index 9ff47838b4e43fedbec6dd61028c1a7cfe6fb561..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_curve_fitter.h +++ /dev/null @@ -1,139 +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_CURVE_FITTER_H -#define QWT_CURVE_FITTER_H - -#include "qwt/qwt_global.h" -#include <qpolygon.h> -#include <qrect.h> - -class QwtSpline; - -/*! - \brief Abstract base class for a curve fitter -*/ -class QWT_EXPORT QwtCurveFitter -{ -public: - virtual ~QwtCurveFitter(); - - /*! - Find a curve which has the best fit to a series of data points - - \param polygon Series of data points - \return Curve points - */ - virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0; - -protected: - QwtCurveFitter(); - -private: - QwtCurveFitter( const QwtCurveFitter & ); - QwtCurveFitter &operator=( const QwtCurveFitter & ); -}; - -/*! - \brief A curve fitter using cubic splines -*/ -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 ); - FitMode fitMode() const; - - void setSpline( const QwtSpline& ); - const QwtSpline &spline() const; - QwtSpline &spline(); - - void setSplineSize( int size ); - int splineSize() const; - - virtual QPolygonF fitCurve( const QPolygonF & ) const; - -private: - QPolygonF fitSpline( const QPolygonF & ) const; - QPolygonF fitParametric( const QPolygonF & ) const; - - class PrivateData; - PrivateData *d_data; -}; - -/*! - \brief A curve fitter implementing Douglas and Peucker algorithm - - The purpose of the Douglas and Peucker algorithm is that given a 'curve' - composed of line segments to find a curve not too dissimilar but that - has fewer points. The algorithm defines 'too dissimilar' based on the - maximum distance (tolerance) between the original curve and the - smoothed curve. - - The runtime of the algorithm increases non linear ( worst case O( n*n ) ) - and might be very slow for huge polygons. To avoid performance issues - it might be useful to split the polygon ( setChunkSize() ) and to run the algorithm - for these smaller parts. The disadvantage of having no interpolation - at the borders is for most use cases irrelevant. - - The smoothed curve consists of a subset of the points that defined the - original curve. - - In opposite to QwtSplineCurveFitter the Douglas and Peucker algorithm reduces - the number of points. By adjusting the tolerance parameter according to the - axis scales QwtSplineCurveFitter can be used to implement different - level of details to speed up painting of curves of many points. -*/ -class QWT_EXPORT QwtWeedingCurveFitter: public QwtCurveFitter -{ -public: - QwtWeedingCurveFitter( double tolerance = 1.0 ); - virtual ~QwtWeedingCurveFitter(); - - void setTolerance( double ); - double tolerance() const; - - void setChunkSize( uint ); - uint chunkSize() const; - - virtual QPolygonF fitCurve( const QPolygonF & ) const; - -private: - virtual QPolygonF simplify( const QPolygonF & ) const; - - class Line; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_date.h b/include/pli_vis/third_party/qwt/qwt_date.h deleted file mode 100644 index 515af0e75289e941151ea623210ed6f9bd294a49..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_date.h +++ /dev/null @@ -1,128 +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_DATE_H_ -#define _QWT_DATE_H_ - -#include "qwt/qwt_global.h" -#include <qdatetime.h> - -/*! - \brief A collection of methods around date/time values - - Qt offers convenient classes for dealing with date/time values, - but Qwt uses coordinate systems that are based on doubles. - QwtDate offers methods to translate from QDateTime to double and v.v. - - A double is interpreted as the number of milliseconds since - 1970-01-01T00:00:00 Universal Coordinated Time - also known - as "The Epoch". - - While the range of the Julian day in Qt4 is limited to [0, MAX_INT], - Qt5 stores it as qint64 offering a huge range of valid dates. - As the significance of a double is below this ( assuming a - fraction of 52 bits ) the translation is not - bijective with rounding errors for dates very far from Epoch. - For a resolution of 1 ms those start to happen for dates above the - year 144683. - - An axis for a date/time interval is expected to be aligned - and divided in time/date units like seconds, minutes, ... - QwtDate offers several algorithms that are needed to - calculate these axes. - - \sa QwtDateScaleEngine, QwtDateScaleDraw, QDate, QTime -*/ -class QWT_EXPORT QwtDate -{ -public: - /*! - How to identify the first week of year differs between - countries. - */ - enum Week0Type - { - /*! - According to ISO 8601 the first week of a year is defined - as "the week with the year's first Thursday in it". - - FirstThursday corresponds to the numbering that is - implemented in QDate::weekNumber(). - */ - FirstThursday, - - /*! - "The week with January 1.1 in it." - - In the U.S. this definition is more common than - FirstThursday. - */ - FirstDay - }; - - /*! - Classification of an time interval - - Time intervals needs to be classified to decide how to - align and divide it. - */ - enum IntervalType - { - //! The interval is related to milliseconds - Millisecond, - - //! The interval is related to seconds - Second, - - //! The interval is related to minutes - Minute, - - //! The interval is related to hours - Hour, - - //! The interval is related to days - Day, - - //! The interval is related to weeks - Week, - - //! The interval is related to months - Month, - - //! The interval is related to years - Year - }; - - enum - { - //! The Julian day of "The Epoch" - JulianDayForEpoch = 2440588 - }; - - static QDate minDate(); - static QDate maxDate(); - - static QDateTime toDateTime( double value, - Qt::TimeSpec = Qt::UTC ); - - static double toDouble( const QDateTime & ); - - static QDateTime ceil( const QDateTime &, IntervalType ); - static QDateTime floor( const QDateTime &, IntervalType ); - - static QDate dateOfWeek0( int year, Week0Type ); - static int weekNumber( const QDate &, Week0Type ); - - static int utcOffset( const QDateTime & ); - - static QString toString( const QDateTime &, - const QString & format, Week0Type ); -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_date_scale_draw.h b/include/pli_vis/third_party/qwt/qwt_date_scale_draw.h deleted file mode 100644 index 85808b186c457ec1b8bd747bd942591cb7080aad..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_date_scale_draw.h +++ /dev/null @@ -1,86 +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_DATE_SCALE_DRAW_H_ -#define _QWT_DATE_SCALE_DRAW_H_ 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_scale_draw.h" -#include "qwt/qwt_date.h" - -/*! - \brief A class for drawing datetime scales - - QwtDateScaleDraw displays values as datetime labels. - The format of the labels depends on the alignment of - the major tick labels. - - The default format strings are: - - - Millisecond\n - "hh:mm:ss:zzz\nddd dd MMM yyyy" - - Second\n - "hh:mm:ss\nddd dd MMM yyyy" - - Minute\n - "hh:mm\nddd dd MMM yyyy" - - Hour\n - "hh:mm\nddd dd MMM yyyy" - - Day\n - "ddd dd MMM yyyy" - - Week\n - "Www yyyy" - - Month\n - "MMM yyyy" - - Year\n - "yyyy" - - The format strings can be modified using setDateFormat() - or individually for each tick label by overloading dateFormatOfDate(), - - Usually QwtDateScaleDraw is used in combination with - QwtDateScaleEngine, that calculates scales for datetime - intervals. - - \sa QwtDateScaleEngine, QwtPlot::setAxisScaleDraw() -*/ -class QWT_EXPORT QwtDateScaleDraw: public QwtScaleDraw -{ -public: - QwtDateScaleDraw( Qt::TimeSpec = Qt::LocalTime ); - virtual ~QwtDateScaleDraw(); - - void setDateFormat( QwtDate::IntervalType, const QString & ); - QString dateFormat( QwtDate::IntervalType ) const; - - void setTimeSpec( Qt::TimeSpec ); - Qt::TimeSpec timeSpec() const; - - void setUtcOffset( int seconds ); - int utcOffset() const; - - void setWeek0Type( QwtDate::Week0Type ); - QwtDate::Week0Type week0Type() const; - - virtual QwtText label( double ) const; - - QDateTime toDateTime( double ) const; - -protected: - virtual QwtDate::IntervalType - intervalType( const QwtScaleDiv & ) const; - - virtual QString dateFormatOfDate( const QDateTime &, - QwtDate::IntervalType ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_date_scale_engine.h b/include/pli_vis/third_party/qwt/qwt_date_scale_engine.h deleted file mode 100644 index 28fd157856a4c48dbef3a412e4351857ee0f4991..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_date_scale_engine.h +++ /dev/null @@ -1,86 +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_DATE_SCALE_ENGINE_H_ -#define _QWT_DATE_SCALE_ENGINE_H_ 1 - -#include "qwt/qwt_date.h" -#include "qwt/qwt_scale_engine.h" - -/*! - \brief A scale engine for date/time values - - QwtDateScaleEngine builds scales from a time intervals. - Together with QwtDateScaleDraw it can be used for - axes according to date/time values. - - Years, months, weeks, days, hours and minutes are organized - in steps with non constant intervals. QwtDateScaleEngine - classifies intervals and aligns the boundaries and tick positions - according to this classification. - - QwtDateScaleEngine supports representations depending - on Qt::TimeSpec specifications. The valid range for scales - is limited by the range of QDateTime, that differs - between Qt4 and Qt5. - - Datetime values are expected as the number of milliseconds since - 1970-01-01T00:00:00 Universal Coordinated Time - also known - as "The Epoch", that can be converted to QDateTime using - QwtDate::toDateTime(). - - \sa QwtDate, QwtPlot::setAxisScaleEngine(), - QwtAbstractScale::setScaleEngine() -*/ -class QWT_EXPORT QwtDateScaleEngine: public QwtLinearScaleEngine -{ -public: - QwtDateScaleEngine( Qt::TimeSpec = Qt::LocalTime ); - virtual ~QwtDateScaleEngine(); - - void setTimeSpec( Qt::TimeSpec ); - Qt::TimeSpec timeSpec() const; - - void setUtcOffset( int seconds ); - int utcOffset() const; - - void setWeek0Type( QwtDate::Week0Type ); - QwtDate::Week0Type week0Type() const; - - void setMaxWeeks( int ); - int maxWeeks() const; - - virtual void autoScale( int maxNumSteps, - double &x1, double &x2, double &stepSize ) const; - - virtual QwtScaleDiv divideScale( - double x1, double x2, - int maxMajorSteps, int maxMinorSteps, - double stepSize = 0.0 ) const; - - virtual QwtDate::IntervalType intervalType( - const QDateTime &, const QDateTime &, int maxSteps ) const; - - QDateTime toDateTime( double ) const; - -protected: - virtual QDateTime alignDate( const QDateTime &, double stepSize, - QwtDate::IntervalType, bool up ) const; - -private: - QwtScaleDiv buildScaleDiv( const QDateTime &, const QDateTime &, - int maxMajorSteps, int maxMinorSteps, - QwtDate::IntervalType ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_dial.h b/include/pli_vis/third_party/qwt/qwt_dial.h deleted file mode 100644 index e5d2c5b1deabda4a4161cdd101731ae10fea4a4b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_dial.h +++ /dev/null @@ -1,168 +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_DIAL_H -#define QWT_DIAL_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_slider.h" -#include "qwt/qwt_abstract_scale_draw.h" -#include <qframe.h> -#include <qpalette.h> - -class QwtDialNeedle; -class QwtRoundScaleDraw; - -/*! - \brief QwtDial class provides a rounded range control. - - QwtDial is intended as base class for dial widgets like - 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 - other is rotating. If not isReadOnly() the - dial can be rotated by dragging the mouse or using keyboard inputs - (see QwtAbstractSlider::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. - - Often dials have to be updated very often according to values from external - devices. For these high refresh rates QwtDial caches as much as possible. - For derived classes it might be necessary to clear these caches manually - according to attribute changes using invalidateCache(). - - \sa QwtCompass, QwtAnalogClock, QwtDialNeedle - \note The controls and dials examples shows different types of dials. - \note QDial is more similar to QwtKnob than to QwtDial -*/ - -class QWT_EXPORT QwtDial: public QwtAbstractSlider -{ - Q_OBJECT - - Q_ENUMS( Shadow Mode Direction ) - - 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( double minScaleArc READ minScaleArc WRITE setMinScaleArc ) - Q_PROPERTY( double maxScaleArc READ maxScaleArc WRITE setMaxScaleArc ) - -public: - - /*! - \brief Frame shadow - - Unfortunately it is not possible to use QFrame::Shadow - as a property of a widget that is not derived from QFrame. - The following enum is made for the designer only. It is safe - to use QFrame::Shadow instead. - */ - enum Shadow - { - //! QFrame::Plain - Plain = QFrame::Plain, - - //! QFrame::Raised - Raised = QFrame::Raised, - - //! QFrame::Sunken - Sunken = QFrame::Sunken - }; - - //! Mode controlling whether the needle or the scale is rotating - enum Mode - { - //! The needle is rotating - RotateNeedle, - - //! The needle is fixed, the scales are rotating - RotateScale - }; - - explicit QwtDial( QWidget *parent = NULL ); - virtual ~QwtDial(); - - void setFrameShadow( Shadow ); - Shadow frameShadow() const; - - void setLineWidth( int ); - int lineWidth() const; - - void setMode( Mode ); - Mode mode() const; - - void setScaleArc( double min, double max ); - - void setMinScaleArc( double min ); - double minScaleArc() const; - - void setMaxScaleArc( double min ); - double maxScaleArc() const; - - virtual void setOrigin( double ); - double origin() const; - - void setNeedle( QwtDialNeedle * ); - const QwtDialNeedle *needle() const; - QwtDialNeedle *needle(); - - QRect boundingRect() const; - QRect innerRect() const; - - virtual QRect scaleInnerRect() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - void setScaleDraw( QwtRoundScaleDraw * ); - - QwtRoundScaleDraw *scaleDraw(); - const QwtRoundScaleDraw *scaleDraw() const; - -protected: - virtual void wheelEvent( QWheelEvent * ); - virtual void paintEvent( QPaintEvent * ); - virtual void changeEvent( QEvent * ); - - virtual void drawFrame( QPainter *p ); - virtual void drawContents( QPainter * ) const; - virtual void drawFocusIndicator( QPainter * ) const; - - void invalidateCache(); - - virtual void drawScale( QPainter *, - const QPointF ¢er, double radius ) const; - - virtual void drawScaleContents( QPainter *painter, - const QPointF ¢er, double radius ) const; - - virtual void drawNeedle( QPainter *, const QPointF &, - double radius, double direction, QPalette::ColorGroup ) const; - - virtual double scrolledTo( const QPoint & ) const; - virtual bool isScrollPosition( const QPoint & ) const; - - virtual void sliderChange(); - virtual void scaleChange(); - -private: - void setAngleRange( double angle, double span ); - void drawNeedle( QPainter * ) const; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_dial_needle.h b/include/pli_vis/third_party/qwt/qwt_dial_needle.h deleted file mode 100644 index ff1be44338973b9cdaa67d9af61da13ecd734d7b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_dial_needle.h +++ /dev/null @@ -1,187 +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_DIAL_NEEDLE_H -#define QWT_DIAL_NEEDLE_H 1 - -#include "qwt/qwt_global.h" -#include <qpalette.h> - -class QPainter; -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. - - \sa QwtDial, QwtCompass -*/ - -class QWT_EXPORT QwtDialNeedle -{ -public: - QwtDialNeedle(); - virtual ~QwtDialNeedle(); - - 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: - /*! - \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 initialized 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; -}; - -/*! - \brief A needle for dial widgets - - The following colors are used: - - - QPalette::Mid\n - Pointer - - QPalette::Base\n - Knob - - \sa QwtDial, QwtCompass -*/ - -class QWT_EXPORT QwtDialSimpleNeedle: public QwtDialNeedle -{ -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 ); - - void setWidth( double width ); - double width() const; - -protected: - virtual void drawNeedle( QPainter *, double length, - QPalette::ColorGroup ) const; - -private: - Style d_style; - bool d_hasKnob; - double d_width; -}; - -/*! - \brief A magnet needle for compass widgets - - A magnet needle points to two opposite directions indicating - north and south. - - The following colors are used: - - QPalette::Light\n - Used for pointing south - - QPalette::Dark\n - Used for pointing north - - QPalette::Base\n - Knob (ThinStyle only) - - \sa QwtDial, QwtCompass -*/ - -class QWT_EXPORT QwtCompassMagnetNeedle: public QwtDialNeedle -{ -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 ); - -protected: - virtual void drawNeedle( QPainter *, - double length, QPalette::ColorGroup ) const; - -private: - Style d_style; -}; - -/*! - \brief An indicator for the wind direction - - QwtCompassWindArrow shows the direction where the wind comes from. - - - QPalette::Light\n - Used for Style1, or the light half of Style2 - - QPalette::Dark\n - Used for the dark half of Style2 - - \sa QwtDial, QwtCompass -*/ - -class QWT_EXPORT QwtCompassWindArrow: public QwtDialNeedle -{ -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 ); - -protected: - virtual void drawNeedle( QPainter *, - double length, QPalette::ColorGroup ) const; - -private: - Style d_style; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_dyngrid_layout.h b/include/pli_vis/third_party/qwt/qwt_dyngrid_layout.h deleted file mode 100644 index c58cff25547ae389ecebf7008990183df3398cb8..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_dyngrid_layout.h +++ /dev/null @@ -1,83 +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_DYNGRID_LAYOUT_H -#define QWT_DYNGRID_LAYOUT_H - -#include "qwt/qwt_global.h" -#include <qlayout.h> -#include <qsize.h> -#include <qlist.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). - It lays out as many number of columns as possible (limited by maxColumns()). -*/ - -class QWT_EXPORT QwtDynGridLayout : public QLayout -{ - Q_OBJECT -public: - explicit QwtDynGridLayout( QWidget *, int margin = 0, int space = -1 ); - explicit QwtDynGridLayout( int space = -1 ); - - virtual ~QwtDynGridLayout(); - - virtual void invalidate(); - - void setMaxColumns( uint maxCols ); - uint maxColumns() const; - - uint numRows () const; - uint numColumns () const; - - virtual void addItem( QLayoutItem * ); - - virtual QLayoutItem *itemAt( int index ) const; - virtual QLayoutItem *takeAt( int index ); - virtual int count() const; - - void setExpandingDirections( Qt::Orientations ); - virtual Qt::Orientations expandingDirections() const; - QList<QRect> layoutItems( const QRect &, uint numCols ) const; - - virtual int maxItemWidth() const; - - virtual void setGeometry( const QRect &rect ); - - virtual bool hasHeightForWidth() const; - virtual int heightForWidth( int ) const; - - virtual QSize sizeHint() const; - - virtual bool isEmpty() const; - uint itemCount() const; - - virtual uint columnsForWidth( int width ) const; - -protected: - - void layoutGrid( uint numCols, - QVector<int>& rowHeight, QVector<int>& colWidth ) const; - void stretchGrid( const QRect &rect, uint numCols, - QVector<int>& rowHeight, QVector<int>& colWidth ) const; - -private: - void init(); - int maxRowWidth( int numCols ) const; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_event_pattern.h b/include/pli_vis/third_party/qwt/qwt_event_pattern.h deleted file mode 100644 index ab55fc5170161d205d697ae69063f015ea052221..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_event_pattern.h +++ /dev/null @@ -1,240 +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_EVENT_PATTERN -#define QWT_EVENT_PATTERN 1 - -#include "qwt/qwt_global.h" -#include <qnamespace.h> -#include <qvector.h> - -class QMouseEvent; -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 - the application code can be configured by individual mappings. - - \sa QwtPicker, QwtPickerMachine, QwtPlotZoomer -*/ -class QWT_EXPORT QwtEventPattern -{ -public: - /*! - \brief Symbolic mouse input codes - - QwtEventPattern implements 3 different settings for - mice with 1, 2, or 3 buttons that can be activated - using initMousePattern(). The default setting is for - 3 button mice. - - Individual settings can be configured using setMousePattern(). - - \sa initMousePattern(), setMousePattern(), setKeyPattern() - */ - enum MousePatternCode - { - /*! - The default setting for 1, 2 and 3 button mice is: - - - Qt::LeftButton - - Qt::LeftButton - - Qt::LeftButton - */ - MouseSelect1, - - /*! - The default setting for 1, 2 and 3 button mice is: - - - Qt::LeftButton + Qt::ControlModifier - - Qt::RightButton - - Qt::RightButton - */ - MouseSelect2, - - /*! - The default setting for 1, 2 and 3 button mice is: - - - Qt::LeftButton + Qt::AltModifier - - Qt::LeftButton + Qt::AltModifier - - Qt::MidButton - */ - MouseSelect3, - - /*! - The default setting for 1, 2 and 3 button mice is: - - - Qt::LeftButton + Qt::ShiftModifier - - Qt::LeftButton + Qt::ShiftModifier - - Qt::LeftButton + Qt::ShiftModifier - */ - MouseSelect4, - - /*! - The default setting for 1, 2 and 3 button mice is: - - - Qt::LeftButton + Qt::ControlButton | Qt::ShiftModifier - - Qt::RightButton + Qt::ShiftModifier - - Qt::RightButton + Qt::ShiftModifier - */ - MouseSelect5, - - /*! - The default setting for 1, 2 and 3 button mice is: - - - Qt::LeftButton + Qt::AltModifier + Qt::ShiftModifier - - Qt::LeftButton + Qt::AltModifier | Qt::ShiftModifier - - Qt::MidButton + Qt::ShiftModifier - */ - MouseSelect6, - - //! Number of mouse patterns - MousePatternCount - }; - - /*! - \brief Symbolic keyboard input codes - - Individual settings can be configured using setKeyPattern() - - \sa setKeyPattern(), setMousePattern() - */ - enum KeyPatternCode - { - //! Qt::Key_Return - KeySelect1, - - //! Qt::Key_Space - KeySelect2, - - //! Qt::Key_Escape - KeyAbort, - - //! Qt::Key_Left - KeyLeft, - - //! Qt::Key_Right - KeyRight, - - //! Qt::Key_Up - KeyUp, - - //! Qt::Key_Down - KeyDown, - - //! Qt::Key_Plus - KeyRedo, - - //! Qt::Key_Minus - KeyUndo, - - //! Qt::Key_Escape - KeyHome, - - //! Number of key patterns - KeyPatternCount - }; - - //! A pattern for mouse events - class MousePattern - { - public: - //! Constructor - MousePattern( Qt::MouseButton btn = Qt::NoButton, - Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ): - button( btn ), - modifiers( modifierCodes ) - { - } - - //! Button - Qt::MouseButton button; - - //! Keyboard modifier - Qt::KeyboardModifiers modifiers; - }; - - //! A pattern for key events - class KeyPattern - { - public: - //! Constructor - KeyPattern( int keyCode = Qt::Key_unknown, - Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ): - key( keyCode ), - modifiers( modifierCodes ) - { - } - - //! Key code - int key; - - //! Modifiers - Qt::KeyboardModifiers modifiers; - }; - - QwtEventPattern(); - virtual ~QwtEventPattern(); - - void initMousePattern( int numButtons ); - void initKeyPattern(); - - void setMousePattern( MousePatternCode, Qt::MouseButton button, - Qt::KeyboardModifiers = Qt::NoModifier ); - - void setKeyPattern( KeyPatternCode, int keyCode, - Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ); - - void setMousePattern( const QVector<MousePattern> & ); - void setKeyPattern( const QVector<KeyPattern> & ); - - const QVector<MousePattern> &mousePattern() const; - const QVector<KeyPattern> &keyPattern() const; - - QVector<MousePattern> &mousePattern(); - QVector<KeyPattern> &keyPattern(); - - bool mouseMatch( MousePatternCode, const QMouseEvent * ) const; - bool keyMatch( KeyPatternCode, const QKeyEvent * ) const; - -protected: - 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 - QVector<MousePattern> d_mousePattern; - QVector<KeyPattern> d_keyPattern; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -}; - -//! Compare operator -inline bool operator==( QwtEventPattern::MousePattern b1, - QwtEventPattern::MousePattern b2 ) -{ - return b1.button == b2.button && b1.modifiers == b2.modifiers; -} - -//! Compare operator -inline bool operator==( QwtEventPattern::KeyPattern b1, - QwtEventPattern::KeyPattern b2 ) -{ - return b1.key == b2.key && b1.modifiers == b2.modifiers; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_global.h b/include/pli_vis/third_party/qwt/qwt_global.h deleted file mode 100644 index 736ccf192341e39205646291a88efeec37a62467..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_global.h +++ /dev/null @@ -1,41 +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_GLOBAL_H -#define QWT_GLOBAL_H - -#include <qglobal.h> - -// QWT_VERSION is (major << 16) + (minor << 8) + patch. - -#define QWT_VERSION 0x060103 -#define QWT_VERSION_STR "6.1.3" - -#if defined(_MSC_VER) /* MSVC Compiler */ -/* template-class specialization 'identifier' is already instantiated */ -#pragma warning(disable: 4660) -/* inherits via dominance */ -#pragma warning(disable: 4250) -#endif // _MSC_VER - -#ifdef QWT_DLL - -#if defined(QWT_MAKEDLL) // create a Qwt DLL library -#define QWT_EXPORT Q_DECL_EXPORT -#else // use a Qwt DLL library -#define QWT_EXPORT Q_DECL_IMPORT -#endif - -#endif // QWT_DLL - -#ifndef QWT_EXPORT -#define QWT_EXPORT -#endif - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_graphic.h b/include/pli_vis/third_party/qwt/qwt_graphic.h deleted file mode 100644 index b6da4bdc9d0b83aa1af3ec006be1ac45eb2e57ad..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_graphic.h +++ /dev/null @@ -1,176 +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_GRAPHIC_H -#define QWT_GRAPHIC_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_null_paintdevice.h" -#include <qmetatype.h> -#include <qimage.h> -#include <qpixmap.h> - -class QwtPainterCommand; - -/*! - \brief A paint device for scalable graphics - - QwtGraphic is the representation of a graphic that is tailored for - scalability. Like QPicture it will be initialized by QPainter - operations and can be replayed later to any target paint device. - - While the usual image representations QImage and QPixmap are not - scalable Qt offers two paint devices, that might be candidates - for representing a vector graphic: - - - QPicture\n - Unfortunately QPicture had been forgotten, when Qt4 - introduced floating point based render engines. Its API - is still on integers, what make it unusable for proper scaling. - - - QSvgRenderer/QSvgGenerator\n - Unfortunately QSvgRenderer hides to much information about - its nodes in internal APIs, that are necessary for proper - layout calculations. Also it is derived from QObject and - can't be copied like QImage/QPixmap. - - QwtGraphic maps all scalable drawing primitives to a QPainterPath - and stores them together with the painter state changes - ( pen, brush, transformation ... ) in a list of QwtPaintCommands. - For being a complete QPaintDevice it also stores pixmaps or images, - what is somehow against the idea of the class, because these objects - can't be scaled without a loss in quality. - - The main issue about scaling a QwtGraphic object are the pens used for - drawing the outlines of the painter paths. While non cosmetic pens - ( QPen::isCosmetic() ) are scaled with the same ratio as the path, - cosmetic pens have a fixed width. A graphic might have paths with - different pens - cosmetic and non-cosmetic. - - QwtGraphic caches 2 different rectangles: - - - control point rectangle\n - The control point rectangle is the bounding rectangle of all - control point rectangles of the painter paths, or the target - rectangle of the pixmaps/images. - - - bounding rectangle\n - The bounding rectangle extends the control point rectangle by - what is needed for rendering the outline with an unscaled pen. - - Because the offset for drawing the outline depends on the shape - of the painter path ( the peak of a triangle is different than the flat side ) - scaling with a fixed aspect ratio always needs to be calculated from the - control point rectangle. - - \sa QwtPainterCommand - */ -class QWT_EXPORT QwtGraphic: public QwtNullPaintDevice -{ -public: - /*! - Hint how to render a graphic - \sa setRenderHint(), testRenderHint() - */ - enum RenderHint - { - /*! - When rendering a QwtGraphic a specific scaling between - the controlPointRect() and the coordinates of the target rectangle - is set up internally in render(). - - When RenderPensUnscaled is set this specific scaling is applied - for the control points only, but not for the pens. - All other painter transformations ( set up by application code ) - are supposed to work like usual. - - \sa render(); - */ - RenderPensUnscaled = 0x1 - }; - - /*! - \brief Render hints - - The default setting is to disable all hints - */ - typedef QFlags<RenderHint> RenderHints; - - QwtGraphic(); - QwtGraphic( const QwtGraphic & ); - - virtual ~QwtGraphic(); - - QwtGraphic& operator=( const QwtGraphic & ); - - void reset(); - - bool isNull() const; - bool isEmpty() const; - - void render( QPainter * ) const; - - void render( QPainter *, const QSizeF &, - Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; - - void render( QPainter *, const QRectF &, - Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; - - void render( QPainter *, const QPointF &, - Qt::Alignment = Qt::AlignTop | Qt::AlignLeft ) const; - - QPixmap toPixmap() const; - QPixmap toPixmap( const QSize &, - Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; - - QImage toImage() const; - QImage toImage( const QSize &, - Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; - - QRectF scaledBoundingRect( double sx, double sy ) const; - - QRectF boundingRect() const; - QRectF controlPointRect() const; - - const QVector< QwtPainterCommand > &commands() const; - void setCommands( QVector< QwtPainterCommand > & ); - - void setDefaultSize( const QSizeF & ); - QSizeF defaultSize() const; - - void setRenderHint( RenderHint, bool on = true ); - bool testRenderHint( RenderHint ) const; - -protected: - virtual QSize sizeMetrics() const; - - virtual void drawPath( const QPainterPath & ); - - virtual void drawPixmap( const QRectF &, - const QPixmap &, const QRectF & ); - - virtual void drawImage( const QRectF &, - const QImage &, const QRectF &, Qt::ImageConversionFlags ); - - virtual void updateState( const QPaintEngineState &state ); - -private: - void updateBoundingRect( const QRectF & ); - void updateControlPointRect( const QRectF & ); - - class PathInfo; - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtGraphic::RenderHints ) -Q_DECLARE_METATYPE( QwtGraphic ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_interval.h b/include/pli_vis/third_party/qwt/qwt_interval.h deleted file mode 100644 index 1e8e39d43cea4ea8c306261c6815d6db1a0fd70b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_interval.h +++ /dev/null @@ -1,320 +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_H -#define QWT_INTERVAL_H - -#include "qwt/qwt_global.h" -#include <qmetatype.h> - -#ifndef QT_NO_DEBUG_STREAM -#include <qdebug.h> -#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<BorderFlag> 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; -} - -/*! - A interval is valid when minValue() <= maxValue(). - In case of QwtInterval::ExcludeBorders it is true - when minValue() < maxValue() - - \return True, when the interval is valid -*/ -inline bool QwtInterval::isValid() const -{ - if ( ( d_borderFlags & ExcludeBorders ) == 0 ) - return d_minValue <= d_maxValue; - else - return d_minValue < d_maxValue; -} - -/*! - \brief Return the width of an interval - - The width of invalid intervals is 0.0, otherwise the result is - maxValue() - minValue(). - - \return Interval width - \sa isValid() -*/ -inline double QwtInterval::width() const -{ - return isValid() ? ( d_maxValue - d_minValue ) : 0.0; -} - -/*! - \brief Intersection of two intervals - - \param other Interval to intersect with - \return Intersection of this and other - - \sa intersect() -*/ -inline QwtInterval QwtInterval::operator&( - const QwtInterval &other ) const -{ - return intersect( other ); -} - -/*! - Union of two intervals - - \param other Interval to unite with - \return Union of this and other - - \sa unite() -*/ -inline QwtInterval QwtInterval::operator|( - const QwtInterval &other ) const -{ - return unite( other ); -} - -/*! - \brief Compare two intervals - - \param other Interval to compare with - \return True, when this and other are equal -*/ -inline bool QwtInterval::operator==( const QwtInterval &other ) const -{ - return ( d_minValue == other.d_minValue ) && - ( d_maxValue == other.d_maxValue ) && - ( d_borderFlags == other.d_borderFlags ); -} -/*! - \brief Compare two intervals - - \param other Interval to compare with - \return True, when this and other are not equal -*/ -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; -} - -/*! - 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 ) -Q_DECLARE_METATYPE( QwtInterval ) - -#ifndef QT_NO_DEBUG_STREAM -QWT_EXPORT QDebug operator<<( QDebug, const QwtInterval & ); -#endif - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_interval_symbol.h b/include/pli_vis/third_party/qwt/qwt_interval_symbol.h deleted file mode 100644 index d91aa55cfc7aadb7621acbf2d9109284144850f1..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_interval_symbol.h +++ /dev/null @@ -1,87 +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_SYMBOL_H -#define QWT_INTERVAL_SYMBOL_H - -#include "qwt/qwt_global.h" -#include <qpen.h> -#include <qsize.h> - -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 QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - 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/include/pli_vis/third_party/qwt/qwt_knob.h b/include/pli_vis/third_party/qwt/qwt_knob.h deleted file mode 100644 index 575428d7786ae431d3b5fbe019e12eaa4d7cedd9..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_knob.h +++ /dev/null @@ -1,178 +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_KNOB_H -#define QWT_KNOB_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_slider.h" - -class QwtRoundScaleDraw; - -/*! - \brief The Knob Widget - - The QwtKnob widget imitates look and behavior of a volume knob on a radio. - It looks similar to QDial - not to QwtDial. - - The value range of a knob might be divided into several turns. - - The layout of the knob depends on the knobWidth(). - - - width > 0 - The diameter of the knob is fixed and the knob is aligned - according to the alignment() flags inside of the contentsRect(). - - - width <= 0 - The knob is extended to the minimum of width/height of the contentsRect() - and aligned in the other direction according to alignment(). - - Setting a fixed knobWidth() is helpful to align several knobs with different - scale labels. - - \image html knob.png -*/ - -class QWT_EXPORT QwtKnob: public QwtAbstractSlider -{ - Q_OBJECT - - Q_ENUMS ( KnobStyle MarkerStyle ) - - Q_PROPERTY( KnobStyle knobStyle READ knobStyle WRITE setKnobStyle ) - Q_PROPERTY( int knobWidth READ knobWidth WRITE setKnobWidth ) - Q_PROPERTY( Qt::Alignment alignment READ alignment WRITE setAlignment ) - Q_PROPERTY( double totalAngle READ totalAngle WRITE setTotalAngle ) - Q_PROPERTY( int numTurns READ numTurns WRITE setNumTurns ) - Q_PROPERTY( MarkerStyle markerStyle READ markerStyle WRITE setMarkerStyle ) - Q_PROPERTY( int markerSize READ markerSize WRITE setMarkerSize ) - Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) - -public: - /*! - \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. - Flat, - - //! Build a gradient from QPalette::Midlight and QPalette::Button - Raised, - - /*! - Build a gradient from QPalette::Midlight, QPalette::Button - and QPalette::Midlight - */ - Sunken, - - /*! - Build a radial gradient from QPalette::Button - like it is used for QDial in various Qt styles. - */ - Styled - }; - - /*! - \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, - - //! Paint a single tick in QPalette::ButtonText color - Tick, - - //! Paint a triangle in QPalette::ButtonText color - Triangle, - - //! 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 setAlignment( Qt::Alignment ); - Qt::Alignment alignment() const; - - void setKnobWidth( int ); - int knobWidth() const; - - void setNumTurns( int ); - int numTurns() const; - - void setTotalAngle ( double angle ); - double totalAngle() const; - - void setKnobStyle( KnobStyle ); - KnobStyle knobStyle() const; - - void setBorderWidth( int bw ); - int borderWidth() const; - - void setMarkerStyle( MarkerStyle ); - MarkerStyle markerStyle() const; - - void setMarkerSize( int ); - int markerSize() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - void setScaleDraw( QwtRoundScaleDraw * ); - - const QwtRoundScaleDraw *scaleDraw() const; - QwtRoundScaleDraw *scaleDraw(); - - QRect knobRect() const; - -protected: - virtual void paintEvent( QPaintEvent * ); - virtual void changeEvent( QEvent * ); - - virtual void drawKnob( QPainter *, const QRectF & ) const; - - virtual void drawFocusIndicator( QPainter * ) const; - - virtual void drawMarker( QPainter *, - const QRectF &, double arc ) const; - - virtual double scrolledTo( const QPoint & ) const; - virtual bool isScrollPosition( const QPoint & ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_legend.h b/include/pli_vis/third_party/qwt/qwt_legend.h deleted file mode 100644 index 746bf3b463fe5038afec541815380080692b934f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_legend.h +++ /dev/null @@ -1,117 +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_LEGEND_H -#define QWT_LEGEND_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_legend.h" -#include <qvariant.h> - -class QScrollBar; - -/*! - \brief The legend widget - - The QwtLegend widget is a tabular arrangement of legend items. Legend - items might be any type of widget, but in general they will be - a QwtLegendLabel. - - \sa QwtLegendLabel, QwtPlotItem, QwtPlot -*/ - -class QWT_EXPORT QwtLegend : public QwtAbstractLegend -{ - Q_OBJECT - -public: - explicit QwtLegend( QWidget *parent = NULL ); - virtual ~QwtLegend(); - - void setMaxColumns( uint numColums ); - uint maxColumns() const; - - void setDefaultItemMode( QwtLegendData::Mode ); - QwtLegendData::Mode defaultItemMode() const; - - QWidget *contentsWidget(); - const QWidget *contentsWidget() const; - - QWidget *legendWidget( const QVariant & ) const; - QList<QWidget *> legendWidgets( const QVariant & ) const; - - QVariant itemInfo( const QWidget * ) const; - - virtual bool eventFilter( QObject *, QEvent * ); - - virtual QSize sizeHint() const; - virtual int heightForWidth( int w ) const; - - QScrollBar *horizontalScrollBar() const; - QScrollBar *verticalScrollBar() const; - - virtual void renderLegend( QPainter *, - const QRectF &, bool fillBackground ) const; - - virtual void renderItem( QPainter *, - const QWidget *, const QRectF &, bool fillBackground ) const; - - virtual bool isEmpty() const; - virtual int scrollExtent( Qt::Orientation ) const; - -Q_SIGNALS: - /*! - A signal which is emitted when the user has clicked on - a legend label, which is in QwtLegendData::Clickable mode. - - \param itemInfo Info for the item item of the - selected legend item - \param index Index of the legend label in the list of widgets - that are associated with the plot item - - \note clicks are disabled as default - \sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo() - */ - void clicked( const QVariant &itemInfo, int index ); - - /*! - A signal which is emitted when the user has clicked on - a legend label, which is in QwtLegendData::Checkable mode - - \param itemInfo Info for the item of the - selected legend label - \param index Index of the legend label in the list of widgets - that are associated with the plot item - \param on True when the legend label is checked - - \note clicks are disabled as default - \sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo() - */ - void checked( const QVariant &itemInfo, bool on, int index ); - -public Q_SLOTS: - virtual void updateLegend( const QVariant &, - const QList<QwtLegendData> & ); - -protected Q_SLOTS: - void itemClicked(); - void itemChecked( bool ); - -protected: - virtual QWidget *createWidget( const QwtLegendData & ) const; - virtual void updateWidget( QWidget *widget, const QwtLegendData &data ); - -private: - void updateTabOrder(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_legend_data.h b/include/pli_vis/third_party/qwt/qwt_legend_data.h deleted file mode 100644 index 192b5536c8754e0b935783aacfc39197297a84a7..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_legend_data.h +++ /dev/null @@ -1,87 +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_LEGEND_DATA_H -#define QWT_LEGEND_DATA_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_graphic.h" -#include <qvariant.h> -#include <qpixmap.h> -#include <qmap.h> - -/*! - \brief Attributes of an entry on a legend - - QwtLegendData is an abstract container ( like QAbstractModel ) - to exchange attributes, that are only known between to - the plot item and the legend. - - By overloading QwtPlotItem::legendData() any other set of attributes - could be used, that can be handled by a modified ( or completely - different ) implementation of a legend. - - \sa QwtLegend, QwtPlotLegendItem - \note The stockchart example implements a legend as a tree - with checkable items - */ -class QWT_EXPORT QwtLegendData -{ -public: - //! Mode defining how a legend entry interacts - enum Mode - { - //! The legend item is not interactive, like a label - ReadOnly, - - //! The legend item is clickable, like a push button - Clickable, - - //! The legend item is checkable, like a checkable button - Checkable - }; - - //! Identifier how to interprete a QVariant - enum Role - { - // The value is a Mode - ModeRole, - - // The value is a title - TitleRole, - - // The value is an icon - IconRole, - - // Values < UserRole are reserved for internal use - UserRole = 32 - }; - - QwtLegendData(); - ~QwtLegendData(); - - void setValues( const QMap<int, QVariant> & ); - const QMap<int, QVariant> &values() const; - - void setValue( int role, const QVariant & ); - QVariant value( int role ) const; - - bool hasRole( int role ) const; - bool isValid() const; - - QwtGraphic icon() const; - QwtText title() const; - Mode mode() const; - -private: - QMap<int, QVariant> d_map; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_legend_label.h b/include/pli_vis/third_party/qwt/qwt_legend_label.h deleted file mode 100644 index d78ed60bee974bc6c8e3e5f3dff3774fdb1b3c31..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_legend_label.h +++ /dev/null @@ -1,80 +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_LEGEND_LABEL_H -#define QWT_LEGEND_LABEL_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_legend_data.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_text_label.h" -#include <qpixmap.h> - -class QwtLegendData; - -/*! - \brief A widget representing something on a QwtLegend. -*/ -class QWT_EXPORT QwtLegendLabel: public QwtTextLabel -{ - Q_OBJECT -public: - explicit QwtLegendLabel( QWidget *parent = 0 ); - virtual ~QwtLegendLabel(); - - void setData( const QwtLegendData & ); - const QwtLegendData &data() const; - - void setItemMode( QwtLegendData::Mode ); - QwtLegendData::Mode itemMode() const; - - void setSpacing( int spacing ); - int spacing() const; - - virtual void setText( const QwtText & ); - - void setIcon( const QPixmap & ); - QPixmap icon() const; - - virtual QSize sizeHint() const; - - bool isChecked() const; - -public Q_SLOTS: - void setChecked( bool on ); - -Q_SIGNALS: - //! Signal, when the legend item has been clicked - void clicked(); - - //! Signal, when the legend item has been pressed - void pressed(); - - //! Signal, when the legend item has been released - void released(); - - //! Signal, when the legend item has been toggled - void checked( bool ); - -protected: - 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 * ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_magnifier.h b/include/pli_vis/third_party/qwt/qwt_magnifier.h deleted file mode 100644 index 8dd30c0a09bad3e056d2d81dbaf12729525abbcf..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_magnifier.h +++ /dev/null @@ -1,86 +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_MAGNIFIER_H -#define QWT_MAGNIFIER_H 1 - -#include "qwt/qwt_global.h" -#include <qobject.h> - -class QWidget; -class QMouseEvent; -class QWheelEvent; -class QKeyEvent; - -/*! - \brief QwtMagnifier provides zooming, by magnifying in steps. - - Using QwtMagnifier a plot can be zoomed in/out in steps using - keys, the mouse wheel or moving a mouse button in vertical direction. -*/ -class QWT_EXPORT QwtMagnifier: public QObject -{ - Q_OBJECT - -public: - explicit QwtMagnifier( QWidget * ); - virtual ~QwtMagnifier(); - - QWidget *parentWidget(); - const QWidget *parentWidget() const; - - void setEnabled( bool ); - bool isEnabled() const; - - // mouse - void setMouseFactor( double ); - double mouseFactor() const; - - void setMouseButton( Qt::MouseButton, Qt::KeyboardModifiers = Qt::NoModifier ); - void getMouseButton( Qt::MouseButton &, Qt::KeyboardModifiers & ) const; - - // mouse wheel - void setWheelFactor( double ); - double wheelFactor() const; - - void setWheelModifiers( Qt::KeyboardModifiers ); - Qt::KeyboardModifiers wheelModifiers() const; - - // keyboard - void setKeyFactor( double ); - double keyFactor() const; - - void setZoomInKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); - void getZoomInKey( int &key, Qt::KeyboardModifiers & ) const; - - void setZoomOutKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); - void getZoomOutKey( int &key, Qt::KeyboardModifiers & ) const; - - virtual bool eventFilter( QObject *, QEvent * ); - -protected: - /*! - Rescale the parent widget - \param factor Scale factor - */ - 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 * ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_math.h b/include/pli_vis/third_party/qwt/qwt_math.h deleted file mode 100644 index 7a69fec06de36c1830f844ef7d147766e002ab1b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_math.h +++ /dev/null @@ -1,149 +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_MATH_H -#define QWT_MATH_H - -#include "qwt/qwt_global.h" - -#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 <qmath.h> -#include "qwt/qwt_global.h" - -#ifndef M_PI_2 -// For Qt <= 4.8.4 M_PI_2 is not known by MinGW-w64 -// when compiling with -std=c++11 -#define M_PI_2 (1.57079632679489661923) -#endif - -#ifndef LOG_MIN -//! Minimum value for logarithmic scales -#define LOG_MIN 1.0e-100 -#endif - -#ifndef LOG_MAX -//! Maximum value for logarithmic scales -#define LOG_MAX 1.0e100 -#endif - -QWT_EXPORT double qwtGetMin( const double *array, int size ); -QWT_EXPORT double qwtGetMax( const double *array, int size ); - -QWT_EXPORT double qwtNormalizeRadians( double radians ); -QWT_EXPORT double qwtNormalizeDegrees( double degrees ); - -/*! - \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 -*/ -inline int qwtFuzzyCompare( double value1, double value2, double intervalSize ) -{ - const double eps = qAbs( 1.0e-6 * intervalSize ); - - 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 - return 0; -} - -//! Return the square of a number -inline double qwtSqr( double x ) -{ - return x * x; -} - -//! Approximation of arc tangent ( error below 0,005 radians ) -inline double qwtFastAtan( double x ) -{ - if ( x < -1.0 ) - return -M_PI_2 - x / ( x * x + 0.28 ); - - if ( x > 1.0 ) - return M_PI_2 - x / ( x * x + 0.28 ); - - return x / ( 1.0 + x * x * 0.28 ); -} - -//! Approximation of arc tangent ( error below 0,005 radians ) -inline double qwtFastAtan2( double y, double x ) -{ - if ( x > 0 ) - return qwtFastAtan( y / x ); - - if ( x < 0 ) - { - const double d = qwtFastAtan( y / x ); - return ( y >= 0 ) ? d + M_PI : d - M_PI; - } - - if ( y < 0.0 ) - return -M_PI_2; - - if ( y > 0.0 ) - return M_PI_2; - - return 0.0; -} - -//! Translate degrees into radians -inline double qwtRadians( double degrees ) -{ - return degrees * M_PI / 180.0; -} - -//! Translate radians into degrees -inline double qwtDegrees( double degrees ) -{ - return degrees * 180.0 / M_PI; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_matrix_raster_data.h b/include/pli_vis/third_party/qwt/qwt_matrix_raster_data.h deleted file mode 100644 index 475bdb9c3bf80ec4cd9b43713746b46477f8d110..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_matrix_raster_data.h +++ /dev/null @@ -1,74 +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_MATRIX_RASTER_DATA_H -#define QWT_MATRIX_RASTER_DATA_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_raster_data.h" -#include <qvector.h> - -/*! - \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<double> &values, int numColumns ); - const QVector<double> valueMatrix() const; - - void setValue( int row, int col, double value ); - - int numColumns() const; - int 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/include/pli_vis/third_party/qwt/qwt_null_paintdevice.h b/include/pli_vis/third_party/qwt/qwt_null_paintdevice.h deleted file mode 100644 index 825618b5a0def588d9a67e788f85967bc02d6b97..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_null_paintdevice.h +++ /dev/null @@ -1,126 +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_NULL_PAINT_DEVICE_H -#define QWT_NULL_PAINT_DEVICE_H 1 - -#include "qwt/qwt_global.h" -#include <qpaintdevice.h> -#include <qpaintengine.h> - -/*! - \brief A null paint device doing nothing - - Sometimes important layout/rendering geometries are not - available or changeable from the public Qt class interface. - ( f.e hidden in the style implementation ). - - QwtNullPaintDevice can be used to manipulate or filter out - this information 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: - /*! - \brief Render mode - - \sa setMode(), mode() - */ - enum Mode - { - /*! - All vector graphic primitives are painted by - the corresponding draw methods - */ - NormalMode, - - /*! - Vector graphic primitives ( beside polygons ) are mapped to a QPainterPath - and are painted by drawPath. In PathMode mode - only a few draw methods are called: - - - drawPath() - - drawPixmap() - - drawImage() - - drawPolygon() - */ - PolygonPathMode, - - /*! - Vector graphic primitives are mapped to a QPainterPath - and are painted by drawPath. In PathMode mode - only a few draw methods are called: - - - drawPath() - - drawPixmap() - - drawImage() - */ - PathMode - }; - - QwtNullPaintDevice(); - virtual ~QwtNullPaintDevice(); - - void setMode( Mode ); - Mode mode() 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 ); - -protected: - //! \return Size needed to implement metric() - virtual QSize sizeMetrics() const = 0; - -private: - class PaintEngine; - PaintEngine *d_engine; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_painter.h b/include/pli_vis/third_party/qwt/qwt_painter.h deleted file mode 100644 index f0e183a7673b72c4e208d8fca791413914bad4b2..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_painter.h +++ /dev/null @@ -1,188 +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_PAINTER_H -#define QWT_PAINTER_H - -#include "qwt/qwt_global.h" - -#include <qpoint.h> -#include <qrect.h> -#include <qpen.h> -#include <qline.h> -#include <qpalette.h> - -class QPainter; -class QBrush; -class QColor; -class QWidget; -class QPolygonF; -class QRectF; -class QImage; -class QPixmap; -class QwtScaleMap; -class QwtColorMap; -class QwtInterval; - -class QTextDocument; -class QPainterPath; - -/*! - \brief A collection of QPainter workarounds -*/ -class QWT_EXPORT QwtPainter -{ -public: - static void setPolylineSplitting( bool ); - static bool polylineSplitting(); - - static void setRoundingAlignment( bool ); - static bool roundingAlignment(); - static bool roundingAlignment(QPainter *); - - 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 - static void drawSimpleRichText( QPainter *, const QRectF &, - int flags, const QTextDocument & ); -#endif - - 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 QRectF & ); - static void drawPie( QPainter *, const QRectF & r, int a, int alen ); - - 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 & ); - - static void drawPolygon( QPainter *, const QPolygonF & ); - static void drawPolyline( QPainter *, const QPolygonF & ); - static void drawPolyline( QPainter *, const QPointF *, int pointCount ); - - static void drawPolygon( QPainter *, const QPolygon & ); - static void drawPolyline( QPainter *, const QPolygon & ); - static void drawPolyline( QPainter *, const QPoint *, int pointCount ); - - static void drawPoint( QPainter *, const QPoint & ); - static void drawPoints( QPainter *, const QPolygon & ); - static void drawPoints( QPainter *, const QPoint *, int pointCount ); - - static void drawPoint( QPainter *, double x, double y ); - static void drawPoint( QPainter *, const QPointF & ); - static void drawPoints( QPainter *, const QPolygonF & ); - static void drawPoints( QPainter *, const QPointF *, int pointCount ); - - static void drawPath( QPainter *, const QPainterPath & ); - static void drawImage( QPainter *, const QRectF &, const QImage & ); - static void drawPixmap( QPainter *, const QRectF &, const QPixmap & ); - - static void drawRoundFrame( QPainter *, - const QRectF &, const QPalette &, int lineWidth, int frameStyle ); - - static void drawRoundedFrame( QPainter *, - const QRectF &, double xRadius, double yRadius, - const QPalette &, int lineWidth, int frameStyle ); - - static void drawFrame( QPainter *, const QRectF &rect, - const QPalette &palette, QPalette::ColorRole foregroundRole, - int lineWidth, int midLineWidth, int frameStyle ); - - static void drawFocusRect( QPainter *, const QWidget * ); - static void drawFocusRect( QPainter *, const QWidget *, const QRect & ); - - static void drawColorBar( QPainter *painter, - const QwtColorMap &, const QwtInterval &, - const QwtScaleMap &, Qt::Orientation, const QRectF & ); - - static bool isAligning( QPainter *painter ); - static bool isX11GraphicsSystem(); - - static void fillPixmap( const QWidget *, - QPixmap &, const QPoint &offset = QPoint() ); - - static void drawBackgound( QPainter *painter, - const QRectF &rect, const QWidget *widget ); - - static QPixmap backingStore( QWidget *, const QSize & ); - -private: - static bool d_polylineSplitting; - static bool d_roundingAlignment; -}; - -//! Wrapper for QPainter::drawPoint() -inline void QwtPainter::drawPoint( QPainter *painter, double x, double y ) -{ - QwtPainter::drawPoint( painter, QPointF( x, y ) ); -} - -//! Wrapper for QPainter::drawPoints() -inline void QwtPainter::drawPoints( QPainter *painter, const QPolygon &polygon ) -{ - drawPoints( painter, polygon.data(), polygon.size() ); -} - -//! Wrapper for QPainter::drawPoints() -inline void QwtPainter::drawPoints( QPainter *painter, const QPolygonF &polygon ) -{ - drawPoints( painter, polygon.data(), polygon.size() ); -} - -//! 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() ); -} - -/*! - \return True, when line splitting for the raster paint engine is enabled. - \sa setPolylineSplitting() -*/ -inline bool QwtPainter::polylineSplitting() -{ - return d_polylineSplitting; -} - -/*! - Check whether coordinates should be rounded, before they are painted - to a paint engine that rounds to integer values. For other paint engines - ( PDF, SVG ), this flag has no effect. - - \return True, when rounding is enabled - \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/include/pli_vis/third_party/qwt/qwt_painter_command.h b/include/pli_vis/third_party/qwt/qwt_painter_command.h deleted file mode 100644 index ed57f2f35bbc8fd5477cb58652704e22d030ef7b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_painter_command.h +++ /dev/null @@ -1,173 +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_PAINTER_COMMAND_H -#define QWT_PAINTER_COMMAND_H - -#include "qwt/qwt_global.h" -#include <qpaintengine.h> -#include <qpixmap.h> -#include <qimage.h> -#include <qpolygon.h> - -class QPainterPath; - -/*! - QwtPainterCommand represents the attributes of a paint operation - how it is used between QPainter and QPaintDevice - - It is used by QwtGraphic to record and replay paint operations - - \sa QwtGraphic::commands() - */ - -class QWT_EXPORT QwtPainterCommand -{ -public: - //! Type of the paint command - enum Type - { - //! Invalid command - Invalid = -1, - - //! Draw a QPainterPath - Path, - - //! Draw a QPixmap - Pixmap, - - //! Draw a QImage - Image, - - //! QPainter state change - State - }; - - //! Attributes how to paint a QPixmap - struct PixmapData - { - QRectF rect; - QPixmap pixmap; - QRectF subRect; - }; - - //! Attributes how to paint a QImage - struct ImageData - { - QRectF rect; - QImage image; - QRectF subRect; - Qt::ImageConversionFlags flags; - }; - - //! Attributes of a state change - struct StateData - { - QPaintEngine::DirtyFlags flags; - - QPen pen; - QBrush brush; - QPointF brushOrigin; - QBrush backgroundBrush; - Qt::BGMode backgroundMode; - QFont font; - QMatrix matrix; - QTransform transform; - - Qt::ClipOperation clipOperation; - QRegion clipRegion; - QPainterPath clipPath; - bool isClipEnabled; - - QPainter::RenderHints renderHints; - QPainter::CompositionMode compositionMode; - qreal opacity; - }; - - QwtPainterCommand(); - QwtPainterCommand(const QwtPainterCommand &); - - QwtPainterCommand( const QPainterPath & ); - - QwtPainterCommand( const QRectF &rect, - const QPixmap &, const QRectF& subRect ); - - QwtPainterCommand( const QRectF &rect, - const QImage &, const QRectF& subRect, - Qt::ImageConversionFlags ); - - QwtPainterCommand( const QPaintEngineState & ); - - ~QwtPainterCommand(); - - QwtPainterCommand &operator=(const QwtPainterCommand & ); - - Type type() const; - - QPainterPath *path(); - const QPainterPath *path() const; - - PixmapData* pixmapData(); - const PixmapData* pixmapData() const; - - ImageData* imageData(); - const ImageData* imageData() const; - - StateData* stateData(); - const StateData* stateData() const; - -private: - void copy( const QwtPainterCommand & ); - void reset(); - - Type d_type; - - union - { - QPainterPath *d_path; - PixmapData *d_pixmapData; - ImageData *d_imageData; - StateData *d_stateData; - }; -}; - -//! \return Type of the command -inline QwtPainterCommand::Type QwtPainterCommand::type() const -{ - return d_type; -} - -//! \return Painter path to be painted -inline const QPainterPath *QwtPainterCommand::path() const -{ - return d_path; -} - -//! \return Attributes how to paint a QPixmap -inline const QwtPainterCommand::PixmapData* -QwtPainterCommand::pixmapData() const -{ - return d_pixmapData; -} - -//! \return Attributes how to paint a QImage -inline const QwtPainterCommand::ImageData * -QwtPainterCommand::imageData() const -{ - return d_imageData; -} - -//! \return Attributes of a state change -inline const QwtPainterCommand::StateData * -QwtPainterCommand::stateData() const -{ - return d_stateData; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_panner.h b/include/pli_vis/third_party/qwt/qwt_panner.h deleted file mode 100644 index fefe0a2b8a44c332c2a8f67662bc42fcee2b1c64..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_panner.h +++ /dev/null @@ -1,103 +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_PANNER_H -#define QWT_PANNER_H 1 - -#include "qwt/qwt_global.h" -#include <qwidget.h> -#include <qpixmap.h> - -class QCursor; - -/*! - \brief QwtPanner provides panning of a widget - - 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. - 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. -*/ -class QWT_EXPORT QwtPanner: public QWidget -{ - Q_OBJECT - -public: - QwtPanner( QWidget* parent ); - virtual ~QwtPanner(); - - void setEnabled( bool ); - bool isEnabled() const; - - void setMouseButton( Qt::MouseButton, - Qt::KeyboardModifiers = Qt::NoModifier ); - void getMouseButton( Qt::MouseButton &button, - Qt::KeyboardModifiers & ) const; - - void setAbortKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); - void getAbortKey( int &key, Qt::KeyboardModifiers & ) const; - - void setCursor( const QCursor & ); - const QCursor cursor() const; - - void setOrientations( Qt::Orientations ); - Qt::Orientations orientations() const; - - bool isOrientationEnabled( Qt::Orientation ) const; - - virtual bool eventFilter( QObject *, QEvent * ); - -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 ); - - /*! - Signal emitted, while the widget moved, but panning - is not finished. - - \param dx Offset in horizontal direction - \param dy Offset in vertical direction - */ - 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 paintEvent( QPaintEvent * ); - - virtual QBitmap contentsMask() const; - virtual QPixmap grab() const; - -private: -#ifndef QT_NO_CURSOR - void showCursor( bool ); -#endif - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_picker.h b/include/pli_vis/third_party/qwt/qwt_picker.h deleted file mode 100644 index cf72f19a382c2759fb0b6d4d56cf56b20be5ad8c..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_picker.h +++ /dev/null @@ -1,329 +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_PICKER -#define QWT_PICKER 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_event_pattern.h" -#include <qobject.h> -#include <qpen.h> -#include <qfont.h> -#include <qrect.h> -#include <qpainterpath.h> - -class QWidget; -class QMouseEvent; -class QWheelEvent; -class QKeyEvent; -class QwtPickerMachine; -class QwtWidgetOverlay; - -/*! - \brief QwtPicker provides selections on a widget - - QwtPicker filters all enter, leave, mouse and keyboard events of a widget - and translates them into an array of selected points. - - 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: - - - 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 fix up 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 - rubber band and tracker displaying a text for the current mouse - position. - - \par Example - \verbatim #include <qwt_picker.h> -#include <qwt_picker_machine.h> - -QwtPicker *picker = new QwtPicker(widget); -picker->setStateMachine(new QwtPickerDragRectMachine); -picker->setTrackerMode(QwtPicker::ActiveOnly); -picker->setRubberBand(QwtPicker::RectRubberBand); \endverbatim\n - - The state machine triggers the following commands: - - - 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 rubber band is displayed, and the tracker is visible - in case of trackerMode is ActiveOnly or AlwaysOn. - - The cursor can be moved using the arrow keys. All selections can be aborted - using the abort key. (QwtEventPattern::KeyPatternCode) - - \warning In case of QWidget::NoFocus the focus policy of the observed - widget is set to QWidget::WheelFocus and mouse tracking - will be manipulated while the picker is active, - or if trackerMode() is AlwayOn. -*/ - -class QWT_EXPORT QwtPicker: public QObject, public QwtEventPattern -{ - Q_OBJECT - - Q_ENUMS( RubberBand DisplayMode ResizeMode ) - - Q_PROPERTY( bool isEnabled READ isEnabled WRITE setEnabled ) - Q_PROPERTY( ResizeMode resizeMode READ resizeMode WRITE setResizeMode ) - - 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: - /*! - Rubber band style - - The default value is QwtPicker::NoRubberBand. - \sa setRubberBand(), rubberBand() - */ - - enum RubberBand - { - //! No rubberband. - NoRubberBand = 0, - - //! A horizontal line ( only for QwtPickerMachine::PointSelection ) - HLineRubberBand, - - //! A vertical line ( only for QwtPickerMachine::PointSelection ) - VLineRubberBand, - - //! A crosshair ( only for QwtPickerMachine::PointSelection ) - CrossRubberBand, - - //! A rectangle ( only for QwtPickerMachine::RectSelection ) - RectRubberBand, - - //! An ellipse ( only for QwtPickerMachine::RectSelection ) - EllipseRubberBand, - - //! A polygon ( only for QwtPickerMachine::PolygonSelection ) - PolygonRubberBand, - - /*! - Values >= UserRubberBand can be used to define additional - rubber bands. - */ - UserRubberBand = 100 - }; - - /*! - \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. - - 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( RubberBand rubberBand, - DisplayMode trackerMode, QWidget * ); - - virtual ~QwtPicker(); - - void setStateMachine( QwtPickerMachine * ); - const QwtPickerMachine *stateMachine() const; - QwtPickerMachine *stateMachine(); - - void setRubberBand( RubberBand ); - RubberBand rubberBand() const; - - void setTrackerMode( DisplayMode ); - DisplayMode trackerMode() const; - - void setResizeMode( ResizeMode ); - ResizeMode resizeMode() const; - - void setRubberBandPen( const QPen & ); - QPen rubberBandPen() const; - - void setTrackerPen( const QPen & ); - QPen trackerPen() const; - - void setTrackerFont( const QFont & ); - QFont trackerFont() const; - - bool isEnabled() const; - bool isActive() const; - - virtual bool eventFilter( QObject *, QEvent * ); - - QWidget *parentWidget(); - const QWidget *parentWidget() const; - - virtual QPainterPath pickArea() const; - - virtual void drawRubberBand( QPainter * ) const; - virtual void drawTracker( QPainter * ) const; - - virtual QRegion rubberBandMask() const; - - virtual QwtText trackerText( const QPoint &pos ) const; - QPoint trackerPosition() const; - virtual QRect trackerRect( const QFont & ) const; - - QPolygon selection() const; - -public Q_SLOTS: - void setEnabled( bool ); - -Q_SIGNALS: - /*! - 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 polygon Selected points - */ - void selected( const QPolygon &polygon ); - - /*! - A signal emitted when a point has been appended to the selection - - \param pos Position of the appended point. - \sa append(). moved() - */ - void appended( const QPoint &pos ); - - /*! - 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 ); - - /*! - A signal emitted whenever the last appended point of the - selection has been removed. - - \param pos Position of the point, that 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 selection Changed selection - \sa stretchSelection() - */ - void changed( const QPolygon &selection ); - -protected: - virtual QPolygon adjustedPoints( const QPolygon & ) const; - - virtual void transition( const QEvent * ); - - virtual void begin(); - 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 widgetEnterEvent( QEvent * ); - virtual void widgetLeaveEvent( QEvent * ); - - virtual void stretchSelection( const QSize &oldSize, - const QSize &newSize ); - - virtual void updateDisplay(); - - const QwtWidgetOverlay *rubberBandOverlay() const; - const QwtWidgetOverlay *trackerOverlay() const; - - const QPolygon &pickedPoints() const; - -private: - void init( QWidget *, RubberBand rubberBand, DisplayMode trackerMode ); - - void setMouseTracking( bool ); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_picker_machine.h b/include/pli_vis/third_party/qwt/qwt_picker_machine.h deleted file mode 100644 index bbe4eea8d0a276b3ddcf3e9ce9c380571c2fa986..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_picker_machine.h +++ /dev/null @@ -1,214 +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_PICKER_MACHINE -#define QWT_PICKER_MACHINE 1 - -#include "qwt/qwt_global.h" -#include <qlist.h> - -class QEvent; -class QwtEventPattern; - -/*! - \brief A state machine for QwtPicker selections - - QwtPickerMachine accepts key and mouse events and translates them - into selection commands. - - \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode -*/ - -class QWT_EXPORT QwtPickerMachine -{ -public: - /*! - 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 - }; - - QwtPickerMachine( SelectionType ); - virtual ~QwtPickerMachine(); - - //! Transition - virtual QList<Command> transition( - const QwtEventPattern &, const QEvent * ) = 0; - void reset(); - - int state() const; - void setState( int ); - - 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<Command> transition( - const QwtEventPattern &, const QEvent * ); -}; - -/*! - \brief A state machine for point selections - - Pressing QwtEventPattern::MouseSelect1 or - QwtEventPattern::KeySelect1 selects a point. - - \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode -*/ -class QWT_EXPORT QwtPickerClickPointMachine: public QwtPickerMachine -{ -public: - QwtPickerClickPointMachine(); - - virtual QList<Command> 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 - a second press of QwtEventPattern::KeySelect1 terminates it. -*/ -class QWT_EXPORT QwtPickerDragPointMachine: public QwtPickerMachine -{ -public: - QwtPickerDragPointMachine(); - - virtual QList<Command> transition( - const QwtEventPattern &, const QEvent * ); -}; - -/*! - \brief A state machine for rectangle selections - - 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. - - \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode -*/ - -class QWT_EXPORT QwtPickerClickRectMachine: public QwtPickerMachine -{ -public: - QwtPickerClickRectMachine(); - - virtual QList<Command> transition( - const QwtEventPattern &, const QEvent * ); -}; - -/*! - \brief A state machine for rectangle selections - - 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 - the selection. - - \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode -*/ - -class QWT_EXPORT QwtPickerDragRectMachine: public QwtPickerMachine -{ -public: - QwtPickerDragRectMachine(); - - virtual QList<Command> transition( - const QwtEventPattern &, const QEvent * ); -}; - -/*! - \brief A state machine for line selections - - 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 - the selection. - - A common use case of QwtPickerDragLineMachine are pickers for - distance measurements. - - \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode -*/ - -class QWT_EXPORT QwtPickerDragLineMachine: public QwtPickerMachine -{ -public: - QwtPickerDragLineMachine(); - - virtual QList<Command> 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 - appends the last point and terminates the selection. - - \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode -*/ - -class QWT_EXPORT QwtPickerPolygonMachine: public QwtPickerMachine -{ -public: - QwtPickerPolygonMachine(); - - virtual QList<Command> transition( - const QwtEventPattern &, const QEvent * ); -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_pixel_matrix.h b/include/pli_vis/third_party/qwt/qwt_pixel_matrix.h deleted file mode 100644 index 2d5f93b5206516cc4b45b87e3fc542832f46a017..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_pixel_matrix.h +++ /dev/null @@ -1,98 +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_PIXEL_MATRIX_H -#define QWT_PIXEL_MATRIX_H - -#include "qwt/qwt_global.h" -#include <qbitarray.h> -#include <qrect.h> - -/*! - \brief A bit field corresponding to the pixels of a rectangle - - QwtPixelMatrix is intended to filter out duplicates in an - unsorted array of points. -*/ -class QWT_EXPORT QwtPixelMatrix: public QBitArray -{ -public: - QwtPixelMatrix( const QRect& rect ); - ~QwtPixelMatrix(); - - void setRect( const QRect& rect ); - QRect rect() const; - - bool testPixel( int x, int y ) const; - bool testAndSetPixel( int x, int y, bool on ); - - int index( int x, int y ) const; - -private: - QRect d_rect; -}; - -/*! - \brief Test if a pixel has been set - - \param x X-coordinate - \param y Y-coordinate - - \return true, when pos is outside of rect(), or when the pixel - has already been set. - */ -inline bool QwtPixelMatrix::testPixel( int x, int y ) const -{ - const int idx = index( x, y ); - return ( idx >= 0 ) ? testBit( idx ) : true; -} - -/*! - \brief Set a pixel and test if a pixel has been set before - - \param x X-coordinate - \param y Y-coordinate - \param on Set/Clear the pixel - - \return true, when pos is outside of rect(), or when the pixel - was set before. - */ -inline bool QwtPixelMatrix::testAndSetPixel( int x, int y, bool on ) -{ - const int idx = index( x, y ); - if ( idx < 0 ) - return true; - - const bool onBefore = testBit( idx ); - setBit( idx, on ); - - return onBefore; -} - -/*! - \brief Calculate the index in the bit field corresponding to a position - - \param x X-coordinate - \param y Y-coordinate - \return Index, when rect() contains pos - otherwise -1. - */ -inline int QwtPixelMatrix::index( int x, int y ) const -{ - const int dx = x - d_rect.x(); - if ( dx < 0 || dx >= d_rect.width() ) - return -1; - - const int dy = y - d_rect.y(); - if ( dy < 0 || dy >= d_rect.height() ) - return -1; - - return dy * d_rect.width() + dx; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot.h b/include/pli_vis/third_party/qwt/qwt_plot.h deleted file mode 100644 index ed5b58e3eefbbd606397f61fb2f93bdf7218c83a..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot.h +++ /dev/null @@ -1,312 +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_PLOT_H -#define QWT_PLOT_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_plot_dict.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_interval.h" -#include <qframe.h> -#include <qlist.h> -#include <qvariant.h> - -class QwtPlotLayout; -class QwtAbstractLegend; -class QwtScaleWidget; -class QwtScaleEngine; -class QwtScaleDiv; -class QwtScaleDraw; -class QwtTextLabel; - -/*! - \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 - 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 explicitly set (QwtScaleDiv), or - are calculated from the plot items, using algorithms (QwtScaleEngine) which - can be configured separately for each axis. - - The simpleplot example is a good starting point to see how to set up a - plot widget. - - \image html plot.png - - \par Example - The following example shows (schematically) the most simple - way to use QwtPlot. By default, only the left and bottom axes are - visible and their scales are computed automatically. - \verbatim -#include <qwt_plot.h> -#include <qwt_plot_curve.h> - -QwtPlot *myPlot = new QwtPlot("Two Curves", parent); - -// add curves -QwtPlotCurve *curve1 = new QwtPlotCurve("Curve 1"); -QwtPlotCurve *curve2 = new QwtPlotCurve("Curve 2"); - -// connect or copy the data to the curves -curve1->setData(...); -curve2->setData(...); - -curve1->attach(myPlot); -curve2->attach(myPlot); - -// finally, refresh the plot -myPlot->replot(); -\endverbatim -*/ - -class QWT_EXPORT QwtPlot: public QFrame, public QwtPlotDict -{ - Q_OBJECT - - Q_PROPERTY( QBrush canvasBackground - READ canvasBackground WRITE setCanvasBackground ) - Q_PROPERTY( bool autoReplot READ autoReplot WRITE setAutoReplot ) - -#if 0 - // This property is intended to configure the plot - // widget from a special dialog in the deigner plugin. - // Disabled until such a dialog has been implemented. - - Q_PROPERTY( QString propertiesDocument - READ grabProperties WRITE applyProperties ) -#endif - -public: - //! \brief Axis index - enum Axis - { - //! Y axis left of the canvas - yLeft, - - //! Y axis right of the canvas - yRight, - - //! X axis below the canvas - xBottom, - - //! X axis above the canvas - xTop, - - //! Number of axes - axisCnt - }; - - /*! - Position of the legend, relative to the canvas. - - \sa insertLegend() - */ - 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 the footer - BottomLegend, - - //! The legend will be above the title - TopLegend - }; - - explicit QwtPlot( QWidget * = NULL ); - explicit QwtPlot( const QwtText &title, QWidget * = NULL ); - - virtual ~QwtPlot(); - - void applyProperties( const QString & ); - QString grabProperties() const; - - void setAutoReplot( bool = true ); - bool autoReplot() const; - - // Layout - - void setPlotLayout( QwtPlotLayout * ); - - QwtPlotLayout *plotLayout(); - const QwtPlotLayout *plotLayout() const; - - // Title - - void setTitle( const QString & ); - void setTitle( const QwtText &t ); - QwtText title() const; - - QwtTextLabel *titleLabel(); - const QwtTextLabel *titleLabel() const; - - // Footer - - void setFooter( const QString & ); - void setFooter( const QwtText &t ); - QwtText footer() const; - - QwtTextLabel *footerLabel(); - const QwtTextLabel *footerLabel() const; - - // Canvas - - void setCanvas( QWidget * ); - - QWidget *canvas(); - const QWidget *canvas() const; - - void setCanvasBackground( const QBrush & ); - QBrush canvasBackground() const; - - virtual QwtScaleMap canvasMap( int axisId ) 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 * ); - - 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 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 * ); - - double axisStepSize( int axisId ) const; - QwtInterval axisInterval( int axisId ) const; - - const QwtScaleDiv &axisScaleDiv( int axisId ) const; - - const QwtScaleDraw *axisScaleDraw( int axisId ) const; - QwtScaleDraw *axisScaleDraw( int axisId ); - - const QwtScaleWidget *axisWidget( int axisId ) const; - QwtScaleWidget *axisWidget( int axisId ); - - 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 setAxisMaxMinor( int axisId, int maxMinor ); - int axisMaxMinor( int axisId ) const; - - void setAxisMaxMajor( int axisId, int maxMajor ); - int axisMaxMajor( int axisId ) const; - - // Legend - - void insertLegend( QwtAbstractLegend *, - LegendPosition = QwtPlot::RightLegend, double ratio = -1.0 ); - - QwtAbstractLegend *legend(); - const QwtAbstractLegend *legend() const; - - void updateLegend(); - void updateLegend( const QwtPlotItem * ); - - // Misc - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - virtual void updateLayout(); - virtual void drawCanvas( QPainter * ); - - void updateAxes(); - void updateCanvasMargins(); - - virtual void getCanvasMarginsHint( - const QwtScaleMap maps[], const QRectF &canvasRect, - double &left, double &top, double &right, double &bottom) const; - - virtual bool event( QEvent * ); - virtual bool eventFilter( QObject *, QEvent * ); - - virtual void drawItems( QPainter *, const QRectF &, - const QwtScaleMap maps[axisCnt] ) const; - - virtual QVariant itemToInfo( QwtPlotItem * ) const; - virtual QwtPlotItem *infoToItem( const QVariant & ) const; - -Q_SIGNALS: - /*! - A signal indicating, that an item has been attached/detached - - \param plotItem Plot item - \param on Attached/Detached - */ - void itemAttached( QwtPlotItem *plotItem, bool on ); - - /*! - A signal with the attributes how to update - the legend entries for a plot item. - - \param itemInfo Info about a plot item, build from itemToInfo() - \param data Attributes of the entries ( usually <= 1 ) for - the plot item. - - \sa itemToInfo(), infoToItem(), QwtAbstractLegend::updateLegend() - */ - void legendDataChanged( const QVariant &itemInfo, - const QList<QwtLegendData> &data ); - -public Q_SLOTS: - virtual void replot(); - void autoRefresh(); - -protected: - static bool axisValid( int axisId ); - - virtual void resizeEvent( QResizeEvent *e ); - -private Q_SLOTS: - void updateLegendItems( const QVariant &itemInfo, - const QList<QwtLegendData> &data ); - -private: - friend class QwtPlotItem; - void attachItem( QwtPlotItem *, bool ); - - void initAxesData(); - void deleteAxesData(); - void updateScaleDiv(); - - void initPlot( const QwtText &title ); - - class AxisData; - AxisData *d_axisData[axisCnt]; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_abstract_barchart.h b/include/pli_vis/third_party/qwt/qwt_plot_abstract_barchart.h deleted file mode 100644 index e364097a3b96b49e65f50d9136865e18230ef2b5..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_abstract_barchart.h +++ /dev/null @@ -1,97 +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_PLOT_ABSTRACT_BAR_CHART_H -#define QWT_PLOT_ABSTRACT_BAR_CHART_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_seriesitem.h" -#include "qwt/qwt_series_data.h" - -/*! - \brief Abstract base class for bar chart items - - In opposite to almost all other plot items bar charts can't be - displayed inside of their bounding rectangle and need a special - API how to calculate the width of the bars and how they affect - the layout of the attached plot. - */ -class QWT_EXPORT QwtPlotAbstractBarChart: public QwtPlotSeriesItem -{ -public: - /*! - \brief Mode how to calculate the bar width - - setLayoutPolicy(), setLayoutHint(), barWidthHint() - */ - enum LayoutPolicy - { - /*! - The sample width is calculated by dividing the bounding rectangle - by the number of samples. The layoutHint() is used as a minimum width - in paint device coordinates. - - \sa boundingRectangle() - */ - AutoAdjustSamples, - - /*! - layoutHint() defines an interval in axis coordinates - */ - ScaleSamplesToAxes, - - /*! - The bar width is calculated by multiplying layoutHint() - with the height or width of the canvas. - - \sa boundingRectangle() - */ - ScaleSampleToCanvas, - - /*! - layoutHint() defines a fixed width in paint device coordinates. - */ - FixedSampleSize - }; - - explicit QwtPlotAbstractBarChart( const QwtText &title ); - virtual ~QwtPlotAbstractBarChart(); - - void setLayoutPolicy( LayoutPolicy ); - LayoutPolicy layoutPolicy() const; - - void setLayoutHint( double ); - double layoutHint() const; - - void setSpacing( int ); - int spacing() const; - - void setMargin( int ); - int margin() const; - - void setBaseline( double ); - double baseline() const; - - virtual void getCanvasMarginHint( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, - double &left, double &top, double &right, double &bottom) const; - - -protected: - double sampleWidth( const QwtScaleMap &map, - double canvasSize, double dataSize, - double value ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_barchart.h b/include/pli_vis/third_party/qwt/qwt_plot_barchart.h deleted file mode 100644 index d6894c674205ca69a938451b72996df12a595596..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_barchart.h +++ /dev/null @@ -1,118 +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_PLOT_BAR_CHART_H -#define QWT_PLOT_BAR_CHART_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_abstract_barchart.h" -#include "qwt/qwt_series_data.h" - -class QwtColumnRect; -class QwtColumnSymbol; - -/*! - \brief QwtPlotBarChart displays a series of a values as bars. - - Each bar might be customized individually by implementing - a specialSymbol(). Otherwise it is rendered using a default symbol. - - Depending on its orientation() the bars are displayed horizontally - or vertically. The bars cover the interval between the baseline() - and the value. - - By activating the LegendBarTitles mode each sample will have - its own entry on the legend. - - The most common use case of a bar chart is to display a - list of y coordinates, where the x coordinate is simply the index - in the list. But for other situations ( f.e. when values are related - to dates ) it is also possible to set x coordinates explicitly. - - \sa QwtPlotMultiBarChart, QwtPlotHistogram, QwtPlotCurve::Sticks, - QwtPlotSeriesItem::orientation(), QwtPlotAbstractBarChart::baseline() - */ -class QWT_EXPORT QwtPlotBarChart: - public QwtPlotAbstractBarChart, public QwtSeriesStore<QPointF> -{ -public: - /*! - \brief Legend modes. - - The default setting is QwtPlotBarChart::LegendChartTitle. - \sa setLegendMode(), legendMode() - */ - enum LegendMode - { - /*! - One entry on the legend showing the default symbol - and the title() of the chart - - \sa QwtPlotItem::title() - */ - LegendChartTitle, - - /*! - One entry for each value showing the individual symbol - of the corresponding bar and the bar title. - - \sa specialSymbol(), barTitle() - */ - LegendBarTitles - }; - - explicit QwtPlotBarChart( const QString &title = QString::null ); - explicit QwtPlotBarChart( const QwtText &title ); - - virtual ~QwtPlotBarChart(); - - virtual int rtti() const; - - void setSamples( const QVector<QPointF> & ); - void setSamples( const QVector<double> & ); - void setSamples( QwtSeriesData<QPointF> *series ); - - void setSymbol( QwtColumnSymbol * ); - const QwtColumnSymbol *symbol() const; - - void setLegendMode( LegendMode ); - LegendMode legendMode() const; - - virtual void drawSeries( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual QRectF boundingRect() const; - - virtual QwtColumnSymbol *specialSymbol( - int sampleIndex, const QPointF& ) const; - - virtual QwtText barTitle( int sampleIndex ) const; - -protected: - virtual void drawSample( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, const QwtInterval &boundingInterval, - int index, const QPointF& sample ) const; - - virtual void drawBar( QPainter *, - int sampleIndex, const QPointF& point, - const QwtColumnRect & ) const; - - QList<QwtLegendData> legendData() const; - QwtGraphic legendIcon( int index, const QSizeF & ) const; - -private: - void init(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_canvas.h b/include/pli_vis/third_party/qwt/qwt_plot_canvas.h deleted file mode 100644 index 7f91d8113e3e7d7f1b52282c0eba491331763d8f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_canvas.h +++ /dev/null @@ -1,171 +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_PLOT_CANVAS_H -#define QWT_PLOT_CANVAS_H - -#include "qwt/qwt_global.h" -#include <qframe.h> -#include <qpainterpath.h> - -class QwtPlot; -class QPixmap; - -/*! - \brief Canvas of a QwtPlot. - - Canvas is the widget where all plot items are displayed - - \sa QwtPlot::setCanvas(), QwtPlotGLCanvas -*/ -class QWT_EXPORT QwtPlotCanvas : public QFrame -{ - Q_OBJECT - - Q_PROPERTY( double borderRadius READ borderRadius WRITE setBorderRadius ) - -public: - - /*! - \brief Paint attributes - - The default setting enables BackingStore and Opaque. - - \sa setPaintAttribute(), testPaintAttribute() - */ - enum PaintAttribute - { - /*! - \brief Paint double buffered reusing the content - of the pixmap buffer when possible. - - Using a backing store might improve the performance - significantly, when working with widget overlays ( like rubber bands ). - 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 separate the background from the background border - by reverse engineering to paint the background before and - the border after the plot items. In this order the border - gets perfectly 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<PaintAttribute> PaintAttributes; - - /*! - \brief Focus indicator - The default setting is NoFocusIndicator - \sa setFocusIndicator(), focusIndicator(), drawFocusIndicator() - */ - - enum FocusIndicator - { - //! Don't paint a focus indicator - NoFocusIndicator, - - /*! - The focus is related to the complete canvas. - Paint the focus indicator using drawFocusIndicator() - */ - CanvasFocusIndicator, - - /*! - The focus is related to an item (curve, point, ...) on - the canvas. It is up to the application to display a - focus indication using f.e. highlighting. - */ - ItemFocusIndicator - }; - - explicit QwtPlotCanvas( QwtPlot * = NULL ); - virtual ~QwtPlotCanvas(); - - QwtPlot *plot(); - const QwtPlot *plot() const; - - void setFocusIndicator( FocusIndicator ); - FocusIndicator focusIndicator() const; - - void setBorderRadius( double ); - double borderRadius() const; - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - const QPixmap *backingStore() const; - void invalidateBackingStore(); - - virtual bool event( QEvent * ); - - Q_INVOKABLE QPainterPath borderPath( const QRect & ) const; - -public Q_SLOTS: - void replot(); - -protected: - virtual void paintEvent( QPaintEvent * ); - virtual void resizeEvent( QResizeEvent * ); - - virtual void drawFocusIndicator( QPainter * ); - virtual void drawBorder( QPainter * ); - - void updateStyleSheetInfo(); - -private: - void drawCanvas( QPainter *, bool withBackground ); - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCanvas::PaintAttributes ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_curve.h b/include/pli_vis/third_party/qwt/qwt_plot_curve.h deleted file mode 100644 index 79ac6818ceda4560e0412e63ebc4fe9fc5c2aa89..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_curve.h +++ /dev/null @@ -1,337 +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_PLOT_CURVE_H -#define QWT_PLOT_CURVE_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_seriesitem.h" -#include "qwt/qwt_series_data.h" -#include "qwt/qwt_text.h" -#include <qpen.h> -#include <qstring.h> - -class QPainter; -class QPolygonF; -class QwtScaleMap; -class QwtSymbol; -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 ) - and symbols. - - \par Usage - <dl><dt>a) Assign curve properties</dt> - <dd>When a curve is created, it is configured to draw black solid lines - with in QwtPlotCurve::Lines style and no symbols. - You can change this by calling - setPen(), setStyle() and setSymbol().</dd> - <dt>b) Connect/Assign data.</dt> - <dd>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 QwtSeriesData, that also store - the points inside ( like QStandardItemModel ). QwtPlotCurve also offers - a couple of variations of setSamples(), that build QwtSeriesData objects from - arrays internally.</dd> - <dt>c) Attach the curve to a plot</dt> - <dd>See QwtPlotItem::attach() - </dd></dl> - - \par Example: - see examples/bode - - \sa QwtPointSeriesData, QwtSymbol, QwtScaleMap -*/ -class QWT_EXPORT QwtPlotCurve: - public QwtPlotSeriesItem, public QwtSeriesStore<QPointF> -{ -public: - /*! - Curve styles. - \sa setStyle(), style() - */ - enum CurveStyle - { - /*! - 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 - \sa setCurveAttribute(), testCurveAttribute(), curveFitter() - */ - enum CurveAttribute - { - /*! - 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 temporary 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<CurveAttribute> CurveAttributes; - - /*! - Attributes how to represent the curve on the legend - - \sa setLegendAttribute(), testLegendAttribute(), - QwtPlotItem::legendData(), legendIcon() - */ - - 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<LegendAttribute> LegendAttributes; - - /*! - Attributes to modify the drawing algorithm. - The default setting enables ClipPolygons | FilterPoints - - \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, - - /*! - 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 algorithms are implemented. - */ - FilterPoints = 0x02, - - /*! - Minimize memory usage that is temporarily needed for the - translated points, before they get painted. - This might slow down the performance of painting - */ - MinimizeMemory = 0x04, - - /*! - Render the points to a temporary image and paint the image. - This is a very special optimization for Dots style, when - having a huge amount of points. - With a reasonable number of points QPainter::drawPoints() - will be faster. - */ - ImageBuffer = 0x08 - }; - - //! Paint attributes - typedef QFlags<PaintAttribute> PaintAttributes; - - explicit QwtPlotCurve( const QString &title = QString::null ); - explicit QwtPlotCurve( const QwtText &title ); - - virtual ~QwtPlotCurve(); - - virtual int rtti() const; - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - void setLegendAttribute( LegendAttribute, bool on = true ); - bool testLegendAttribute( LegendAttribute ) const; - -#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<double> &xData, const QVector<double> &yData ); -#endif - void setSamples( const QVector<QPointF> & ); - void setSamples( QwtSeriesData<QPointF> * ); - - 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 setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setPen( const QPen & ); - const QPen &pen() const; - - void setBrush( const QBrush & ); - const QBrush &brush() const; - - void setBaseline( double ); - double baseline() const; - - void setStyle( CurveStyle style ); - CurveStyle style() const; - - void setSymbol( QwtSymbol * ); - const QwtSymbol *symbol() const; - - void setCurveFitter( QwtCurveFitter * ); - QwtCurveFitter *curveFitter() const; - - virtual void drawSeries( QPainter *, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; - -protected: - - void init(); - - virtual void drawCurve( QPainter *p, int style, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual void drawSymbols( QPainter *p, const QwtSymbol &, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual void drawLines( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual void drawSticks( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual void drawDots( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual 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 &, - const QRectF &canvasRect, QPolygonF & ) const; - - void closePolyline( QPainter *, - const QwtScaleMap &, const QwtScaleMap &, QPolygonF & ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -//! boundingRect().left() -inline double QwtPlotCurve::minXValue() const -{ - return boundingRect().left(); -} - -//! boundingRect().right() -inline double QwtPlotCurve::maxXValue() const -{ - return boundingRect().right(); -} - -//! boundingRect().top() -inline double QwtPlotCurve::minYValue() const -{ - return boundingRect().top(); -} - -//! 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/include/pli_vis/third_party/qwt/qwt_plot_dict.h b/include/pli_vis/third_party/qwt/qwt_plot_dict.h deleted file mode 100644 index e370907a770c2cb17af705e26a75be963e4959a3..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_dict.h +++ /dev/null @@ -1,58 +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_PLOT_DICT -#define QWT_PLOT_DICT - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include <qlist.h> - -/// \var typedef QList< QwtPlotItem *> QwtPlotItemList -/// \brief See QT 4.x assistant documentation for QList -typedef QList<QwtPlotItem *> QwtPlotItemList; -typedef QList<QwtPlotItem *>::ConstIterator QwtPlotItemIterator; - -/*! - \brief A dictionary for plot items - - QwtPlotDict organizes plot items in increasing z-order. - If autoDelete() is enabled, all attached items will be deleted - in the destructor of the dictionary. - QwtPlotDict can be used to get access to all QwtPlotItem items - or all - items of a specific type - that are currently on the plot. - - \sa QwtPlotItem::attach(), QwtPlotItem::detach(), QwtPlotItem::z() -*/ -class QWT_EXPORT QwtPlotDict -{ -public: - explicit QwtPlotDict(); - virtual ~QwtPlotDict(); - - 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 ); - -protected: - void insertItem( QwtPlotItem * ); - void removeItem( QwtPlotItem * ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_directpainter.h b/include/pli_vis/third_party/qwt/qwt_plot_directpainter.h deleted file mode 100644 index e0510b1b3e680223ee2a7aea232088ff493a853b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_directpainter.h +++ /dev/null @@ -1,100 +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_PLOT_DIRECT_PAINTER_H -#define QWT_PLOT_DIRECT_PAINTER_H - -#include "qwt/qwt_global.h" -#include <qobject.h> - -class QRegion; -class QwtPlotSeriesItem; - -/*! - \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 explicitly 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 backing store 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<Attribute> 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( QwtPlotSeriesItem *, 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/include/pli_vis/third_party/qwt/qwt_plot_glcanvas.h b/include/pli_vis/third_party/qwt/qwt_plot_glcanvas.h deleted file mode 100644 index fd597313303c7388d3ac0ea3ce2a49e683a54611..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_glcanvas.h +++ /dev/null @@ -1,131 +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_PLOT_GLCANVAS_H -#define QWT_PLOT_GLCANVAS_H - -#include "qwt/qwt_global.h" -#include <qframe.h> -#include <qopengl.h> -#include <qopenglwidget.h> - -class QwtPlot; - -/*! - \brief An alternative canvas for a QwtPlot derived from QGLWidget - - QwtPlotGLCanvas implements the very basics to act as canvas - inside of a QwtPlot widget. It might be extended to a full - featured alternative to QwtPlotCanvas in a future version of Qwt. - - Even if QwtPlotGLCanvas is not derived from QFrame it imitates - its API. When using style sheets it supports the box model - beside - backgrounds with rounded borders. - - \sa QwtPlot::setCanvas(), QwtPlotCanvas - - \note With Qt4 you might want to use the QPaintEngine::OpenGL paint engine - ( see QGL::setPreferredPaintEngine() ). On a Linux test system - QPaintEngine::OpenGL2 shows very basic problems like translated - geometries. -*/ -class QWT_EXPORT QwtPlotGLCanvas: public QOpenGLWidget -{ - Q_OBJECT - - Q_ENUMS( Shape Shadow ) - - Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow ) - Q_PROPERTY( Shape frameShape READ frameShape WRITE setFrameShape ) - Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth ) - Q_PROPERTY( int midLineWidth READ midLineWidth WRITE setMidLineWidth ) - Q_PROPERTY( int frameWidth READ frameWidth ) - Q_PROPERTY( QRect frameRect READ frameRect DESIGNABLE false ) - -public: - /*! - \brief Frame shadow - - Unfortunately it is not possible to use QFrame::Shadow - as a property of a widget that is not derived from QFrame. - The following enum is made for the designer only. It is safe - to use QFrame::Shadow instead. - */ - enum Shadow - { - //! QFrame::Plain - Plain = QFrame::Plain, - - //! QFrame::Raised - Raised = QFrame::Raised, - - //! QFrame::Sunken - Sunken = QFrame::Sunken - }; - - /*! - \brief Frame shape - - Unfortunately it is not possible to use QFrame::Shape - as a property of a widget that is not derived from QFrame. - The following enum is made for the designer only. It is safe - to use QFrame::Shadow instead. - - \note QFrame::StyledPanel and QFrame::WinPanel are unsuported - and will be displayed as QFrame::Panel. - */ - enum Shape - { - NoFrame = QFrame::NoFrame, - - Box = QFrame::Box, - Panel = QFrame::Panel - }; - - explicit QwtPlotGLCanvas( QwtPlot * = NULL ); - virtual ~QwtPlotGLCanvas(); - - void setFrameStyle( int style ); - int frameStyle() const; - - void setFrameShadow( Shadow ); - Shadow frameShadow() const; - - void setFrameShape( Shape ); - Shape frameShape() const; - - void setLineWidth( int ); - int lineWidth() const; - - void setMidLineWidth( int ); - int midLineWidth() const; - - int frameWidth() const; - QRect frameRect() const; - - Q_INVOKABLE QPainterPath borderPath( const QRect & ) const; - - virtual bool event( QEvent * ); - -public Q_SLOTS: - void replot(); - -protected: - virtual void paintEvent( QPaintEvent * ); - - virtual void drawBackground( QPainter * ); - virtual void drawBorder( QPainter * ); - virtual void drawItems( QPainter * ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_grid.h b/include/pli_vis/third_party/qwt/qwt_plot_grid.h deleted file mode 100644 index d6d5da025e9753cabb3c54bf8bb7fbb83f7cd61d..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_grid.h +++ /dev/null @@ -1,87 +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_PLOT_GRID_H -#define QWT_PLOT_GRID_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_scale_div.h" - -class QPainter; -class QPen; -class QwtScaleMap; -class QwtScaleDiv; - -/*! - \brief A class which draws a coordinate grid - - The QwtPlotGrid class can be used to draw a coordinate grid. - A coordinate grid consists of major and minor vertical - and horizontal grid lines. The locations of the grid lines - are determined by the X and Y scale divisions which can - be assigned with setXDiv() and setYDiv(). - The draw() member draws the grid within a bounding - rectangle. -*/ - -class QWT_EXPORT QwtPlotGrid: public QwtPlotItem -{ -public: - explicit QwtPlotGrid(); - virtual ~QwtPlotGrid(); - - virtual int rtti() const; - - void enableX( bool tf ); - bool xEnabled() const; - - void enableY( bool tf ); - bool yEnabled() const; - - void enableXMin( bool tf ); - bool xMinEnabled() const; - - void enableYMin( bool tf ); - bool yMinEnabled() const; - - void setXDiv( const QwtScaleDiv &sx ); - const QwtScaleDiv &xScaleDiv() const; - - void setYDiv( const QwtScaleDiv &sy ); - const QwtScaleDiv &yScaleDiv() const; - - void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setPen( const QPen & ); - - void setMajorPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setMajorPen( const QPen & ); - const QPen& majorPen() const; - - void setMinorPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setMinorPen( const QPen &p ); - const QPen& minorPen() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - - virtual void updateScaleDiv( - const QwtScaleDiv &xMap, const QwtScaleDiv &yMap ); - -private: - void drawLines( QPainter *painter, const QRectF &, - Qt::Orientation orientation, const QwtScaleMap &, - const QList<double> & ) const; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_histogram.h b/include/pli_vis/third_party/qwt/qwt_plot_histogram.h deleted file mode 100644 index 0cdb0c0c1d01968a24b1c04b3730ef606298e625..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_histogram.h +++ /dev/null @@ -1,139 +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_PLOT_HISTOGRAM_H -#define QWT_PLOT_HISTOGRAM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_seriesitem.h" -#include "qwt/qwt_column_symbol.h" -#include <qcolor.h> -#include <qvector.h> - -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. - - \sa QwtPlotBarChart, QwtPlotMultiBarChart -*/ - -class QWT_EXPORT QwtPlotHistogram: - public QwtPlotSeriesItem, public QwtSeriesStore<QwtIntervalSample> -{ -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 QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setPen( const QPen & ); - const QPen &pen() const; - - void setBrush( const QBrush & ); - const QBrush &brush() const; - - void setSamples( const QVector<QwtIntervalSample> & ); - void setSamples( QwtSeriesData<QwtIntervalSample> * ); - - 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 QwtGraphic legendIcon( int index, const QSizeF & ) 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/include/pli_vis/third_party/qwt/qwt_plot_intervalcurve.h b/include/pli_vis/third_party/qwt/qwt_plot_intervalcurve.h deleted file mode 100644 index 81dcadf011962cc33f18f0cfc1cf396b2569a1ae..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_intervalcurve.h +++ /dev/null @@ -1,132 +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_PLOT_INTERVAL_CURVE_H -#define QWT_PLOT_INTERVAL_CURVE_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_seriesitem.h" -#include "qwt/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 display error bars or the area between 2 curves. -*/ -class QWT_EXPORT QwtPlotIntervalCurve: - public QwtPlotSeriesItem, public QwtSeriesStore<QwtIntervalSample> -{ -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<PaintAttribute> 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<QwtIntervalSample> & ); - void setSamples( QwtSeriesData<QwtIntervalSample> * ); - - void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - 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 QwtGraphic legendIcon( int index, const QSizeF & ) 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/include/pli_vis/third_party/qwt/qwt_plot_item.h b/include/pli_vis/third_party/qwt/qwt_plot_item.h deleted file mode 100644 index 2cbac2909ca1f944c0e734060caf6f9483cf4f12..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_item.h +++ /dev/null @@ -1,307 +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_PLOT_ITEM_H -#define QWT_PLOT_ITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_legend_data.h" -#include "qwt/qwt_graphic.h" -#include <qrect.h> -#include <qlist.h> -#include <qmetatype.h> - -class QPainter; -class QwtScaleMap; -class QwtScaleDiv; -class QwtPlot; - -/*! - \brief Base class for items on the plot canvas - - A plot item is "something", that can be painted on the plot canvas, - or only affects the scales of the plot widget. They can be categorized as: - - - Representator\n - A "Representator" is an item that represents some sort of data - on the plot canvas. The different representator classes are organized - according to the characteristics of the data: - - QwtPlotMarker - Represents a point or a horizontal/vertical coordinate - - QwtPlotCurve - Represents a series of points - - QwtPlotSpectrogram ( QwtPlotRasterItem ) - Represents raster data - - ... - - - Decorators\n - A "Decorator" is an item, that displays additional information, that - is not related to any data: - - QwtPlotGrid - - QwtPlotScaleItem - - QwtPlotSvgItem - - ... - - Depending on the QwtPlotItem::ItemAttribute flags, an item is included - into autoscaling or has an entry on the legend. - - Before misusing the existing item classes it might be better to - 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. - - \sa The cpuplot example shows the implementation of additional plot items. -*/ - -class QWT_EXPORT QwtPlotItem -{ -public: - /*! - \brief Runtime type information - - RttiValues is used to cast plot items, without - having to enable runtime type information of the compiler. - */ - enum RttiValues - { - //! Unspecific value, that can be used, when it doesn't matter - Rtti_PlotItem = 0, - - //! For QwtPlotGrid - Rtti_PlotGrid, - - //! For QwtPlotScaleItem - Rtti_PlotScale, - - //! For QwtPlotLegendItem - Rtti_PlotLegend, - - //! For QwtPlotMarker - Rtti_PlotMarker, - - //! For QwtPlotCurve - Rtti_PlotCurve, - - //! For QwtPlotSpectroCurve - Rtti_PlotSpectroCurve, - - //! For QwtPlotIntervalCurve - Rtti_PlotIntervalCurve, - - //! For QwtPlotHistogram - Rtti_PlotHistogram, - - //! For QwtPlotSpectrogram - Rtti_PlotSpectrogram, - - //! For QwtPlotSvgItem - Rtti_PlotSVG, - - //! For QwtPlotTradingCurve - Rtti_PlotTradingCurve, - - //! For QwtPlotBarChart - Rtti_PlotBarChart, - - //! For QwtPlotMultiBarChart - Rtti_PlotMultiBarChart, - - //! For QwtPlotShapeItem - Rtti_PlotShape, - - //! For QwtPlotTextLabel - Rtti_PlotTextLabel, - - //! For QwtPlotZoneItem - Rtti_PlotZone, - - /*! - Values >= Rtti_PlotUserItem are reserved for plot items - not implemented in the Qwt library. - */ - Rtti_PlotUserItem = 1000 - }; - - /*! - \brief Plot Item Attributes - - Various aspects of a plot widget depend on the attributes of - the attached plot items. If and how a single plot item - participates in these updates depends on its attributes. - - \sa setItemAttribute(), testItemAttribute(), ItemInterest - */ - enum ItemAttribute - { - //! The item is represented on the legend. - Legend = 0x01, - - /*! - The boundingRect() of the item is included in the - autoscaling calculation as long as its width or height - is >= 0.0. - */ - AutoScale = 0x02, - - /*! - The item needs extra space to display something outside - its bounding rectangle. - \sa getCanvasMarginHint() - */ - Margins = 0x04 - }; - - //! Plot Item Attributes - typedef QFlags<ItemAttribute> ItemAttributes; - - /*! - \brief Plot Item Interests - - Plot items might depend on the situation of the corresponding - plot widget. By enabling an interest the plot item will be - notified, when the corresponding attribute of the plot widgets - has changed. - - \sa setItemAttribute(), testItemAttribute(), ItemInterest - */ - enum ItemInterest - { - /*! - The item is interested in updates of the scales - \sa updateScaleDiv() - */ - ScaleInterest = 0x01, - - /*! - The item is interested in updates of the legend ( of other items ) - This flag is intended for items, that want to implement a legend - for displaying entries of other plot item. - - \note If the plot item wants to be represented on a legend - enable QwtPlotItem::Legend instead. - - \sa updateLegend() - */ - LegendInterest = 0x02 - }; - - //! Plot Item Interests - typedef QFlags<ItemInterest> ItemInterests; - - //! Render hints - enum RenderHint - { - //! Enable antialiasing - RenderAntialiased = 0x1 - }; - - //! Render hints - typedef QFlags<RenderHint> RenderHints; - - explicit QwtPlotItem( const QwtText &title = QwtText() ); - virtual ~QwtPlotItem(); - - void attach( QwtPlot *plot ); - void detach(); - - QwtPlot *plot() const; - - 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 setItemInterest( ItemInterest, bool on = true ); - bool testItemInterest( ItemInterest ) const; - - void setRenderHint( RenderHint, bool on = true ); - bool testRenderHint( RenderHint ) const; - - void setRenderThreadCount( uint numThreads ); - uint renderThreadCount() const; - - void setLegendIconSize( const QSize & ); - QSize legendIconSize() const; - - double z() const; - void setZ( double z ); - - void show(); - void hide(); - virtual void setVisible( bool ); - bool isVisible () const; - - void setAxes( int xAxis, int yAxis ); - - void setXAxis( int axis ); - int xAxis() const; - - void setYAxis( int axis ); - int yAxis() const; - - virtual void itemChanged(); - virtual void legendChanged(); - - /*! - \brief Draw the item - - \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 in painter coordinates - */ - virtual void draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const = 0; - - virtual QRectF boundingRect() const; - - virtual void getCanvasMarginHint( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasSize, - double &left, double &top, double &right, double &bottom) const; - - virtual void updateScaleDiv( - const QwtScaleDiv&, const QwtScaleDiv& ); - - virtual void updateLegend( const QwtPlotItem *, - const QList<QwtLegendData> & ); - - QRectF scaleRect( const QwtScaleMap &, const QwtScaleMap & ) const; - QRectF paintRect( const QwtScaleMap &, const QwtScaleMap & ) const; - - virtual QList<QwtLegendData> legendData() const; - - virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; - -protected: - QwtGraphic defaultIcon( const QBrush &, const QSizeF & ) const; - -private: - // Disabled copy constructor and operator= - QwtPlotItem( const QwtPlotItem & ); - QwtPlotItem &operator=( const QwtPlotItem & ); - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::ItemAttributes ) -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::ItemInterests ) -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::RenderHints ) - -Q_DECLARE_METATYPE( QwtPlotItem * ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_layout.h b/include/pli_vis/third_party/qwt/qwt_plot_layout.h deleted file mode 100644 index dc31b6105b6e973b733bca72df5ffca813127e6e..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_layout.h +++ /dev/null @@ -1,122 +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_PLOT_LAYOUT_H -#define QWT_PLOT_LAYOUT_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot.h" - -/*! - \brief Layout engine for QwtPlot. - - It is used by the QwtPlot widget to organize its internal widgets - or by QwtPlot::print() to render its content to a QPaintDevice like - a QPrinter, QPixmap/QImage or QSvgRenderer. - - \sa QwtPlot::setPlotLayout() -*/ - -class QWT_EXPORT QwtPlotLayout -{ -public: - /*! - Options to configure the plot layout engine - \sa activate(), QwtPlotRenderer - */ - enum Option - { - //! 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, - - //! Ignore the title. - IgnoreTitle = 0x10, - - //! Ignore the footer. - IgnoreFooter = 0x20 - }; - - //! Layout options - typedef QFlags<Option> Options; - - explicit QwtPlotLayout(); - virtual ~QwtPlotLayout(); - - void setCanvasMargin( int margin, int axis = -1 ); - int canvasMargin( int axis ) const; - - void setAlignCanvasToScales( bool ); - - void setAlignCanvasToScale( int axisId, bool ); - bool alignCanvasToScale( int axisId ) const; - - void setSpacing( int ); - int spacing() const; - - void setLegendPosition( QwtPlot::LegendPosition pos, double ratio ); - void setLegendPosition( QwtPlot::LegendPosition pos ); - QwtPlot::LegendPosition legendPosition() const; - - void setLegendRatio( double ratio ); - double legendRatio() const; - - virtual QSize minimumSizeHint( const QwtPlot * ) const; - - virtual void activate( const QwtPlot *, - const QRectF &rect, Options options = 0x00 ); - - virtual void invalidate(); - - QRectF titleRect() const; - QRectF footerRect() const; - QRectF legendRect() const; - QRectF scaleRect( int axis ) const; - QRectF canvasRect() const; - - class LayoutData; - -protected: - - void setTitleRect( const QRectF & ); - void setFooterRect( const QRectF & ); - void setLegendRect( const QRectF & ); - void setScaleRect( int axis, const QRectF & ); - void setCanvasRect( const QRectF & ); - - QRectF layoutLegend( Options options, const QRectF & ) const; - QRectF alignLegend( const QRectF &canvasRect, - const QRectF &legendRect ) const; - - void expandLineBreaks( Options options, const QRectF &rect, - int &dimTitle, int &dimFooter, int dimAxes[QwtPlot::axisCnt] ) const; - - void alignScales( Options options, QRectF &canvasRect, - QRectF scaleRect[QwtPlot::axisCnt] ) const; - -private: - class PrivateData; - - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotLayout::Options ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_legenditem.h b/include/pli_vis/third_party/qwt/qwt_plot_legenditem.h deleted file mode 100644 index 81e90b74a8c00497fe55c61eda05d87eb76f9d98..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_legenditem.h +++ /dev/null @@ -1,136 +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_PLOT_LEGEND_ITEM_H -#define QWT_PLOT_LEGEND_ITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_legend_data.h" - -class QFont; - -/*! - \brief A class which draws a legend inside the plot canvas - - QwtPlotLegendItem can be used to draw a inside the plot canvas. - It can be used together with a QwtLegend or instead of it - to have more space for the plot canvas. - - In opposite to QwtLegend the legend item is not interactive. - To identify mouse clicks on a legend item an event filter - needs to be installed catching mouse events ob the plot canvas. - The geometries of the legend items are available using - legendGeometries(). - - The legend item is aligned to plot canvas according to - its alignment() flags. It might have a background for the - complete legend ( usually semi transparent ) or for - each legend item. - - \note An external QwtLegend with a transparent background - on top the plot canvas might be another option - with a similar effect. -*/ - -class QWT_EXPORT QwtPlotLegendItem: public QwtPlotItem -{ -public: - /*! - \brief Background mode - - Depending on the mode the complete legend or each item - might have an background. - - The default setting is LegendBackground. - - \sa setBackgroundMode(), setBackgroundBrush(), drawBackground() - */ - enum BackgroundMode - { - //! The legend has a background - LegendBackground, - - //! Each item has a background - ItemBackground - }; - - explicit QwtPlotLegendItem(); - virtual ~QwtPlotLegendItem(); - - virtual int rtti() const; - - void setAlignment( Qt::Alignment ); - Qt::Alignment alignment() const; - - void setMaxColumns( uint ); - uint maxColumns() const; - - void setMargin( int ); - int margin() const; - - void setSpacing( int ); - int spacing() const; - - void setItemMargin( int ); - int itemMargin() const; - - void setItemSpacing( int ); - int itemSpacing() const; - - void setFont( const QFont& ); - QFont font() const; - - void setBorderDistance( int numPixels ); - int borderDistance() const; - - void setBorderRadius( double ); - double borderRadius() const; - - void setBorderPen( const QPen & ); - QPen borderPen() const; - - void setBackgroundBrush( const QBrush & ); - QBrush backgroundBrush() const; - - void setBackgroundMode( BackgroundMode ); - BackgroundMode backgroundMode() const; - - void setTextPen( const QPen & ); - QPen textPen() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - - void clearLegend(); - - virtual void updateLegend( const QwtPlotItem *, - const QList<QwtLegendData> & ); - - virtual QRect geometry( const QRectF &canvasRect ) const; - - virtual QSize minimumSize( const QwtLegendData & ) const; - virtual int heightForWidth( const QwtLegendData &, int w ) const; - - QList< const QwtPlotItem * > plotItems() const; - QList< QRect > legendGeometries( const QwtPlotItem * ) const; - -protected: - virtual void drawLegendData( QPainter *painter, - const QwtPlotItem *, const QwtLegendData &, const QRectF & ) const; - - virtual void drawBackground( QPainter *, const QRectF &rect ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_magnifier.h b/include/pli_vis/third_party/qwt/qwt_plot_magnifier.h deleted file mode 100644 index 96d01f261ef7e924fcf2e0407c3cfe6e42549b99..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_magnifier.h +++ /dev/null @@ -1,54 +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_PLOT_MAGNIFIER_H -#define QWT_PLOT_MAGNIFIER_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_magnifier.h" - -class QwtPlot; - -/*! - \brief QwtPlotMagnifier provides zooming, by magnifying in steps. - - Using QwtPlotMagnifier a plot can be zoomed in/out in steps using - keys, the mouse wheel or moving a mouse button in vertical direction. - - Together with QwtPlotZoomer and QwtPlotPanner it is possible to implement - individual and powerful navigation of the plot canvas. - - \sa QwtPlotZoomer, QwtPlotPanner, QwtPlot -*/ -class QWT_EXPORT QwtPlotMagnifier: public QwtMagnifier -{ - Q_OBJECT - -public: - explicit QwtPlotMagnifier( QWidget * ); - virtual ~QwtPlotMagnifier(); - - void setAxisEnabled( int axis, bool on ); - bool isAxisEnabled( int axis ) const; - - QWidget *canvas(); - const QWidget *canvas() const; - - QwtPlot *plot(); - const QwtPlot *plot() const; - -protected: - virtual void rescale( double factor ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_marker.h b/include/pli_vis/third_party/qwt/qwt_plot_marker.h deleted file mode 100644 index 9fab1edc6e316a53d5d85862019b8c26efcff1c7..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_marker.h +++ /dev/null @@ -1,130 +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_PLOT_MARKER_H -#define QWT_PLOT_MARKER_H - -#include <qpen.h> -#include <qfont.h> -#include <qstring.h> -#include <qbrush.h> -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" - -class QRectF; -class QwtText; -class QwtSymbol; - -/*! - \brief A class for drawing markers - - A marker can be a horizontal line, a vertical line, - a symbol, a label or any combination of them, which can - be drawn around a center point inside a bounding rectangle. - - The setSymbol() member assigns a symbol to the marker. - The symbol is drawn at the specified point. - - With setLabel(), a label can be assigned to the marker. - The setLabelAlignment() member specifies where the label is - drawn. All the Align*-constants in Qt::AlignmentFlags (see Qt documentation) - are valid. The interpretation of the alignment depends on the marker's - line style. The alignment refers to the center point of - the marker, which means, for example, that the label would be printed - left above the center point if the alignment was set to - Qt::AlignLeft | Qt::AlignTop. - - \note QwtPlotTextLabel is intended to align a text label - according to the geometry of canvas - ( unrelated to plot coordinates ) -*/ - -class QWT_EXPORT QwtPlotMarker: public QwtPlotItem -{ -public: - - /*! - Line styles. - \sa setLineStyle(), lineStyle() - */ - enum LineStyle - { - //! No line - NoLine, - - //! A horizontal line - HLine, - - //! A vertical line - VLine, - - //! A crosshair - Cross - }; - - explicit QwtPlotMarker( const QString &title = QString::null ); - explicit QwtPlotMarker( const QwtText &title ); - - virtual ~QwtPlotMarker(); - - virtual int rtti() const; - - double xValue() const; - double yValue() const; - QPointF value() const; - - void setXValue( double ); - void setYValue( double ); - void setValue( double, double ); - void setValue( const QPointF & ); - - void setLineStyle( LineStyle st ); - LineStyle lineStyle() const; - - void setLinePen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setLinePen( const QPen &p ); - const QPen &linePen() const; - - void setSymbol( const QwtSymbol * ); - const QwtSymbol *symbol() const; - - void setLabel( const QwtText& ); - QwtText label() const; - - void setLabelAlignment( Qt::Alignment ); - Qt::Alignment labelAlignment() const; - - void setLabelOrientation( Qt::Orientation ); - Qt::Orientation labelOrientation() const; - - void setSpacing( int ); - int spacing() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF & ) const; - - virtual QRectF boundingRect() const; - - virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; - -protected: - virtual void drawLines( QPainter *, - const QRectF &, const QPointF & ) const; - - virtual void drawLabel( QPainter *, - const QRectF &, const QPointF & ) const; - -private: - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_multi_barchart.h b/include/pli_vis/third_party/qwt/qwt_plot_multi_barchart.h deleted file mode 100644 index acade4910c7c636111ba909f4fad4219d0bc196e..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_multi_barchart.h +++ /dev/null @@ -1,127 +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_PLOT_MULTI_BAR_CHART_H -#define QWT_PLOT_MULTI_BAR_CHART_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_abstract_barchart.h" -#include "qwt/qwt_series_data.h" - -class QwtColumnRect; -class QwtColumnSymbol; - -/*! - \brief QwtPlotMultiBarChart displays a series of a samples that consist - each of a set of values. - - Each value is displayed as a bar, the bars of each set can be organized - side by side or accumulated. - - Each bar of a set is rendered by a QwtColumnSymbol, that is set by setSymbol(). - The bars of different sets use the same symbols. Exceptions are possible - by overloading specialSymbol() or overloading drawBar(). - - Depending on its orientation() the bars are displayed horizontally - or vertically. The bars cover the interval between the baseline() - and the value. - - In opposite to most other plot items, QwtPlotMultiBarChart returns more - than one entry for the legend - one for each symbol. - - \sa QwtPlotBarChart, QwtPlotHistogram - QwtPlotSeriesItem::orientation(), QwtPlotAbstractBarChart::baseline() - */ -class QWT_EXPORT QwtPlotMultiBarChart: - public QwtPlotAbstractBarChart, public QwtSeriesStore<QwtSetSample> -{ -public: - /*! - \brief Chart styles. - - The default setting is QwtPlotMultiBarChart::Grouped. - \sa setStyle(), style() - */ - enum ChartStyle - { - //! The bars of a set are displayed side by side - Grouped, - - /*! - The bars are displayed on top of each other accumulating - to a single bar. All values of a set need to have the same - sign. - */ - Stacked - }; - - explicit QwtPlotMultiBarChart( const QString &title = QString::null ); - explicit QwtPlotMultiBarChart( const QwtText &title ); - - virtual ~QwtPlotMultiBarChart(); - - virtual int rtti() const; - - void setBarTitles( const QList<QwtText> & ); - QList<QwtText> barTitles() const; - - void setSamples( const QVector<QwtSetSample> & ); - void setSamples( const QVector< QVector<double> > & ); - void setSamples( QwtSeriesData<QwtSetSample> * ); - - void setStyle( ChartStyle style ); - ChartStyle style() const; - - void setSymbol( int barIndex, QwtColumnSymbol *symbol ); - const QwtColumnSymbol *symbol( int barIndex ) const; - - void resetSymbolMap(); - - virtual void drawSeries( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual QRectF boundingRect() const; - - virtual QList<QwtLegendData> legendData() const; - - virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; - -protected: - QwtColumnSymbol *symbol( int barIndex ); - - virtual QwtColumnSymbol *specialSymbol( - int sampleIndex, int valueIndex ) const; - - virtual void drawSample( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, const QwtInterval &boundingInterval, - int index, const QwtSetSample& sample ) const; - - virtual void drawBar( QPainter *, int sampleIndex, - int barIndex, const QwtColumnRect & ) const; - - void drawStackedBars( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int index, - double sampleWidth, const QwtSetSample& sample ) const; - - void drawGroupedBars( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int index, - double sampleWidth, const QwtSetSample& sample ) const; - -private: - void init(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_panner.h b/include/pli_vis/third_party/qwt/qwt_plot_panner.h deleted file mode 100644 index b7e392055ab545c9f4b7ea81ed242579ee7da98b..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_panner.h +++ /dev/null @@ -1,60 +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_PLOT_PANNER_H -#define QWT_PLOT_PANNER_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_panner.h" - -class QwtPlot; - -/*! - \brief QwtPlotPanner provides panning of a plot canvas - - QwtPlotPanner is a panner for a plot canvas, that - adjusts the scales of the axes after dropping - the canvas on its new position. - - Together with QwtPlotZoomer and QwtPlotMagnifier powerful ways - of navigating on a QwtPlot widget can be implemented easily. - - \note The axes are not updated, while dragging the canvas - \sa QwtPlotZoomer, QwtPlotMagnifier -*/ -class QWT_EXPORT QwtPlotPanner: public QwtPanner -{ - Q_OBJECT - -public: - explicit QwtPlotPanner( QWidget * ); - virtual ~QwtPlotPanner(); - - QWidget *canvas(); - const QWidget *canvas() const; - - QwtPlot *plot(); - const QwtPlot *plot() const; - - void setAxisEnabled( int axis, bool on ); - bool isAxisEnabled( int axis ) const; - -protected Q_SLOTS: - virtual void moveCanvas( int dx, int dy ); - -protected: - virtual QBitmap contentsMask() const; - virtual QPixmap grab() const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_picker.h b/include/pli_vis/third_party/qwt/qwt_plot_picker.h deleted file mode 100644 index d48e89f3ed9b670e69f1b22903aa191c60fadda6..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_picker.h +++ /dev/null @@ -1,111 +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_PLOT_PICKER_H -#define QWT_PLOT_PICKER_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_picker.h" -#include <qvector.h> - -class QwtPlot; - -/*! - \brief QwtPlotPicker provides selections on a plot canvas - - QwtPlotPicker is a QwtPicker tailored for selections on - a plot canvas. It is set to a x-Axis and y-Axis and - translates all pixel coordinates into this coordinate system. -*/ - -class QWT_EXPORT QwtPlotPicker: public QwtPicker -{ - Q_OBJECT - -public: - explicit QwtPlotPicker( QWidget *canvas ); - virtual ~QwtPlotPicker(); - - explicit QwtPlotPicker( int xAxis, int yAxis, QWidget * ); - - explicit QwtPlotPicker( int xAxis, int yAxis, - RubberBand rubberBand, DisplayMode trackerMode, QWidget * ); - - virtual void setAxis( int xAxis, int yAxis ); - - int xAxis() const; - int yAxis() const; - - QwtPlot *plot(); - const QwtPlot *plot() const; - - QWidget *canvas(); - const QWidget *canvas() const; - -Q_SIGNALS: - - /*! - A signal emitted in case of QwtPickerMachine::PointSelection. - \param pos Selected point - */ - void selected( const QPointF &pos ); - - /*! - A signal emitted in case of QwtPickerMachine::RectSelection. - \param rect Selected rectangle - */ - void selected( const QRectF &rect ); - - /*! - A signal emitting the selected points, - at the end of a selection. - - \param pa Selected points - */ - void selected( const QVector<QPointF> &pa ); - - /*! - A signal emitted when a point has been appended to the selection - - \param pos Position of the appended point. - \sa append(). moved() - */ - void appended( const QPointF &pos ); - - /*! - 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 QPointF &pos ); - -protected: - QRectF scaleRect() const; - - QRectF invTransform( const QRect & ) const; - QRect transform( const QRectF & ) const; - - QPointF invTransform( const QPoint & ) const; - QPoint transform( const QPointF & ) const; - - virtual QwtText trackerText( const QPoint & ) const; - virtual QwtText trackerTextF( const QPointF & ) const; - - virtual void move( const QPoint & ); - virtual void append( const QPoint & ); - virtual bool end( bool ok = true ); - -private: - int d_xAxis; - int d_yAxis; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_rasteritem.h b/include/pli_vis/third_party/qwt/qwt_plot_rasteritem.h deleted file mode 100644 index 5409aa9cf4b71fabf9c7957a850a63217867a2a4..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_rasteritem.h +++ /dev/null @@ -1,152 +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_PLOT_RASTERITEM_H -#define QWT_PLOT_RASTERITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_interval.h" -#include <qglobal.h> -#include <qstring.h> -#include <qimage.h> - -/*! - \brief A class, which displays raster data - - Raster data is a grid of pixel values, that can be represented - as a QImage. It is used for many types of information like - spectrograms, cartograms, geographical maps ... - - Often a plot has several types of raster data organized in layers. - ( f.e a geographical map, with weather statistics ). - Using setAlpha() raster items can be stacked easily. - - QwtPlotRasterItem is only implemented for images of the following formats: - QImage::Format_Indexed8, QImage::Format_ARGB32. - - \sa QwtPlotSpectrogram -*/ - -class QWT_EXPORT QwtPlotRasterItem: public QwtPlotItem -{ -public: - /*! - \brief Cache policy - The default policy is NoCache - */ - enum CachePolicy - { - /*! - renderImage() is called each time the item has to be repainted - */ - NoCache, - - /*! - renderImage() is called, whenever the image cache is not valid, - or the scales, or the size of the canvas has changed. - - This type of cache is useful for improving the performance - of hide/show operations or manipulations of the alpha value. - All other situations are handled by the canvas backing store. - */ - PaintCache - }; - - /*! - Attributes to modify the drawing algorithm. - \sa setPaintAttribute(), testPaintAttribute() - */ - enum PaintAttribute - { - /*! - When the image is rendered according to the data pixels - ( QwtRasterData::pixelHint() ) it can be expanded to paint - device resolution before it is passed to QPainter. - The expansion algorithm rounds the pixel borders in the same - way as the axis ticks, what is usually better than the - scaling algorithm implemented in Qt. - Disabling this flag might make sense, to reduce the size of a - document/file. If this is possible for a document format - depends on the implementation of the specific QPaintEngine. - */ - - PaintInDeviceResolution = 1 - }; - - //! Paint attributes - typedef QFlags<PaintAttribute> PaintAttributes; - - explicit QwtPlotRasterItem( const QString& title = QString::null ); - explicit QwtPlotRasterItem( const QwtText& title ); - virtual ~QwtPlotRasterItem(); - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - void setAlpha( int alpha ); - int alpha() const; - - void setCachePolicy( CachePolicy ); - CachePolicy cachePolicy() const; - - void invalidateCache(); - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - - virtual QRectF pixelHint( const QRectF & ) const; - - virtual QwtInterval interval(Qt::Axis) const; - virtual QRectF boundingRect() const; - -protected: - /*! - \brief Render an image - - An implementation of render() might iterate over all - pixels of imageRect. Each pixel has to be translated into - the corresponding position in scale coordinates using the maps. - This position can be used to look up a value in a implementation - specific way and to map it into a color. - - \param xMap X-Scale Map - \param yMap Y-Scale Map - \param area Requested area for the image in scale coordinates - \param imageSize Requested size of the image - - \return Rendered image - */ - virtual QImage renderImage( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRectF &area, - const QSize &imageSize ) const = 0; - - virtual QwtScaleMap imageMap( Qt::Orientation, - const QwtScaleMap &map, const QRectF &area, - const QSize &imageSize, double pixelSize) const; - -private: - QwtPlotRasterItem( const QwtPlotRasterItem & ); - QwtPlotRasterItem &operator=( const QwtPlotRasterItem & ); - - void init(); - - QImage compose( const QwtScaleMap &, const QwtScaleMap &, - const QRectF &imageArea, const QRectF &paintRect, - const QSize &imageSize, bool doCache) const; - - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotRasterItem::PaintAttributes ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_renderer.h b/include/pli_vis/third_party/qwt/qwt_plot_renderer.h deleted file mode 100644 index 080654e1bfc22d9d4f0eb2e3778ba315c9dfc0e6..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_renderer.h +++ /dev/null @@ -1,170 +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_PLOT_RENDERER_H -#define QWT_PLOT_RENDERER_H - -#include "qwt/qwt_global.h" -#include <qobject.h> -#include <qsize.h> - -class QwtPlot; -class QwtScaleMap; -class QRectF; -class QPainter; -class QPaintDevice; - -#ifndef QT_NO_PRINTER -class QPrinter; -#endif - -#ifndef QWT_NO_SVG -#ifdef QT_SVG_LIB -class QSvgGenerator; -#endif -#endif - -/*! - \brief Renderer for exporting a plot to a document, a printer - or anything else, that is supported by QPainter/QPaintDevice -*/ -class QWT_EXPORT QwtPlotRenderer: public QObject -{ - Q_OBJECT - -public: - //! Disard flags - enum DiscardFlag - { - //! Render all components of the plot - DiscardNone = 0x00, - - //! Don't render the background of the plot - DiscardBackground = 0x01, - - //! Don't render the title of the plot - DiscardTitle = 0x02, - - //! Don't render the legend of the plot - DiscardLegend = 0x04, - - //! Don't render the background of the canvas - DiscardCanvasBackground = 0x08, - - //! Don't render the footer of the plot - DiscardFooter = 0x10, - - /*! - Don't render the frame of the canvas - - \note This flag has no effect when using - style sheets, where the frame is part - of the background - */ - DiscardCanvasFrame = 0x20 - - }; - - //! Disard flags - typedef QFlags<DiscardFlag> DiscardFlags; - - /*! - \brief Layout flags - \sa setLayoutFlag(), testLayoutFlag() - */ - enum LayoutFlag - { - //! Use the default layout as on screen - DefaultLayout = 0x00, - - /*! - Instead of the scales a box is painted around the plot canvas, - where the scale ticks are aligned to. - */ - FrameWithScales = 0x01 - }; - - //! Layout flags - typedef QFlags<LayoutFlag> LayoutFlags; - - explicit QwtPlotRenderer( QObject * = NULL ); - virtual ~QwtPlotRenderer(); - - void setDiscardFlag( DiscardFlag flag, bool on = true ); - bool testDiscardFlag( DiscardFlag flag ) const; - - void setDiscardFlags( DiscardFlags flags ); - DiscardFlags discardFlags() const; - - void setLayoutFlag( LayoutFlag flag, bool on = true ); - bool testLayoutFlag( LayoutFlag flag ) const; - - void setLayoutFlags( LayoutFlags flags ); - LayoutFlags layoutFlags() const; - - void renderDocument( QwtPlot *, const QString &fileName, - const QSizeF &sizeMM, int resolution = 85 ); - - void renderDocument( QwtPlot *, - const QString &fileName, const QString &format, - const QSizeF &sizeMM, int resolution = 85 ); - -#ifndef QWT_NO_SVG -#ifdef QT_SVG_LIB -#if QT_VERSION >= 0x040500 - void renderTo( QwtPlot *, QSvgGenerator & ) const; -#endif -#endif -#endif - -#ifndef QT_NO_PRINTER - void renderTo( QwtPlot *, QPrinter & ) const; -#endif - - void renderTo( QwtPlot *, QPaintDevice &p ) const; - - virtual void render( QwtPlot *, - QPainter *, const QRectF &rect ) const; - - virtual void renderTitle( const QwtPlot *, - QPainter *, const QRectF & ) const; - - virtual void renderFooter( const QwtPlot *, - QPainter *, const QRectF & ) const; - - virtual void renderScale( const QwtPlot *, QPainter *, - int axisId, int startDist, int endDist, - int baseDist, const QRectF & ) const; - - virtual void renderCanvas( const QwtPlot *, - QPainter *, const QRectF &canvasRect, - const QwtScaleMap* maps ) const; - - virtual void renderLegend( - const QwtPlot *, QPainter *, const QRectF & ) const; - - bool exportTo( QwtPlot *, const QString &documentName, - const QSizeF &sizeMM = QSizeF( 300, 200 ), int resolution = 85 ); - -private: - void buildCanvasMaps( const QwtPlot *, - const QRectF &, QwtScaleMap maps[] ) const; - - bool updateCanvasMargins( QwtPlot *, - const QRectF &, const QwtScaleMap maps[] ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotRenderer::DiscardFlags ) -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotRenderer::LayoutFlags ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_rescaler.h b/include/pli_vis/third_party/qwt/qwt_plot_rescaler.h deleted file mode 100644 index 1cd9099a7fc28cbebcf304441768e3cfcec253bc..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_rescaler.h +++ /dev/null @@ -1,142 +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_PLOT_RESCALER_H -#define QWT_PLOT_RESCALER_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include "qwt/qwt_plot.h" -#include <qobject.h> - -class QwtPlot; -class QResizeEvent; - -/*! - \brief QwtPlotRescaler takes care of fixed aspect ratios for plot scales - - QwtPlotRescaler auto adjusts the axes of a QwtPlot according - to fixed aspect ratios. -*/ - -class QWT_EXPORT QwtPlotRescaler: public QObject -{ -public: - /*! - The rescale policy defines how to rescale the reference axis and - their depending axes. - - \sa ExpandingDirection, setIntervalHint() - */ - enum RescalePolicy - { - /*! - The interval of the reference axis remains unchanged, when the - geometry of the canvas changes. All other axes - will be adjusted according to their aspect ratio. - */ - Fixed, - - /*! - The interval of the reference axis will be shrunk/expanded, - when the geometry of the canvas changes. All other axes - will be adjusted according to their aspect ratio. - - The interval, that is represented by one pixel is fixed. - - */ - Expanding, - - /*! - The intervals of the axes are calculated, so that all axes include - their interval hint. - */ - Fitting - }; - - /*! - When rescalePolicy() is set to Expanding its direction depends - on ExpandingDirection - */ - enum ExpandingDirection - { - //! The upper limit of the scale is adjusted - ExpandUp, - - //! The lower limit of the scale is adjusted - ExpandDown, - - //! Both limits of the scale are adjusted - ExpandBoth - }; - - explicit QwtPlotRescaler( QWidget *canvas, - int referenceAxis = QwtPlot::xBottom, - RescalePolicy = Expanding ); - - virtual ~QwtPlotRescaler(); - - void setEnabled( bool ); - bool isEnabled() const; - - void setRescalePolicy( RescalePolicy ); - RescalePolicy rescalePolicy() const; - - void setExpandingDirection( ExpandingDirection ); - void setExpandingDirection( int axis, ExpandingDirection ); - ExpandingDirection expandingDirection( int axis ) const; - - void setReferenceAxis( int axis ); - int referenceAxis() const; - - void setAspectRatio( double ratio ); - void setAspectRatio( int axis, double ratio ); - double aspectRatio( int axis ) const; - - void setIntervalHint( int axis, const QwtInterval& ); - QwtInterval intervalHint( int axis ) const; - - QWidget *canvas(); - const QWidget *canvas() const; - - QwtPlot *plot(); - const QwtPlot *plot() const; - - virtual bool eventFilter( QObject *, QEvent * ); - - void rescale() const; - -protected: - virtual void canvasResizeEvent( QResizeEvent * ); - - virtual void rescale( const QSize &oldSize, const QSize &newSize ) const; - virtual QwtInterval expandScale( - int axis, const QSize &oldSize, const QSize &newSize ) const; - - virtual QwtInterval syncScale( - int axis, const QwtInterval& reference, - const QSize &size ) const; - - virtual void updateScales( - QwtInterval intervals[QwtPlot::axisCnt] ) const; - - Qt::Orientation orientation( int axis ) const; - QwtInterval interval( int axis ) const; - QwtInterval expandInterval( const QwtInterval &, - double width, ExpandingDirection ) const; - -private: - double pixelDist( int axis, const QSize & ) const; - - class AxisData; - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_scaleitem.h b/include/pli_vis/third_party/qwt/qwt_plot_scaleitem.h deleted file mode 100644 index c67a5fd20233eacf0bee15e5c8d23abed8d69832..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_scaleitem.h +++ /dev/null @@ -1,94 +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_PLOT_SCALE_ITEM_H -#define QWT_PLOT_SCALE_ITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_scale_draw.h" - -class QPalette; - -/*! - \brief A class which draws a scale inside the plot canvas - - QwtPlotScaleItem can be used to draw an axis inside the plot canvas. - It might by synchronized to one of the axis of the plot, but can - also display its own ticks and labels. - - It is allowed to synchronize the scale item with a disabled axis. - In plots with vertical and horizontal scale items, it might be - necessary to remove ticks at the intersections, by overloading - updateScaleDiv(). - - The scale might be at a specific position (f.e 0.0) or it might be - aligned to a canvas border. - - \par Example - The following example shows how to replace the left axis, by a scale item - at the x position 0.0. - \verbatim -QwtPlotScaleItem *scaleItem = - new QwtPlotScaleItem(QwtScaleDraw::RightScale, 0.0); -scaleItem->setFont(plot->axisWidget(QwtPlot::yLeft)->font()); -scaleItem->attach(plot); - -plot->enableAxis(QwtPlot::yLeft, false); -\endverbatim -*/ - -class QWT_EXPORT QwtPlotScaleItem: public QwtPlotItem -{ -public: - explicit QwtPlotScaleItem( - QwtScaleDraw::Alignment = QwtScaleDraw::BottomScale, - const double pos = 0.0 ); - - virtual ~QwtPlotScaleItem(); - - virtual int rtti() const; - - void setScaleDiv( const QwtScaleDiv& ); - const QwtScaleDiv& scaleDiv() const; - - void setScaleDivFromAxis( bool on ); - bool isScaleDivFromAxis() const; - - void setPalette( const QPalette & ); - QPalette palette() const; - - void setFont( const QFont& ); - QFont font() const; - - void setScaleDraw( QwtScaleDraw * ); - - const QwtScaleDraw *scaleDraw() const; - QwtScaleDraw *scaleDraw(); - - void setPosition( double pos ); - double position() const; - - void setBorderDistance( int numPixels ); - int borderDistance() const; - - void setAlignment( QwtScaleDraw::Alignment ); - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - - virtual void updateScaleDiv( const QwtScaleDiv &, const QwtScaleDiv & ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_seriesitem.h b/include/pli_vis/third_party/qwt/qwt_plot_seriesitem.h deleted file mode 100644 index 7df3aad9ee374c68844ca2244946b7a79b5cadf0..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_seriesitem.h +++ /dev/null @@ -1,66 +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_PLOT_SERIES_ITEM_H -#define QWT_PLOT_SERIES_ITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_series_data.h" -#include "qwt/qwt_series_store.h" - -/*! - \brief Base class for plot items representing a series of samples -*/ -class QWT_EXPORT QwtPlotSeriesItem: public QwtPlotItem, - public virtual QwtAbstractSeriesStore -{ -public: - explicit QwtPlotSeriesItem( const QString &title = QString::null ); - explicit QwtPlotSeriesItem( const QwtText &title ); - - virtual ~QwtPlotSeriesItem(); - - void setOrientation( Qt::Orientation ); - Qt::Orientation orientation() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF & ) const; - - /*! - 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 rectangle 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. - */ - virtual void drawSeries( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const = 0; - - virtual QRectF boundingRect() const; - - virtual void updateScaleDiv( - const QwtScaleDiv &, const QwtScaleDiv & ); - -protected: - virtual void dataChanged(); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_shapeitem.h b/include/pli_vis/third_party/qwt/qwt_plot_shapeitem.h deleted file mode 100644 index 006f885c84cdab7744735678cf31050f89756a1f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_shapeitem.h +++ /dev/null @@ -1,111 +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_PLOT_SHAPE_ITEM_H -#define QWT_PLOT_SHAPE_ITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include <qpainterpath.h> - -/*! - \brief A plot item, which displays any graphical shape, - that can be defined by a QPainterPath - - A QPainterPath is a shape composed from intersecting and uniting - regions, rectangles, ellipses or irregular areas defined by lines, and curves. - QwtPlotShapeItem displays a shape with a pen and brush. - - QwtPlotShapeItem offers a couple of optimizations like clipping or weeding. - These algorithms need to convert the painter path into polygons that might be - less performant for paths built from curves and ellipses. - - \sa QwtPlotZone -*/ -class QWT_EXPORT QwtPlotShapeItem: public QwtPlotItem -{ -public: - /*! - Attributes to modify the drawing algorithm. - The default disables all attributes - - \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 - - But polygon clipping will convert the painter path into - polygons what might introduce a negative impact on the - performance of paths composed from curves or ellipses. - */ - ClipPolygons = 0x01, - }; - - //! Paint attributes - typedef QFlags<PaintAttribute> PaintAttributes; - - //! Mode how to display the item on the legend - enum LegendMode - { - //! Display a scaled down version of the shape - LegendShape, - - //! Display a filled rectangle - LegendColor - }; - - explicit QwtPlotShapeItem( const QString &title = QString::null ); - explicit QwtPlotShapeItem( const QwtText &title ); - - virtual ~QwtPlotShapeItem(); - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - void setLegendMode( LegendMode ); - LegendMode legendMode() const; - - void setRect( const QRectF & ); - void setPolygon( const QPolygonF & ); - - void setShape( const QPainterPath & ); - QPainterPath shape() const; - - void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setPen( const QPen & ); - QPen pen() const; - - void setBrush( const QBrush & ); - QBrush brush() const; - - void setRenderTolerance( double ); - double renderTolerance() const; - - virtual QRectF boundingRect() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - - virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; - - virtual int rtti() const; - -private: - void init(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_spectrocurve.h b/include/pli_vis/third_party/qwt/qwt_plot_spectrocurve.h deleted file mode 100644 index 2aa69a5a1e74ca0b11a452e26d8228d11f11abd8..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_spectrocurve.h +++ /dev/null @@ -1,79 +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_PLOT_CURVE_3D_H -#define QWT_PLOT_CURVE_3D_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_seriesitem.h" -#include "qwt/qwt_series_data.h" - -class QwtSymbol; -class QwtColorMap; - -/*! - \brief Curve that displays 3D points as dots, where the z coordinate is - mapped to a color. -*/ -class QWT_EXPORT QwtPlotSpectroCurve: - public QwtPlotSeriesItem, QwtSeriesStore<QwtPoint3D> -{ -public: - //! Paint attributes - enum PaintAttribute - { - //! Clip points outside the canvas rectangle - ClipPoints = 1 - }; - - //! Paint attributes - typedef QFlags<PaintAttribute> PaintAttributes; - - explicit QwtPlotSpectroCurve( const QString &title = QString::null ); - explicit QwtPlotSpectroCurve( const QwtText &title ); - - virtual ~QwtPlotSpectroCurve(); - - virtual int rtti() const; - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - void setSamples( const QVector<QwtPoint3D> & ); - void setSamples( QwtSeriesData<QwtPoint3D> * ); - - - void setColorMap( QwtColorMap * ); - const QwtColorMap *colorMap() const; - - void setColorRange( const QwtInterval & ); - QwtInterval & colorRange() const; - - virtual void drawSeries( QPainter *, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - void setPenWidth(double width); - double penWidth() const; - -protected: - virtual void drawDots( QPainter *, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - -private: - void init(); - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotSpectroCurve::PaintAttributes ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_spectrogram.h b/include/pli_vis/third_party/qwt/qwt_plot_spectrogram.h deleted file mode 100644 index 2acca3cd4d38ac53c0ceff241eb6edbfb9dc197a..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_spectrogram.h +++ /dev/null @@ -1,118 +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_PLOT_SPECTROGRAM_H -#define QWT_PLOT_SPECTROGRAM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_raster_data.h" -#include "qwt/qwt_plot_rasteritem.h" -#include <qlist.h> - -class QwtColorMap; - -/*! - \brief A plot item, which displays a spectrogram - - A spectrogram displays 3-dimensional data, where the 3rd dimension - ( the intensity ) is displayed using colors. The colors are calculated - from the values using a color map. - - On multi-core systems the performance of the image composition - can often be improved by dividing the area into tiles - each of them - rendered in a different thread ( see QwtPlotItem::setRenderThreadCount() ). - - In ContourMode contour lines are painted for the contour levels. - - \image html spectrogram3.png - - \sa QwtRasterData, QwtColorMap, QwtPlotItem::setRenderThreadCount() -*/ - -class QWT_EXPORT QwtPlotSpectrogram: public QwtPlotRasterItem -{ -public: - /*! - The display mode controls how the raster data will be represented. - \sa setDisplayMode(), testDisplayMode() - */ - - enum DisplayMode - { - //! The values are mapped to colors using a color map. - ImageMode = 0x01, - - //! The data is displayed using contour lines - ContourMode = 0x02 - }; - - //! Display modes - typedef QFlags<DisplayMode> DisplayModes; - - explicit QwtPlotSpectrogram( const QString &title = QString::null ); - virtual ~QwtPlotSpectrogram(); - - void setDisplayMode( DisplayMode, bool on = true ); - bool testDisplayMode( DisplayMode ) const; - - void setData( QwtRasterData *data ); - const QwtRasterData *data() const; - QwtRasterData *data(); - - void setColorMap( QwtColorMap * ); - const QwtColorMap *colorMap() const; - - virtual QwtInterval interval(Qt::Axis) const; - virtual QRectF pixelHint( const QRectF & ) const; - - void setDefaultContourPen( const QColor &, - qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setDefaultContourPen( const QPen & ); - QPen defaultContourPen() const; - - virtual QPen contourPen( double level ) const; - - void setConrecFlag( QwtRasterData::ConrecFlag, bool on ); - bool testConrecFlag( QwtRasterData::ConrecFlag ) const; - - void setContourLevels( const QList<double> & ); - QList<double> contourLevels() const; - - virtual int rtti() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - -protected: - virtual QImage renderImage( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &area, const QSize &imageSize ) const; - - virtual QSize contourRasterSize( - const QRectF &, const QRect & ) const; - - virtual QwtRasterData::ContourLines renderContourLines( - const QRectF &rect, const QSize &raster ) const; - - virtual void drawContourLines( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtRasterData::ContourLines& lines ) const; - - void renderTile( const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &imageRect, QImage *image ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotSpectrogram::DisplayModes ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_svgitem.h b/include/pli_vis/third_party/qwt/qwt_plot_svgitem.h deleted file mode 100644 index 9d6af167410bf56fdd2272c426d374bac06922a3..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_svgitem.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_PLOT_SVGITEM_H -#define QWT_PLOT_SVGITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include <qstring.h> - -#ifndef QT_NO_SVG - -class QSvgRenderer; -class QByteArray; - -/*! - \brief A plot item, which displays - data in Scalable Vector Graphics (SVG) format. - - SVG images are often used to display maps -*/ - -class QWT_EXPORT QwtPlotSvgItem: public QwtPlotItem -{ -public: - explicit QwtPlotSvgItem( const QString& title = QString::null ); - explicit QwtPlotSvgItem( const QwtText& title ); - virtual ~QwtPlotSvgItem(); - - bool loadFile( const QRectF&, const QString &fileName ); - bool loadData( const QRectF&, const QByteArray & ); - - virtual QRectF boundingRect() const; - - virtual void draw( QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &rect ) const; - - virtual int rtti() const; - -protected: - const QSvgRenderer &renderer() const; - QSvgRenderer &renderer(); - - void render( QPainter *painter, - const QRectF &viewBox, const QRectF &rect ) const; - - QRectF viewBox( const QRectF &area ) const; - -private: - void init(); - - class PrivateData; - PrivateData *d_data; -}; - -#endif - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_textlabel.h b/include/pli_vis/third_party/qwt/qwt_plot_textlabel.h deleted file mode 100644 index 063adf283f336e262a83aeeeefa3e81a7257a5b7..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_textlabel.h +++ /dev/null @@ -1,75 +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_PLOT_TEXT_LABEL_H -#define QWT_PLOT_TEXT_LABEL_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_text.h" - -/*! - \brief A plot item, which displays a text label - - QwtPlotTextLabel displays a text label aligned to the plot canvas. - - In opposite to QwtPlotMarker the position of the label is unrelated to - plot coordinates. - - As drawing a text is an expensive operation the label is cached - in a pixmap to speed up replots. - - \par Example - The following code shows how to add a title. - -\verbatim - QwtText title( "Plot Title" ); - title.setRenderFlags( Qt::AlignHCenter | Qt::AlignTop ); - - QFont font; - font.setBold( true ); - title.setFont( font ); - - QwtPlotTextLabel *titleItem = new QwtPlotTextLabel(); - titleItem->setText( title ); - titleItem->attach( this ); -\endverbatim - - \sa QwtPlotMarker -*/ - -class QWT_EXPORT QwtPlotTextLabel: public QwtPlotItem -{ -public: - QwtPlotTextLabel(); - virtual ~QwtPlotTextLabel(); - - virtual int rtti() const; - - void setText( const QwtText & ); - QwtText text() const; - - void setMargin( int margin ); - int margin() const; - - virtual QRectF textRect( const QRectF &, const QSizeF & ) const; - -protected: - virtual void draw( QPainter *, - const QwtScaleMap &, const QwtScaleMap &, - const QRectF &) const; - - void invalidateCache(); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_tradingcurve.h b/include/pli_vis/third_party/qwt/qwt_plot_tradingcurve.h deleted file mode 100644 index 923a81b58d6e8b716cfe84821a2dd85e3ad87d87..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_tradingcurve.h +++ /dev/null @@ -1,174 +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_PLOT_TRADING_CURVE_H -#define QWT_PLOT_TRADING_CURVE_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_seriesitem.h" -#include "qwt/qwt_series_data.h" - -/*! - \brief QwtPlotTradingCurve illustrates movements in the price of a - financial instrument over time. - - QwtPlotTradingCurve supports candlestick or bar ( OHLC ) charts - that are used in the domain of technical analysis. - - While the length ( height or width depending on orientation() ) - of each symbol depends on the corresponding OHLC sample the size - of the other dimension can be controlled using: - - - setSymbolExtent() - - setSymbolMinWidth() - - setSymbolMaxWidth() - - The extent is a size in scale coordinates, so that the symbol width - is increasing when the plot is zoomed in. Minimum/Maximum width - is in widget coordinates independent from the zoom level. - When setting the minimum and maximum to the same value, the width of - the symbol is fixed. -*/ -class QWT_EXPORT QwtPlotTradingCurve: - public QwtPlotSeriesItem, QwtSeriesStore<QwtOHLCSample> -{ -public: - /*! - \brief Symbol styles. - - The default setting is QwtPlotSeriesItem::CandleStick. - \sa setSymbolStyle(), symbolStyle() - */ - enum SymbolStyle - { - //! Nothing is displayed - NoSymbol = -1, - - /*! - A line on the chart shows the price range (the highest and lowest - prices) over one unit of time, e.g. one day or one hour. - Tick marks project from each side of the line indicating the - opening and closing price. - */ - Bar, - - /*! - The range between opening/closing price are displayed as - a filled box. The fill brush depends on the direction of the - price movement. The box is connected to the highest/lowest - values by lines. - */ - CandleStick, - - /*! - SymbolTypes >= UserSymbol are displayed by drawUserSymbol(), - that needs to be overloaded and implemented in derived - curve classes. - - \sa drawUserSymbol() - */ - UserSymbol = 100 - }; - - /*! - \brief Direction of a price movement - */ - enum Direction - { - //! The closing price is higher than the opening price - Increasing, - - //! The closing price is lower than the opening price - Decreasing - }; - - /*! - Attributes to modify the drawing algorithm. - \sa setPaintAttribute(), testPaintAttribute() - */ - enum PaintAttribute - { - //! Check if a symbol is on the plot canvas before painting it. - ClipSymbols = 0x01 - }; - - //! Paint attributes - typedef QFlags<PaintAttribute> PaintAttributes; - - explicit QwtPlotTradingCurve( const QString &title = QString::null ); - explicit QwtPlotTradingCurve( const QwtText &title ); - - virtual ~QwtPlotTradingCurve(); - - virtual int rtti() const; - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - void setSamples( const QVector<QwtOHLCSample> & ); - void setSamples( QwtSeriesData<QwtOHLCSample> * ); - - void setSymbolStyle( SymbolStyle style ); - SymbolStyle symbolStyle() const; - - void setSymbolPen( const QColor &, - qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setSymbolPen( const QPen & ); - QPen symbolPen() const; - - void setSymbolBrush( Direction, const QBrush & ); - QBrush symbolBrush( Direction ) const; - - void setSymbolExtent( double width ); - double symbolExtent() const; - - void setMinSymbolWidth( double ); - double minSymbolWidth() const; - - void setMaxSymbolWidth( double ); - double maxSymbolWidth() const; - - virtual void drawSeries( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual QRectF boundingRect() const; - - virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; - -protected: - - void init(); - - virtual void drawSymbols( QPainter *, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const; - - virtual void drawUserSymbol( QPainter *, - SymbolStyle, const QwtOHLCSample &, - Qt::Orientation, bool inverted, double width ) const; - - void drawBar( QPainter *painter, const QwtOHLCSample &, - Qt::Orientation, bool inverted, double width ) const; - - void drawCandleStick( QPainter *, const QwtOHLCSample &, - Qt::Orientation, double width ) const; - - virtual double scaledSymbolWidth( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotTradingCurve::PaintAttributes ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_zoneitem.h b/include/pli_vis/third_party/qwt/qwt_plot_zoneitem.h deleted file mode 100644 index a79ce6e4eb086ef9a64baa7a734ae392885cd5f1..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_zoneitem.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_PLOT_ZONE_ITEM_H -#define QWT_PLOT_ZONE_ITEM_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_interval.h" - -class QPen; -class QBrush; - -/*! - \brief A plot item, which displays a zone - - A horizontal zone highlights an interval of the y axis - a vertical - zone an interval of the x axis - and is unbounded in the opposite direction. - It is filled with a brush and its border lines are optionally displayed with a pen. - - \note For displaying an area that is bounded for x and y coordinates - use QwtPlotShapeItem -*/ - -class QWT_EXPORT QwtPlotZoneItem: - public QwtPlotItem -{ -public: - explicit QwtPlotZoneItem(); - virtual ~QwtPlotZoneItem(); - - virtual int rtti() const; - - void setOrientation( Qt::Orientation ); - Qt::Orientation orientation(); - - void setInterval( double min, double max ); - void setInterval( const QwtInterval & ); - QwtInterval interval() const; - - void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setPen( const QPen & ); - const QPen &pen() const; - - void setBrush( const QBrush & ); - const QBrush &brush() const; - - virtual void draw( QPainter *, - const QwtScaleMap &, const QwtScaleMap &, - const QRectF &) const; - - virtual QRectF boundingRect() const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_plot_zoomer.h b/include/pli_vis/third_party/qwt/qwt_plot_zoomer.h deleted file mode 100644 index eab37c8d814785aa5436cc27232cd595333b0123..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_plot_zoomer.h +++ /dev/null @@ -1,140 +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_PLOT_ZOOMER_H -#define QWT_PLOT_ZOOMER_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_plot_picker.h" -#include <qstack.h> - -/*! - \brief QwtPlotZoomer provides stacked zooming for a plot widget - - QwtPlotZoomer selects rectangles from user inputs ( mouse or keyboard ) - translates them into plot coordinates and adjusts the axes to them. - The selection is supported by a rubber band and optionally by displaying - the coordinates of the current mouse position. - - Zooming can be repeated as often as possible, limited only by - maxStackDepth() or minZoomSize(). Each rectangle is pushed on a stack. - - The default setting how to select rectangles is - a QwtPickerDragRectMachine with the following bindings: - - - QwtEventPattern::MouseSelect1\n - The first point of the zoom rectangle is selected by a mouse press, - the second point from the position, where the mouse is released. - - - QwtEventPattern::KeySelect1\n - The first key press selects the first, the second key press - selects the second point. - - - QwtEventPattern::KeyAbort\n - Discard the selection in the state, where the first point - is selected. - - To traverse the zoom stack the following bindings are used: - - - QwtEventPattern::MouseSelect3, QwtEventPattern::KeyUndo\n - Zoom out one position on the zoom stack - - - QwtEventPattern::MouseSelect6, QwtEventPattern::KeyRedo\n - Zoom in one position on the zoom stack - - - QwtEventPattern::MouseSelect2, QwtEventPattern::KeyHome\n - Zoom to the zoom base - - The setKeyPattern() and setMousePattern() functions can be used - to configure the zoomer actions. The following example - shows, how to configure the 'I' and 'O' keys for zooming in and out - one position on the zoom stack. The "Home" key is used to - "unzoom" the plot. - - \code - zoomer = new QwtPlotZoomer( plot ); - zoomer->setKeyPattern( QwtEventPattern::KeyRedo, Qt::Key_I, Qt::ShiftModifier ); - zoomer->setKeyPattern( QwtEventPattern::KeyUndo, Qt::Key_O, Qt::ShiftModifier ); - zoomer->setKeyPattern( QwtEventPattern::KeyHome, Qt::Key_Home ); - \endcode - - QwtPlotZoomer is tailored for plots with one x and y axis, but it is - allowed to attach a second QwtPlotZoomer ( without rubber band and tracker ) - for the other axes. - - \note The realtime example includes an derived zoomer class that adds - scrollbars to the plot canvas. - - \sa QwtPlotPanner, QwtPlotMagnifier -*/ - -class QWT_EXPORT QwtPlotZoomer: public QwtPlotPicker -{ - Q_OBJECT -public: - explicit QwtPlotZoomer( QWidget *, bool doReplot = true ); - explicit QwtPlotZoomer( int xAxis, int yAxis, - QWidget *, bool doReplot = true ); - - virtual ~QwtPlotZoomer(); - - virtual void setZoomBase( bool doReplot = true ); - virtual void setZoomBase( const QRectF & ); - - QRectF zoomBase() const; - QRectF zoomRect() const; - - virtual void setAxis( int xAxis, int yAxis ); - - void setMaxStackDepth( int ); - int maxStackDepth() const; - - const QStack<QRectF> &zoomStack() const; - void setZoomStack( const QStack<QRectF> &, - int zoomRectIndex = -1 ); - - uint zoomRectIndex() const; - -public Q_SLOTS: - void moveBy( double x, double y ); - virtual void moveTo( const QPointF & ); - - virtual void zoom( const QRectF & ); - virtual void zoom( int up ); - -Q_SIGNALS: - /*! - A signal emitting the zoomRect(), when the plot has been - zoomed in or out. - - \param rect Current zoom rectangle. - */ - - void zoomed( const QRectF &rect ); - -protected: - virtual void rescale(); - - virtual QSizeF minZoomSize() const; - - virtual void widgetMouseReleaseEvent( QMouseEvent * ); - virtual void widgetKeyPressEvent( QKeyEvent * ); - - virtual void begin(); - virtual bool end( bool ok = true ); - virtual bool accept( QPolygon & ) const; - -private: - void init( bool doReplot ); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_point_3d.h b/include/pli_vis/third_party/qwt/qwt_point_3d.h deleted file mode 100644 index af8dbc39a855f11e858dc2369b8bece599bdfab8..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_point_3d.h +++ /dev/null @@ -1,189 +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_POINT_3D_H -#define QWT_POINT_3D_H 1 - -#include "qwt/qwt_global.h" -#include <qpoint.h> -#ifndef QT_NO_DEBUG_STREAM -#include <qdebug.h> -#endif - -/*! - \brief QwtPoint3D class defines a 3D point in double coordinates -*/ - -class QWT_EXPORT QwtPoint3D -{ -public: - QwtPoint3D(); - QwtPoint3D( double x, double y, double z ); - QwtPoint3D( const QwtPoint3D & ); - QwtPoint3D( const QPointF & ); - - bool isNull() const; - - double x() const; - double y() const; - double z() const; - - double &rx(); - double &ry(); - double &rz(); - - void setX( double x ); - void setY( double y ); - void setZ( double y ); - - QPointF toPoint() const; - - bool operator==( const QwtPoint3D & ) const; - bool operator!=( const QwtPoint3D & ) const; - -private: - double d_x; - double d_y; - double d_z; -}; - -Q_DECLARE_TYPEINFO(QwtPoint3D, Q_MOVABLE_TYPE); - -#ifndef QT_NO_DEBUG_STREAM -QWT_EXPORT QDebug operator<<( QDebug, const QwtPoint3D & ); -#endif - -/*! - Constructs a null point. - \sa isNull() -*/ -inline QwtPoint3D::QwtPoint3D(): - d_x( 0.0 ), - d_y( 0.0 ), - d_z( 0.0 ) -{ -} - -//! Constructs a point with coordinates specified by x, y and z. -inline QwtPoint3D::QwtPoint3D( double x, double y, double z = 0.0 ): - d_x( x ), - d_y( y ), - d_z( z ) -{ -} - -/*! - Copy constructor. - Constructs a point using the values of the point specified. -*/ -inline QwtPoint3D::QwtPoint3D( const QwtPoint3D &other ): - d_x( other.d_x ), - d_y( other.d_y ), - d_z( other.d_z ) -{ -} - -/*! - Constructs a point with x and y coordinates from a 2D point, - and a z coordinate of 0. -*/ -inline QwtPoint3D::QwtPoint3D( const QPointF &other ): - d_x( other.x() ), - d_y( other.y() ), - d_z( 0.0 ) -{ -} - -/*! - \return True if the point is null; otherwise returns false. - - A point is considered to be null if x, y and z-coordinates - are equal to zero. -*/ -inline bool QwtPoint3D::isNull() const -{ - return d_x == 0.0 && d_y == 0.0 && d_z == 0.0; -} - -//! \return The x-coordinate of the point. -inline double QwtPoint3D::x() const -{ - return d_x; -} - -//! \return The y-coordinate of the point. -inline double QwtPoint3D::y() const -{ - return d_y; -} - -//! \return The z-coordinate of the point. -inline double QwtPoint3D::z() const -{ - return d_z; -} - -//! \return A reference to the x-coordinate of the point. -inline double &QwtPoint3D::rx() -{ - return d_x; -} - -//! \return A reference to the y-coordinate of the point. -inline double &QwtPoint3D::ry() -{ - return d_y; -} - -//! \return A reference to the z-coordinate of the point. -inline double &QwtPoint3D::rz() -{ - return d_z; -} - -//! Sets the x-coordinate of the point to the value specified by x. -inline void QwtPoint3D::setX( double x ) -{ - d_x = x; -} - -//! Sets the y-coordinate of the point to the value specified by y. -inline void QwtPoint3D::setY( double y ) -{ - d_y = y; -} - -//! Sets the z-coordinate of the point to the value specified by z. -inline void QwtPoint3D::setZ( double z ) -{ - d_z = z; -} - -/*! - \return 2D point, where the z coordinate is dropped. -*/ -inline QPointF QwtPoint3D::toPoint() const -{ - return QPointF( d_x, d_y ); -} - -//! \return True, if this point and other are equal; otherwise returns false. -inline bool QwtPoint3D::operator==( const QwtPoint3D &other ) const -{ - return ( d_x == other.d_x ) && ( d_y == other.d_y ) && ( d_z == other.d_z ); -} - -//! \return True if this rect and other are different; otherwise returns false. -inline bool QwtPoint3D::operator!=( const QwtPoint3D &other ) const -{ - return !operator==( other ); -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_point_data.h b/include/pli_vis/third_party/qwt/qwt_point_data.h deleted file mode 100644 index e914d06667e15c3a144b65ead4d28639d861d775..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_point_data.h +++ /dev/null @@ -1,146 +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_POINT_DATA_H -#define QWT_POINT_DATA_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_series_data.h" - -/*! - \brief Interface for iterating over two QVector<double> objects. -*/ -class QWT_EXPORT QwtPointArrayData: public QwtSeriesData<QPointF> -{ -public: - QwtPointArrayData( const QVector<double> &x, const QVector<double> &y ); - QwtPointArrayData( const double *x, const double *y, size_t size ); - - virtual QRectF boundingRect() const; - - virtual size_t size() const; - virtual QPointF sample( size_t i ) const; - - const QVector<double> &xData() const; - const QVector<double> &yData() const; - -private: - QVector<double> d_x; - QVector<double> d_y; -}; - -/*! - \brief Data class containing two pointers to memory blocks of doubles. - */ -class QWT_EXPORT QwtCPointerData: public QwtSeriesData<QPointF> -{ -public: - QwtCPointerData( const double *x, const double *y, size_t size ); - - virtual QRectF boundingRect() const; - virtual size_t size() const; - virtual QPointF sample( size_t i ) const; - - const double *xData() const; - const double *yData() const; - -private: - const double *d_x; - const double *d_y; - size_t d_size; -}; - -/*! - \brief Synthetic point data - - QwtSyntheticPointData provides a fixed number of points for an interval. - The points are calculated in equidistant steps in x-direction. - - If the interval is invalid, the points are calculated for - the "rectangle of interest", what normally is the displayed area on the - plot canvas. In this mode you get different levels of detail, when - zooming in/out. - - \par Example - - The following example shows how to implement a sinus curve. - - \code -#include <cmath> -#include <qwt_series_data.h> -#include <qwt_plot_curve.h> -#include <qwt_plot.h> -#include <qapplication.h> - -class SinusData: public QwtSyntheticPointData -{ -public: - SinusData(): - QwtSyntheticPointData( 100 ) - { - } - - virtual double y( double x ) const - { - return qSin( x ); - } -}; - -int main(int argc, char **argv) -{ - QApplication a( argc, argv ); - - QwtPlot plot; - plot.setAxisScale( QwtPlot::xBottom, 0.0, 10.0 ); - plot.setAxisScale( QwtPlot::yLeft, -1.0, 1.0 ); - - QwtPlotCurve *curve = new QwtPlotCurve( "y = sin(x)" ); - curve->setData( new SinusData() ); - curve->attach( &plot ); - - plot.show(); - return a.exec(); -} - \endcode -*/ -class QWT_EXPORT QwtSyntheticPointData: public QwtSeriesData<QPointF> -{ -public: - QwtSyntheticPointData( size_t size, - const QwtInterval & = QwtInterval() ); - - void setSize( size_t size ); - virtual size_t size() const; - - void setInterval( const QwtInterval& ); - QwtInterval interval() const; - - virtual QRectF boundingRect() const; - virtual QPointF sample( size_t i ) const; - - /*! - Calculate a y value for a x value - - \param x x value - \return Corresponding y value - */ - virtual double y( double x ) const = 0; - virtual double x( uint index ) const; - - virtual void setRectOfInterest( const QRectF & ); - QRectF rectOfInterest() const; - -private: - size_t d_size; - QwtInterval d_interval; - QRectF d_rectOfInterest; - QwtInterval d_intervalOfInterest; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_point_mapper.h b/include/pli_vis/third_party/qwt/qwt_point_mapper.h deleted file mode 100644 index d2931df0d5aab9509418cd536287d053e53dcefb..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_point_mapper.h +++ /dev/null @@ -1,89 +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_POINT_MAPPER_H -#define QWT_POINT_MAPPER_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_series_data.h" -#include <qimage.h> - -class QwtScaleMap; -class QPolygonF; -class QPolygon; - -/*! - \brief A helper class for translating a series of points - - QwtPointMapper is a collection of methods and optimizations - for translating a series of points into paint device coordinates. - It is used by QwtPlotCurve but might also be useful for - similar plot items displaying a QwtSeriesData<QPointF>. - */ -class QWT_EXPORT QwtPointMapper -{ -public: - /*! - \brief Flags affecting the transformation process - \sa setFlag(), setFlags() - */ - enum TransformationFlag - { - //! Round points to integer values - RoundPoints = 0x01, - - /*! - Try to remove points, that are translated to the - same position. - */ - WeedOutPoints = 0x02 - }; - - /*! - \brief Flags affecting the transformation process - \sa setFlag(), setFlags() - */ - typedef QFlags<TransformationFlag> TransformationFlags; - - QwtPointMapper(); - ~QwtPointMapper(); - - void setFlags( TransformationFlags ); - TransformationFlags flags() const; - - void setFlag( TransformationFlag, bool on = true ); - bool testFlag( TransformationFlag ) const; - - void setBoundingRect( const QRectF & ); - QRectF boundingRect() const; - - QPolygonF toPolygonF( const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const; - - QPolygon toPolygon( const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const; - - QPolygon toPoints( const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const; - - QPolygonF toPointsF( const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const; - - QImage toImage( const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to, - const QPen &, bool antialiased, uint numThreads ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPointMapper::TransformationFlags ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_point_polar.h b/include/pli_vis/third_party/qwt/qwt_point_polar.h deleted file mode 100644 index d141811c43ee75795c04b04523010663197d2b34..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_point_polar.h +++ /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 - *****************************************************************************/ - -/*! \file */ -#ifndef _QWT_POINT_POLAR_H_ -#define _QWT_POINT_POLAR_H_ 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_math.h" -#include <qpoint.h> -#ifndef QT_NO_DEBUG_STREAM -#include <qdebug.h> -#endif - -/*! - \brief A point in polar coordinates - - In polar coordinates a point is determined by an angle and a distance. - See http://en.wikipedia.org/wiki/Polar_coordinate_system -*/ - -class QWT_EXPORT QwtPointPolar -{ -public: - QwtPointPolar(); - QwtPointPolar( double azimuth, double radius ); - QwtPointPolar( const QwtPointPolar & ); - QwtPointPolar( const QPointF & ); - - void setPoint( const QPointF & ); - QPointF toPoint() const; - - bool isValid() const; - bool isNull() const; - - double radius() const; - double azimuth() const; - - double &rRadius(); - double &rAzimuth(); - - void setRadius( double ); - void setAzimuth( double ); - - bool operator==( const QwtPointPolar & ) const; - bool operator!=( const QwtPointPolar & ) const; - - QwtPointPolar normalized() const; - -private: - double d_azimuth; - double d_radius; -}; - -/*! - Constructs a null point, with a radius and azimuth set to 0.0. - \sa QPointF::isNull() -*/ -inline QwtPointPolar::QwtPointPolar(): - d_azimuth( 0.0 ), - d_radius( 0.0 ) -{ -} - -/*! - Constructs a point with coordinates specified by radius and azimuth. - - \param azimuth Azimuth - \param radius Radius -*/ -inline QwtPointPolar::QwtPointPolar( double azimuth, double radius ): - d_azimuth( azimuth ), - d_radius( radius ) -{ -} - -/*! - Constructs a point using the values of the point specified. - \param other Other point -*/ -inline QwtPointPolar::QwtPointPolar( const QwtPointPolar &other ): - d_azimuth( other.d_azimuth ), - d_radius( other.d_radius ) -{ -} - -//! Returns true if radius() >= 0.0 -inline bool QwtPointPolar::isValid() const -{ - return d_radius >= 0.0; -} - -//! Returns true if radius() >= 0.0 -inline bool QwtPointPolar::isNull() const -{ - return d_radius == 0.0; -} - -//! Returns the radius. -inline double QwtPointPolar::radius() const -{ - return d_radius; -} - -//! Returns the azimuth. -inline double QwtPointPolar::azimuth() const -{ - return d_azimuth; -} - -//! Returns the radius. -inline double &QwtPointPolar::rRadius() -{ - return d_radius; -} - -//! Returns the azimuth. -inline double &QwtPointPolar::rAzimuth() -{ - return d_azimuth; -} - -//! Sets the radius to radius. -inline void QwtPointPolar::setRadius( double radius ) -{ - d_radius = radius; -} - -//! Sets the atimuth to atimuth. -inline void QwtPointPolar::setAzimuth( double azimuth ) -{ - d_azimuth = azimuth; -} - -#ifndef QT_NO_DEBUG_STREAM -QWT_EXPORT QDebug operator<<( QDebug, const QwtPointPolar & ); -#endif - -inline QPoint qwtPolar2Pos( const QPoint &pole, - double radius, double angle ) -{ - const double x = pole.x() + radius * qCos( angle ); - const double y = pole.y() - radius * qSin( angle ); - - return QPoint( qRound( x ), qRound( y ) ); -} - -inline QPoint qwtDegree2Pos( const QPoint &pole, - double radius, double angle ) -{ - return qwtPolar2Pos( pole, radius, angle / 180.0 * M_PI ); -} - -inline QPointF qwtPolar2Pos( const QPointF &pole, - double radius, double angle ) -{ - const double x = pole.x() + radius * qCos( angle ); - const double y = pole.y() - radius * qSin( angle ); - - return QPointF( x, y); -} - -inline QPointF qwtDegree2Pos( const QPointF &pole, - double radius, double angle ) -{ - return qwtPolar2Pos( pole, radius, angle / 180.0 * M_PI ); -} - -inline QPointF qwtFastPolar2Pos( const QPointF &pole, - double radius, double angle ) -{ -#if QT_VERSION < 0x040601 - const double x = pole.x() + radius * ::cos( angle ); - const double y = pole.y() - radius * ::sin( angle ); -#else - const double x = pole.x() + radius * qFastCos( angle ); - const double y = pole.y() - radius * qFastSin( angle ); -#endif - - return QPointF( x, y); -} - -inline QPointF qwtFastDegree2Pos( const QPointF &pole, - double radius, double angle ) -{ - return qwtFastPolar2Pos( pole, radius, angle / 180.0 * M_PI ); -} - -inline QwtPointPolar qwtFastPos2Polar( const QPointF &pos ) -{ - return QwtPointPolar( qwtFastAtan2( pos.y(), pos.x() ), - qSqrt( qwtSqr( pos.x() ) + qwtSqr( pos.y() ) ) ); -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_raster_data.h b/include/pli_vis/third_party/qwt/qwt_raster_data.h deleted file mode 100644 index 754b7b1ca5e469af03431d27835bf6c5ab59b4fb..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_raster_data.h +++ /dev/null @@ -1,95 +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_RASTER_DATA_H -#define QWT_RASTER_DATA_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include <qmap.h> -#include <qlist.h> -#include <qpolygon.h> - -class QwtScaleMap; - -/*! - \brief QwtRasterData defines an interface to any type of raster data. - - QwtRasterData is an abstract interface, that is used by - QwtPlotRasterItem to find the values at the pixels of its raster. - - Often a raster item is used to display values from a matrix. Then the - derived raster data class needs to implement some sort of resampling, - that maps the raster of the matrix into the requested raster of - the raster item ( depending on resolution and scales of the canvas ). -*/ -class QWT_EXPORT QwtRasterData -{ -public: - //! Contour lines - typedef QMap<double, QPolygonF> ContourLines; - - //! Flags to modify the contour algorithm - enum ConrecFlag - { - //! Ignore all vertices on the same level - IgnoreAllVerticesOnLevel = 0x01, - - //! Ignore all values, that are out of range - IgnoreOutOfRange = 0x02 - }; - - //! Flags to modify the contour algorithm - typedef QFlags<ConrecFlag> ConrecFlags; - - QwtRasterData(); - virtual ~QwtRasterData(); - - virtual void setInterval( Qt::Axis, const QwtInterval & ); - const QwtInterval &interval(Qt::Axis) const; - - virtual QRectF pixelHint( const QRectF & ) const; - - virtual void initRaster( const QRectF &, const QSize& raster ); - virtual void discardRaster(); - - /*! - \return the value at a raster position - \param x X value in plot coordinates - \param y Y value in plot coordinates - */ - virtual double value( double x, double y ) const = 0; - - virtual ContourLines contourLines( const QRectF &rect, - const QSize &raster, const QList<double> &levels, - ConrecFlags ) const; - - class Contour3DPoint; - class ContourPlane; - -private: - // Disabled copy constructor and operator= - QwtRasterData( const QwtRasterData & ); - QwtRasterData &operator=( const QwtRasterData & ); - - QwtInterval d_intervals[3]; -}; - -/*! - \return Bounding interval for a axis - \sa setInterval -*/ -inline const QwtInterval &QwtRasterData::interval( Qt::Axis axis) const -{ - return d_intervals[axis]; -} - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtRasterData::ConrecFlags ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_round_scale_draw.h b/include/pli_vis/third_party/qwt/qwt_round_scale_draw.h deleted file mode 100644 index 346b12a33325a6325e92c9b4e66a4d6f746a1e2f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_round_scale_draw.h +++ /dev/null @@ -1,66 +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_ROUND_SCALE_DRAW_H -#define QWT_ROUND_SCALE_DRAW_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_scale_draw.h" -#include <qpoint.h> - -/*! - \brief A class for drawing round scales - - QwtRoundScaleDraw can be used to draw round scales. - The circle segment can be adjusted by setAngleRange(). - The geometry of the scale can be specified with - moveCenter() and setRadius(). - - After a scale division has been specified as a QwtScaleDiv object - using QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &s), - the scale can be drawn with the QwtAbstractScaleDraw::draw() member. -*/ - -class QWT_EXPORT QwtRoundScaleDraw: public QwtAbstractScaleDraw -{ -public: - QwtRoundScaleDraw(); - virtual ~QwtRoundScaleDraw(); - - void setRadius( double radius ); - double radius() const; - - void moveCenter( double x, double y ); - void moveCenter( const QPointF & ); - QPointF center() const; - - void setAngleRange( double angle1, double angle2 ); - - virtual double extent( const QFont & ) const; - -protected: - virtual void drawTick( QPainter *, double val, double len ) const; - virtual void drawBackbone( QPainter * ) const; - virtual void drawLabel( QPainter *, double val ) const; - -private: - QwtRoundScaleDraw( const QwtRoundScaleDraw & ); - QwtRoundScaleDraw &operator=( const QwtRoundScaleDraw &other ); - - class PrivateData; - PrivateData *d_data; -}; - -//! Move the center of the scale draw, leaving the radius unchanged -inline void QwtRoundScaleDraw::moveCenter( double x, double y ) -{ - moveCenter( QPointF( x, y ) ); -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_samples.h b/include/pli_vis/third_party/qwt/qwt_samples.h deleted file mode 100644 index 0c26438da364ab9a943298a499db91d1f6cda4a2..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_samples.h +++ /dev/null @@ -1,239 +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_SAMPLES_H -#define QWT_SAMPLES_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include <qvector.h> -#include <qrect.h> - -//! \brief A sample of the types (x1-x2, y) or (x, y1-y2) -class QWT_EXPORT QwtIntervalSample -{ -public: - QwtIntervalSample(); - QwtIntervalSample( double, const QwtInterval & ); - QwtIntervalSample( double value, double min, double max ); - - bool operator==( const QwtIntervalSample & ) const; - bool operator!=( const QwtIntervalSample & ) const; - - //! Value - double value; - - //! Interval - QwtInterval interval; -}; - -/*! - Constructor - The value is set to 0.0, the interval is invalid -*/ -inline QwtIntervalSample::QwtIntervalSample(): - value( 0.0 ) -{ -} - -//! Constructor -inline QwtIntervalSample::QwtIntervalSample( - double v, const QwtInterval &intv ): - value( v ), - interval( intv ) -{ -} - -//! Constructor -inline QwtIntervalSample::QwtIntervalSample( - double v, double min, double max ): - value( v ), - interval( min, max ) -{ -} - -//! Compare operator -inline bool QwtIntervalSample::operator==( - const QwtIntervalSample &other ) const -{ - return value == other.value && interval == other.interval; -} - -//! Compare operator -inline bool QwtIntervalSample::operator!=( - const QwtIntervalSample &other ) const -{ - return !( *this == other ); -} - -//! \brief A sample of the types (x1...xn, y) or (x, y1..yn) -class QWT_EXPORT QwtSetSample -{ -public: - QwtSetSample(); - QwtSetSample( double, const QVector<double> & = QVector<double>() ); - - bool operator==( const QwtSetSample &other ) const; - bool operator!=( const QwtSetSample &other ) const; - - double added() const; - - //! value - double value; - - //! Vector of values associated to value - QVector<double> set; -}; - -/*! - Constructor - The value is set to 0.0 -*/ -inline QwtSetSample::QwtSetSample(): - value( 0.0 ) -{ -} - -/*! - Constructor - - \param v Value - \param s Set of values -*/ -inline QwtSetSample::QwtSetSample( double v, const QVector< double > &s ): - value( v ), - set( s ) -{ -} - -//! Compare operator -inline bool QwtSetSample::operator==( const QwtSetSample &other ) const -{ - return value == other.value && set == other.set; -} - -//! Compare operator -inline bool QwtSetSample::operator!=( const QwtSetSample &other ) const -{ - return !( *this == other ); -} - -//! \return All values of the set added -inline double QwtSetSample::added() const -{ - double y = 0.0; - for ( int i = 0; i < set.size(); i++ ) - y += set[i]; - - return y; -} - -/*! - \brief Open-High-Low-Close sample used in financial charts - - In financial charts the movement of a price in a time interval is often - represented by the opening/closing prices and the lowest/highest prices - in this interval. - - \sa QwtTradingChartData -*/ -class QWT_EXPORT QwtOHLCSample -{ -public: - QwtOHLCSample( double time = 0.0, - double open = 0.0, double high = 0.0, - double low = 0.0, double close = 0.0 ); - - QwtInterval boundingInterval() const; - - bool isValid() const; - - /*! - Time of the sample, usually a number representing - a specific interval - like a day. - */ - double time; - - //! Opening price - double open; - - //! Highest price - double high; - - //! Lowest price - double low; - - //! Closing price - double close; -}; - - -/*! - Constructor - - \param t Time value - \param o Open value - \param h High value - \param l Low value - \param c Close value -*/ -inline QwtOHLCSample::QwtOHLCSample( double t, - double o, double h, double l, double c ): - time( t ), - open( o ), - high( h ), - low( l ), - close( c ) -{ -} - -/*! - \brief Check if a sample is valid - - A sample is valid, when all of the following checks are true: - - - low <= high - - low <= open <= high - - low <= close <= high - - \return True, when the sample is valid - */ -inline bool QwtOHLCSample::isValid() const -{ - return ( low <= high ) - && ( open >= low ) - && ( open <= high ) - && ( close >= low ) - && ( close <= high ); -} - -/*! - \brief Calculate the bounding interval of the OHLC values - - For valid samples the limits of this interval are always low/high. - - \return Bounding interval - \sa isValid() - */ -inline QwtInterval QwtOHLCSample::boundingInterval() const -{ - double minY = open; - minY = qMin( minY, high ); - minY = qMin( minY, low ); - minY = qMin( minY, close ); - - double maxY = open; - maxY = qMax( maxY, high ); - maxY = qMax( maxY, low ); - maxY = qMax( maxY, close ); - - return QwtInterval( minY, maxY ); -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_sampling_thread.h b/include/pli_vis/third_party/qwt/qwt_sampling_thread.h deleted file mode 100644 index f73bd94476295141a1d109fb0b584e97b5b05551..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_sampling_thread.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _QWT_SAMPLING_THREAD_H_ -#define _QWT_SAMPLING_THREAD_H_ - -#include "qwt/qwt_global.h" -#include <qthread.h> - -/*! - \brief A thread collecting samples at regular intervals. - - Continuous signals are converted into a discrete signal by - collecting samples at regular intervals. A discrete signal - can be displayed by a QwtPlotSeriesItem on a QwtPlot widget. - - QwtSamplingThread starts a thread calling periodically sample(), - to collect and store ( or emit ) a single sample. - - \sa QwtPlotCurve, QwtPlotSeriesItem -*/ -class QWT_EXPORT QwtSamplingThread: public QThread -{ - Q_OBJECT - -public: - virtual ~QwtSamplingThread(); - - double interval() const; - double elapsed() const; - -public Q_SLOTS: - void setInterval( double interval ); - void stop(); - -protected: - explicit QwtSamplingThread( QObject *parent = NULL ); - - virtual void run(); - - /*! - Collect a sample - - \param elapsed Time since the thread was started in milliseconds - */ - virtual void sample( double elapsed ) = 0; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_scale_div.h b/include/pli_vis/third_party/qwt/qwt_scale_div.h deleted file mode 100644 index 1b912cb7d12eea03c2bb35881a2addc464918cec..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_scale_div.h +++ /dev/null @@ -1,110 +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_SCALE_DIV_H -#define QWT_SCALE_DIV_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_interval.h" -#include <qlist.h> - -#ifndef QT_NO_DEBUG_STREAM -#include <qdebug.h> -#endif - -/*! - \brief A class representing a scale division - - A Qwt scale is defined by its boundaries and 3 list - for the positions of the major, medium and minor ticks. - - The upperBound() might be smaller than the lowerBound() - to indicate inverted scales. - - Scale divisions can be calculated from a QwtScaleEngine. - - \sa QwtScaleEngine::divideScale(), QwtPlot::setAxisScaleDiv(), - QwtAbstractSlider::setScaleDiv() -*/ - -class QWT_EXPORT QwtScaleDiv -{ -public: - //! Scale tick types - enum TickType - { - //! No ticks - NoTick = -1, - - //! Minor ticks - MinorTick, - - //! Medium ticks - MediumTick, - - //! Major ticks - MajorTick, - - //! Number of valid tick types - NTickTypes - }; - - explicit QwtScaleDiv( double lowerBound = 0.0, - double upperBound = 0.0 ); - - explicit QwtScaleDiv( const QwtInterval &, QList<double>[NTickTypes] ); - - explicit QwtScaleDiv( double lowerBound, double upperBound, - QList<double>[NTickTypes] ); - - explicit QwtScaleDiv( double lowerBound, double upperBound, - const QList<double> &minorTicks, const QList<double> &mediumTicks, - const QList<double> &majorTicks ); - - bool operator==( const QwtScaleDiv & ) const; - bool operator!=( const QwtScaleDiv & ) const; - - void setInterval( double lowerBound, double upperBound ); - void setInterval( const QwtInterval & ); - QwtInterval interval() const; - - void setLowerBound( double ); - double lowerBound() const; - - void setUpperBound( double ); - double upperBound() const; - - double range() const; - - bool contains( double value ) const; - - void setTicks( int tickType, const QList<double> & ); - QList<double> ticks( int tickType ) const; - - bool isEmpty() const; - bool isIncreasing() const; - - void invert(); - QwtScaleDiv inverted() const; - - QwtScaleDiv bounded( double lowerBound, double upperBound ) const; - -private: - double d_lowerBound; - double d_upperBound; - QList<double> d_ticks[NTickTypes]; -}; - -Q_DECLARE_TYPEINFO( QwtScaleDiv, Q_MOVABLE_TYPE ); - -#ifndef QT_NO_DEBUG_STREAM -QWT_EXPORT QDebug operator<<( QDebug, const QwtScaleDiv & ); -#endif - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_scale_draw.h b/include/pli_vis/third_party/qwt/qwt_scale_draw.h deleted file mode 100644 index c187c4ad56533b2333e83c1f2db174cc9458116f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_scale_draw.h +++ /dev/null @@ -1,120 +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_SCALE_DRAW_H -#define QWT_SCALE_DRAW_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_scale_draw.h" -#include <qpoint.h> -#include <qrect.h> -#include <qtransform.h> - -/*! - \brief A class for drawing scales - - QwtScaleDraw can be used to draw linear or logarithmic scales. - A scale has a position, an alignment and a length, which can be specified . - The labels can be rotated and aligned - to the ticks using setLabelRotation() and setLabelAlignment(). - - After a scale division has been specified as a QwtScaleDiv object - using QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &s), - the scale can be drawn with the QwtAbstractScaleDraw::draw() member. -*/ -class QWT_EXPORT QwtScaleDraw: public QwtAbstractScaleDraw -{ -public: - /*! - Alignment of the scale draw - \sa setAlignment(), alignment() - */ - enum Alignment - { - //! The scale is below - BottomScale, - - //! The scale is above - TopScale, - - //! The scale is left - LeftScale, - - //! The scale is right - RightScale - }; - - QwtScaleDraw(); - virtual ~QwtScaleDraw(); - - void getBorderDistHint( const QFont &, int &start, int &end ) const; - int minLabelDist( const QFont & ) const; - - int minLength( const QFont & ) const; - virtual double extent( const QFont & ) const; - - void move( double x, double y ); - void move( const QPointF & ); - void setLength( double length ); - - Alignment alignment() const; - void setAlignment( Alignment ); - - Qt::Orientation orientation() const; - - QPointF pos() const; - double length() const; - - void setLabelAlignment( Qt::Alignment ); - Qt::Alignment labelAlignment() const; - - void setLabelRotation( double rotation ); - double labelRotation() const; - - int maxLabelHeight( const QFont & ) const; - int maxLabelWidth( const QFont & ) const; - - QPointF labelPosition( double val ) const; - - QRectF labelRect( const QFont &, double val ) const; - QSizeF labelSize( const QFont &, double val ) const; - - QRect boundingLabelRect( const QFont &, double val ) const; - -protected: - QTransform labelTransformation( const QPointF &, const QSizeF & ) const; - - virtual void drawTick( QPainter *, double val, double len ) const; - virtual void drawBackbone( QPainter * ) const; - virtual void drawLabel( QPainter *, double val ) const; - -private: - QwtScaleDraw( const QwtScaleDraw & ); - QwtScaleDraw &operator=( const QwtScaleDraw &other ); - - void updateMap(); - - class PrivateData; - PrivateData *d_data; -}; - -/*! - Move the position of the scale - - \param x X coordinate - \param y Y coordinate - - \sa move(const QPointF &) -*/ -inline void QwtScaleDraw::move( double x, double y ) -{ - move( QPointF( x, y ) ); -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_scale_engine.h b/include/pli_vis/third_party/qwt/qwt_scale_engine.h deleted file mode 100644 index 93edb724500b4c590b1a06c1894e6de1ea0c585e..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_scale_engine.h +++ /dev/null @@ -1,220 +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_SCALE_ENGINE_H -#define QWT_SCALE_ENGINE_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_interval.h" - -class QwtTransform; - -/*! - \brief Arithmetic including a tolerance -*/ -class QWT_EXPORT QwtScaleArithmetic -{ -public: - static double ceilEps( double value, double intervalSize ); - static double floorEps( double value, double intervalSize ); - - static double divideEps( double interval, double steps ); - - static double divideInterval( double interval, - int numSteps, uint base ); -}; - -/*! - \brief Base class for scale engines. - - A scale engine tries to find "reasonable" ranges and step sizes - for scales. - - The layout of the scale can be varied with setAttribute(). - - Qwt offers implementations for logarithmic and linear scales. -*/ - -class QWT_EXPORT QwtScaleEngine -{ -public: - /*! - Layout attributes - \sa setAttribute(), testAttribute(), reference(), - lowerMargin(), upperMargin() - */ - - enum Attribute - { - //! No attributes - NoAttribute = 0x00, - - //! Build a scale which includes the reference() value. - IncludeReference = 0x01, - - //! Build a scale which is symmetric to the reference() value. - Symmetric = 0x02, - - /*! - The endpoints of the scale are supposed to be equal the - outmost included values plus the specified margins - (see setMargins()). - If this attribute is *not* set, the endpoints of the scale will - be integer multiples of the step size. - */ - Floating = 0x04, - - //! Turn the scale upside down. - Inverted = 0x08 - }; - - //! Layout attributes - typedef QFlags<Attribute> Attributes; - - explicit QwtScaleEngine( uint base = 10 ); - virtual ~QwtScaleEngine(); - - void setBase( uint base ); - uint base() const; - - void setAttribute( Attribute, bool on = true ); - bool testAttribute( Attribute ) const; - - void setAttributes( Attributes ); - Attributes attributes() const; - - void setReference( double reference ); - double reference() const; - - void setMargins( double lower, double upper ); - double lowerMargin() const; - double upperMargin() const; - - /*! - Align and divide an interval - - \param maxNumSteps Max. number of steps - \param x1 First limit of the interval (In/Out) - \param x2 Second limit of the interval (In/Out) - \param stepSize Step size (Return value) - */ - virtual void autoScale( int maxNumSteps, - double &x1, double &x2, double &stepSize ) const = 0; - - /*! - \brief Calculate a scale division - - \param x1 First interval limit - \param x2 Second interval limit - \param maxMajorSteps Maximum for the number of major steps - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size. If stepSize == 0.0, the scaleEngine - calculates one. - - \return Calculated scale division - */ - virtual QwtScaleDiv divideScale( double x1, double x2, - int maxMajorSteps, int maxMinorSteps, - double stepSize = 0.0 ) const = 0; - - void setTransformation( QwtTransform * ); - QwtTransform *transformation() const; - -protected: - bool contains( const QwtInterval &, double val ) const; - QList<double> strip( const QList<double>&, const QwtInterval & ) const; - - double divideInterval( double interval, int numSteps ) const; - - QwtInterval buildInterval( double v ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -/*! - \brief A scale engine for linear scales - - The step size will fit into the pattern - \f$\left\{ 1,2,5\right\} \cdot 10^{n}\f$, where n is an integer. -*/ - -class QWT_EXPORT QwtLinearScaleEngine: public QwtScaleEngine -{ -public: - QwtLinearScaleEngine( uint base = 10 ); - virtual ~QwtLinearScaleEngine(); - - virtual void autoScale( int maxSteps, - double &x1, double &x2, double &stepSize ) const; - - virtual QwtScaleDiv divideScale( double x1, double x2, - int numMajorSteps, int numMinorSteps, - double stepSize = 0.0 ) const; - - -protected: - QwtInterval align( const QwtInterval&, double stepSize ) const; - - void buildTicks( - const QwtInterval &, double stepSize, int maxMinSteps, - QList<double> ticks[QwtScaleDiv::NTickTypes] ) const; - - QList<double> buildMajorTicks( - const QwtInterval &interval, double stepSize ) const; - - void buildMinorTicks( const QList<double>& majorTicks, - int maxMinorSteps, double stepSize, - QList<double> &minorTicks, QList<double> &mediumTicks ) const; -}; - -/*! - \brief A scale engine for logarithmic scales - - The step size is measured in *decades* - and the major step size will be adjusted to fit the pattern - \f$\left\{ 1,2,3,5\right\} \cdot 10^{n}\f$, where n is a natural number - including zero. - - \warning the step size as well as the margins are measured in *decades*. -*/ - -class QWT_EXPORT QwtLogScaleEngine: public QwtScaleEngine -{ -public: - QwtLogScaleEngine( uint base = 10 ); - virtual ~QwtLogScaleEngine(); - - virtual void autoScale( int maxSteps, - double &x1, double &x2, double &stepSize ) const; - - virtual QwtScaleDiv divideScale( double x1, double x2, - int numMajorSteps, int numMinorSteps, - double stepSize = 0.0 ) const; - -protected: - QwtInterval align( const QwtInterval&, double stepSize ) const; - - void buildTicks( - const QwtInterval &, double stepSize, int maxMinSteps, - QList<double> ticks[QwtScaleDiv::NTickTypes] ) const; - - QList<double> buildMajorTicks( - const QwtInterval &interval, double stepSize ) const; - - void buildMinorTicks( const QList<double>& majorTicks, - int maxMinorSteps, double stepSize, - QList<double> &minorTicks, QList<double> &mediumTicks ) const; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtScaleEngine::Attributes ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_scale_map.h b/include/pli_vis/third_party/qwt/qwt_scale_map.h deleted file mode 100644 index f46953e116f5e47d42a9a913568ad4ddcf20fb77..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_scale_map.h +++ /dev/null @@ -1,175 +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_SCALE_MAP_H -#define QWT_SCALE_MAP_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_transform.h" -#include <qrect.h> - -#ifndef QT_NO_DEBUG_STREAM -#include <qdebug.h> -#endif - -class QRectF; - -/*! - \brief A scale map - - QwtScaleMap offers transformations from the coordinate system - of a scale into the linear coordinate system of a paint device - and vice versa. -*/ -class QWT_EXPORT QwtScaleMap -{ -public: - QwtScaleMap(); - QwtScaleMap( const QwtScaleMap& ); - - ~QwtScaleMap(); - - QwtScaleMap &operator=( const QwtScaleMap & ); - - void setTransformation( QwtTransform * ); - const QwtTransform *transformation() const; - - void setPaintInterval( double p1, double p2 ); - void setScaleInterval( double s1, double s2 ); - - double transform( double s ) const; - double invTransform( double p ) const; - - double p1() const; - double p2() const; - - double s1() const; - double s2() const; - - double pDist() const; - double sDist() const; - - static QRectF transform( const QwtScaleMap &, - const QwtScaleMap &, const QRectF & ); - static QRectF invTransform( const QwtScaleMap &, - const QwtScaleMap &, const QRectF & ); - - static QPointF transform( const QwtScaleMap &, - const QwtScaleMap &, const QPointF & ); - static QPointF invTransform( const QwtScaleMap &, - const QwtScaleMap &, const QPointF & ); - - bool isInverting() const; - -private: - void updateFactor(); - - double d_s1, d_s2; // scale interval boundaries - double d_p1, d_p2; // paint device interval boundaries - - double d_cnv; // conversion factor - double d_ts1; - - QwtTransform *d_transform; -}; - -/*! - \return First border of the scale interval -*/ -inline double QwtScaleMap::s1() const -{ - return d_s1; -} - -/*! - \return Second border of the scale interval -*/ -inline double QwtScaleMap::s2() const -{ - return d_s2; -} - -/*! - \return First border of the paint interval -*/ -inline double QwtScaleMap::p1() const -{ - return d_p1; -} - -/*! - \return Second border of the paint interval -*/ -inline double QwtScaleMap::p2() const -{ - return d_p2; -} - -/*! - \return qwtAbs(p2() - p1()) -*/ -inline double QwtScaleMap::pDist() const -{ - return qAbs( d_p2 - d_p1 ); -} - -/*! - \return qwtAbs(s2() - s1()) -*/ -inline double QwtScaleMap::sDist() const -{ - return qAbs( d_s2 - d_s1 ); -} - -/*! - Transform a point related to the scale interval into an point - related to the interval of the paint device - - \param s Value relative to the coordinates of the scale - \return Transformed value - - \sa invTransform() -*/ -inline double QwtScaleMap::transform( double s ) const -{ - if ( d_transform ) - s = d_transform->transform( s ); - - return d_p1 + ( s - d_ts1 ) * d_cnv; -} - -/*! - Transform an paint device value into a value in the - interval of the scale. - - \param p Value relative to the coordinates of the paint device - \return Transformed value - - \sa transform() -*/ -inline double QwtScaleMap::invTransform( double p ) const -{ - double s = d_ts1 + ( p - d_p1 ) / d_cnv; - if ( d_transform ) - s = d_transform->invTransform( s ); - - return s; -} - -//! \return True, when ( p1() < p2() ) != ( s1() < s2() ) -inline bool QwtScaleMap::isInverting() const -{ - return ( ( d_p1 < d_p2 ) != ( d_s1 < d_s2 ) ); -} - -#ifndef QT_NO_DEBUG_STREAM -QWT_EXPORT QDebug operator<<( QDebug, const QwtScaleMap & ); -#endif - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_scale_widget.h b/include/pli_vis/third_party/qwt/qwt_scale_widget.h deleted file mode 100644 index 3abe9351dc9eb956e5a57d27f0f9d8a6a9357725..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_scale_widget.h +++ /dev/null @@ -1,136 +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_SCALE_WIDGET_H -#define QWT_SCALE_WIDGET_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_scale_draw.h" -#include <qwidget.h> -#include <qfont.h> -#include <qcolor.h> -#include <qstring.h> - -class QPainter; -class QwtTransform; -class QwtScaleDiv; -class QwtColorMap; - -/*! - \brief A Widget which contains a scale - - This Widget can be used to decorate composite widgets with - a scale. -*/ - -class QWT_EXPORT QwtScaleWidget : public QWidget -{ - Q_OBJECT - -public: - //! Layout flags of the title - enum LayoutFlag - { - /*! - The title of vertical scales is painted from top to bottom. - Otherwise it is painted from bottom to top. - */ - TitleInverted = 1 - }; - - //! Layout flags of the title - typedef QFlags<LayoutFlag> LayoutFlags; - - explicit QwtScaleWidget( QWidget *parent = NULL ); - explicit QwtScaleWidget( QwtScaleDraw::Alignment, QWidget *parent = NULL ); - virtual ~QwtScaleWidget(); - -Q_SIGNALS: - //! Signal emitted, whenever the scale division changes - void scaleDivChanged(); - -public: - void setTitle( const QString &title ); - void setTitle( const QwtText &title ); - QwtText title() const; - - void setLayoutFlag( LayoutFlag, bool on ); - bool testLayoutFlag( LayoutFlag ) const; - - void setBorderDist( int start, int end ); - int startBorderDist() const; - int endBorderDist() const; - - void getBorderDistHint( int &start, int &end ) const; - - void getMinBorderDist( int &start, int &end ) const; - void setMinBorderDist( int start, int end ); - - void setMargin( int ); - int margin() const; - - void setSpacing( int td ); - int spacing() const; - - void setScaleDiv( const QwtScaleDiv &sd ); - void setTransformation( QwtTransform * ); - - void setScaleDraw( QwtScaleDraw * ); - const QwtScaleDraw *scaleDraw() const; - QwtScaleDraw *scaleDraw(); - - void setLabelAlignment( Qt::Alignment ); - void setLabelRotation( double rotation ); - - void setColorBarEnabled( bool ); - bool isColorBarEnabled() const; - - void setColorBarWidth( int ); - int colorBarWidth() const; - - void setColorMap( const QwtInterval &, QwtColorMap * ); - - QwtInterval colorBarInterval() const; - const QwtColorMap *colorMap() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - int titleHeightForWidth( int width ) const; - int dimForLength( int length, const QFont &scaleFont ) const; - - void drawColorBar( QPainter *painter, const QRectF & ) const; - void drawTitle( QPainter *painter, QwtScaleDraw::Alignment, - const QRectF &rect ) const; - - void setAlignment( QwtScaleDraw::Alignment ); - QwtScaleDraw::Alignment alignment() const; - - QRectF colorBarRect( const QRectF& ) const; - -protected: - virtual void paintEvent( QPaintEvent * ); - virtual void resizeEvent( QResizeEvent * ); - - void draw( QPainter *p ) const; - - void scaleChange(); - void layoutScale( bool update = true ); - -private: - void initScale( QwtScaleDraw::Alignment ); - - class PrivateData; - PrivateData *d_data; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtScaleWidget::LayoutFlags ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_series_data.h b/include/pli_vis/third_party/qwt/qwt_series_data.h deleted file mode 100644 index be915285eb4024f1b2275b8943e2334b66629676..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_series_data.h +++ /dev/null @@ -1,355 +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_SERIES_DATA_H -#define QWT_SERIES_DATA_H 1 - -#include "qwt/qwt_global.h" -#include "qwt/qwt_samples.h" -#include "qwt/qwt_point_3d.h" -#include "qwt/qwt_point_polar.h" -#include <qvector.h> -#include <qrect.h> - -/*! - \brief Abstract interface for iterating over samples - - Qwt offers several implementations of the QwtSeriesData API, - but in situations, where data of an application specific format - needs to be displayed, without having to copy it, it is recommended - to implement an individual data access. - - A subclass of QwtSeriesData<QPointF> must implement: - - - size()\n - Should return number of data points. - - - sample()\n - Should return values x and y values of the sample at specific position - as QPointF object. - - - boundingRect()\n - Should return the bounding rectangle of the data series. - It is used for autoscaling and might help certain algorithms for displaying - the data. You can use qwtBoundingRect() for an implementation - but often it is possible to implement a more efficient algorithm - depending on the characteristics of the series. - The member d_boundingRect is intended for caching the calculated rectangle. - -*/ -template <typename T> -class QwtSeriesData -{ -public: - //! Constructor - QwtSeriesData(); - - //! Destructor - virtual ~QwtSeriesData(); - - //! \return Number of samples - virtual size_t size() const = 0; - - /*! - Return a sample - \param i Index - \return Sample at position i - */ - virtual T sample( size_t i ) const = 0; - - /*! - Calculate the bounding rect of all samples - - The bounding rect is necessary for autoscaling and can be used - for a couple of painting optimizations. - - qwtBoundingRect(...) offers slow implementations iterating - over the samples. For large sets it is recommended to implement - something faster f.e. by caching the bounding rectangle. - - \return Bounding rectangle - */ - virtual QRectF boundingRect() const = 0; - - /*! - Set a the "rect of interest" - - QwtPlotSeriesItem defines the current area of the plot canvas - as "rectangle of interest" ( QwtPlotSeriesItem::updateScaleDiv() ). - It can be used to implement different levels of details. - - The default implementation does nothing. - - \param rect Rectangle of interest - */ - virtual void setRectOfInterest( const QRectF &rect ); - -protected: - //! Can be used to cache a calculated bounding rectangle - mutable QRectF d_boundingRect; - -private: - QwtSeriesData<T> &operator=( const QwtSeriesData<T> & ); -}; - -template <typename T> -QwtSeriesData<T>::QwtSeriesData(): - d_boundingRect( 0.0, 0.0, -1.0, -1.0 ) -{ -} - -template <typename T> -QwtSeriesData<T>::~QwtSeriesData() -{ -} - -template <typename T> -void QwtSeriesData<T>::setRectOfInterest( const QRectF & ) -{ -} - -/*! - \brief Template class for data, that is organized as QVector - - QVector uses implicit data sharing and can be - passed around as argument efficiently. -*/ -template <typename T> -class QwtArraySeriesData: public QwtSeriesData<T> -{ -public: - //! Constructor - QwtArraySeriesData(); - - /*! - Constructor - \param samples Array of samples - */ - QwtArraySeriesData( const QVector<T> &samples ); - - /*! - Assign an array of samples - \param samples Array of samples - */ - void setSamples( const QVector<T> &samples ); - - //! \return Array of samples - const QVector<T> samples() const; - - //! \return Number of samples - virtual size_t size() const; - - /*! - \return Sample at a specific position - - \param index Index - \return Sample at position index - */ - virtual T sample( size_t index ) const; - -protected: - //! Vector of samples - QVector<T> d_samples; -}; - -template <typename T> -QwtArraySeriesData<T>::QwtArraySeriesData() -{ -} - -template <typename T> -QwtArraySeriesData<T>::QwtArraySeriesData( const QVector<T> &samples ): - d_samples( samples ) -{ -} - -template <typename T> -void QwtArraySeriesData<T>::setSamples( const QVector<T> &samples ) -{ - QwtSeriesData<T>::d_boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); - d_samples = samples; -} - -template <typename T> -const QVector<T> QwtArraySeriesData<T>::samples() const -{ - return d_samples; -} - -template <typename T> -size_t QwtArraySeriesData<T>::size() const -{ - return d_samples.size(); -} - -template <typename T> -T QwtArraySeriesData<T>::sample( size_t i ) const -{ - return d_samples[ static_cast<int>( i ) ]; -} - -//! Interface for iterating over an array of points -class QWT_EXPORT QwtPointSeriesData: public QwtArraySeriesData<QPointF> -{ -public: - QwtPointSeriesData( - const QVector<QPointF> & = QVector<QPointF>() ); - - virtual QRectF boundingRect() const; -}; - -//! Interface for iterating over an array of 3D points -class QWT_EXPORT QwtPoint3DSeriesData: public QwtArraySeriesData<QwtPoint3D> -{ -public: - QwtPoint3DSeriesData( - const QVector<QwtPoint3D> & = QVector<QwtPoint3D>() ); - virtual QRectF boundingRect() const; -}; - -//! Interface for iterating over an array of intervals -class QWT_EXPORT QwtIntervalSeriesData: public QwtArraySeriesData<QwtIntervalSample> -{ -public: - QwtIntervalSeriesData( - const QVector<QwtIntervalSample> & = QVector<QwtIntervalSample>() ); - - virtual QRectF boundingRect() const; -}; - -//! Interface for iterating over an array of samples -class QWT_EXPORT QwtSetSeriesData: public QwtArraySeriesData<QwtSetSample> -{ -public: - QwtSetSeriesData( - const QVector<QwtSetSample> & = QVector<QwtSetSample>() ); - - virtual QRectF boundingRect() const; -}; - -/*! - Interface for iterating over an array of OHLC samples -*/ -class QWT_EXPORT QwtTradingChartData: public QwtArraySeriesData<QwtOHLCSample> -{ -public: - QwtTradingChartData( - const QVector<QwtOHLCSample> & = QVector<QwtOHLCSample>() ); - - virtual QRectF boundingRect() const; -}; - -QWT_EXPORT QRectF qwtBoundingRect( - const QwtSeriesData<QPointF> &, int from = 0, int to = -1 ); - -QWT_EXPORT QRectF qwtBoundingRect( - const QwtSeriesData<QwtPoint3D> &, int from = 0, int to = -1 ); - -QWT_EXPORT QRectF qwtBoundingRect( - const QwtSeriesData<QwtPointPolar> &, int from = 0, int to = -1 ); - -QWT_EXPORT QRectF qwtBoundingRect( - const QwtSeriesData<QwtIntervalSample> &, int from = 0, int to = -1 ); - -QWT_EXPORT QRectF qwtBoundingRect( - const QwtSeriesData<QwtSetSample> &, int from = 0, int to = -1 ); - -QWT_EXPORT QRectF qwtBoundingRect( - const QwtSeriesData<QwtOHLCSample> &, int from = 0, int to = -1 ); - -/*! - Binary search for a sorted series of samples - - qwtUpperSampleIndex returns the index of sample that is the upper bound - of value. Is the the value smaller than the smallest value the return - value will be 0. Is the value greater or equal than the largest - value the return value will be -1. - - \par Example - The following example shows finds a point of curve from an x - coordinate - - \verbatim -#include <qwt_series_data.h> -#include <qwt_plot_curve.h> - -struct compareX -{ - inline bool operator()( const double x, const QPointF &pos ) const - { - return ( x < pos.x() ); - } -}; - -QLineF curveLineAt( const QwtPlotCurve *curve, double x ) -{ - int index = qwtUpperSampleIndex<QPointF>( - *curve->data(), x, compareX() ); - - if ( index == -1 && - x == curve->sample( curve->dataSize() - 1 ).x() ) - { - // the last sample is excluded from qwtUpperSampleIndex - index = curve->dataSize() - 1; - } - - QLineF line; // invalid - if ( index > 0 ) - { - line.setP1( curve->sample( index - 1 ) ); - line.setP2( curve->sample( index ) ); - } - - return line; -} - -\endverbatim - - - \param series Series of samples - \param value Value - \param lessThan Compare operation - - \note The samples must be sorted according to the order specified - by the lessThan object - -of the range [begin, end) and returns the position of the one-past-the-last occurrence of value. If no such item is found, returns the position where the item should be inserted. - */ -template <typename T, typename LessThan> -inline int qwtUpperSampleIndex( const QwtSeriesData<T> &series, - double value, LessThan lessThan ) -{ - const int indexMax = series.size() - 1; - - if ( indexMax < 0 || !lessThan( value, series.sample( indexMax ) ) ) - return -1; - - int indexMin = 0; - int n = indexMax; - - while ( n > 0 ) - { - const int half = n >> 1; - const int indexMid = indexMin + half; - - if ( lessThan( value, series.sample( indexMid ) ) ) - { - n = half; - } - else - { - indexMin = indexMid + 1; - n -= half + 1; - } - } - - return indexMin; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_series_store.h b/include/pli_vis/third_party/qwt/qwt_series_store.h deleted file mode 100644 index 3dfa09e878fd16e47a4124b56410cef61041d128..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_series_store.h +++ /dev/null @@ -1,199 +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_SERIES_STORE_H -#define QWT_SERIES_STORE_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_series_data.h" - -/*! - \brief Bridge between QwtSeriesStore and QwtPlotSeriesItem - - QwtAbstractSeriesStore is an abstract interface only - to make it possible to isolate the template based methods ( QwtSeriesStore ) - from the regular methods ( QwtPlotSeriesItem ) to make it possible - to derive from QwtPlotSeriesItem without any hassle with templates. -*/ -class QwtAbstractSeriesStore -{ -protected: - //! Destructor - virtual ~QwtAbstractSeriesStore() {} - - //! dataChanged() indicates, that the series has been changed. - virtual void dataChanged() = 0; - - /*! - Set a the "rectangle of interest" for the stored series - \sa QwtSeriesData<T>::setRectOfInterest() - */ - virtual void setRectOfInterest( const QRectF & ) = 0; - - //! \return Bounding rectangle of the stored series - virtual QRectF dataRect() const = 0; - - //! \return Number of samples - virtual size_t dataSize() const = 0; -}; - -/*! - \brief Class storing a QwtSeriesData object - - QwtSeriesStore and QwtPlotSeriesItem are intended as base classes for all - plot items iterating over a series of samples. Both classes share - a virtual base class ( QwtAbstractSeriesStore ) to bridge between them. - - QwtSeriesStore offers the template based part for the plot item API, so - that QwtPlotSeriesItem can be derived without any hassle with templates. - */ -template <typename T> -class QwtSeriesStore: public virtual QwtAbstractSeriesStore -{ -public: - /*! - \brief Constructor - The store contains no series - */ - explicit QwtSeriesStore<T>(); - - //! Destructor - ~QwtSeriesStore<T>(); - - /*! - Assign a series of samples - - \param series Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. - */ - void setData( QwtSeriesData<T> *series ); - - //! \return the the series data - QwtSeriesData<T> *data(); - - //! \return the the series data - const QwtSeriesData<T> *data() const; - - /*! - \param index Index - \return Sample at position index - */ - T sample( int index ) const; - - /*! - \return Number of samples of the series - \sa setData(), QwtSeriesData<T>::size() - */ - virtual size_t dataSize() const; - - /*! - \return Bounding rectangle of the series - or an invalid rectangle, when no series is stored - - \sa QwtSeriesData<T>::boundingRect() - */ - virtual QRectF dataRect() const; - - /*! - Set a the "rect of interest" for the series - - \param rect Rectangle of interest - \sa QwtSeriesData<T>::setRectOfInterest() - */ - virtual void setRectOfInterest( const QRectF &rect ); - - /*! - Replace a series without deleting the previous one - - \param series New series - \return Previously assigned series - */ - QwtSeriesData<T> *swapData( QwtSeriesData<T> *series ); - -private: - QwtSeriesData<T> *d_series; -}; - -template <typename T> -QwtSeriesStore<T>::QwtSeriesStore(): - d_series( NULL ) -{ -} - -template <typename T> -QwtSeriesStore<T>::~QwtSeriesStore() -{ - delete d_series; -} - -template <typename T> -inline QwtSeriesData<T> *QwtSeriesStore<T>::data() -{ - return d_series; -} - -template <typename T> -inline const QwtSeriesData<T> *QwtSeriesStore<T>::data() const -{ - return d_series; -} - -template <typename T> -inline T QwtSeriesStore<T>::sample( int index ) const -{ - return d_series ? d_series->sample( index ) : T(); -} - -template <typename T> -void QwtSeriesStore<T>::setData( QwtSeriesData<T> *series ) -{ - if ( d_series != series ) - { - delete d_series; - d_series = series; - dataChanged(); - } -} - -template <typename T> -size_t QwtSeriesStore<T>::dataSize() const -{ - if ( d_series == NULL ) - return 0; - - return d_series->size(); -} - -template <typename T> -QRectF QwtSeriesStore<T>::dataRect() const -{ - if ( d_series == NULL ) - return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid - - return d_series->boundingRect(); -} - -template <typename T> -void QwtSeriesStore<T>::setRectOfInterest( const QRectF &rect ) -{ - if ( d_series ) - d_series->setRectOfInterest( rect ); -} - -template <typename T> -QwtSeriesData<T>* QwtSeriesStore<T>::swapData( QwtSeriesData<T> *series ) -{ - QwtSeriesData<T> * swappedSeries = d_series; - d_series = series; - - return swappedSeries; -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_slider.h b/include/pli_vis/third_party/qwt/qwt_slider.h deleted file mode 100644 index 7570d484f0d3a0e3519621055bf6009688e8ba20..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_slider.h +++ /dev/null @@ -1,130 +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_SLIDER_H -#define QWT_SLIDER_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_slider.h" - -class QwtScaleDraw; - -/*! - \brief The Slider Widget - - QwtSlider is a slider widget which operates on an interval - of type double. Its position is related to a scale showing - the current value. - - The slider can be customized by having a through, a groove - or both. - - \image html sliders.png -*/ - -class QWT_EXPORT QwtSlider: public QwtAbstractSlider -{ - Q_OBJECT - - Q_ENUMS( ScalePosition BackgroundStyle ) - - Q_PROPERTY( Qt::Orientation orientation - READ orientation WRITE setOrientation ) - Q_PROPERTY( ScalePosition scalePosition READ scalePosition - WRITE setScalePosition ) - - Q_PROPERTY( bool trough READ hasTrough WRITE setTrough ) - Q_PROPERTY( bool groove READ hasGroove WRITE setGroove ) - - Q_PROPERTY( QSize handleSize READ handleSize WRITE setHandleSize ) - Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) - Q_PROPERTY( int spacing READ spacing WRITE setSpacing ) - -public: - - /*! - Position of the scale - \sa QwtSlider(), setScalePosition(), setOrientation() - */ - enum ScalePosition - { - //! The slider has no scale - NoScale, - - //! The scale is right of a vertical or below a horizontal slider - LeadingScale, - - //! The scale is left of a vertical or above a horizontal slider - TrailingScale - }; - - explicit QwtSlider( QWidget *parent = NULL ); - explicit QwtSlider( Qt::Orientation, QWidget *parent = NULL ); - - virtual ~QwtSlider(); - - void setOrientation( Qt::Orientation ); - Qt::Orientation orientation() const; - - void setScalePosition( ScalePosition ); - ScalePosition scalePosition() const; - - void setTrough( bool ); - bool hasTrough() const; - - void setGroove( bool ); - bool hasGroove() const; - - void setHandleSize( const QSize & ); - QSize handleSize() const; - - void setBorderWidth( int bw ); - int borderWidth() const; - - void setSpacing( int ); - int spacing() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - void setScaleDraw( QwtScaleDraw * ); - const QwtScaleDraw *scaleDraw() const; - - void setUpdateInterval( int ); - int updateInterval() const; - -protected: - virtual double scrolledTo( const QPoint & ) const; - virtual bool isScrollPosition( const QPoint & ) const; - - virtual void drawSlider ( QPainter *, const QRect & ) const; - virtual void drawHandle( QPainter *, const QRect &, int pos ) const; - - virtual void mousePressEvent( QMouseEvent * ); - virtual void mouseReleaseEvent( QMouseEvent * ); - virtual void resizeEvent( QResizeEvent * ); - virtual void paintEvent ( QPaintEvent * ); - virtual void changeEvent( QEvent * ); - virtual void timerEvent( QTimerEvent * ); - - virtual void scaleChange(); - - QRect sliderRect() const; - QRect handleRect() const; - -private: - QwtScaleDraw *scaleDraw(); - - void layoutSlider( bool ); - void initSlider( Qt::Orientation ); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_spline.h b/include/pli_vis/third_party/qwt/qwt_spline.h deleted file mode 100644 index e62e6092a3c790a225adc9026a11878961033e07..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_spline.h +++ /dev/null @@ -1,101 +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_SPLINE_H -#define QWT_SPLINE_H - -#include "qwt/qwt_global.h" -#include <qpolygon.h> -#include <qvector.h> - -/*! - \brief A class for spline interpolation - - The QwtSpline class is used for cubical spline interpolation. - Two types of splines, natural and periodic, are supported. - - \par Usage: - <ol> - <li>First call setPoints() to determine the spline coefficients - for a tabulated function y(x). - <li>After the coefficients have been set up, the interpolated - function value for an argument x can be determined by calling - QwtSpline::value(). - </ol> - - \par Example: - \code -#include <qwt_spline.h> - -QPolygonF interpolate(const QPolygonF& points, int numValues) -{ - QwtSpline spline; - if ( !spline.setPoints(points) ) - return points; - - QPolygonF interpolatedPoints(numValues); - - const double delta = - (points[numPoints - 1].x() - points[0].x()) / (points.size() - 1); - for(i = 0; i < points.size(); i++) / interpolate - { - const double x = points[0].x() + i * delta; - interpolatedPoints[i].setX(x); - interpolatedPoints[i].setY(spline.value(x)); - } - return interpolatedPoints; -} - \endcode -*/ - -class QWT_EXPORT QwtSpline -{ -public: - //! Spline type - enum SplineType - { - //! A natural spline - Natural, - - //! A periodic spline - Periodic - }; - - QwtSpline(); - QwtSpline( const QwtSpline & ); - - ~QwtSpline(); - - QwtSpline &operator=( const QwtSpline & ); - - void setSplineType( SplineType ); - SplineType splineType() const; - - bool setPoints( const QPolygonF& points ); - QPolygonF points() const; - - void reset(); - - bool isValid() const; - double value( double x ) const; - - const QVector<double> &coefficientsA() const; - const QVector<double> &coefficientsB() const; - const QVector<double> &coefficientsC() const; - -protected: - bool buildNaturalSpline( const QPolygonF & ); - bool buildPeriodicSpline( const QPolygonF & ); - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_symbol.h b/include/pli_vis/third_party/qwt/qwt_symbol.h deleted file mode 100644 index 037c4a989208dd2b8dc1cbe7a2a74680a8183417..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_symbol.h +++ /dev/null @@ -1,258 +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_SYMBOL_H -#define QWT_SYMBOL_H - -#include "qwt/qwt_global.h" -#include <qpolygon.h> - -class QPainter; -class QRect; -class QSize; -class QBrush; -class QPen; -class QColor; -class QPointF; -class QPolygonF; -class QPainterPath; -class QPixmap; -class QByteArray; -class QwtGraphic; - -//! A class for drawing symbols -class QWT_EXPORT QwtSymbol -{ -public: - /*! - Symbol Style - \sa setStyle(), style() - */ - enum Style - { - //! No Style. The symbol cannot be drawn. - NoSymbol = -1, - - //! Ellipse or circle - Ellipse, - - //! Rectangle - Rect, - - //! Diamond - Diamond, - - //! Triangle pointing upwards - Triangle, - - //! Triangle pointing downwards - DTriangle, - - //! Triangle pointing upwards - UTriangle, - - //! Triangle pointing left - LTriangle, - - //! Triangle pointing right - RTriangle, - - //! Cross (+) - Cross, - - //! Diagonal cross (X) - XCross, - - //! Horizontal line - HLine, - - //! Vertical line - VLine, - - //! X combined with + - Star1, - - //! Six-pointed star - Star2, - - //! Hexagon - Hexagon, - - /*! - The symbol is represented by a painter path, where the - origin ( 0, 0 ) of the path coordinate system is mapped to - the position of the symbol. - - \sa setPath(), path() - */ - Path, - - /*! - The symbol is represented by a pixmap. The pixmap is centered - or aligned to its pin point. - - \sa setPinPoint() - */ - Pixmap, - - /*! - The symbol is represented by a graphic. The graphic is centered - or aligned to its pin point. - - \sa setPinPoint() - */ - Graphic, - - /*! - The symbol is represented by a SVG graphic. The graphic is centered - or aligned to its pin point. - - \sa setPinPoint() - */ - SvgDocument, - - /*! - Styles >= QwtSymbol::UserSymbol are reserved for derived - classes of QwtSymbol that overload drawSymbols() with - additional application specific symbol types. - */ - UserStyle = 1000 - }; - - /*! - Depending on the render engine and the complexity of the - symbol shape it might be faster to render the symbol - to a pixmap and to paint this pixmap. - - F.e. the raster paint engine is a pure software renderer - where in cache mode a draw operation usually ends in - raster operation with the the backing store, that are usually - faster, than the algorithms for rendering polygons. - But the opposite can be expected for graphic pipelines - that can make use of hardware acceleration. - - The default setting is AutoCache - - \sa setCachePolicy(), cachePolicy() - - \note The policy has no effect, when the symbol is painted - to a vector graphics format ( PDF, SVG ). - \warning Since Qt 4.8 raster is the default backend on X11 - */ - - enum CachePolicy - { - //! Don't use a pixmap cache - NoCache, - - //! Always use a pixmap cache - Cache, - - /*! - Use a cache when one of the following conditions is true: - - - The symbol is rendered with the software - renderer ( QPaintEngine::Raster ) - */ - AutoCache - }; - -public: - QwtSymbol( Style = NoSymbol ); - QwtSymbol( Style, const QBrush &, const QPen &, const QSize & ); - QwtSymbol( const QPainterPath &, const QBrush &, const QPen & ); - - virtual ~QwtSymbol(); - - void setCachePolicy( CachePolicy ); - CachePolicy cachePolicy() const; - - void setSize( const QSize & ); - void setSize( int width, int height = -1 ); - const QSize& size() const; - - void setPinPoint( const QPointF &pos, bool enable = true ); - QPointF pinPoint() const; - - void setPinPointEnabled( bool ); - bool isPinPointEnabled() const; - - virtual void setColor( const QColor & ); - - void setBrush( const QBrush& b ); - const QBrush& brush() const; - - void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); - void setPen( const QPen & ); - const QPen& pen() const; - - void setStyle( Style ); - Style style() const; - - void setPath( const QPainterPath & ); - const QPainterPath &path() const; - - void setPixmap( const QPixmap & ); - const QPixmap &pixmap() const; - - void setGraphic( const QwtGraphic & ); - const QwtGraphic &graphic() const; - -#ifndef QWT_NO_SVG - void setSvgDocument( const QByteArray & ); -#endif - - void drawSymbol( QPainter *, const QRectF & ) const; - void drawSymbol( QPainter *, const QPointF & ) const; - void drawSymbols( QPainter *, const QPolygonF & ) const; - void drawSymbols( QPainter *, - const QPointF *, int numPoints ) const; - - virtual QRect boundingRect() const; - void invalidateCache(); - -protected: - virtual void renderSymbols( QPainter *, - const QPointF *, int numPoints ) const; - -private: - // Disabled copy constructor and operator= - QwtSymbol( const QwtSymbol & ); - QwtSymbol &operator=( const QwtSymbol & ); - - class PrivateData; - PrivateData *d_data; -}; - -/*! - \brief Draw the symbol at a specified position - - \param painter Painter - \param pos Position of the symbol in screen coordinates -*/ -inline void QwtSymbol::drawSymbol( - QPainter *painter, const QPointF &pos ) const -{ - drawSymbols( painter, &pos, 1 ); -} - -/*! - \brief Draw symbols at the specified points - - \param painter Painter - \param points Positions of the symbols in screen coordinates -*/ - -inline void QwtSymbol::drawSymbols( - QPainter *painter, const QPolygonF &points ) const -{ - drawSymbols( painter, points.data(), points.size() ); -} - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_system_clock.h b/include/pli_vis/third_party/qwt/qwt_system_clock.h deleted file mode 100644 index b458392e926657cfb06256c072b99bccf41b031d..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_system_clock.h +++ /dev/null @@ -1,47 +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_SYSTEM_CLOCK_H -#define QWT_SYSTEM_CLOCK_H - -#include "qwt/qwt_global.h" - -/*! - \brief QwtSystemClock provides high resolution clock time functions. - - Sometimes the resolution offered by QTime ( millisecond ) is not accurate - enough for implementing time measurements ( f.e. sampling ). - QwtSystemClock offers a subset of the QTime functionality using higher - resolution timers ( if possible ). - - Precision and time intervals are multiples of milliseconds (ms). - - \note The implementation uses high-resolution performance counter on Windows, - mach_absolute_time() on the Mac or POSIX timers on other systems. - If none is available it falls back on QTimer. -*/ - -class QWT_EXPORT QwtSystemClock -{ -public: - QwtSystemClock(); - virtual ~QwtSystemClock(); - - bool isNull() const; - - void start(); - double restart(); - double elapsed() const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_text.h b/include/pli_vis/third_party/qwt/qwt_text.h deleted file mode 100644 index 3907d63d03e2f8621f03d26431d72b2fb124bcdc..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_text.h +++ /dev/null @@ -1,223 +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_TEXT_H -#define QWT_TEXT_H - -#include "qwt/qwt_global.h" -#include <qstring.h> -#include <qsize.h> -#include <qfont.h> -#include <qmetatype.h> - -class QColor; -class QPen; -class QBrush; -class QRectF; -class QPainter; -class QwtTextEngine; - -/*! - \brief A class representing a text - - A QwtText is a text including a set of attributes how to render it. - - - Format\n - A text might include control sequences (f.e tags) describing - how to render it. Each format (f.e MathML, TeX, Qt Rich Text) - has its own set of control sequences, that can be handles by - a special QwtTextEngine for this format. - - Background\n - A text might have a background, defined by a QPen and QBrush - to improve its visibility. The corners of the background might - be rounded. - - Font\n - A text might have an individual font. - - Color\n - A text might have an individual color. - - Render Flags\n - Flags from Qt::AlignmentFlag and Qt::TextFlag used like in - QPainter::drawText(). - - \sa QwtTextEngine, QwtTextLabel -*/ - -class QWT_EXPORT QwtText -{ -public: - - /*! - \brief Text format - - The text format defines the QwtTextEngine, that is used to render - the text. - - \sa QwtTextEngine, setTextEngine() - */ - - enum TextFormat - { - /*! - The text format is determined using QwtTextEngine::mightRender() for - all available text engines in increasing order > PlainText. - If none of the text engines can render the text is rendered - like QwtText::PlainText. - */ - AutoText = 0, - - //! Draw the text as it is, using a QwtPlainTextEngine. - PlainText, - - //! Use the Scribe framework (Qt Rich Text) to render the text. - RichText, - - /*! - Use a MathML (http://en.wikipedia.org/wiki/MathML) render engine - to display the text. The Qwt MathML extension offers such an engine - based on the MathML renderer of the Qt solutions package. - To enable MathML support the following code needs to be added to the - application: -\verbatim QwtText::setTextEngine(QwtText::MathMLText, new QwtMathMLTextEngine()); \endverbatim - */ - MathMLText, - - /*! - Use a TeX (http://en.wikipedia.org/wiki/TeX) render engine - to display the text ( not implemented yet ). - */ - TeXText, - - /*! - The number of text formats can be extended using setTextEngine. - Formats >= QwtText::OtherFormat are not used by Qwt. - */ - OtherFormat = 100 - }; - - /*! - \brief Paint Attributes - - Font and color and background are optional attributes of a QwtText. - The paint attributes hold the information, if they are set. - */ - enum PaintAttribute - { - //! The text has an individual font. - PaintUsingTextFont = 0x01, - - //! The text has an individual color. - PaintUsingTextColor = 0x02, - - //! The text has an individual background. - PaintBackground = 0x04 - }; - - //! Paint attributes - typedef QFlags<PaintAttribute> PaintAttributes; - - /*! - \brief Layout Attributes - The layout attributes affects some aspects of the layout of the text. - */ - enum LayoutAttribute - { - /*! - Layout the text without its margins. This mode is useful if a - text needs to be aligned accurately, like the tick labels of a scale. - If QwtTextEngine::textMargins is not implemented for the format - of the text, MinimumLayout has no effect. - */ - MinimumLayout = 0x01 - }; - - //! Layout attributes - typedef QFlags<LayoutAttribute> LayoutAttributes; - - QwtText( const QString & = QString::null, - TextFormat textFormat = AutoText ); - QwtText( const QwtText & ); - ~QwtText(); - - QwtText &operator=( const QwtText & ); - - bool operator==( const QwtText & ) const; - bool operator!=( const QwtText & ) const; - - void setText( const QString &, - QwtText::TextFormat textFormat = AutoText ); - QString text() const; - - bool isNull() const; - bool isEmpty() const; - - void setFont( const QFont & ); - QFont font() const; - - QFont usedFont( const QFont & ) const; - - void setRenderFlags( int flags ); - int renderFlags() const; - - void setColor( const QColor & ); - QColor color() const; - - QColor usedColor( const QColor & ) const; - - void setBorderRadius( double ); - double borderRadius() const; - - void setBorderPen( const QPen & ); - QPen borderPen() const; - - void setBackgroundBrush( const QBrush & ); - QBrush backgroundBrush() const; - - void setPaintAttribute( PaintAttribute, bool on = true ); - bool testPaintAttribute( PaintAttribute ) const; - - void setLayoutAttribute( LayoutAttribute, bool on = true ); - bool testLayoutAttribute( LayoutAttribute ) const; - - double heightForWidth( double width, const QFont & = QFont() ) const; - QSizeF textSize( const QFont & = QFont() ) const; - - void draw( QPainter *painter, const QRectF &rect ) const; - - static const QwtTextEngine *textEngine( - const QString &text, QwtText::TextFormat = AutoText ); - - static const QwtTextEngine *textEngine( QwtText::TextFormat ); - static void setTextEngine( QwtText::TextFormat, QwtTextEngine * ); - -private: - class PrivateData; - PrivateData *d_data; - - class LayoutCache; - LayoutCache *d_layoutCache; -}; - -//! \return text().isNull() -inline bool QwtText::isNull() const -{ - return text().isNull(); -} - -//! \return text().isEmpty() -inline bool QwtText::isEmpty() const -{ - return text().isEmpty(); -} - -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtText::PaintAttributes ) -Q_DECLARE_OPERATORS_FOR_FLAGS( QwtText::LayoutAttributes ) - -Q_DECLARE_METATYPE( QwtText ) - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_text_engine.h b/include/pli_vis/third_party/qwt/qwt_text_engine.h deleted file mode 100644 index 27825c5f6cd7e415596f563220fdd99aa824b10f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_text_engine.h +++ /dev/null @@ -1,172 +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_TEXT_ENGINE_H -#define QWT_TEXT_ENGINE_H 1 - -#include "qwt/qwt_global.h" -#include <qsize.h> - -class QFont; -class QRectF; -class QString; -class QPainter; - -/*! - \brief Abstract base class for rendering text strings - - A text engine is responsible for rendering texts for a - specific text format. They are used by QwtText to render a text. - - QwtPlainTextEngine and QwtRichTextEngine are part of the Qwt library. - The implementation of QwtMathMLTextEngine uses code from the - Qt solution package. Because of license implications it is built into - a separate library. - - \sa QwtText::setTextEngine() -*/ - -class QWT_EXPORT QwtTextEngine -{ -public: - virtual ~QwtTextEngine(); - - /*! - Find the height for a given width - - \param font Font of the text - \param flags Bitwise OR of the flags used like in QPainter::drawText - \param text Text to be rendered - \param width Width - - \return Calculated height - */ - virtual double heightForWidth( const QFont &font, int flags, - const QString &text, double width ) const = 0; - - /*! - Returns the size, that is needed to render text - - \param font Font of the text - \param flags Bitwise OR of the flags like in for QPainter::drawText - \param text Text to be rendered - - \return Calculated size - */ - virtual QSizeF textSize( const QFont &font, int flags, - const QString &text ) const = 0; - - /*! - Test if a string can be rendered by this text engine - - \param text Text to be tested - \return true, if it can be rendered - */ - virtual bool mightRender( const QString &text ) const = 0; - - /*! - Return margins around the texts - - The textSize might include margins around the - text, like QFontMetrics::descent(). In situations - where texts need to be aligned in detail, knowing - these margins might improve the layout calculations. - - \param font Font of the text - \param text Text to be rendered - \param left Return value for the left margin - \param right Return value for the right margin - \param top Return value for the top margin - \param bottom Return value for the bottom margin - */ - virtual void textMargins( const QFont &font, const QString &text, - double &left, double &right, double &top, double &bottom ) const = 0; - - /*! - Draw the text in a clipping rectangle - - \param painter Painter - \param rect Clipping rectangle - \param flags Bitwise OR of the flags like in for QPainter::drawText() - \param text Text to be rendered - */ - virtual void draw( QPainter *painter, const QRectF &rect, - int flags, const QString &text ) const = 0; - -protected: - QwtTextEngine(); -}; - - -/*! - \brief A text engine for plain texts - - QwtPlainTextEngine renders texts using the basic Qt classes - QPainter and QFontMetrics. -*/ -class QWT_EXPORT QwtPlainTextEngine: public QwtTextEngine -{ -public: - QwtPlainTextEngine(); - virtual ~QwtPlainTextEngine(); - - virtual double heightForWidth( const QFont &font, int flags, - const QString &text, double width ) const; - - virtual QSizeF textSize( const QFont &font, int flags, - const QString &text ) const; - - virtual void draw( QPainter *painter, const QRectF &rect, - int flags, const QString &text ) const; - - virtual bool mightRender( const QString & ) const; - - virtual void textMargins( const QFont &, const QString &, - double &left, double &right, double &top, double &bottom ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - - -#ifndef QT_NO_RICHTEXT - -/*! - \brief A text engine for Qt rich texts - - QwtRichTextEngine renders Qt rich texts using the classes - of the Scribe framework of Qt. -*/ -class QWT_EXPORT QwtRichTextEngine: public QwtTextEngine -{ -public: - QwtRichTextEngine(); - - virtual double heightForWidth( const QFont &font, int flags, - const QString &text, double width ) const; - - virtual QSizeF textSize( const QFont &font, int flags, - const QString &text ) const; - - virtual void draw( QPainter *painter, const QRectF &rect, - int flags, const QString &text ) const; - - virtual bool mightRender( const QString & ) const; - - virtual void textMargins( const QFont &, const QString &, - double &left, double &right, double &top, double &bottom ) const; - -private: - QString taggedText( const QString &, int flags ) const; -}; - -#endif // !QT_NO_RICHTEXT - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_text_label.h b/include/pli_vis/third_party/qwt/qwt_text_label.h deleted file mode 100644 index 00b48afb4624d993843aeefb72404b46c065be8f..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_text_label.h +++ /dev/null @@ -1,77 +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_TEXT_LABEL_H -#define QWT_TEXT_LABEL_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_text.h" -#include <qframe.h> - -class QString; -class QPaintEvent; -class QPainter; - -/*! - \brief A Widget which displays a QwtText -*/ - -class QWT_EXPORT QwtTextLabel : public QFrame -{ - Q_OBJECT - - Q_PROPERTY( int indent READ indent WRITE setIndent ) - Q_PROPERTY( int margin READ margin WRITE setMargin ) - Q_PROPERTY( QString plainText READ plainText WRITE setPlainText ) - -public: - explicit QwtTextLabel( QWidget *parent = NULL ); - explicit QwtTextLabel( const QwtText &, QWidget *parent = NULL ); - virtual ~QwtTextLabel(); - - void setPlainText( const QString & ); - QString plainText() const; - -public Q_SLOTS: - void setText( const QString &, - QwtText::TextFormat textFormat = QwtText::AutoText ); - virtual void setText( const QwtText & ); - - void clear(); - -public: - const QwtText &text() const; - - int indent() const; - void setIndent( int ); - - int margin() const; - void setMargin( int ); - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - virtual int heightForWidth( int ) const; - - QRect textRect() const; - - virtual void drawText( QPainter *, const QRectF & ); - -protected: - virtual void paintEvent( QPaintEvent *e ); - virtual void drawContents( QPainter * ); - -private: - void init(); - int defaultIndent() const; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_thermo.h b/include/pli_vis/third_party/qwt/qwt_thermo.h deleted file mode 100644 index d4b1ee26d0aa459d7ce49213ed9536c1364e9947..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_thermo.h +++ /dev/null @@ -1,178 +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_THERMO_H -#define QWT_THERMO_H - -#include "qwt/qwt_global.h" -#include "qwt/qwt_abstract_scale.h" -#include "qwt/qwt_interval.h" - -class QwtScaleDraw; -class QwtColorMap; - -/*! - \brief The Thermometer Widget - - QwtThermo is a widget which displays a value in an interval. It supports: - - a horizontal or vertical layout; - - a range; - - a scale; - - an alarm level. - - \image html sysinfo.png - - The fill colors might be calculated from an optional color map - If no color map has been assigned QwtThermo uses the - following colors/brushes from the widget palette: - - - QPalette::Base - Background of the pipe - - QPalette::ButtonText - Fill brush below the alarm level - - QPalette::Highlight - Fill brush for the values above the alarm level - - QPalette::WindowText - For the axis of the scale - - QPalette::Text - For the labels of the scale -*/ -class QWT_EXPORT QwtThermo: public QwtAbstractScale -{ - Q_OBJECT - - Q_ENUMS( ScalePosition ) - Q_ENUMS( OriginMode ) - - Q_PROPERTY( Qt::Orientation orientation - READ orientation WRITE setOrientation ) - Q_PROPERTY( ScalePosition scalePosition - READ scalePosition WRITE setScalePosition ) - Q_PROPERTY( OriginMode originMode READ originMode WRITE setOriginMode ) - - Q_PROPERTY( bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled ) - Q_PROPERTY( double alarmLevel READ alarmLevel WRITE setAlarmLevel ) - Q_PROPERTY( double origin READ origin WRITE setOrigin ) - Q_PROPERTY( int spacing READ spacing WRITE setSpacing ) - Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) - Q_PROPERTY( int pipeWidth READ pipeWidth WRITE setPipeWidth ) - Q_PROPERTY( double value READ value WRITE setValue ) - -public: - - /*! - Position of the scale - \sa setScalePosition(), setOrientation() - */ - enum ScalePosition - { - //! The slider has no scale - NoScale, - - //! The scale is right of a vertical or below of a horizontal slider - LeadingScale, - - //! The scale is left of a vertical or above of a horizontal slider - TrailingScale - }; - - /*! - Origin mode. This property specifies where the beginning of the liquid - is placed. - - \sa setOriginMode(), setOrigin() - */ - enum OriginMode - { - //! The origin is the minimum of the scale - OriginMinimum, - - //! The origin is the maximum of the scale - OriginMaximum, - - //! The origin is specified using the origin() property - OriginCustom - }; - - explicit QwtThermo( QWidget *parent = NULL ); - virtual ~QwtThermo(); - - void setOrientation( Qt::Orientation ); - Qt::Orientation orientation() const; - - void setScalePosition( ScalePosition ); - ScalePosition scalePosition() const; - - void setSpacing( int ); - int spacing() const; - - void setBorderWidth( int w ); - int borderWidth() const; - - void setOriginMode( OriginMode ); - OriginMode originMode() const; - - void setOrigin( double ); - double origin() const; - - void setFillBrush( const QBrush &b ); - QBrush fillBrush() const; - - void setAlarmBrush( const QBrush &b ); - QBrush alarmBrush() const; - - void setAlarmLevel( double v ); - double alarmLevel() const; - - void setAlarmEnabled( bool tf ); - bool alarmEnabled() const; - - void setColorMap( QwtColorMap * ); - QwtColorMap *colorMap(); - const QwtColorMap *colorMap() const; - - void setPipeWidth( int w ); - int pipeWidth() const; - - void setRangeFlags( QwtInterval::BorderFlags ); - QwtInterval::BorderFlags rangeFlags() const; - - double value() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - void setScaleDraw( QwtScaleDraw * ); - const QwtScaleDraw *scaleDraw() const; - -public Q_SLOTS: - virtual void setValue( double val ); - -protected: - virtual void drawLiquid( QPainter *, const QRect & ) const; - virtual void scaleChange(); - - virtual void paintEvent( QPaintEvent * ); - virtual void resizeEvent( QResizeEvent * ); - virtual void changeEvent( QEvent * ); - - QwtScaleDraw *scaleDraw(); - - QRect pipeRect() const; - QRect fillRect( const QRect & ) const; - QRect alarmRect( const QRect & ) const; - -private: - void layoutThermo( bool ); - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_transform.h b/include/pli_vis/third_party/qwt/qwt_transform.h deleted file mode 100644 index 7e271123c87c31c6d347c4ac9f468a31186b7e40..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_transform.h +++ /dev/null @@ -1,142 +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_TRANSFORM_H -#define QWT_TRANSFORM_H - -#include "qwt/qwt_global.h" - -/*! - \brief A transformation between coordinate systems - - QwtTransform manipulates values, when being mapped between - the scale and the paint device coordinate system. - - A transformation consists of 2 methods: - - - transform - - invTransform - - where one is is the inverse function of the other. - - When p1, p2 are the boundaries of the paint device coordinates - and s1, s2 the boundaries of the scale, QwtScaleMap uses the - following calculations: - - - p = p1 + ( p2 - p1 ) * ( T( s ) - T( s1 ) / ( T( s2 ) - T( s1 ) ); - - s = invT ( T( s1 ) + ( T( s2 ) - T( s1 ) ) * ( p - p1 ) / ( p2 - p1 ) ); -*/ -class QWT_EXPORT QwtTransform -{ -public: - QwtTransform(); - virtual ~QwtTransform(); - - /*! - Modify value to be a valid value for the transformation. - The default implementation does nothing. - */ - virtual double bounded( double value ) const; - - /*! - Transformation function - - \param value Value - \return Modified value - - \sa invTransform() - */ - virtual double transform( double value ) const = 0; - - /*! - Inverse transformation function - - \param value Value - \return Modified value - - \sa transform() - */ - virtual double invTransform( double value ) const = 0; - - //! Virtualized copy operation - virtual QwtTransform *copy() const = 0; -}; - -/*! - \brief Null transformation - - QwtNullTransform returns the values unmodified. - - */ -class QWT_EXPORT QwtNullTransform: public QwtTransform -{ -public: - QwtNullTransform(); - virtual ~QwtNullTransform(); - - virtual double transform( double value ) const; - virtual double invTransform( double value ) const; - - virtual QwtTransform *copy() const; -}; -/*! - \brief Logarithmic transformation - - QwtLogTransform modifies the values using log() and exp(). - - \note In the calculations of QwtScaleMap the base of the log function - has no effect on the mapping. So QwtLogTransform can be used - for log2(), log10() or any other logarithmic scale. - */ -class QWT_EXPORT QwtLogTransform: public QwtTransform -{ -public: - QwtLogTransform(); - virtual ~QwtLogTransform(); - - virtual double transform( double value ) const; - virtual double invTransform( double value ) const; - - virtual double bounded( double value ) const; - - virtual QwtTransform *copy() const; - -#if QT_VERSION >= 0x050400 - static const double LogMin; - static const double LogMax; -#else - QT_STATIC_CONST double LogMin; - QT_STATIC_CONST double LogMax; -#endif -}; - -/*! - \brief A transformation using pow() - - QwtPowerTransform preserves the sign of a value. - F.e. a transformation with a factor of 2 - transforms a value of -3 to -9 and v.v. Thus QwtPowerTransform - can be used for scales including negative values. - */ -class QWT_EXPORT QwtPowerTransform: public QwtTransform -{ -public: - QwtPowerTransform( double exponent ); - virtual ~QwtPowerTransform(); - - virtual double transform( double value ) const; - virtual double invTransform( double value ) const; - - virtual QwtTransform *copy() const; - -private: - const double d_exponent; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_wheel.h b/include/pli_vis/third_party/qwt/qwt_wheel.h deleted file mode 100644 index 92f1e883de5e132a019a99deba2d37b2db2c1af6..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_wheel.h +++ /dev/null @@ -1,178 +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_WHEEL_H -#define QWT_WHEEL_H - -#include "qwt/qwt_global.h" -#include <qwidget.h> - -/*! - \brief The Wheel Widget - - The wheel widget can be used to change values over a very large range - in very small steps. Using the setMass() member, it can be configured - as a flying wheel. - - The default range of the wheel is [0.0, 100.0] - - \sa The radio example. -*/ -class QWT_EXPORT QwtWheel: public QWidget -{ - Q_OBJECT - - Q_PROPERTY( Qt::Orientation orientation - READ orientation WRITE setOrientation ) - - Q_PROPERTY( double value READ value WRITE setValue ) - Q_PROPERTY( double minimum READ minimum WRITE setMinimum ) - Q_PROPERTY( double maximum READ maximum WRITE setMaximum ) - - Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep ) - Q_PROPERTY( int pageStepCount READ pageStepCount WRITE setPageStepCount ) - Q_PROPERTY( bool stepAlignment READ stepAlignment WRITE setStepAlignment ) - - Q_PROPERTY( bool tracking READ isTracking WRITE setTracking ) - Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) - Q_PROPERTY( bool inverted READ isInverted WRITE setInverted ) - - Q_PROPERTY( double mass READ mass WRITE setMass ) - Q_PROPERTY( int updateInterval READ updateInterval WRITE setUpdateInterval ) - - Q_PROPERTY( double totalAngle READ totalAngle WRITE setTotalAngle ) - Q_PROPERTY( double viewAngle READ viewAngle WRITE setViewAngle ) - Q_PROPERTY( int tickCount READ tickCount WRITE setTickCount ) - Q_PROPERTY( int wheelWidth READ wheelWidth WRITE setWheelWidth ) - Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) - Q_PROPERTY( int wheelBorderWidth READ wheelBorderWidth WRITE setWheelBorderWidth ) - -public: - explicit QwtWheel( QWidget *parent = NULL ); - virtual ~QwtWheel(); - - double value() const; - - void setOrientation( Qt::Orientation ); - Qt::Orientation orientation() const; - - double totalAngle() const; - double viewAngle() const; - - void setTickCount( int ); - int tickCount() const; - - void setWheelWidth( int ); - int wheelWidth() const; - - void setWheelBorderWidth( int ); - int wheelBorderWidth() const; - - void setBorderWidth( int ); - int borderWidth() const; - - void setInverted( bool tf ); - bool isInverted() const; - - void setWrapping( bool tf ); - bool wrapping() const; - - void setSingleStep( double ); - double singleStep() const; - - void setPageStepCount( int ); - int pageStepCount() const; - - void setStepAlignment( bool on ); - bool stepAlignment() const; - - void setRange( double vmin, double vmax ); - - void setMinimum( double min ); - double minimum() const; - - void setMaximum( double max ); - double maximum() const; - - void setUpdateInterval( int ); - int updateInterval() const; - - void setTracking( bool enable ); - bool isTracking() const; - - double mass() const; - -public Q_SLOTS: - void setValue( double ); - void setTotalAngle ( double ); - void setViewAngle( double ); - void setMass( double ); - -Q_SIGNALS: - - /*! - \brief Notify a change of value. - - When tracking is enabled this signal will be emitted every - time the value changes. - - \param value new value - \sa setTracking() - */ - void valueChanged( double value ); - - /*! - This signal is emitted when the user presses the - the wheel with the mouse - */ - void wheelPressed(); - - /*! - This signal is emitted when the user releases the mouse - */ - void wheelReleased(); - - /*! - This signal is emitted when the user moves the - wheel with the mouse. - - \param value new value - */ - void wheelMoved( double value ); - -protected: - virtual void paintEvent( QPaintEvent * ); - virtual void mousePressEvent( QMouseEvent * ); - virtual void mouseReleaseEvent( QMouseEvent * ); - virtual void mouseMoveEvent( QMouseEvent * ); - virtual void keyPressEvent( QKeyEvent * ); - virtual void wheelEvent( QWheelEvent * ); - virtual void timerEvent( QTimerEvent * ); - - void stopFlying(); - - QRect wheelRect() const; - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - - virtual void drawTicks( QPainter *, const QRectF & ); - virtual void drawWheelBackground( QPainter *, const QRectF & ); - - virtual double valueAt( const QPoint & ) const; - -private: - double alignedValue( double ) const; - double boundedValue( double ) const; - - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/qwt_widget_overlay.h b/include/pli_vis/third_party/qwt/qwt_widget_overlay.h deleted file mode 100644 index d2abf0a412d81497e1e67e321dbbddb0b4d4df95..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/qwt_widget_overlay.h +++ /dev/null @@ -1,148 +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_WIDGET_OVERLAY_H -#define QWT_WIDGET_OVERLAY_H - -#include "qwt/qwt_global.h" -#include <qwidget.h> -#include <qregion.h> - -class QPainter; - -/*! - \brief An overlay for a widget - - The main use case of an widget overlay is to avoid - heavy repaint operation of the widget below. - - F.e. in combination with the plot canvas an overlay - avoid replots as the content of the canvas can be restored from - its backing store. - - QwtWidgetOverlay is an abstract base class. Deriving classes are - supposed to reimplement the following methods: - - - drawOverlay() - - maskHint() - - Internally QwtPlotPicker uses overlays for displaying - the rubber band and the tracker text. - - \sa QwtPlotCanvas::BackingStore - */ -class QWT_EXPORT QwtWidgetOverlay: public QWidget -{ -public: - /*! - \brief Mask mode - - When using masks the widget below gets paint events for - the masked regions of the overlay only. Otherwise - Qt triggers full repaints. On less powerful hardware - ( f.e embedded systems ) - or when using the raster paint - engine on a remote desktop - bit blitting is a noticeable - operation, that needs to be avoided. - - If and how to mask depends on how expensive the calculation - of the mask is and how many pixels can be excluded by the mask. - - The default setting is MaskHint. - - \sa setMaskMode(), maskMode() - */ - enum MaskMode - { - //! Don't use a mask. - NoMask, - - /*! - \brief Use maskHint() as mask - - For many situations a fast approximation is good enough - and it is not necessary to build a more detailed mask - ( f.e the bounding rectangle of a text ). - */ - MaskHint, - - /*! - \brief Calculate a mask by checking the alpha values - - Sometimes it is not possible to give a fast approximation - and the mask needs to be calculated by drawing the overlay - and testing the result. - - When a valid maskHint() is available - only pixels inside this approximation are checked. - */ - AlphaMask - }; - - /*! - \brief Render mode - - For calculating the alpha mask the overlay has already - been painted to a temporary QImage. Instead of rendering - the overlay twice this buffer can be copied for drawing - the overlay. - - On graphic systems using the raster paint engine ( QWS, Windows ) - it means usually copying some memory only. On X11 it results in an - expensive operation building a pixmap and for simple overlays - it might not be recommended. - - \note The render mode has no effect, when maskMode() != AlphaMask. - */ - enum RenderMode - { - //! Copy the buffer, when using the raster paint engine. - AutoRenderMode, - - //! Always copy the buffer - CopyAlphaMask, - - //! Never copy the buffer - DrawOverlay - }; - - QwtWidgetOverlay( QWidget* ); - virtual ~QwtWidgetOverlay(); - - void setMaskMode( MaskMode ); - MaskMode maskMode() const; - - void setRenderMode( RenderMode ); - RenderMode renderMode() const; - - void updateOverlay(); - - virtual bool eventFilter( QObject *, QEvent *); - -protected: - virtual void paintEvent( QPaintEvent* event ); - virtual void resizeEvent( QResizeEvent* event ); - - virtual QRegion maskHint() const; - - /*! - Draw the widget overlay - \param painter Painter - */ - virtual void drawOverlay( QPainter *painter ) const = 0; - -private: - void updateMask(); - void draw( QPainter * ) const; - -private: - class PrivateData; - PrivateData *d_data; -}; - -#endif diff --git a/include/pli_vis/third_party/qwt/src.pri b/include/pli_vis/third_party/qwt/src.pri deleted file mode 100644 index 65d79a397eb5c0661e2acfd3261a37b623802a01..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/src.pri +++ /dev/null @@ -1,247 +0,0 @@ -################################################################ -# 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 -################################################################ - - -HEADERS += \ - qwt.h \ - qwt_abstract_scale_draw.h \ - qwt_clipper.h \ - qwt_color_map.h \ - qwt_compat.h \ - qwt_column_symbol.h \ - qwt_date.h \ - qwt_date_scale_draw.h \ - qwt_date_scale_engine.h \ - qwt_dyngrid_layout.h \ - qwt_global.h \ - qwt_graphic.h \ - qwt_interval.h \ - qwt_interval_symbol.h \ - qwt_math.h \ - qwt_magnifier.h \ - qwt_null_paintdevice.h \ - qwt_painter.h \ - qwt_painter_command.h \ - qwt_panner.h \ - qwt_picker.h \ - qwt_picker_machine.h \ - qwt_pixel_matrix.h \ - qwt_point_3d.h \ - qwt_point_polar.h \ - qwt_round_scale_draw.h \ - qwt_scale_div.h \ - qwt_scale_draw.h \ - qwt_scale_engine.h \ - qwt_scale_map.h \ - qwt_spline.h \ - qwt_symbol.h \ - qwt_system_clock.h \ - qwt_text_engine.h \ - qwt_text_label.h \ - qwt_text.h \ - qwt_transform.h \ - qwt_widget_overlay.h - -SOURCES += \ - qwt_abstract_scale_draw.cpp \ - qwt_clipper.cpp \ - qwt_color_map.cpp \ - qwt_column_symbol.cpp \ - qwt_date.cpp \ - qwt_date_scale_draw.cpp \ - qwt_date_scale_engine.cpp \ - qwt_dyngrid_layout.cpp \ - qwt_event_pattern.cpp \ - qwt_graphic.cpp \ - qwt_interval.cpp \ - qwt_interval_symbol.cpp \ - qwt_math.cpp \ - qwt_magnifier.cpp \ - qwt_null_paintdevice.cpp \ - qwt_painter.cpp \ - qwt_painter_command.cpp \ - qwt_panner.cpp \ - qwt_picker.cpp \ - qwt_picker_machine.cpp \ - qwt_pixel_matrix.cpp \ - qwt_point_3d.cpp \ - qwt_point_polar.cpp \ - qwt_round_scale_draw.cpp \ - qwt_scale_div.cpp \ - qwt_scale_draw.cpp \ - qwt_scale_map.cpp \ - qwt_spline.cpp \ - qwt_scale_engine.cpp \ - qwt_symbol.cpp \ - qwt_system_clock.cpp \ - qwt_text_engine.cpp \ - qwt_text_label.cpp \ - qwt_text.cpp \ - qwt_transform.cpp \ - qwt_widget_overlay.cpp - - -contains(QWT_CONFIG, QwtPlot) { - - HEADERS += \ - qwt_curve_fitter.h \ - qwt_event_pattern.h \ - qwt_abstract_legend.h \ - qwt_legend.h \ - qwt_legend_data.h \ - qwt_legend_label.h \ - qwt_plot.h \ - qwt_plot_renderer.h \ - qwt_plot_curve.h \ - qwt_plot_dict.h \ - qwt_plot_directpainter.h \ - qwt_plot_grid.h \ - qwt_plot_histogram.h \ - qwt_plot_item.h \ - qwt_plot_abstract_barchart.h \ - qwt_plot_barchart.h \ - qwt_plot_multi_barchart.h \ - qwt_plot_intervalcurve.h \ - qwt_plot_tradingcurve.h \ - qwt_plot_layout.h \ - qwt_plot_marker.h \ - qwt_plot_zoneitem.h \ - qwt_plot_textlabel.h \ - qwt_plot_rasteritem.h \ - qwt_plot_spectrogram.h \ - qwt_plot_spectrocurve.h \ - qwt_plot_scaleitem.h \ - qwt_plot_legenditem.h \ - qwt_plot_seriesitem.h \ - qwt_plot_shapeitem.h \ - qwt_plot_canvas.h \ - qwt_plot_panner.h \ - qwt_plot_picker.h \ - qwt_plot_zoomer.h \ - qwt_plot_magnifier.h \ - qwt_plot_rescaler.h \ - qwt_point_mapper.h \ - qwt_raster_data.h \ - qwt_matrix_raster_data.h \ - qwt_sampling_thread.h \ - qwt_samples.h \ - qwt_series_data.h \ - qwt_series_store.h \ - qwt_point_data.h \ - qwt_scale_widget.h - - SOURCES += \ - qwt_curve_fitter.cpp \ - qwt_abstract_legend.cpp \ - qwt_legend.cpp \ - qwt_legend_data.cpp \ - qwt_legend_label.cpp \ - qwt_plot.cpp \ - qwt_plot_renderer.cpp \ - qwt_plot_xml.cpp \ - qwt_plot_axis.cpp \ - qwt_plot_curve.cpp \ - qwt_plot_dict.cpp \ - qwt_plot_directpainter.cpp \ - qwt_plot_grid.cpp \ - qwt_plot_histogram.cpp \ - qwt_plot_item.cpp \ - qwt_plot_abstract_barchart.cpp \ - qwt_plot_barchart.cpp \ - qwt_plot_multi_barchart.cpp \ - qwt_plot_intervalcurve.cpp \ - qwt_plot_zoneitem.cpp \ - qwt_plot_tradingcurve.cpp \ - qwt_plot_spectrogram.cpp \ - qwt_plot_spectrocurve.cpp \ - qwt_plot_scaleitem.cpp \ - qwt_plot_legenditem.cpp \ - qwt_plot_seriesitem.cpp \ - qwt_plot_shapeitem.cpp \ - qwt_plot_marker.cpp \ - qwt_plot_textlabel.cpp \ - qwt_plot_layout.cpp \ - qwt_plot_canvas.cpp \ - qwt_plot_panner.cpp \ - qwt_plot_rasteritem.cpp \ - qwt_plot_picker.cpp \ - qwt_plot_zoomer.cpp \ - qwt_plot_magnifier.cpp \ - qwt_plot_rescaler.cpp \ - qwt_point_mapper.cpp \ - qwt_raster_data.cpp \ - qwt_matrix_raster_data.cpp \ - qwt_sampling_thread.cpp \ - qwt_series_data.cpp \ - qwt_point_data.cpp \ - qwt_scale_widget.cpp -} - -greaterThan(QT_MAJOR_VERSION, 4) { - - QT += printsupport - QT += concurrent -} - -contains(QWT_CONFIG, QwtSvg) { - - QT += svg - - HEADERS += qwt_plot_svgitem.h - SOURCES += qwt_plot_svgitem.cpp -} -else { - - DEFINES += QWT_NO_SVG -} - -contains(QWT_CONFIG, QwtOpenGL) { - - QT += opengl - - HEADERS += qwt_plot_glcanvas.h - SOURCES += qwt_plot_glcanvas.cpp -} -else { - - DEFINES += QWT_NO_OPENGL -} - -contains(QWT_CONFIG, QwtWidgets) { - - HEADERS += \ - qwt_abstract_slider.h \ - qwt_abstract_scale.h \ - qwt_arrow_button.h \ - qwt_analog_clock.h \ - qwt_compass.h \ - qwt_compass_rose.h \ - qwt_counter.h \ - qwt_dial.h \ - qwt_dial_needle.h \ - qwt_knob.h \ - qwt_slider.h \ - qwt_thermo.h \ - qwt_wheel.h - - SOURCES += \ - qwt_abstract_slider.cpp \ - qwt_abstract_scale.cpp \ - qwt_arrow_button.cpp \ - qwt_analog_clock.cpp \ - qwt_compass.cpp \ - qwt_compass_rose.cpp \ - qwt_counter.cpp \ - qwt_dial.cpp \ - qwt_dial_needle.cpp \ - qwt_knob.cpp \ - qwt_slider.cpp \ - qwt_thermo.cpp \ - qwt_wheel.cpp -} diff --git a/include/pli_vis/third_party/qwt/src.pro b/include/pli_vis/third_party/qwt/src.pro deleted file mode 100644 index a352b9921dbcc372090f7a7a538867773d0a0742..0000000000000000000000000000000000000000 --- a/include/pli_vis/third_party/qwt/src.pro +++ /dev/null @@ -1,103 +0,0 @@ -################################################################ -# 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 project file for building the qwt libraries - -QWT_ROOT = $${PWD}/.. -include( $${QWT_ROOT}/qwtconfig.pri ) -include( $${QWT_ROOT}/qwtbuild.pri ) -include( $${QWT_ROOT}/qwtfunctions.pri ) - -QWT_OUT_ROOT = $${OUT_PWD}/.. - -TEMPLATE = lib -TARGET = $$qwtLibraryTarget(qwt) - -DESTDIR = $${QWT_OUT_ROOT}/lib - -contains(QWT_CONFIG, QwtDll) { - - CONFIG += dll - win32|symbian: DEFINES += QT_DLL QWT_DLL QWT_MAKEDLL -} -else { - CONFIG += staticlib -} - -contains(QWT_CONFIG, QwtFramework) { - - CONFIG += lib_bundle -} - -include ( $${PWD}/src.pri ) - -# Install directives - -target.path = $${QWT_INSTALL_LIBS} -INSTALLS = target - -CONFIG(lib_bundle) { - - FRAMEWORK_HEADERS.version = Versions - FRAMEWORK_HEADERS.files = $${HEADERS} - FRAMEWORK_HEADERS.path = Headers - QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS -} -else { - - headers.files = $${HEADERS} - headers.path = $${QWT_INSTALL_HEADERS} - INSTALLS += headers -} - -contains(QWT_CONFIG, QwtPkgConfig) { - - CONFIG += create_pc create_prl no_install_prl - - QMAKE_PKGCONFIG_NAME = Qwt$${QWT_VER_MAJ} - QMAKE_PKGCONFIG_DESCRIPTION = Qt Widgets for Technical Applications - - QMAKE_PKGCONFIG_LIBDIR = $${QWT_INSTALL_LIBS} - QMAKE_PKGCONFIG_INCDIR = $${QWT_INSTALL_HEADERS} - - QMAKE_PKGCONFIG_DESTDIR = pkgconfig - - greaterThan(QT_MAJOR_VERSION, 4) { - - QMAKE_PKGCONFIG_FILE = Qt$${QT_MAJOR_VERSION}$${QMAKE_PKGCONFIG_NAME} - QMAKE_PKGCONFIG_REQUIRES = Qt5Widgets Qt5Concurrent Qt5PrintSupport - - contains(QWT_CONFIG, QwtSvg) { - QMAKE_PKGCONFIG_REQUIRES += Qt5Svg - } - - contains(QWT_CONFIG, QwtOpenGL) { - QMAKE_PKGCONFIG_REQUIRES += Qt5OpenGL - } - - QMAKE_DISTCLEAN += $${DESTDIR}/$${QMAKE_PKGCONFIG_DESTDIR}/$${QMAKE_PKGCONFIG_FILE}.pc - } - else { - - # there is no QMAKE_PKGCONFIG_FILE fo Qt4 - QMAKE_PKGCONFIG_REQUIRES = QtGui - - contains(QWT_CONFIG, QwtSvg) { - QMAKE_PKGCONFIG_REQUIRES += QtSvg - } - - contains(QWT_CONFIG, QwtOpenGL) { - QMAKE_PKGCONFIG_REQUIRES += QtOpenGL - } - - QMAKE_DISTCLEAN += $${DESTDIR}/$${QMAKE_PKGCONFIG_DESTDIR}/$${TARGET}.pc - } - - QMAKE_DISTCLEAN += $${DESTDIR}/libqwt.prl -} diff --git a/include/pli_vis/third_party/stb/stb_image_write.h b/include/pli_vis/third_party/stb/stb_image_write.h new file mode 100644 index 0000000000000000000000000000000000000000..1a460f9777dc5c9c0afc5946b2c4318dbeff3f62 --- /dev/null +++ b/include/pli_vis/third_party/stb/stb_image_write.h @@ -0,0 +1,1459 @@ +/* stb_image_write - v1.07 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicity, not optimal image file size + or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + +USAGE: + + There are four functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data); + + There are also four equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + misc enhancements: + Tim Kelsey + TGA RLE + Alan Hickman + initial file IO callback implementation + Emmanuel Julien + JPEG + Jon Olick (original jo_jpeg.cpp code) + Daniel Gibson + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +extern int stbi_write_tga_with_rle; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include <stdio.h> +#endif // STBI_WRITE_NO_STDIO + +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include <assert.h> +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + for (j = y - 1; j >= 0; --j) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (j != 0) ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + f = fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<<bits[1])-1); +} + +static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) { + const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] }; + const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] }; + int dataOff, i, diff, end0pos; + int DU[64]; + + // DCT rows + for(dataOff=0; dataOff<64; dataOff+=8) { + stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]); + } + // DCT columns + for(dataOff=0; dataOff<8; ++dataOff) { + stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]); + } + // Quantize/descale/zigzag the coefficients + for(i=0; i<64; ++i) { + float v = CDU[i]*fdtbl[i]; + // DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f)); + // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway? + DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f); + } + + // Encode DC + diff = DU[0] - DC; + if (diff == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]); + } else { + unsigned short bits[2]; + stbiw__jpg_calcBits(diff, bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + // Encode ACs + end0pos = 63; + for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + const unsigned char *imageData = (const unsigned char *)data; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + int x, y, pos; + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float YDU[64], UDU[64], VDU[64]; + for(row = y, pos = 0; row < y+8; ++row) { + for(col = x; col < x+8; ++col, ++pos) { + int p = row*width*comp + col*comp; + float r, g, b; + if(row >= height) { + p -= width*comp*(row+1 - height); + } + if(col >= width) { + p -= comp*(col+1 - width); + } + + r = imageData[p+0]; + g = imageData[p+ofsG]; + b = imageData[p+ofsB]; + YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; + UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; + VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ + diff --git a/include/pli_vis/ui/plugins/color_plugin.hpp b/include/pli_vis/ui/plugins/color_plugin.hpp index 2e95f902c219df42d00b5cf68e3d6b0e7a20b69d..ec0f8ced168921c221aac3b7d879b5c5f77c4f4c 100644 --- a/include/pli_vis/ui/plugins/color_plugin.hpp +++ b/include/pli_vis/ui/plugins/color_plugin.hpp @@ -16,9 +16,13 @@ signals : public: explicit color_plugin(QWidget* parent = nullptr); - int mode () const; - float k () const; - bool inverted() const; + int mode () const; + float k () const; + bool inverted () const; + + void set_mode (const int mode ); + void set_k (const float k ); + void set_inverted(const bool inverted); }; } diff --git a/include/pli_vis/ui/plugins/data_plugin.hpp b/include/pli_vis/ui/plugins/data_plugin.hpp index 7abe881b2606597aa2e1c08c0920635c3a4748bc..84ce7a222261ea699ebacba9ba29b4465389d4fa 100644 --- a/include/pli_vis/ui/plugins/data_plugin.hpp +++ b/include/pli_vis/ui/plugins/data_plugin.hpp @@ -67,15 +67,27 @@ public: { return *unit_vector_; } - + + const std::string& filepath() const + { + return io_.filepath(); + } + std::array<std::size_t, 3> selection_offset() const; + std::array<std::size_t, 3> selection_bounds() const; std::array<std::size_t, 3> selection_size () const; std::array<std::size_t, 3> selection_stride() const; boost::multi_array<unsigned char, 2> generate_preview_image (std::size_t x_resolution = 2048 ); boost::multi_array<unsigned char, 2> generate_selection_image(std::size_t x_resolution = 2048 ); boost::multi_array<float3, 3> generate_vectors (bool cartesian = false); - + + void unserialize( + const std::string& file , + const std::array<std::size_t, 3>& offset, + const std::array<std::size_t, 3>& bounds, + const std::array<std::size_t, 3>& stride); + signals: void on_load(); diff --git a/include/pli_vis/ui/plugins/demo_plugin.hpp b/include/pli_vis/ui/plugins/demo_plugin.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d5492fe078f0dee12b9320af6ecf02826f9906bc --- /dev/null +++ b/include/pli_vis/ui/plugins/demo_plugin.hpp @@ -0,0 +1,31 @@ +#ifndef PLI_VIS_DEMO_PLUGIN_HPP_ +#define PLI_VIS_DEMO_PLUGIN_HPP_ + +#include <pli_vis/ui/plugin.hpp> +#include <ui_demo_toolbox.h> + +namespace pli +{ +class demo_plugin : public plugin<demo_plugin, Ui_demo_toolbox> +{ +public: + explicit demo_plugin (QWidget* parent = nullptr); + demo_plugin (const demo_plugin& that) = delete ; + demo_plugin ( demo_plugin&& temp) = default; + virtual ~demo_plugin () = default; + demo_plugin& operator=(const demo_plugin& that) = delete ; + demo_plugin& operator=( demo_plugin&& temp) = default; + +protected: + void start () override; + + void create_default() const; + void load_preset (std::size_t index) const; + void save_preset (std::size_t index) const; + + std::vector<QPushButton*> buttons_ ; + std::string presets_filepath_ = "presets.json"; +}; +} + +#endif \ No newline at end of file diff --git a/include/pli_vis/ui/plugins/demo_toolbox.ui b/include/pli_vis/ui/plugins/demo_toolbox.ui new file mode 100644 index 0000000000000000000000000000000000000000..e90f579a2c972de4f46444509131d370b4fbc59a --- /dev/null +++ b/include/pli_vis/ui/plugins/demo_toolbox.ui @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>demo_toolbox</class> + <widget class="QWidget" name="demo_toolbox"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>478</width> + <height>155</height> + </rect> + </property> + <property name="windowTitle"> + <string>Demo Toolbox</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="text_presets"> + <property name="text"> + <string>Presets</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QPushButton" name="button_1"> + <property name="text"> + <string>1</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="button_2"> + <property name="text"> + <string>2</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="button_3"> + <property name="text"> + <string>3</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QPushButton" name="button_4"> + <property name="text"> + <string>4</string> + </property> + </widget> + </item> + <item row="0" column="4"> + <widget class="QPushButton" name="button_5"> + <property name="text"> + <string>5</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="button_6"> + <property name="text"> + <string>6</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="button_7"> + <property name="text"> + <string>7</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="button_8"> + <property name="text"> + <string>8</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QPushButton" name="button_9"> + <property name="text"> + <string>9</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QPushButton" name="button_10"> + <property name="text"> + <string>10</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="text_description"> + <property name="text"> + <string>Description</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPlainTextEdit" name="text_content"/> + </item> + <item row="2" column="0" colspan="2"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>188</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/include/pli_vis/ui/plugins/global_tractography_plugin.hpp b/include/pli_vis/ui/plugins/global_tractography_plugin.hpp deleted file mode 100644 index ddad5f5cd49835d36839a2e7a5136bf5b8ba7f54..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/plugins/global_tractography_plugin.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef PLI_VIS_GLOBAL_TRACTOGRAPHY_PLUGIN_HPP_ -#define PLI_VIS_GLOBAL_TRACTOGRAPHY_PLUGIN_HPP_ - -#include <future> - -#include <pli_vis/ui/plugin.hpp> -#include <pli_vis/visualization/algorithms/streamline_renderer.hpp> -#include <ui_global_tractography_toolbox.h> - -namespace pli -{ -class global_tractography_plugin : public plugin<global_tractography_plugin, Ui_global_tractography_toolbox> -{ -public: - explicit global_tractography_plugin(QWidget* parent = nullptr); - - void start() override; - -protected: - void trace(); - - std::future<void> future_; - streamline_renderer* streamline_renderer_ = nullptr; -}; -} - -#endif \ No newline at end of file diff --git a/include/pli_vis/ui/plugins/global_tractography_toolbox.ui b/include/pli_vis/ui/plugins/global_tractography_toolbox.ui deleted file mode 100644 index a617302823a94f0b2f39a4f7bfffb62fc5c751be..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/plugins/global_tractography_toolbox.ui +++ /dev/null @@ -1,76 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>global_tractography_toolbox</class> - <widget class="QWidget" name="global_tractography_toolbox"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>345</width> - <height>81</height> - </rect> - </property> - <property name="windowTitle"> - <string>Global Tractography Toolbox</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_enabled"> - <property name="text"> - <string>Enabled</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QCheckBox" name="checkbox_enabled"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0" colspan="2"> - <widget class="QPushButton" name="button_trace_selection"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Trace Selection</string> - </property> - </widget> - </item> - <item row="2" column="0" colspan="2"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>318</width> - <height>12</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/include/pli_vis/ui/plugins/interactor_toolbox.ui b/include/pli_vis/ui/plugins/interactor_toolbox.ui index 2ab80dc6f99a3bfd56ebb5375beee8945defb729..b583644489d93462c78b40b5d0151d9863e76a03 100644 --- a/include/pli_vis/ui/plugins/interactor_toolbox.ui +++ b/include/pli_vis/ui/plugins/interactor_toolbox.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>253</width> - <height>188</height> + <height>147</height> </rect> </property> <property name="windowTitle"> @@ -27,7 +27,7 @@ </property> </widget> </item> - <item row="0" column="1" colspan="2"> + <item row="0" column="1"> <widget class="QSplitter" name="splitter_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -40,11 +40,6 @@ <bool>true</bool> </property> </widget> - <widget class="QRadioButton" name="radio_button_orbit"> - <property name="text"> - <string>Orbit</string> - </property> - </widget> <widget class="QRadioButton" name="radio_button_wasd"> <property name="text"> <string>WASD</string> @@ -53,42 +48,6 @@ </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label_projection"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Projection</string> - </property> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QSplitter" name="splitter"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <widget class="QRadioButton" name="radio_button_perspective"> - <property name="text"> - <string>Perspective</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - <widget class="QRadioButton" name="radio_button_orthographic"> - <property name="text"> - <string>Orthographic</string> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </widget> - </item> - <item row="2" column="0"> <widget class="QLabel" name="label_move_speed"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -101,7 +60,7 @@ </property> </widget> </item> - <item row="2" column="1"> + <item row="1" column="1"> <widget class="QSlider" name="slider_move_speed"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -129,7 +88,7 @@ </property> </widget> </item> - <item row="2" column="2"> + <item row="1" column="2"> <widget class="QLineEdit" name="line_edit_move_speed"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -148,7 +107,7 @@ </property> </widget> </item> - <item row="3" column="0"> + <item row="2" column="0"> <widget class="QLabel" name="label_look_speed"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -161,7 +120,7 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="2" column="1"> <widget class="QSlider" name="slider_look_speed"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -186,7 +145,7 @@ </property> </widget> </item> - <item row="3" column="2"> + <item row="2" column="2"> <widget class="QLineEdit" name="line_edit_look_speed"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -205,7 +164,7 @@ </property> </widget> </item> - <item row="4" column="0" colspan="3"> + <item row="3" column="0" colspan="3"> <widget class="QPushButton" name="button_reset_camera"> <property name="enabled"> <bool>true</bool> @@ -221,7 +180,7 @@ </property> </widget> </item> - <item row="5" column="1"> + <item row="4" column="1"> <spacer name="spacer"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/include/pli_vis/ui/plugins/local_tractography_plugin.hpp b/include/pli_vis/ui/plugins/local_tractography_plugin.hpp index 1b82a37718d6f5b7797900a656823e6dc3b85b52..817845c3a781c1ae4e05233145a79b3425aca7a1 100644 --- a/include/pli_vis/ui/plugins/local_tractography_plugin.hpp +++ b/include/pli_vis/ui/plugins/local_tractography_plugin.hpp @@ -1,7 +1,12 @@ #ifndef PLI_VIS_LOCAL_TRACTOGRAPHY_PLUGIN_HPP_ #define PLI_VIS_LOCAL_TRACTOGRAPHY_PLUGIN_HPP_ +#include <cstddef> #include <future> +#include <memory> +#include <vector> + +#include <vector_types.h> #include <pli_vis/aspects/renderable.hpp> #include <pli_vis/ui/plugin.hpp> @@ -9,24 +14,41 @@ namespace pli { +class remote_viewer; class local_tractography_plugin : public plugin<local_tractography_plugin, Ui_local_tractography_toolbox> { public: explicit local_tractography_plugin(QWidget* parent = nullptr); void start() override; - -private: - void trace(); - + std::array<std::size_t, 3> seed_offset() const; std::array<std::size_t, 3> seed_size () const; std::array<std::size_t, 3> seed_stride() const; + + float step () const + { + return float(slider_integration_step->value()) / slider_integration_step->maximum(); + } + std::size_t iterations() const + { + return slider_iterations->value(); + } + float streamline_radius () const + { + return float(slider_streamline_radius->value()) / slider_streamline_radius->maximum(); + } - renderable* streamline_renderer_; - std::future<void> future_ ; - bool line_ao_ = false; - bool gpu_tracing_ = true ; +private: + void trace(); + void remote_trace(); + + std::vector<float4> vertices_ ; + std::vector<float4> tangents_ ; + std::vector<unsigned> indices_ ; + renderable* streamline_renderer_; + std::future<void> future_ ; + std::unique_ptr<remote_viewer> remote_viewer_ = nullptr; }; } diff --git a/include/pli_vis/ui/plugins/local_tractography_toolbox.ui b/include/pli_vis/ui/plugins/local_tractography_toolbox.ui index 7920201e6ff8a8f57bcd54b31ef77ef9c1864ca6..fb17e9cbb3d0326ee907cdb37617330ab767b377 100644 --- a/include/pli_vis/ui/plugins/local_tractography_toolbox.ui +++ b/include/pli_vis/ui/plugins/local_tractography_toolbox.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>337</width> - <height>480</height> + <height>615</height> </rect> </property> <property name="windowTitle"> @@ -40,7 +40,7 @@ </property> </widget> </item> - <item row="1" column="0" colspan="5"> + <item row="1" column="0" colspan="4"> <widget class="QxtLetterBoxWidget" name="letterbox"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> @@ -507,7 +507,7 @@ </layout> </widget> </item> - <item row="2" column="0" colspan="5"> + <item row="2" column="0" colspan="4"> <layout class="QGridLayout" name="gridLayout_4"> <item row="0" column="1"> <widget class="QLabel" name="label_offset"> @@ -1025,7 +1025,7 @@ </property> </widget> </item> - <item row="3" column="2" colspan="2"> + <item row="3" column="2"> <widget class="QSlider" name="slider_integration_step"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -1053,7 +1053,7 @@ </property> </widget> </item> - <item row="3" column="4"> + <item row="3" column="3"> <widget class="QLineEdit" name="line_edit_integration_step"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -1073,7 +1073,7 @@ </property> </widget> </item> - <item row="4" column="2" colspan="2"> + <item row="4" column="2"> <widget class="QSlider" name="slider_iterations"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -1101,7 +1101,7 @@ </property> </widget> </item> - <item row="4" column="4"> + <item row="4" column="3"> <widget class="QLineEdit" name="line_edit_iterations"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -1114,82 +1114,137 @@ </property> </widget> </item> - <item row="5" column="3" colspan="2"> - <widget class="QGroupBox" name="groupBox_2"> - <property name="enabled"> - <bool>true</bool> + <item row="5" column="0" colspan="2"> + <widget class="QLabel" name="label_streamline_radius"> + <property name="text"> + <string>Streamline Radius</string> </property> + </widget> + </item> + <item row="5" column="2"> + <widget class="QSlider" name="slider_streamline_radius"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>4</horstretch> + <verstretch>0</verstretch> </sizepolicy> </property> - <property name="title"> - <string>Shading</string> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="value"> + <number>1000</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>6</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QRadioButton" name="radio_button_regular"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Regular</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="radio_button_lineao"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Line AO</string> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> </widget> </item> - <item row="6" column="0" colspan="5"> - <widget class="QPushButton" name="button_trace_selection"> - <property name="enabled"> - <bool>true</bool> + <item row="5" column="3"> + <widget class="QLineEdit" name="line_edit_streamline_radius"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="placeholderText"> + <string>0.1</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2"> + <widget class="QLabel" name="label_remote_address"> + <property name="text"> + <string>Remote Address</string> </property> + </widget> + </item> + <item row="6" column="2" colspan="2"> + <widget class="QLineEdit" name="line_edit_remote_address"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>1</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string>Trace Selection</string> + <string/> + </property> + <property name="placeholderText"> + <string>tcp://linuxihdc090.rz.rwth-aachen.de:14130</string> </property> </widget> </item> - <item row="7" column="0"> + <item row="7" column="0" colspan="2"> + <widget class="QLabel" name="label_dataset_folder"> + <property name="text"> + <string>Remote Folder</string> + </property> + </widget> + </item> + <item row="7" column="2" colspan="2"> + <widget class="QLineEdit" name="line_edit_dataset_folder"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>/home/ad784563/data/</string> + </property> + </widget> + </item> + <item row="8" column="0" colspan="4"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="button_local_trace"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Local Trace</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_remote_trace"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Remote Trace</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="9" column="0"> <spacer name="spacer_vertical"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -1202,53 +1257,6 @@ </property> </spacer> </item> - <item row="5" column="0" colspan="3"> - <widget class="QGroupBox" name="groupBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Device</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>6</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QRadioButton" name="radio_button_gpu"> - <property name="text"> - <string>GPU</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="radio_button_cpu"> - <property name="text"> - <string>CPU</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> </layout> </widget> <customwidgets> @@ -1287,11 +1295,12 @@ <tabstop>line_edit_integration_step</tabstop> <tabstop>slider_iterations</tabstop> <tabstop>line_edit_iterations</tabstop> - <tabstop>radio_button_gpu</tabstop> - <tabstop>radio_button_cpu</tabstop> - <tabstop>radio_button_regular</tabstop> - <tabstop>radio_button_lineao</tabstop> - <tabstop>button_trace_selection</tabstop> + <tabstop>slider_streamline_radius</tabstop> + <tabstop>line_edit_streamline_radius</tabstop> + <tabstop>line_edit_remote_address</tabstop> + <tabstop>line_edit_dataset_folder</tabstop> + <tabstop>button_local_trace</tabstop> + <tabstop>button_remote_trace</tabstop> </tabstops> <resources/> <connections/> diff --git a/include/pli_vis/ui/plugins/odf_plugin.hpp b/include/pli_vis/ui/plugins/odf_plugin.hpp index 8fc8f5ce63a95ede890619c861da552e8c36c99d..935e197f3f48a3cccfa193d248066e57fdad35c2 100644 --- a/include/pli_vis/ui/plugins/odf_plugin.hpp +++ b/include/pli_vis/ui/plugins/odf_plugin.hpp @@ -23,13 +23,9 @@ public: private: void calculate (); - void extract_peaks (); void set_visible_layers() const; - float threshold_multiplier_ = 0.01F; - std::size_t maxima_count_ = 3; boost::multi_array<float , 4> coefficients_; - boost::multi_array<float3, 4> maxima_ ; odf_field* odf_field_ ; std::future<void> future_ ; cusolverDnHandle_t cusolver_ ; diff --git a/include/pli_vis/ui/plugins/odf_toolbox.ui b/include/pli_vis/ui/plugins/odf_toolbox.ui index 144e64a8a9982f3ab807342d9519b34ee3ee987b..aab87587c25b885adf07c280d2aaf283b7624325 100644 --- a/include/pli_vis/ui/plugins/odf_toolbox.ui +++ b/include/pli_vis/ui/plugins/odf_toolbox.ui @@ -64,7 +64,7 @@ </property> </widget> </item> - <item row="2" column="1" colspan="2"> + <item row="2" column="1"> <widget class="QSlider" name="slider_vector_block_x"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -98,7 +98,7 @@ </property> </widget> </item> - <item row="2" column="3"> + <item row="2" column="2"> <widget class="QLineEdit" name="line_edit_vector_block_x"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -127,7 +127,7 @@ </property> </widget> </item> - <item row="3" column="1" colspan="2"> + <item row="3" column="1"> <widget class="QSlider" name="slider_vector_block_y"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -155,7 +155,7 @@ </property> </widget> </item> - <item row="3" column="3"> + <item row="3" column="2"> <widget class="QLineEdit" name="line_edit_vector_block_y"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -184,7 +184,7 @@ </property> </widget> </item> - <item row="4" column="1" colspan="2"> + <item row="4" column="1"> <widget class="QSlider" name="slider_vector_block_z"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -212,7 +212,7 @@ </property> </widget> </item> - <item row="4" column="3"> + <item row="4" column="2"> <widget class="QLineEdit" name="line_edit_vector_block_z"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -241,7 +241,7 @@ </property> </widget> </item> - <item row="5" column="1" colspan="2"> + <item row="5" column="1"> <widget class="QSlider" name="slider_histogram_theta"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -266,7 +266,7 @@ </property> </widget> </item> - <item row="5" column="3"> + <item row="5" column="2"> <widget class="QLineEdit" name="line_edit_histogram_theta"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -295,7 +295,7 @@ </property> </widget> </item> - <item row="6" column="1" colspan="2"> + <item row="6" column="1"> <widget class="QSlider" name="slider_histogram_phi"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -320,7 +320,7 @@ </property> </widget> </item> - <item row="6" column="3"> + <item row="6" column="2"> <widget class="QLineEdit" name="line_edit_histogram_phi"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -349,7 +349,7 @@ </property> </widget> </item> - <item row="7" column="1" colspan="2"> + <item row="7" column="1"> <widget class="QSlider" name="slider_maximum_sh_degree"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -374,7 +374,7 @@ </property> </widget> </item> - <item row="7" column="3"> + <item row="7" column="2"> <widget class="QLineEdit" name="line_edit_maximum_sh_degree"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -403,7 +403,7 @@ </property> </widget> </item> - <item row="8" column="1" colspan="2"> + <item row="8" column="1"> <widget class="QSlider" name="slider_sampling_theta"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -428,7 +428,7 @@ </property> </widget> </item> - <item row="8" column="3"> + <item row="8" column="2"> <widget class="QLineEdit" name="line_edit_sampling_theta"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -457,7 +457,7 @@ </property> </widget> </item> - <item row="9" column="1" colspan="2"> + <item row="9" column="1"> <widget class="QSlider" name="slider_sampling_phi"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -482,7 +482,7 @@ </property> </widget> </item> - <item row="9" column="3"> + <item row="9" column="2"> <widget class="QLineEdit" name="line_edit_sampling_phi"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -537,7 +537,7 @@ </property> </widget> </item> - <item row="11" column="1" colspan="3"> + <item row="11" column="1" colspan="2"> <widget class="QWidget" name="layout_layer_checkboxes" native="true"> <property name="enabled"> <bool>false</bool> @@ -664,110 +664,14 @@ </layout> </widget> </item> - <item row="12" column="0"> - <widget class="QLabel" name="label_clustering_enabled"> - <property name="text"> - <string>Clustering</string> - </property> - </widget> - </item> - <item row="12" column="1"> - <widget class="QCheckBox" name="checkbox_clustering_enabled"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="toolTip"> - <string>See [HDAG2017].</string> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="13" column="0"> - <widget class="QLabel" name="label_threshold"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Threshold</string> - </property> - </widget> - </item> - <item row="13" column="1" colspan="2"> - <widget class="QSlider" name="slider_threshold"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="toolTip"> - <string>See [HDAG2017].</string> - </property> - <property name="maximum"> - <number>1000</number> - </property> - <property name="value"> - <number>500</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="13" column="3"> - <widget class="QLineEdit" name="line_edit_threshold"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>0</string> - </property> - </widget> - </item> - <item row="14" column="0" colspan="2"> + <item row="12" column="0" colspan="3"> <widget class="QPushButton" name="button_calculate"> <property name="text"> <string>Calculate</string> </property> </widget> </item> - <item row="14" column="2" colspan="2"> - <widget class="QPushButton" name="button_extract_peaks"> - <property name="text"> - <string>Extract Peaks</string> - </property> - </widget> - </item> - <item row="15" column="0"> + <item row="13" column="0" colspan="3"> <spacer name="spacer"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -812,11 +716,7 @@ <tabstop>checkbox_depth_7</tabstop> <tabstop>checkbox_depth_8</tabstop> <tabstop>checkbox_depth_9</tabstop> - <tabstop>checkbox_clustering_enabled</tabstop> - <tabstop>slider_threshold</tabstop> - <tabstop>line_edit_threshold</tabstop> <tabstop>button_calculate</tabstop> - <tabstop>button_extract_peaks</tabstop> </tabstops> <resources/> <connections/> diff --git a/include/pli_vis/ui/plugins/volume_rendering_plugin.hpp b/include/pli_vis/ui/plugins/volume_rendering_plugin.hpp deleted file mode 100644 index 30a46d834280ac0d0cd9d8747426e7a66471fc12..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/plugins/volume_rendering_plugin.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PLI_VIS_VOLUME_RENDERING_PLUGIN_HPP_ -#define PLI_VIS_VOLUME_RENDERING_PLUGIN_HPP_ - -#include <pli_vis/ui/plugin.hpp> -#include <ui_volume_rendering_toolbox.h> - -namespace pli -{ -class volume_renderer; - -class volume_rendering_plugin : public plugin<volume_rendering_plugin, Ui_volume_rendering_toolbox> -{ -public: - explicit volume_rendering_plugin(QWidget* parent = nullptr); - - void start () override; - -private: - void upload(); - - volume_renderer* volume_renderer_ = nullptr; -}; -} - -#endif diff --git a/include/pli_vis/ui/plugins/volume_rendering_toolbox.ui b/include/pli_vis/ui/plugins/volume_rendering_toolbox.ui deleted file mode 100644 index b41316647b07c8c308c4b362813b3114514897c6..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/plugins/volume_rendering_toolbox.ui +++ /dev/null @@ -1,177 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>volume_rendering_toolbox</class> - <widget class="QWidget" name="volume_rendering_toolbox"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>280</width> - <height>126</height> - </rect> - </property> - <property name="windowTitle"> - <string>Volume Rendering Toolbox</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_enabled"> - <property name="text"> - <string>Enabled</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QCheckBox" name="checkbox_enabled"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_step_size"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Step Size</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSlider" name="slider_step_size"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - <property name="value"> - <number>1</number> - </property> - <property name="sliderPosition"> - <number>1</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLineEdit" name="line_edit_step_size"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>1</string> - </property> - </widget> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QLabel" name="label_transfer_function"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Transfer Function</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="3"> - <spacer name="spacer_vertical"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>258</width> - <height>130</height> - </size> - </property> - </spacer> - </item> - <item row="3" column="0" colspan="3"> - <widget class="QFrame" name="transfer_function_frame"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Sunken</enum> - </property> - <property name="lineWidth"> - <number>2</number> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="pli::transfer_function_editor" name="transfer_function_editor" native="true"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>pli::transfer_function_editor</class> - <extends>QWidget</extends> - <header location="global">pli_vis/ui/widgets/transfer_function_editor.hpp</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/include/pli_vis/ui/plugins/zernike_plugin.hpp b/include/pli_vis/ui/plugins/zernike_plugin.hpp deleted file mode 100644 index cec43ea17538f1b4527b3f1e9ba32faa99ede351..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/plugins/zernike_plugin.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PLI_VIS_ZERNIKE_PLUGIN_HPP_ -#define PLI_VIS_ZERNIKE_PLUGIN_HPP_ - -#include <future> - -#include <vector_types.h> - -#include <pli_vis/ui/plugin.hpp> -#include <ui_zernike_toolbox.h> - -namespace pli -{ -class zernike_field; - -class zernike_plugin : public plugin<zernike_plugin, Ui_zernike_toolbox> -{ -public: - struct parameters - { - uint2 vectors_size ; - uint2 superpixel_size; - uint2 partitions ; - unsigned maximum_degree ; - bool symmetric ; - bool normalize ; - bool even_only ; - bool edge_only ; - }; - - explicit zernike_plugin(QWidget* parent = nullptr); - - void start () override; - parameters get_parameters() const ; - -private: - std::future<void> future_ ; - zernike_field* zernike_field_ = nullptr; -}; -} - -#endif diff --git a/include/pli_vis/ui/plugins/zernike_toolbox.ui b/include/pli_vis/ui/plugins/zernike_toolbox.ui deleted file mode 100644 index cd5deca28d28799d7e4dc04150bd8dce66c7757d..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/plugins/zernike_toolbox.ui +++ /dev/null @@ -1,423 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>zernike_toolbox</class> - <widget class="QWidget" name="zernike_toolbox"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>312</width> - <height>427</height> - </rect> - </property> - <property name="windowTitle"> - <string>Zernike Moments Toolbox</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_enabled"> - <property name="text"> - <string>Enabled</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QCheckBox" name="checkbox_enabled"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_superpixel_x"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Superpixel X extent</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSlider" name="slider_superpixel_x"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>256</number> - </property> - <property name="singleStep"> - <number>1</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="tickPosition"> - <enum>QSlider::NoTicks</enum> - </property> - <property name="tickInterval"> - <number>1</number> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLineEdit" name="line_edit_superpixel_x"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>0</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_superpixel_y"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Superpixel Y extent</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QSlider" name="slider_superpixel_y"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>256</number> - </property> - <property name="singleStep"> - <number>1</number> - </property> - <property name="value"> - <number>64</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLineEdit" name="line_edit_superpixel_y"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>0</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_partitions_theta"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Angular partitions</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QSlider" name="slider_partitions_theta"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>360</number> - </property> - <property name="value"> - <number>60</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QLineEdit" name="line_edit_partitions_theta"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>0</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_partitions_rho"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Radial partitions</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QSlider" name="slider_partitions_rho"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>360</number> - </property> - <property name="value"> - <number>60</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QLineEdit" name="line_edit_partitions_rho"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>0</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_maximum_degree"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Maximum degree</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QSlider" name="slider_maximum_degree"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>4</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>250</number> - </property> - <property name="value"> - <number>6</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="QLineEdit" name="line_edit_maximum_degree"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="placeholderText"> - <string>0</string> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_symmetric"> - <property name="text"> - <string>Symmetric accumulation</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QCheckBox" name="checkbox_symmetric"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_normalize"> - <property name="text"> - <string>Normalize histograms</string> - </property> - </widget> - </item> - <item row="7" column="1"> - <widget class="QCheckBox" name="checkbox_normalize"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="label_even_only"> - <property name="text"> - <string>Even degrees only</string> - </property> - </widget> - </item> - <item row="8" column="1"> - <widget class="QCheckBox" name="checkbox_even_only"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="9" column="0"> - <widget class="QLabel" name="label_edge_only"> - <property name="text"> - <string>Edges only</string> - </property> - </widget> - </item> - <item row="9" column="1"> - <widget class="QCheckBox" name="checkbox_edge_only"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="10" column="0" colspan="3"> - <widget class="QPushButton" name="button_calculate"> - <property name="text"> - <string>Calculate</string> - </property> - </widget> - </item> - <item row="11" column="0" colspan="3"> - <spacer name="spacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>288</width> - <height>209</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/include/pli_vis/ui/utility/plot_interactor.hpp b/include/pli_vis/ui/utility/plot_interactor.hpp deleted file mode 100644 index e853f54651cea4219790824561ecc94d624bca04..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/utility/plot_interactor.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef PLI_VIS_PLOT_INTERACTOR_ -#define PLI_VIS_PLOT_INTERACTOR_ - -#include <QObject> - -class QCustomEvent; -class QPoint; - -class QwtPlot; -class QwtPlotCurve; - -namespace pli -{ -class plot_interactor : public QObject -{ - Q_OBJECT - -public: - plot_interactor(QwtPlot* plot); - - virtual bool eventFilter(QObject* sender, QEvent* event); - virtual bool event (QEvent* event); - -signals: - void on_change(); - -private: - void select_or_add (const QPoint& point); - void remove (const QPoint& point); - void move (const QPoint& point); - void move_by (int x, int y); - - void show_cursor (bool enable); - void shift_point_cursor(bool up ); - void shift_curve_cursor(bool up ); - - QwtPlot* plot(); - const QwtPlot* plot() const; - - QwtPlotCurve* selected_curve_; - int selected_point_; -}; -} - -#endif diff --git a/include/pli_vis/ui/widgets/remote_viewer.hpp b/include/pli_vis/ui/widgets/remote_viewer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0c9a0987b375f241ce47319b5e8d223325bada6 --- /dev/null +++ b/include/pli_vis/ui/widgets/remote_viewer.hpp @@ -0,0 +1,75 @@ +#ifndef PLI_VIS_REMOTE_VIEWER_HPP_ +#define PLI_VIS_REMOTE_VIEWER_HPP_ + +#include <array> +#include <atomic> +#include <cstddef> +#include <future> +#include <string> + +#include <boost/signals2.hpp> +#include <glm/glm.hpp> +#include <QCloseEvent> +#include <QImage> +#include <QKeyEvent> +#include <QLabel> +#include <QMouseEvent> +#include <QTimer> + +#include <pli_vis/visualization/interactors/interactor.hpp> + +namespace pli +{ +class application; + +class remote_viewer : public QLabel +{ +public: + explicit remote_viewer (const std::string& address, const std::string& folder, application* owner, interactor* interactor, QWidget* parent = nullptr); + remote_viewer (const remote_viewer& that) = default; + remote_viewer ( remote_viewer&& temp) = default; + virtual ~remote_viewer (); + remote_viewer& operator=(const remote_viewer& that) = default; + remote_viewer& operator=( remote_viewer&& temp) = default; + + void closeEvent (QCloseEvent* event) override; + void keyPressEvent (QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; + void mouseMoveEvent (QMouseEvent* event) override; + + boost::signals2::signal<void()> on_close ; + boost::signals2::signal<void()> on_render; + +protected: + std::string address_ ; + std::string folder_ ; + + application* owner_ ; + interactor* interactor_ ; + std::atomic<bool> alive_ ; + std::future<void> future_ ; + + std::string filepath_ ; + std::array<std::size_t, 3> offset_ ; + std::array<std::size_t, 3> size_ ; + std::array<std::size_t, 3> stride_ ; + float step_ ; + std::size_t iterations_ ; + std::array<std::size_t, 3> seed_offset_ ; + std::array<std::size_t, 3> seed_size_ ; + std::array<std::size_t, 3> seed_stride_ ; + int color_mapping_ ; + float k_ ; + glm::vec3 translation_ ; + glm::vec3 forward_ ; + glm::vec3 up_ ; + std::array<std::size_t, 2> image_size_ ; + float streamline_radius_; + QImage image_ ; + QTimer timer_ ; + +}; +} + +#endif \ No newline at end of file diff --git a/include/pli_vis/ui/widgets/transfer_function_editor.hpp b/include/pli_vis/ui/widgets/transfer_function_editor.hpp deleted file mode 100644 index 13f844b436064c6ecc41e259d706954e185260ec..0000000000000000000000000000000000000000 --- a/include/pli_vis/ui/widgets/transfer_function_editor.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef PLI_VIS_TRANSFER_FUNCTION_WIDGET_ -#define PLI_VIS_TRANSFER_FUNCTION_WIDGET_ - -#include <array> - -#include <qwt/qwt_plot.h> -#include <vector_types.h> - -class QwtPlotCurve; -class QwtPlotHistogram; - -namespace pli -{ -class transfer_function_editor : public QwtPlot -{ - Q_OBJECT - -public: - transfer_function_editor(QWidget* parent = nullptr); - - std::vector<float4> get_function(); - - void set_histogram_entries(const std::vector<std::size_t>& histogram_entries); - -signals: - void on_change(); - -protected: - std::array<QwtPlotCurve*, 4> curves_ ; - QwtPlotHistogram* histogram_; -}; -} - -#endif diff --git a/include/pli_vis/ui/widgets/viewer.hpp b/include/pli_vis/ui/widgets/viewer.hpp index cea0c0c2ed8295aaa00bfd83f05c94a12d846d80..1b77b52449c2ed2dce4c87447bf6f4feebf8f928 100644 --- a/include/pli_vis/ui/widgets/viewer.hpp +++ b/include/pli_vis/ui/widgets/viewer.hpp @@ -7,6 +7,7 @@ #include <pli_vis/opengl/opengl.hpp> #include <QOpenGLWidget> +#include <QTimer> #include <pli_vis/aspects/loggable.hpp> #include <pli_vis/aspects/renderable.hpp> @@ -48,6 +49,7 @@ private: std::vector<std::unique_ptr<renderable>> renderables_ ; pli::camera camera_ ; std::unique_ptr<pli::interactor> interactor_ ; + QTimer timer_ ; }; template <typename type, typename ... args> diff --git a/include/pli_vis/ui/window.ui b/include/pli_vis/ui/window.ui index 481c1725a23bf0de70983b44ce2af94ed1d54eab..18f3b1b49d512bab2225b4182017eb9ef0cc1fc6 100644 --- a/include/pli_vis/ui/window.ui +++ b/include/pli_vis/ui/window.ui @@ -2,6 +2,9 @@ <ui version="4.0"> <class>window</class> <widget class="QMainWindow" name="window"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="geometry"> <rect> <x>0</x> @@ -44,7 +47,7 @@ <widget class="QSplitter" name="splitter_vertical_left"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>1</horstretch> + <horstretch>3</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> @@ -153,9 +156,12 @@ </widget> </widget> <widget class="QToolBox" name="toolbox"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> + <horstretch>1</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> @@ -171,6 +177,12 @@ <bold>false</bold> </font> </property> + <property name="mouseTracking"> + <bool>false</bool> + </property> + <property name="inputMethodHints"> + <set>Qt::ImhNone</set> + </property> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> @@ -194,8 +206,8 @@ <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <property name="font"> @@ -213,12 +225,12 @@ <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> - <string>Interactor</string> + <string>Camera / Interaction</string> </attribute> </widget> <widget class="pli::color_plugin" name="plugin_color"> @@ -226,8 +238,8 @@ <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> @@ -239,8 +251,8 @@ <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> @@ -252,8 +264,8 @@ <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> @@ -261,70 +273,57 @@ </attribute> <layout class="QGridLayout" name="grid_layout_fom"/> </widget> - <widget class="pli::odf_plugin" name="plugin_odf"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>117</width> - <height>364</height> - </rect> - </property> - <attribute name="label"> - <string>ODF Maps</string> - </attribute> - <layout class="QGridLayout" name="grid_layout_fdm"/> - </widget> - <widget class="pli::local_tractography_plugin" name="plugin_local_tractography"> + <widget class="pli::polar_plot_plugin" name="plugin_polar_plots"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> - <string>Local Tractography</string> + <string>Polar Plots</string> </attribute> </widget> - <widget class="pli::global_tractography_plugin" name="plugin_global_tractography"> + <widget class="pli::odf_plugin" name="plugin_odf"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> - <string>Global Tractography</string> + <string>Orientation Distribution Functions</string> </attribute> + <layout class="QGridLayout" name="grid_layout_fdm"/> </widget> - <widget class="pli::zernike_plugin" name="plugin_zernike_moments"> + <widget class="pli::local_tractography_plugin" name="plugin_local_tractography"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> - <string>Zernike Moments</string> + <string>Local Tractography</string> </attribute> </widget> - <widget class="pli::polar_plot_plugin" name="plugin_polar_plots"> + <widget class="pli::demo_plugin" name="plugin_demo"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>117</width> - <height>364</height> + <width>139</width> + <height>385</height> </rect> </property> <attribute name="label"> - <string>Polar Plots</string> + <string>Demo Presets</string> </attribute> </widget> </widget> @@ -430,21 +429,15 @@ <container>1</container> </customwidget> <customwidget> - <class>pli::zernike_plugin</class> - <extends>QWidget</extends> - <header location="global">pli_vis/ui/plugins/zernike_plugin.hpp</header> - <container>1</container> - </customwidget> - <customwidget> - <class>pli::global_tractography_plugin</class> + <class>pli::polar_plot_plugin</class> <extends>QWidget</extends> - <header location="global">pli_vis/ui/plugins/global_tractography_plugin.hpp</header> + <header location="global">pli_vis/ui/plugins/polar_plot_plugin.hpp</header> <container>1</container> </customwidget> <customwidget> - <class>pli::polar_plot_plugin</class> + <class>pli::demo_plugin</class> <extends>QWidget</extends> - <header location="global">pli_vis/ui/plugins/polar_plot_plugin.hpp</header> + <header location="global">pli_vis/ui/plugins/demo_plugin.hpp</header> <container>1</container> </customwidget> </customwidgets> diff --git a/include/pli_vis/visualization/algorithms/color_mapper.hpp b/include/pli_vis/visualization/algorithms/color_mapper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d97d243743e410710ecf022dd3a77e4e2fa2276b --- /dev/null +++ b/include/pli_vis/visualization/algorithms/color_mapper.hpp @@ -0,0 +1,83 @@ +#ifndef COLOR_MAPPER_HPP_ +#define COLOR_MAPPER_HPP_ + +#include <math.h> + +#include <vector_types.h> + +#include <pli_vis/cuda/utility/convert.h> +#include <pli_vis/cuda/utility/vector_ops.h> + +namespace color_mapper +{ +namespace detail +{ +template<typename type> +type convert (const type& input) +{ + auto output = pli::to_spherical_coords(input); + + if (output.y < 0.0F) + output.y += M_PI; + if (output.y >= M_PI) + output.y -= M_PI; + output.y = M_PI - output.y; + + if (output.z < 0.0F) + output.z = abs(output.z); + if (output.z >= M_PI / 2.0F) + output.z = M_PI - output.z; + + return output; +} +template<typename type> +float4 hue_to_rgba(const type& hue ) +{ + return clamp(float4 + { + abs(hue * 6.0F - 3.0F) - 1.0F, + 2.0F - abs(hue * 6.0F - 2.0F), + 2.0F - abs(hue * 6.0F - 4.0F), + 1.0F + }, 0.0F, 1.0F); +} +template<typename type> +float4 hsl_to_rgba(const type& hsl ) +{ + return (detail::hue_to_rgba(hsl.x) - 0.5F) * (1.0F - abs(2.0F * hsl.z - 1.0F)) * hsl.y + hsl.z; +} +template<typename type> +float4 hsv_to_rgba(const type& hsv ) +{ + return ((detail::hue_to_rgba(hsv.x) - 1.0F) * hsv.y + 1.0F) * hsv.z; +} +} + +template<typename type> +float4 to_hsl (const type& vector, const bool fixed_saturation = true, const float fixed_value = 0.5F) +{ + auto converted = detail::convert(vector); + auto theta = converted.y / float(M_PI); + auto phi = converted.z / float(M_PI / 2.0F); + return fixed_saturation + ? detail::hsl_to_rgba(float3{theta, fixed_value, phi}) + : detail::hsl_to_rgba(float3{theta, phi, fixed_value}); +} +template<typename type> +float4 to_hsv (const type& vector, const bool fixed_saturation = true, const float fixed_value = 0.5F) +{ + auto converted = detail::convert(vector); + auto theta = converted.y / float(M_PI); + auto phi = converted.z / float(M_PI / 2.0F); + return fixed_saturation + ? detail::hsv_to_rgba(float3{theta, fixed_value, phi}) + : detail::hsv_to_rgba(float3{theta, phi, fixed_value}); +} +template<typename type> +float4 to_rgb (const type& vector) +{ + return float4 {abs(vector.x), abs(vector.z), abs(vector.y), 1.0}; +} +} + +#endif diff --git a/include/pli_vis/visualization/algorithms/streamline_renderer.hpp b/include/pli_vis/visualization/algorithms/streamline_renderer.hpp index 6d056de15ddc5debf8b144dc7a1c6dc33e291d19..91ab1053450630ec9b68a440495d8973709eed4e 100644 --- a/include/pli_vis/visualization/algorithms/streamline_renderer.hpp +++ b/include/pli_vis/visualization/algorithms/streamline_renderer.hpp @@ -18,8 +18,9 @@ public: void render (const camera* camera) override; void set_data( - const std::vector<float3>& points , - const std::vector<float3>& directions); + const std::vector<float4>& points , + const std::vector<float4>& directions, + const std::vector<unsigned>& indices ); private: std::size_t draw_count_ = 0; @@ -27,6 +28,7 @@ private: std::unique_ptr<gl::vertex_array> vertex_array_ ; std::unique_ptr<gl::array_buffer> vertex_buffer_ ; std::unique_ptr<gl::array_buffer> direction_buffer_; + std::unique_ptr<gl::index_buffer> index_buffer_ ; }; } diff --git a/include/pli_vis/visualization/algorithms/volume_renderer.hpp b/include/pli_vis/visualization/algorithms/volume_renderer.hpp deleted file mode 100644 index 5a6cadd155f592316978029dde6eac3b03cdf712..0000000000000000000000000000000000000000 --- a/include/pli_vis/visualization/algorithms/volume_renderer.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef PLI_VIS_VOLUME_RENDERER_HPP_ -#define PLI_VIS_VOLUME_RENDERER_HPP_ - -#include <memory> - -#include <pli_vis/aspects/renderable.hpp> -#include <pli_vis/opengl/all.hpp> - -namespace pli -{ -class volume_renderer : public renderable -{ -public: - void initialize() override; - void render (const camera* camera) override; - - void set_data (const uint3& dimensions, const float* data); - void set_transfer_function(const std::vector<float4>& transfer_function); - void set_step_size (float step_size); - -private: - std::unique_ptr<gl::program> prepass_shader_program_ ; - std::unique_ptr<gl::program> shader_program_ ; - - std::unique_ptr<gl::vertex_array> prepass_vertex_array_ ; - std::unique_ptr<gl::vertex_array> vertex_array_ ; - - std::unique_ptr<gl::array_buffer> vertex_buffer_ ; - std::unique_ptr<gl::array_buffer> color_buffer_ ; - std::unique_ptr<gl::index_buffer> index_buffer_ ; - - std::unique_ptr<gl::texture_1d> transfer_function_texture_; - std::unique_ptr<gl::texture_3d> volume_texture_ ; - - std::unique_ptr<gl::framebuffer> framebuffer_ ; - std::unique_ptr<gl::texture_2d> exit_points_color_texture_; - std::unique_ptr<gl::texture_2d> exit_points_depth_texture_; - - std::size_t draw_count_ = 0; -}; -} - -#endif \ No newline at end of file diff --git a/include/pli_vis/visualization/algorithms/zernike_field.hpp b/include/pli_vis/visualization/algorithms/zernike_field.hpp deleted file mode 100644 index 5561bd5e58ac890edf5514465564e576b638272a..0000000000000000000000000000000000000000 --- a/include/pli_vis/visualization/algorithms/zernike_field.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef PLI_VIS_ZERNIKE_FIELD_HPP_ -#define PLI_VIS_ZERNIKE_FIELD_HPP_ - -#include <memory> - -#include <pli_vis/aspects/renderable.hpp> -#include <pli_vis/opengl/all.hpp> -#include <pli_vis/opengl/auxiliary/glm_uniforms.hpp> -#include <pli_vis/visualization/utility/render_target.hpp> - -namespace pli -{ -class zernike_field final : public renderable -{ -public: - void initialize() override; - void render (const camera* camera) override; - - void set_data (const uint2& dimensions, const uint2& spacing, const unsigned coefficients_per_voxel, const std::vector<float>& coefficients); - -private: - bool needs_update_ = false; - glm::uvec2 dimensions_ ; - glm::uvec2 spacing_ ; - unsigned coefficients_per_voxel_ = 0; - std::size_t draw_count_ = 0; - std::size_t primitive_count_ = 0; - - std::unique_ptr<gl::program> prepass_program_ ; - std::unique_ptr<gl::vertex_array> prepass_vertex_array_ ; - std::unique_ptr<gl::program> main_program_ ; - std::unique_ptr<gl::vertex_array> main_vertex_array_ ; - - std::unique_ptr<gl::array_buffer> vertex_buffer_ ; - std::unique_ptr<gl::array_buffer> texcoord_buffer_ ; - std::unique_ptr<gl::index_buffer> index_buffer_ ; - std::unique_ptr<gl::shader_storage_buffer> coefficient_buffer_ ; - - std::unique_ptr<render_target> render_target_ ; -}; -} - -#endif \ No newline at end of file diff --git a/include/pli_vis/visualization/interactors/orbit_interactor.hpp b/include/pli_vis/visualization/interactors/orbit_interactor.hpp deleted file mode 100644 index 544285fb5ceb827cafc1e2e747efa19aba84e49d..0000000000000000000000000000000000000000 --- a/include/pli_vis/visualization/interactors/orbit_interactor.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PLI_VIS_ORBIT_INTERACTOR_HPP_ -#define PLI_VIS_ORBIT_INTERACTOR_HPP_ - -#include <QPoint> - -#include <pli_vis/visualization/interactors/interactor.hpp> - -class QKeyEvent; -class QMouseEvent; - -namespace pli -{ -class orbit_interactor : public interactor -{ -public: - orbit_interactor(camera* camera); - - void mouse_press_handler(QMouseEvent* event) override; - void mouse_move_handler (QMouseEvent* event) override; - -private: - QPoint last_mouse_position_; -}; -} - -#endif \ No newline at end of file diff --git a/license.txt b/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..9049a46bf1d1c3776ae961ca6dc878adc4bd2a44 --- /dev/null +++ b/license.txt @@ -0,0 +1,7 @@ +Copyright 2018-2020 Visual Computing Institute at RWTH Aachen University + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/proto/camera.proto b/proto/camera.proto new file mode 100644 index 0000000000000000000000000000000000000000..7b1c60581464f2c71a9abb94ba0e265147599dcf --- /dev/null +++ b/proto/camera.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +import "vector_types.proto"; + +package tt; + +message camera +{ + fvec3 position = 1; + fvec3 forward = 2; + fvec3 up = 3; +} \ No newline at end of file diff --git a/proto/color_mapping.proto b/proto/color_mapping.proto new file mode 100644 index 0000000000000000000000000000000000000000..ae6db24f2f89eb2baf704bc8f7cee355e456ca91 --- /dev/null +++ b/proto/color_mapping.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package tt; + +enum color_mapping +{ + tkp_hsl = 0; + tpk_hsl = 1; + tkp_hsv = 2; + tpk_hsv = 3; + xzy_rgb = 4; +} \ No newline at end of file diff --git a/proto/dataset_format.proto b/proto/dataset_format.proto new file mode 100644 index 0000000000000000000000000000000000000000..1e8fae670ef0aa2c86a1f0993aa3996fd72737c2 --- /dev/null +++ b/proto/dataset_format.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package tt; + +enum dataset_format +{ + msa0309 = 0; + vervet1818 = 1; +} \ No newline at end of file diff --git a/proto/image.proto b/proto/image.proto new file mode 100644 index 0000000000000000000000000000000000000000..5549ece5836de25ad87a2916d3246169c9695677 --- /dev/null +++ b/proto/image.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +import "vector_types.proto"; + +package tt; + +message image +{ + uvec2 size = 1; + bytes data = 2; +} \ No newline at end of file diff --git a/proto/parameters.proto b/proto/parameters.proto new file mode 100644 index 0000000000000000000000000000000000000000..43b6f09caa4f01344693b883a2d63fe5e2bf42fb --- /dev/null +++ b/proto/parameters.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +import "camera.proto"; +import "color_mapping.proto"; +import "dataset_format.proto"; +import "selection.proto"; +import "vector_types.proto"; + +package tt; + +message data_loading_parameters +{ + string filepath = 1; + dataset_format dataset_format = 2; + selection selection = 3; +} +message particle_tracing_parameters +{ + float step = 1; + uint32 iterations = 2; + selection seeds = 3; + // TODO: Extend with arbitrary, non-cubic seeding. +} +message color_mapping_parameters +{ + color_mapping mapping = 1; + float k = 2; // Unused when mapping is xzy_rgb. +} +message raytracing_parameters +{ + camera camera = 1; + uvec2 image_size = 2; + float streamline_radius = 3; + // TODO: Extend with OSPRenderer, OSPModel, OSPLight, OSPCamera, OSPMaterial, OSPFrameBuffer. +} + +message parameters +{ + data_loading_parameters data_loading = 1; + particle_tracing_parameters particle_tracing = 2; + color_mapping_parameters color_mapping = 3; + raytracing_parameters raytracing = 4; +} \ No newline at end of file diff --git a/proto/selection.proto b/proto/selection.proto new file mode 100644 index 0000000000000000000000000000000000000000..571d607602abfed6b2ce13041b5b374831c993bd --- /dev/null +++ b/proto/selection.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +import "vector_types.proto"; + +package tt; + +message selection +{ + uvec3 offset = 1; + uvec3 size = 2; + uvec3 stride = 3; +} \ No newline at end of file diff --git a/proto/vector_types.proto b/proto/vector_types.proto new file mode 100644 index 0000000000000000000000000000000000000000..f3e8ff3837224f746004c71af7e35cf8e63eac9e --- /dev/null +++ b/proto/vector_types.proto @@ -0,0 +1,94 @@ +syntax = "proto3"; + +message bvec2 +{ + bool x = 1; + bool y = 2; +} +message ivec2 +{ + int32 x = 1; + int32 y = 2; +} +message uvec2 +{ + uint32 x = 1; + uint32 y = 2; +} +message fvec2 +{ + float x = 1; + float y = 2; +} +message dvec2 +{ + double x = 1; + double y = 2; +} + +message bvec3 +{ + bool x = 1; + bool y = 2; + bool z = 3; +} +message ivec3 +{ + int32 x = 1; + int32 y = 2; + int32 z = 3; +} +message uvec3 +{ + uint32 x = 1; + uint32 y = 2; + uint32 z = 3; +} +message fvec3 +{ + float x = 1; + float y = 2; + float z = 3; +} +message dvec3 +{ + double x = 1; + double y = 2; + double z = 3; +} + +message bvec4 +{ + bool x = 1; + bool y = 2; + bool z = 3; + bool w = 4; +} +message ivec4 +{ + int32 x = 1; + int32 y = 2; + int32 z = 3; + int32 w = 4; +} +message uvec4 +{ + uint32 x = 1; + uint32 y = 2; + uint32 z = 3; + uint32 w = 4; +} +message fvec4 +{ + float x = 1; + float y = 2; + float z = 3; + float w = 4; +} +message dvec4 +{ + double x = 1; + double y = 2; + double z = 3; + double w = 4; +} \ No newline at end of file diff --git a/shaders/fullscreen_texture.frag.glsl b/shaders/fullscreen_texture.frag.glsl new file mode 100644 index 0000000000000000000000000000000000000000..f08dbba96ebc83524f4e49e20f892c301aa7603d --- /dev/null +++ b/shaders/fullscreen_texture.frag.glsl @@ -0,0 +1,27 @@ +#ifndef FULLSCREEN_TEXTURE_FRAG_GLSL_ +#define FULLSCREEN_TEXTURE_FRAG_GLSL_ + +#include <string> + +namespace shaders +{ +static std::string fullscreen_texture_frag = R"(\ +#version 450 + +uniform sampler2D texture_unit; + +in vertex_data +{ + vec2 texcoords; +} fs_in; + +layout(location = 0) out vec4 color; + +void main() +{ + color = texture(texture_unit, fs_in.texcoords); +} +)"; +} + +#endif diff --git a/shaders/fullscreen_texture.vert.glsl b/shaders/fullscreen_texture.vert.glsl new file mode 100644 index 0000000000000000000000000000000000000000..dde7a3a84bbc745b57b8f6ff53fb97030606a6f2 --- /dev/null +++ b/shaders/fullscreen_texture.vert.glsl @@ -0,0 +1,27 @@ +#ifndef FULLSCREEN_TEXTURE_VERT_GLSL_ +#define FULLSCREEN_TEXTURE_VERT_GLSL_ + +#include <string> + +namespace shaders +{ +static std::string fullscreen_texture_vert = R"(\ +#version 450 + +layout(location = 0) in vec3 position ; +layout(location = 1) in vec2 texcoords; + +layout(location = 0) out vertex_data +{ + vec2 texcoords; +} vs_out; + +void main() +{ + gl_Position = vec4(position, 1.0); + vs_out.texcoords = texcoords; +} +)"; +} + +#endif \ No newline at end of file diff --git a/shaders/streamline_renderer.frag.glsl b/shaders/streamline_renderer.frag.glsl index 5ea450fa16b5bdb433919b7e64dd4ef6406996be..f5bf8661470b48ff810e505b866a0841e777054d 100644 --- a/shaders/streamline_renderer.frag.glsl +++ b/shaders/streamline_renderer.frag.glsl @@ -11,7 +11,7 @@ static std::string streamline_renderer_frag = R"(\ uniform int color_mode = 0 ; uniform float color_k = 0.5 ; uniform bool color_inverted = false; -flat in vec3 vert_direction ; +flat in vec4 vert_direction ; out vec4 frag_color ; vec3 hue_to_rgb(float hue) @@ -70,7 +70,7 @@ vec3 map_color(vec3 direction) void main() { - frag_color = vec4(map_color(vert_direction), 1.0); + frag_color = vec4(map_color(vert_direction.xyz), 1.0); } )"; } diff --git a/shaders/streamline_renderer.vert.glsl b/shaders/streamline_renderer.vert.glsl index 89928c75d5c6e147367a92bf313654dfee97bc5b..38624d345b769b1e831f3e1e778eda477648f262 100644 --- a/shaders/streamline_renderer.vert.glsl +++ b/shaders/streamline_renderer.vert.glsl @@ -11,13 +11,13 @@ static std::string streamline_renderer_vert = R"(\ uniform mat4 model ; uniform mat4 view ; uniform mat4 projection ; -in vec3 vertex ; -in vec3 direction ; -flat out vec3 vert_direction; +in vec4 vertex ; +in vec4 direction ; +flat out vec4 vert_direction; void main() { - gl_Position = projection * view * model * vec4(vertex, 1.0); + gl_Position = projection * view * model * vec4(vertex.xyz, 1.0); vert_direction = direction; } )"; diff --git a/shaders/volume_renderer.frag.glsl b/shaders/volume_renderer.frag.glsl deleted file mode 100644 index 4ab96f2d38a891d467954b571f27b6ce7bf11b9c..0000000000000000000000000000000000000000 --- a/shaders/volume_renderer.frag.glsl +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef VOLUME_RENDERER_FRAG_GLSL_ -#define VOLUME_RENDERER_FRAG_GLSL_ - -#include <string> - -namespace shaders -{ -std::string volume_renderer_frag = R"(\ -#version 400 - -const uint iterations = 10000u; -uniform vec4 background_color = vec4(0.0, 0.0, 0.0, 0.0); -uniform float step_size = 0.001; -uniform uvec2 screen_size ; -uniform sampler1D transfer_function; -uniform sampler2D exit_points ; -uniform sampler3D volume ; -in vec3 vert_color ; // Entry point. -out vec4 frag_color ; - -void main() -{ - vec3 exit_point = texture(exit_points, vec2(gl_FragCoord.x / screen_size.x, gl_FragCoord.y / screen_size.y)).xyz; - - if(vert_color == exit_point) - discard; - - vec3 ray = (exit_point - vert_color).xyz; - float ray_length = length(ray); - - vec3 delta = normalize(ray) * step_size; - float delta_length = length(delta); - - vec3 current_step = vert_color.xyz; - float current_length; - - float volume_sample; - vec4 transfer_function_sample; - - for(uint i = 0; i < iterations; i++) - { - volume_sample = texture(volume, current_step).x; - transfer_function_sample = texture(transfer_function, volume_sample); - - // Calculate contribution. - if(transfer_function_sample.a > 0.0) - { - transfer_function_sample.a = 1.0 - pow(1.0 - transfer_function_sample.a, step_size); - frag_color.rgb += (1.0 - frag_color.a) * transfer_function_sample.rgb * transfer_function_sample.a; - frag_color.a += (1.0 - frag_color.a) * transfer_function_sample.a; - } - - current_step += delta; - current_length += delta_length; - - // Early termination. - if(current_length >= ray_length) - { - frag_color.rgb = frag_color.a * frag_color.rgb + (1.0 - frag_color.a) * background_color.rgb; - break; - } - else if(frag_color.a > 1.0) - { - frag_color.a = 1.0; - break; - } - } - - //frag_color = vec4(vert_color, 1.0); - //frag_color = vec4(exit_point, 1.0); - //frag_color = vec4(normalize(ray), 1.0); -} -)"; -} - - -#endif \ No newline at end of file diff --git a/shaders/volume_renderer.vert.glsl b/shaders/volume_renderer.vert.glsl deleted file mode 100644 index 5130b47ba3f372889079daf092679e2921fa1318..0000000000000000000000000000000000000000 --- a/shaders/volume_renderer.vert.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef VOLUME_RENDERER_VERT_GLSL_ -#define VOLUME_RENDERER_VERT_GLSL_ - -#include <string> - -namespace shaders -{ -std::string volume_renderer_vert = R"(\ -#version 400 - -uniform mat4 model ; -uniform mat4 view ; -uniform mat4 projection; -in vec3 vertex ; -out vec3 vert_color; - -void main() -{ - vert_color = vertex; - gl_Position = projection * view * model * vec4(vertex, 1.0); -} -)"; -} - - -#endif \ No newline at end of file diff --git a/shaders/volume_renderer_prepass.frag.glsl b/shaders/volume_renderer_prepass.frag.glsl deleted file mode 100644 index 3f05b70ae7acc809599603d7585e98bb730f4f8f..0000000000000000000000000000000000000000 --- a/shaders/volume_renderer_prepass.frag.glsl +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef VOLUME_RENDERER_PREPASS_FRAG_GLSL_ -#define VOLUME_RENDERER_PREPASS_FRAG_GLSL_ - -#include <string> - -namespace shaders -{ -std::string volume_renderer_prepass_frag = R"(\ -#version 400 - - in vec3 vert_color; -layout (location = 0) out vec4 frag_color; - -void main() -{ - frag_color = vec4(vert_color, 1.0); -} -)"; -} - - -#endif \ No newline at end of file diff --git a/shaders/volume_renderer_prepass.vert.glsl b/shaders/volume_renderer_prepass.vert.glsl deleted file mode 100644 index 8fe8229857a823dffaa1f785fbb19c66c77cc2d1..0000000000000000000000000000000000000000 --- a/shaders/volume_renderer_prepass.vert.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef VOLUME_RENDERER_PREPASS_VERT_GLSL_ -#define VOLUME_RENDERER_PREPASS_VERT_GLSL_ - -#include <string> - -namespace shaders -{ -std::string volume_renderer_prepass_vert = R"(\ -#version 400 - -uniform mat4 model ; -uniform mat4 view ; -uniform mat4 projection; -in vec3 vertex ; -out vec3 vert_color; - -void main() -{ - vert_color = vertex; - gl_Position = projection * view * model * vec4(vertex, 1.0); -} -)"; -} - - -#endif \ No newline at end of file diff --git a/shaders/zernike.frag.glsl b/shaders/zernike.frag.glsl deleted file mode 100644 index cae7e41f9cc2116e945e49946c283a687d4579c5..0000000000000000000000000000000000000000 --- a/shaders/zernike.frag.glsl +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef ZERNIKE_FRAG_GLSL_ -#define ZERNIKE_FRAG_GLSL_ - -#include <string> - -namespace shaders -{ -static std::string zernike_frag = R"(\ -#version 450 -#extension GL_ARB_explicit_attrib_location : enable - -const float pi = 3.1415926535897932384626433832795; -const float infinity = 1.0 / 0.0; - -in vertex_data -{ - vec3 relative_position; - flat uint offset; -} fs_in; - -layout(std430, binding=0) buffer Coefficients -{ - float coefficients[]; -}; -uniform uint coefficients_per_voxel; -uniform int color_mode = 0 ; -uniform float color_k = 0.5 ; -uniform bool color_inverted = false; - -layout(location = 0) out vec4 color; - -vec3 hue_to_rgb(float hue) -{ - float R = abs(hue * 6 - 3) - 1; - float G = 2 - abs(hue * 6 - 2); - float B = 2 - abs(hue * 6 - 4); - return clamp(vec3(R,G,B), 0, 1); -} -vec3 hsv_to_rgb(vec3 hsv) -{ - vec3 rgb = hue_to_rgb(hsv.x); - return ((rgb - 1.0) * hsv.y + 1.0) * hsv.z; -} -vec3 hsl_to_rgb(vec3 hsl) -{ - vec3 rgb = hue_to_rgb(hsl.x); - float C = (1 - abs(2 * hsl.z - 1)) * hsl.y; - return (rgb - 0.5) * C + hsl.z; -} -vec3 map_color(vec2 radial, float scalar) -{ - if(radial.y < 0.0) radial.y += radians(180.0); - if(radial.y >= radians(180.0)) radial.y -= radians(180.0); - radial.y = radians(180.0) - radial.y; - - float t = radial.y / radians(180.0); - if(color_inverted) - scalar = 1.0 - scalar; - - if(color_mode == 0) - return hsl_to_rgb(vec3(t, color_k, scalar)); - if(color_mode == 1) - return hsl_to_rgb(vec3(t, scalar, color_k)); - if(color_mode == 2) - return hsv_to_rgb(vec3(t, color_k, scalar)); - if(color_mode == 3) - return hsv_to_rgb(vec3(t, scalar, color_k)); - return vec3(scalar, scalar, scalar); -} - -vec2 to_radial(vec2 cartesian) -{ - return vec2(length(cartesian), atan(cartesian.y, cartesian.x)); -} -ivec2 quantum_index(int index) -{ - ivec2 nm; - nm.x = int(ceil((-3.0 + sqrt(float(9 + 8 * index))) / 2.0)); - nm.y = 2 * index - nm.x * (nm.x + 2); - return nm; -} -float factorial(int n) -{ - float result = 1.0; - for(int i = 2; i <= n; i++) - result *= float(i); - return result; -} -float mode(ivec2 nm, float rho) -{ - float result = 0.0; - for(int i = 0; i <= (nm.x - nm.y) / 2; i++) - result += pow(rho, float(nm.x - 2 * i)) * ((mod(i, 2) == 0 ? 1.0 : -1.0) * factorial(nm.x - i)) / (factorial(i) * factorial((nm.x + nm.y) / 2 - i) * factorial((nm.x - nm.y) / 2 - i)); - return result; -} -float evaluate(ivec2 nm, vec2 rt) -{ - return (nm.y >= 0 ? 1.0f : -1.0f) * sqrt((2.0f * float(nm.x) + 2.0f) / (1.0f + (nm.y == 0 ? 1.0f : 0.0f))) * mode(ivec2(abs(nm.x), abs(nm.y)), rt.x) * (nm.y >= 0 ? cos(float(nm.y) * rt.y) : sin(float(-nm.y) * rt.y)); -} - -void main() -{ - int coefficient_offset = int(fs_in.offset * coefficients_per_voxel); - vec2 radial = to_radial(2.0 * (fs_in.relative_position.xy - vec2(0.5, 0.5))); - if (radial.x >= 1.0) discard; - radial.y += pi; - - float scalar = 0.0; - for(int i = 0; i < int(coefficients_per_voxel); i++) - scalar += coefficients[coefficient_offset + i] * evaluate(quantum_index(i), radial); - - color = vec4(map_color(radial, abs(scalar)), 1.0); -} -)"; -} - -#endif diff --git a/shaders/zernike.vert.glsl b/shaders/zernike.vert.glsl deleted file mode 100644 index c7fa96990a6e721d6a128b414f5a25f12608c6fc..0000000000000000000000000000000000000000 --- a/shaders/zernike.vert.glsl +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ZERNIKE_VERT_GLSL_ -#define ZERNIKE_VERT_GLSL_ - -#include <string> - -namespace shaders -{ -static std::string zernike_vert = R"(\ -#version 450 -#extension GL_ARB_explicit_attrib_location : enable - -layout(location = 0) in vec3 position; - -uniform uvec2 dimensions; -uniform uvec2 spacing ; - -layout(location = 0) out vertex_data -{ - vec3 relative_position; - flat uint offset; -} vs_out; - -void main() -{ - uvec2 size = dimensions * spacing; - uvec2 location = uvec2(gl_InstanceID / dimensions.x % dimensions.y, gl_InstanceID % dimensions.x); - vec3 translation = vec3(location.x * spacing.x, location.y * spacing.y, 0.0); - vec3 scale = vec3( spacing.x, spacing.y, 1.0); - - gl_Position = vec4(position * scale + translation, 1.0) / vec4(size.x, size.y, 1.0, 1.0); - vs_out.relative_position = position; - vs_out.offset = gl_InstanceID; -} -)"; -} - -#endif \ No newline at end of file diff --git a/source/cuda/odf_field.cu b/source/cuda/odf_field.cu index 8002defe85e3bf7eb1f6015196d4ee1e36c5f768..e0029e9ea56e95d9580f7f9e4dad652e5575a5da 100644 --- a/source/cuda/odf_field.cu +++ b/source/cuda/odf_field.cu @@ -24,46 +24,26 @@ namespace pli template<typename vector_type, typename scalar_type> __global__ void quantify_and_project_kernel( // Input related parameters. - uint3 dimensions , - uint3 vectors_dimensions , + uint3 dimensions , + uint3 vectors_dimensions , // Quantification related parameters. - const vector_type* vectors , - unsigned histogram_bin_count, - vector_type* histogram_vectors , - // Projection related parameters. - unsigned maximum_degree , - const scalar_type* inverse_transform , - scalar_type* coefficient_vectors) + const vector_type* vectors , + unsigned histogram_bin_count , + vector_type* histogram_vectors , + scalar_type* histogram_magnitudes) { - auto x = blockIdx.x * blockDim.x + threadIdx.x; - auto y = blockIdx.y * blockDim.y + threadIdx.y; - auto z = blockIdx.z * blockDim.z + threadIdx.z; + const auto x = blockIdx.x * blockDim.x + threadIdx.x; + const auto y = blockIdx.y * blockDim.y + threadIdx.y; + const auto z = blockIdx.z * blockDim.z + threadIdx.z; if (x >= dimensions.x || y >= dimensions.y || z >= dimensions.z) return; - auto volume_index = z + dimensions.z * (y + dimensions.y * x); - auto coefficient_count = pli::coefficient_count(maximum_degree); - auto coefficient_vector_offset = volume_index * coefficient_count; - auto alpha = 1.0F; - auto beta = 0.0F; - - float* histogram_magnitudes; - cudaMalloc(&histogram_magnitudes, histogram_bin_count * sizeof(float)); - for(auto i = 0; i < histogram_bin_count; ++i) - histogram_magnitudes[i] = 0.0F; - - uint3 offset { - vectors_dimensions.x * x, - vectors_dimensions.y * y, - vectors_dimensions.z * z }; - uint3 size { - vectors_dimensions.x * dimensions.x, - vectors_dimensions.y * dimensions.y, - vectors_dimensions.z * dimensions.z }; - - cublasHandle_t cublas; - cublasCreate(&cublas); + const auto volume_index = z + dimensions.z * (y + dimensions.y * x); + const auto histogram_offset = volume_index * histogram_bin_count; + + uint3 offset { vectors_dimensions.x * x , vectors_dimensions.y * y , vectors_dimensions.z * z }; + uint3 size { vectors_dimensions.x * dimensions.x, vectors_dimensions.y * dimensions.y, vectors_dimensions.z * dimensions.z }; accumulate_kernel<<<grid_size_3d(vectors_dimensions), block_size_3d()>>>( vectors_dimensions , @@ -72,28 +52,8 @@ __global__ void quantify_and_project_kernel( vectors , histogram_bin_count , histogram_vectors , - histogram_magnitudes); - __syncthreads(); + histogram_magnitudes + histogram_offset); cudaDeviceSynchronize(); - __syncthreads(); - - cublasSgemv( - cublas , - CUBLAS_OP_N , - coefficient_count , - histogram_bin_count , - &alpha , - inverse_transform , - coefficient_count , - histogram_magnitudes , - 1 , - &beta , - coefficient_vectors + coefficient_vector_offset, - 1 ); - - cublasDestroy(cublas); - - cudaFree(histogram_magnitudes); } // Call on a dimensions.x x dimensions.y x dimensions.z 3D grid. @@ -180,8 +140,10 @@ void calculate_odfs( status_callback("Allocating histogram vector and magnitudes."); auto histogram_bin_count = histogram_bins.x * histogram_bins.y; - thrust::device_vector<float3> histogram_vectors(histogram_bin_count); - auto histogram_vectors_ptr = raw_pointer_cast(&histogram_vectors[0]); + thrust::device_vector<float3> histogram_vectors (histogram_bin_count); + thrust::device_vector<float> histogram_magnitudes(histogram_bin_count * voxel_count, 0.0f); + auto histogram_vectors_ptr = raw_pointer_cast(&histogram_vectors [0]); + auto histogram_magnitudes_ptr = raw_pointer_cast(&histogram_magnitudes[0]); status_callback("Allocating spherical harmonics basis matrix."); auto coefficient_count = pli::coefficient_count(maximum_degree); @@ -325,18 +287,34 @@ void calculate_odfs( status_callback("Accumulating histograms and projecting via V E^-1 U^T * h. This might take a while."); quantify_and_project_kernel<<<dimensions, dim3(1, 1, 1)>>> ( - dimensions , - vectors_dimensions , - gpu_vectors_ptr , - histogram_bin_count , - histogram_vectors_ptr , - maximum_degree , - V_EI_UT_ptr , - gpu_coefficients_ptr ); + dimensions , + vectors_dimensions , + gpu_vectors_ptr , + histogram_bin_count , + histogram_vectors_ptr , + histogram_magnitudes_ptr); cudaDeviceSynchronize(); gpu_vectors .clear(); histogram_vectors.clear(); - + + for (auto i = 0; i < voxel_count; ++i) + cublasSgemv( + cublas , + CUBLAS_OP_N , + coefficient_count , + histogram_bin_count , + &alpha , + V_EI_UT_ptr , + coefficient_count , + histogram_magnitudes_ptr + i * histogram_bin_count, + 1 , + &beta , + gpu_coefficients_ptr + i * coefficient_count , + 1 ); + cudaDeviceSynchronize(); + V_EI_UT .clear(); + histogram_magnitudes.clear(); + status_callback("Copying coefficients to CPU."); cudaMemcpy(coefficients, gpu_coefficients_ptr, sizeof(float) * total_coefficient_count, cudaMemcpyDeviceToHost); @@ -511,58 +489,4 @@ void sample_odfs( std::chrono::duration<double> elapsed_time = end_time - start_time; status_callback("Cuda ODF sampling operations took " + std::to_string(elapsed_time.count()) + " seconds."); } - -void extract_peaks( - const uint3& dimensions , - const unsigned maximum_degree, - const float* coefficients , - const uint2& tessellations , - const unsigned maxima_count , - float3* maxima , - std::function<void(const std::string&)> status_callback) -{ - auto start_time = std::chrono::system_clock::now(); - - auto voxel_count = dimensions.x * dimensions.y * dimensions.z; - auto coefficient_count = pli::coefficient_count(maximum_degree); - - status_callback("Allocating and copying the spherical harmonics coefficients."); - thrust::device_vector<float> coefficient_vectors(voxel_count * coefficient_count); - auto coefficients_ptr = raw_pointer_cast(&coefficient_vectors[0]); - copy_n(coefficients, coefficient_vectors.size(), coefficient_vectors.begin()); - cudaDeviceSynchronize(); - - status_callback("Allocating the maxima vectors."); - thrust::device_vector<float3> maxima_vectors(voxel_count * maxima_count); - auto maxima_ptr = raw_pointer_cast(&maxima_vectors[0]); - - status_callback("Extracting maxima."); - extract_maxima<<<grid_size_3d(dimensions), block_size_3d()>>>( - dimensions , - coefficient_count, - coefficients_ptr , - tessellations , - maxima_count , - maxima_ptr ); - cudaDeviceSynchronize(); - - status_callback("Converting the maxima to Cartesian coordinates."); - thrust::transform( - thrust::device, - maxima_vectors.begin(), - maxima_vectors.end (), - maxima_vectors.begin(), - [] __host__ __device__(const float3& point) - { - return to_cartesian_coords(point); - }); - cudaDeviceSynchronize(); - - status_callback("Copying maxima to CPU."); - cudaMemcpy(maxima, maxima_ptr, sizeof(float3) * maxima_vectors.size(), cudaMemcpyDeviceToHost); - - auto end_time = std::chrono::system_clock::now(); - std::chrono::duration<double> elapsed_time = end_time - start_time; - status_callback("Cuda ODF sampling operations took " + std::to_string(elapsed_time.count()) + " seconds."); -} } diff --git a/source/cuda/pt/tracer.cu b/source/cuda/pt/tracer.cu index 238f354a82082f95b1de9c458b489bb463382a83..dfdf476ac8cd2b367ad89e86bf0b742c9cad5c7a 100644 --- a/source/cuda/pt/tracer.cu +++ b/source/cuda/pt/tracer.cu @@ -16,7 +16,7 @@ __global__ void trace_kernel( const std::size_t iteration_count, const float step_size , const uint3 data_dimensions, - const float3 data_spacing , + const data_type data_spacing , const data_type* data , const std::size_t seed_size , const data_type* seeds , @@ -44,24 +44,24 @@ __global__ void trace_kernel( } } -std::vector<std::vector<float3>> trace( +std::vector<std::vector<float4>> trace( const std::size_t iteration_count, const float step_size , const uint3 data_dimensions, - const float3 data_spacing , - const std::vector<float3>& data , - const std::vector<float3>& seeds ) + const float4 data_spacing , + const std::vector<float4>& data , + const std::vector<float4>& seeds ) { - thrust::device_vector<float3> data_gpu = data ; - thrust::device_vector<float3> seeds_gpu = seeds; - thrust::device_vector<float3> traces_gpu(iteration_count * seeds.size(), float3{0.0f, 0.0f, 0.0f}); + thrust::device_vector<float4> data_gpu = data ; + thrust::device_vector<float4> seeds_gpu = seeds; + thrust::device_vector<float4> traces_gpu(iteration_count * seeds.size(), float4{0.0f, 0.0f, 0.0f, 1.0f}); const auto data_gpu_ptr = raw_pointer_cast(&data_gpu [0]); const auto seeds_gpu_ptr = raw_pointer_cast(&seeds_gpu [0]); const auto traces_gpu_ptr = raw_pointer_cast(&traces_gpu[0]); cudaDeviceSynchronize(); trace_kernel - <float3, runge_kutta_4_integrator<float3, trilinear_interpolator<float3>>> + <float4, runge_kutta_4_integrator<float4, trilinear_interpolator<float4>>> <<<pli::grid_size_1d(seeds.size()), pli::block_size_1d()>>>( iteration_count, step_size , @@ -73,13 +73,13 @@ std::vector<std::vector<float3>> trace( traces_gpu_ptr ); cudaDeviceSynchronize(); - std::vector<float3> traces_linear(traces_gpu.size()); + std::vector<float4> traces_linear(traces_gpu.size()); thrust::copy (traces_gpu.begin(), traces_gpu.end (), traces_linear.begin()); cudaDeviceSynchronize(); - std::vector<std::vector<float3>> traces(seeds.size()); + std::vector<std::vector<float4>> traces(seeds.size()); for(auto i = 0; i < traces.size(); ++i) - traces[i] = std::vector<float3>(traces_linear.begin() + i * iteration_count, traces_linear.begin() + (i + 1) * iteration_count); + traces[i] = std::vector<float4>(traces_linear.begin() + i * iteration_count, traces_linear.begin() + (i + 1) * iteration_count); return traces; } } \ No newline at end of file diff --git a/source/cuda/zernike/launch.cu b/source/cuda/zernike/launch.cu deleted file mode 100644 index e2d6c28d352518172782def3124a200c1729c005..0000000000000000000000000000000000000000 --- a/source/cuda/zernike/launch.cu +++ /dev/null @@ -1,328 +0,0 @@ -#include <pli_vis/cuda/zernike/launch.h> - -#include <cublas_v2.h> -#include <cusolverDn.h> -#include <thrust/extrema.h> - -#include <pli_vis/cuda/utility/vector_ops.h> -#include <pli_vis/cuda/zernike/disk.h> -#include <pli_vis/cuda/zernike/zernike.h> - -namespace zer -{ -__host__ thrust::device_vector<float> pseudoinverse(const uint2& size, thrust::device_vector<float>& data) -{ - cublasHandle_t cublas ; - cusolverDnHandle_t cusolver; - cusolverDnCreate(&cusolver); - cublasCreate (&cublas ); - - int buffer_size; - cusolverDnSgesvd_bufferSize(cusolver, size.x, size.y, &buffer_size); - cudaDeviceSynchronize (); - auto complex_buffer_size = static_cast<float>(buffer_size); - - thrust::device_vector<float> buffer (buffer_size, 0.0); - thrust::device_vector<int> info (1); - thrust::device_vector<float> u (size.x * size.x); - thrust::device_vector<float> e (size.y); - thrust::device_vector<float> vt (size.y * size.y); - thrust::device_vector<float> ut (size.x * size.x); - thrust::device_vector<float> ei_ut (size.x * size.y); - thrust::device_vector<float> v_ei_ut(size.x * size.y); - auto alpha = 1.0F; - auto beta = 0.0F; - - cusolverDnSgesvd( - cusolver , - 'A' , - 'A' , - size.x , - size.y , - data.data().get() , - size.x , - e.data().get() , - u.data().get() , - size.x , - vt.data().get() , - size.y , - buffer.data().get() , - buffer_size , - &complex_buffer_size, - info.data().get() ); - cudaDeviceSynchronize(); - buffer.clear(); - - cublasSgeam( - cublas , - CUBLAS_OP_T , - CUBLAS_OP_N , - size.x , - size.x , - &alpha , - u.data().get() , - size.x , - &beta , - nullptr , - size.x , - ut.data().get(), - size.x ); - cudaDeviceSynchronize(); - u.clear(); - - thrust::transform( - e.begin(), - e.end (), - e.begin(), - [] __host__ __device__(float& entry) -> float - { - if (int(entry) == 0) - return 0; - return entry = 1.0F / entry; - }); - cudaDeviceSynchronize(); - - cublasSdgmm( - cublas , - CUBLAS_SIDE_LEFT , - size.y , - size.x , - ut.data().get() , - size.x , - e.data().get() , - 1 , - ei_ut.data().get(), - size.y ); - cudaDeviceSynchronize(); - ut.clear(); - e .clear(); - - cublasSgemm( - cublas , - CUBLAS_OP_T , - CUBLAS_OP_N , - size.y , - size.x , - size.y , - &alpha , - vt.data().get() , - size.y , - ei_ut.data().get() , - size.y , - &beta , - v_ei_ut.data().get(), - size.y ); - cudaDeviceSynchronize(); - vt .clear(); - ei_ut.clear(); - - cusolverDnDestroy(cusolver); - cublasDestroy (cublas ); - - return v_ei_ut; -} - -__global__ void accumulate( - const uint2 vectors_size , - const float3* vectors , - const uint2 disk_partitions , - const float2* disk_samples , - const uint2 superpixel_size , - const uint2 superpixel_dimensions, - float* intermediates , - bool symmetric ) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - if (x >= vectors_size.x || y >= vectors_size.y) - return; - - const auto& vector = vectors[y + vectors_size.y * x]; - - const auto superpixel_x = x / superpixel_size.x; - const auto superpixel_y = y / superpixel_size.y; - const auto superpixel_index = superpixel_y + superpixel_dimensions.y * superpixel_x; - const auto sample_count = disk_partitions.x * disk_partitions.y; - const auto intermediate_offset = sample_count * superpixel_index; - - auto min_distance = 2.0F; - auto min_index = 0 ; - for(auto i = 0; i < sample_count; i++) - { - const auto temp_distance = sqrt(pow(cos(vector.z), 2) + pow(disk_samples[i].x, 2) - 2.0F * cos(vector.z) * disk_samples[i].x * cos(vector.y - disk_samples[i].y)); - if (temp_distance < min_distance) - { - min_distance = temp_distance; - min_index = i; - } - } - atomicAdd(&intermediates[intermediate_offset + min_index], 1.0f); - - // Change this to Freitag's method of sampling points in proportion to the current radius. - if(symmetric) - { - auto symmetric_distance = 2.0F; - auto symmetric_index = 0 ; - for(auto i = 0; i < sample_count; i++) - { - const auto temp_distance = sqrt(pow(disk_samples[min_index].x, 2) + pow(disk_samples[i].x, 2) - 2.0F * disk_samples[min_index].x * disk_samples[i].x * cos((disk_samples[min_index].y + M_PI) - disk_samples[i].y)); - if (temp_distance < symmetric_distance) - { - symmetric_distance = temp_distance; - symmetric_index = i; - } - } - atomicAdd(&intermediates[intermediate_offset + symmetric_index], -1.0f); - } -} - -__global__ void project( - const uint2 dimensions , - const float* basis_matrix , - const unsigned sample_count , - const float* intermediates , - const unsigned coefficient_count , - float* coefficients ) -{ - const auto x = blockIdx.x * blockDim.x + threadIdx.x; - const auto y = blockIdx.y * blockDim.y + threadIdx.y; - if (x >= dimensions.x || y >= dimensions.y) - return; - - const auto linear_index = y + dimensions.y * x; - const auto intermediate_offset = sample_count * linear_index; - const auto coefficient_offset = coefficient_count * linear_index; - - cublasHandle_t cublas; - cublasCreate(&cublas); - auto alpha = 1.0F; - auto beta = 0.0F; - cublasSgemv( - cublas , - CUBLAS_OP_N , - coefficient_count , - sample_count , - &alpha , - basis_matrix , - coefficient_count , - &intermediates[intermediate_offset], - 1 , - &beta , - &coefficients [coefficient_offset ], - 1 ); - cublasDestroy(cublas); -} - -thrust::device_vector<float> launch( - const thrust::device_vector<float3>& vectors , - const uint2& vectors_size , - const uint2& superpixel_size, - const uint2& disk_partitions, - const unsigned maximum_degree , - bool symmetric , - bool normalize , - bool even_only , - bool edge_only ) -{ - const auto superpixel_dimensions = uint2{vectors_size.x / superpixel_size.x, vectors_size.y / superpixel_size.y}; - const auto superpixel_count = superpixel_dimensions.x * superpixel_dimensions.y; - const auto sample_count = disk_partitions.x * disk_partitions.y; - const auto coefficient_count = expansion_size(maximum_degree); - - // Sample a unit disk. - thrust::device_vector<float2> disk_samples(sample_count); - sample_disk<<<grid_size_2d(dim3(disk_partitions.x, disk_partitions.y)), block_size_2d()>>>( - disk_partitions , - disk_samples.data().get(), - false ); - cudaDeviceSynchronize(); - - // Compute Zernike basis for the samples. - thrust::device_vector<float> basis_matrix(sample_count * coefficient_count); - compute_basis<<<grid_size_2d(dim3(sample_count, coefficient_count)), block_size_2d()>>>( - sample_count , - disk_samples.data().get() , - coefficient_count , - basis_matrix.data().get() , - even_only , - edge_only ); - cudaDeviceSynchronize(); - - // Compute the inverse of the basis matrix. - auto inverse_basis_matrix = pseudoinverse({sample_count, coefficient_count}, basis_matrix); - - // Accumulate vectors into superpixels. - thrust::device_vector<float> intermediates(superpixel_count * sample_count); - accumulate<<<grid_size_2d(dim3(vectors_size.x, vectors_size.y)), block_size_2d()>>> ( - vectors_size , - vectors .data().get(), - disk_partitions , - disk_samples .data().get(), - superpixel_size , - superpixel_dimensions , - intermediates.data().get(), - symmetric ); - cudaDeviceSynchronize(); - - // Project superpixels to the Zernike basis. - thrust::device_vector<float> coefficients(superpixel_count * coefficient_count); - project<<<grid_size_2d(dim3(superpixel_dimensions.x, superpixel_dimensions.y)), block_size_2d()>>> ( - superpixel_dimensions , - inverse_basis_matrix.data().get(), - sample_count , - intermediates.data().get() , - coefficient_count , - coefficients.data().get()) ; - cudaDeviceSynchronize(); - - // Normalize. - if(normalize) - { - for(auto i = 0; i < superpixel_count; i++) - { - const auto start_iterator = coefficients.begin() + i * coefficient_count; - const auto end_iterator = coefficients.begin() + (i + 1) * coefficient_count; - const auto max_coefficient = abs(*max_element(start_iterator, end_iterator, - [=] __host__ __device__(float lhs, float rhs) - { - return std::abs(lhs) < std::abs(rhs); - })); - thrust::transform(start_iterator, end_iterator, start_iterator, - [=] __host__ __device__(const float& coefficient) - { - return coefficient / max_coefficient; - }); - } - } - - return coefficients; -} - -std::vector<float> launch( - const std::vector<float3>& vectors , - const uint2& vectors_size , - const uint2& superpixel_size, - const uint2& disk_partitions, - const unsigned maximum_degree , - bool symmetric , - bool normalize , - bool even_only , - bool edge_only ) -{ - thrust::device_vector<float3> vectors_gpu(vectors.size()); - thrust::copy(vectors.begin(), vectors.end(), vectors_gpu.begin()); - auto coefficients = zer::launch( - vectors_gpu , - vectors_size , - superpixel_size, - disk_partitions, - maximum_degree , - symmetric , - normalize , - even_only , - edge_only ); - std::vector<float> coefficients_cpu(coefficients.size()); - thrust::copy(coefficients.begin(), coefficients.end(), coefficients_cpu.begin()); - return coefficients_cpu; -} -} diff --git a/source/main.cpp b/source/main.cpp index 891feb18c15e0cc4ff9be3e4a01fb3e1baa8660b..605fd1742ba172569ae22a7a597563287fe3e0a9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -6,7 +6,6 @@ extern "C" } #endif -#include <omp.h> #include <QApplication> #include <QSurfaceFormat> @@ -14,8 +13,6 @@ extern "C" int main(int argc, char** argv) { - omp_set_num_threads(4); - QSurfaceFormat format; format.setProfile (QSurfaceFormat::CompatibilityProfile); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer ); diff --git a/source/third_party/qwt/qwt_abstract_legend.cpp b/source/third_party/qwt/qwt_abstract_legend.cpp deleted file mode 100644 index fb4f9e36337575d641f1f759abfee2cecf3cb441..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_abstract_legend.cpp +++ /dev/null @@ -1,38 +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/qwt_abstract_legend.h" - -/*! - Constructor - - \param parent Parent widget -*/ -QwtAbstractLegend::QwtAbstractLegend( QWidget *parent ): - QFrame( parent ) -{ -} - -//! Destructor -QwtAbstractLegend::~QwtAbstractLegend() -{ -} - -/*! - Return the extent, that is needed for elements to scroll - the legend ( usually scrollbars ), - - \param orientation Orientation - \return Extent of the corresponding scroll element -*/ -int QwtAbstractLegend::scrollExtent( Qt::Orientation orientation ) const -{ - Q_UNUSED( orientation ); - return 0; -} diff --git a/source/third_party/qwt/qwt_abstract_scale.cpp b/source/third_party/qwt/qwt_abstract_scale.cpp deleted file mode 100644 index fae30693417804e0da6a78c042db88e4773141ef..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_abstract_scale.cpp +++ /dev/null @@ -1,449 +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/qwt_abstract_scale.h" -#include "qwt/qwt_scale_engine.h" -#include "qwt/qwt_scale_draw.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_interval.h" - -class QwtAbstractScale::PrivateData -{ -public: - PrivateData(): - maxMajor( 5 ), - maxMinor( 3 ), - stepSize( 0.0 ) - { - scaleEngine = new QwtLinearScaleEngine(); - scaleDraw = new QwtScaleDraw(); - } - - ~PrivateData() - { - delete scaleEngine; - delete scaleDraw; - } - - QwtScaleEngine *scaleEngine; - QwtAbstractScaleDraw *scaleDraw; - - int maxMajor; - int maxMinor; - double stepSize; -}; - -/*! - Constructor - - \param parent Parent widget - - Creates a default QwtScaleDraw and a QwtLinearScaleEngine. - The initial scale boundaries are set to [ 0.0, 100.0 ] - - The scaleStepSize() is initialized to 0.0, scaleMaxMajor() to 5 - and scaleMaxMajor to 3. -*/ - -QwtAbstractScale::QwtAbstractScale( QWidget *parent ): - QWidget( parent ) -{ - d_data = new PrivateData; - rescale( 0.0, 100.0, d_data->stepSize ); -} - -//! Destructor -QwtAbstractScale::~QwtAbstractScale() -{ - delete d_data; -} - -/*! - Set the lower bound of the scale - - \param value Lower bound - - \sa lowerBound(), setScale(), setUpperBound() - \note For inverted scales the lower bound - is greater than the upper bound -*/ -void QwtAbstractScale::setLowerBound( double value ) -{ - setScale( value, upperBound() ); -} - -/*! - \return Lower bound of the scale - \sa setLowerBound(), setScale(), upperBound() -*/ -double QwtAbstractScale::lowerBound() const -{ - return d_data->scaleDraw->scaleDiv().lowerBound(); -} - -/*! - Set the upper bound of the scale - - \param value Upper bound - - \sa upperBound(), setScale(), setLowerBound() - \note For inverted scales the lower bound - is greater than the upper bound -*/ -void QwtAbstractScale::setUpperBound( double value ) -{ - setScale( lowerBound(), value ); -} - -/*! - \return Upper bound of the scale - \sa setUpperBound(), setScale(), lowerBound() -*/ -double QwtAbstractScale::upperBound() const -{ - return d_data->scaleDraw->scaleDiv().upperBound(); -} - -/*! - \brief Specify a scale. - - Define a scale by an interval - - The ticks are calculated using scaleMaxMinor(), - scaleMaxMajor() and scaleStepSize(). - - \param lowerBound lower limit of the scale interval - \param upperBound upper limit of the scale interval - - \note For inverted scales the lower bound - is greater than the upper bound -*/ -void QwtAbstractScale::setScale( double lowerBound, double upperBound ) -{ - rescale( lowerBound, upperBound, d_data->stepSize ); -} - -/*! - \brief Specify a scale. - - Define a scale by an interval - - The ticks are calculated using scaleMaxMinor(), - scaleMaxMajor() and scaleStepSize(). - - \param interval Interval -*/ -void QwtAbstractScale::setScale( const QwtInterval &interval ) -{ - setScale( interval.minValue(), interval.maxValue() ); -} - -/*! - \brief Specify a scale. - - scaleMaxMinor(), scaleMaxMajor() and scaleStepSize() and have no effect. - - \param scaleDiv Scale division - \sa setAutoScale() -*/ -void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv ) -{ - if ( scaleDiv != d_data->scaleDraw->scaleDiv() ) - { -#if 1 - if ( d_data->scaleEngine ) - { - d_data->scaleDraw->setTransformation( - d_data->scaleEngine->transformation() ); - } -#endif - - d_data->scaleDraw->setScaleDiv( scaleDiv ); - - scaleChange(); - } -} - -/*! - \brief Set the maximum number of major tick intervals. - - The scale's major ticks are calculated automatically such that - the number of major intervals does not exceed ticks. - - The default value is 5. - - \param ticks Maximal number of major ticks. - - \sa scaleMaxMajor(), setScaleMaxMinor(), - setScaleStepSize(), QwtScaleEngine::divideInterval() -*/ -void QwtAbstractScale::setScaleMaxMajor( int ticks ) -{ - if ( ticks != d_data->maxMajor ) - { - d_data->maxMajor = ticks; - updateScaleDraw(); - } -} - -/*! - \return Maximal number of major tick intervals - \sa setScaleMaxMajor(), scaleMaxMinor() -*/ -int QwtAbstractScale::scaleMaxMajor() const -{ - return d_data->maxMajor; -} - -/*! - \brief Set the maximum number of minor tick intervals - - The scale's minor ticks are calculated automatically such that - the number of minor intervals does not exceed ticks. - The default value is 3. - - \param ticks Maximal number of minor ticks. - - \sa scaleMaxMajor(), setScaleMaxMinor(), - setScaleStepSize(), QwtScaleEngine::divideInterval() -*/ -void QwtAbstractScale::setScaleMaxMinor( int ticks ) -{ - if ( ticks != d_data->maxMinor ) - { - d_data->maxMinor = ticks; - updateScaleDraw(); - } -} - -/*! - \return Maximal number of minor tick intervals - \sa setScaleMaxMinor(), scaleMaxMajor() -*/ -int QwtAbstractScale::scaleMaxMinor() const -{ - return d_data->maxMinor; -} - -/*! - \brief Set the step size used for calculating a scale division - - The step size is hint for calculating the intervals for - the major ticks of the scale. A value of 0.0 is interpreted - as no hint. - - \param stepSize Hint for the step size of the scale - - \sa scaleStepSize(), QwtScaleEngine::divideScale() - - \note Position and distance between the major ticks also - depends on scaleMaxMajor(). -*/ -void QwtAbstractScale::setScaleStepSize( double stepSize ) -{ - if ( stepSize != d_data->stepSize ) - { - d_data->stepSize = stepSize; - updateScaleDraw(); - } -} - -/*! - \return Hint for the step size of the scale - \sa setScaleStepSize(), QwtScaleEngine::divideScale() -*/ -double QwtAbstractScale::scaleStepSize() const -{ - return d_data->stepSize; -} - -/*! - \brief Set a scale draw - - scaleDraw has to be created with new and will be deleted in - the destructor or the next call of setAbstractScaleDraw(). - - \sa abstractScaleDraw() -*/ -void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw ) -{ - if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw ) - return; - - if ( d_data->scaleDraw != NULL ) - scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() ); - - delete d_data->scaleDraw; - d_data->scaleDraw = scaleDraw; -} - -/*! - \return Scale draw - \sa setAbstractScaleDraw() -*/ -QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() -{ - return d_data->scaleDraw; -} - -/*! - \return Scale draw - \sa setAbstractScaleDraw() -*/ -const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const -{ - return d_data->scaleDraw; -} - -/*! - \brief Set a scale engine - - The scale engine is responsible for calculating the scale division - and provides a transformation between scale and widget coordinates. - - scaleEngine has to be created with new and will be deleted in - the destructor or the next call of setScaleEngine. -*/ -void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine ) -{ - if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine ) - { - delete d_data->scaleEngine; - d_data->scaleEngine = scaleEngine; - } -} - -/*! - \return Scale engine - \sa setScaleEngine() -*/ -const QwtScaleEngine *QwtAbstractScale::scaleEngine() const -{ - return d_data->scaleEngine; -} - -/*! - \return Scale engine - \sa setScaleEngine() -*/ -QwtScaleEngine *QwtAbstractScale::scaleEngine() -{ - return d_data->scaleEngine; -} - -/*! - \return Scale boundaries and positions of the ticks - - The scale division might have been assigned explicitly - or calculated implicitly by rescale(). - */ -const QwtScaleDiv &QwtAbstractScale::scaleDiv() const -{ - return d_data->scaleDraw->scaleDiv(); -} - -/*! - \return Map to translate between scale and widget coordinates - */ -const QwtScaleMap &QwtAbstractScale::scaleMap() const -{ - return d_data->scaleDraw->scaleMap(); -} - -/*! - Translate a scale value into a widget coordinate - - \param value Scale value - \return Corresponding widget coordinate for value - \sa scaleMap(), invTransform() - */ -int QwtAbstractScale::transform( double value ) const -{ - return qRound( d_data->scaleDraw->scaleMap().transform( value ) ); -} - -/*! - Translate a widget coordinate into a scale value - - \param value Widget coordinate - \return Corresponding scale coordinate for value - \sa scaleMap(), transform() - */ -double QwtAbstractScale::invTransform( int value ) const -{ - return d_data->scaleDraw->scaleMap().invTransform( value ); -} - -/*! - \return True, when the scale is increasing in opposite direction - to the widget coordinates - */ -bool QwtAbstractScale::isInverted() const -{ - return d_data->scaleDraw->scaleMap().isInverting(); -} - -/*! - \return The boundary with the smaller value - \sa maximum(), lowerBound(), upperBound() - */ -double QwtAbstractScale::minimum() const -{ - return qMin( d_data->scaleDraw->scaleDiv().lowerBound(), - d_data->scaleDraw->scaleDiv().upperBound() ); -} - -/*! - \return The boundary with the larger value - \sa minimum(), lowerBound(), upperBound() - */ -double QwtAbstractScale::maximum() const -{ - return qMax( d_data->scaleDraw->scaleDiv().lowerBound(), - d_data->scaleDraw->scaleDiv().upperBound() ); -} - -//! Notify changed scale -void QwtAbstractScale::scaleChange() -{ -} - -/*! - Recalculate the scale division and update the scale. - - \param lowerBound Lower limit of the scale interval - \param upperBound Upper limit of the scale interval - \param stepSize Major step size - - \sa scaleChange() -*/ -void QwtAbstractScale::rescale( - double lowerBound, double upperBound, double stepSize ) -{ - const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale( - lowerBound, upperBound, d_data->maxMajor, d_data->maxMinor, stepSize ); - - if ( scaleDiv != d_data->scaleDraw->scaleDiv() ) - { -#if 1 - d_data->scaleDraw->setTransformation( - d_data->scaleEngine->transformation() ); -#endif - - d_data->scaleDraw->setScaleDiv( scaleDiv ); - scaleChange(); - } -} - -void QwtAbstractScale::updateScaleDraw() -{ - rescale( d_data->scaleDraw->scaleDiv().lowerBound(), - d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize ); -} diff --git a/source/third_party/qwt/qwt_abstract_scale_draw.cpp b/source/third_party/qwt/qwt_abstract_scale_draw.cpp deleted file mode 100644 index 743b4c7903a4a28fbedc4cdab4a803215c85cb95..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_abstract_scale_draw.cpp +++ /dev/null @@ -1,420 +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/qwt_abstract_scale_draw.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include <qpainter.h> -#include <qpalette.h> -#include <qmap.h> -#include <qlocale.h> - -class QwtAbstractScaleDraw::PrivateData -{ -public: - PrivateData(): - spacing( 4.0 ), - penWidth( 0 ), - minExtent( 0.0 ) - { - components = QwtAbstractScaleDraw::Backbone - | QwtAbstractScaleDraw::Ticks - | QwtAbstractScaleDraw::Labels; - - tickLength[QwtScaleDiv::MinorTick] = 4.0; - tickLength[QwtScaleDiv::MediumTick] = 6.0; - tickLength[QwtScaleDiv::MajorTick] = 8.0; - } - - ScaleComponents components; - - QwtScaleMap map; - QwtScaleDiv scaleDiv; - - double spacing; - double tickLength[QwtScaleDiv::NTickTypes]; - int penWidth; - - double minExtent; - - QMap<double, QwtText> labelCache; -}; - -/*! - \brief Constructor - - The range of the scale is initialized to [0, 100], - The spacing (distance between ticks and labels) is - set to 4, the tick lengths are set to 4,6 and 8 pixels -*/ -QwtAbstractScaleDraw::QwtAbstractScaleDraw() -{ - d_data = new QwtAbstractScaleDraw::PrivateData; -} - -//! Destructor -QwtAbstractScaleDraw::~QwtAbstractScaleDraw() -{ - delete d_data; -} - -/*! - En/Disable a component of the scale - - \param component Scale component - \param enable On/Off - - \sa hasComponent() -*/ -void QwtAbstractScaleDraw::enableComponent( - ScaleComponent component, bool enable ) -{ - if ( enable ) - d_data->components |= component; - else - d_data->components &= ~component; -} - -/*! - Check if a component is enabled - - \param component Component type - \return true, when component is enabled - \sa enableComponent() -*/ -bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const -{ - return ( d_data->components & component ); -} - -/*! - Change the scale division - \param scaleDiv New scale division -*/ -void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &scaleDiv ) -{ - d_data->scaleDiv = scaleDiv; - d_data->map.setScaleInterval( scaleDiv.lowerBound(), scaleDiv.upperBound() ); - d_data->labelCache.clear(); -} - -/*! - Change the transformation of the scale - \param transformation New scale transformation -*/ -void QwtAbstractScaleDraw::setTransformation( - QwtTransform *transformation ) -{ - d_data->map.setTransformation( transformation ); -} - -//! \return Map how to translate between scale and pixel values -const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const -{ - return d_data->map; -} - -//! \return Map how to translate between scale and pixel values -QwtScaleMap &QwtAbstractScaleDraw::scaleMap() -{ - return d_data->map; -} - -//! \return scale division -const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const -{ - return d_data->scaleDiv; -} - -/*! - \brief Specify the width of the scale pen - \param width Pen width - \sa penWidth() -*/ -void QwtAbstractScaleDraw::setPenWidth( int width ) -{ - if ( width < 0 ) - width = 0; - - if ( width != d_data->penWidth ) - d_data->penWidth = width; -} - -/*! - \return Scale pen width - \sa setPenWidth() -*/ -int QwtAbstractScaleDraw::penWidth() const -{ - return d_data->penWidth; -} - -/*! - \brief Draw the scale - - \param painter The painter - - \param palette Palette, text color is used for the labels, - foreground color for ticks and backbone -*/ -void QwtAbstractScaleDraw::draw( QPainter *painter, - const QPalette& palette ) const -{ - painter->save(); - - QPen pen = painter->pen(); - pen.setWidth( d_data->penWidth ); - pen.setCosmetic( false ); - painter->setPen( pen ); - - if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) - { - painter->save(); - painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style - - const QList<double> &majorTicks = - d_data->scaleDiv.ticks( QwtScaleDiv::MajorTick ); - - for ( int i = 0; i < majorTicks.count(); i++ ) - { - const double v = majorTicks[i]; - if ( d_data->scaleDiv.contains( v ) ) - drawLabel( painter, v ); - } - - painter->restore(); - } - - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) - { - painter->save(); - - QPen pen = painter->pen(); - pen.setColor( palette.color( QPalette::WindowText ) ); - pen.setCapStyle( Qt::FlatCap ); - - painter->setPen( pen ); - - for ( int tickType = QwtScaleDiv::MinorTick; - tickType < QwtScaleDiv::NTickTypes; tickType++ ) - { - const double tickLen = d_data->tickLength[tickType]; - if ( tickLen <= 0.0 ) - continue; - - const QList<double> &ticks = d_data->scaleDiv.ticks( tickType ); - for ( int i = 0; i < ticks.count(); i++ ) - { - const double v = ticks[i]; - if ( d_data->scaleDiv.contains( v ) ) - drawTick( painter, v, tickLen ); - } - } - - painter->restore(); - } - - if ( hasComponent( QwtAbstractScaleDraw::Backbone ) ) - { - painter->save(); - - QPen pen = painter->pen(); - pen.setColor( palette.color( QPalette::WindowText ) ); - pen.setCapStyle( Qt::FlatCap ); - - painter->setPen( pen ); - - drawBackbone( painter ); - - painter->restore(); - } - - painter->restore(); -} - -/*! - \brief Set the spacing between tick and labels - - The spacing is the distance between ticks and labels. - The default spacing is 4 pixels. - - \param spacing Spacing - - \sa spacing() -*/ -void QwtAbstractScaleDraw::setSpacing( double spacing ) -{ - if ( spacing < 0 ) - spacing = 0; - - d_data->spacing = spacing; -} - -/*! - \brief Get the spacing - - The spacing is the distance between ticks and labels. - The default spacing is 4 pixels. - - \return Spacing - \sa setSpacing() -*/ -double QwtAbstractScaleDraw::spacing() const -{ - return d_data->spacing; -} - -/*! - \brief Set a minimum for the extent - - The extent is calculated from the components of the - scale draw. In situations, where the labels are - changing and the layout depends on the extent (f.e scrolling - a scale), setting an upper limit as minimum extent will - avoid jumps of the layout. - - \param minExtent Minimum extent - - \sa extent(), minimumExtent() -*/ -void QwtAbstractScaleDraw::setMinimumExtent( double minExtent ) -{ - if ( minExtent < 0.0 ) - minExtent = 0.0; - - d_data->minExtent = minExtent; -} - -/*! - Get the minimum extent - \return Minimum extent - \sa extent(), setMinimumExtent() -*/ -double QwtAbstractScaleDraw::minimumExtent() const -{ - return d_data->minExtent; -} - -/*! - Set the length of the ticks - - \param tickType Tick type - \param length New length - - \warning the length is limited to [0..1000] -*/ -void QwtAbstractScaleDraw::setTickLength( - QwtScaleDiv::TickType tickType, double length ) -{ - if ( tickType < QwtScaleDiv::MinorTick || - tickType > QwtScaleDiv::MajorTick ) - { - return; - } - - if ( length < 0.0 ) - length = 0.0; - - const double maxTickLen = 1000.0; - if ( length > maxTickLen ) - length = maxTickLen; - - d_data->tickLength[tickType] = length; -} - -/*! - \return Length of the ticks - \sa setTickLength(), maxTickLength() -*/ -double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const -{ - if ( tickType < QwtScaleDiv::MinorTick || - tickType > QwtScaleDiv::MajorTick ) - { - return 0; - } - - return d_data->tickLength[tickType]; -} - -/*! - \return Length of the longest tick - - Useful for layout calculations - \sa tickLength(), setTickLength() -*/ -double QwtAbstractScaleDraw::maxTickLength() const -{ - double length = 0.0; - for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) - length = qMax( length, d_data->tickLength[i] ); - - return length; -} - -/*! - \brief Convert a value into its representing label - - The value is converted to a plain text using - QLocale().toString(value). - This method is often overloaded by applications to have individual - labels. - - \param value Value - \return Label string. -*/ -QwtText QwtAbstractScaleDraw::label( double value ) const -{ - return QLocale().toString( value ); -} - -/*! - \brief Convert a value into its representing label and cache it. - - The conversion between value and label is called very often - in the layout and painting code. Unfortunately the - calculation of the label sizes might be slow (really slow - for rich text in Qt4), so it's necessary to cache the labels. - - \param font Font - \param value Value - - \return Tick label -*/ -const QwtText &QwtAbstractScaleDraw::tickLabel( - const QFont &font, double value ) const -{ - QMap<double, QwtText>::const_iterator it = d_data->labelCache.find( value ); - if ( it == d_data->labelCache.end() ) - { - QwtText lbl = label( value ); - lbl.setRenderFlags( 0 ); - lbl.setLayoutAttribute( QwtText::MinimumLayout ); - - ( void )lbl.textSize( font ); // initialize the internal cache - - it = d_data->labelCache.insert( value, lbl ); - } - - return ( *it ); -} - -/*! - Invalidate the cache used by tickLabel() - - The cache is invalidated, when a new QwtScaleDiv is set. If - the labels need to be changed. while the same QwtScaleDiv is set, - invalidateCache() needs to be called manually. -*/ -void QwtAbstractScaleDraw::invalidateCache() -{ - d_data->labelCache.clear(); -} diff --git a/source/third_party/qwt/qwt_abstract_slider.cpp b/source/third_party/qwt/qwt_abstract_slider.cpp deleted file mode 100644 index 70d2626600743941c10f675c521d91d6fedfaac9..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_abstract_slider.cpp +++ /dev/null @@ -1,822 +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/qwt_abstract_slider.h" -#include "qwt/qwt_abstract_scale_draw.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_scale_map.h" -#include <qevent.h> - -#if QT_VERSION < 0x040601 -#define qFabs(x) ::fabs(x) -#endif - -static double qwtAlignToScaleDiv( - const QwtAbstractSlider *slider, double value ) -{ - const QwtScaleDiv &sd = slider->scaleDiv(); - - const int tValue = slider->transform( value ); - - if ( tValue == slider->transform( sd.lowerBound() ) ) - return sd.lowerBound(); - - if ( tValue == slider->transform( sd.lowerBound() ) ) - return sd.upperBound(); - - for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) - { - const QList<double> ticks = sd.ticks( i ); - for ( int j = 0; j < ticks.size(); j++ ) - { - if ( slider->transform( ticks[ j ] ) == tValue ) - return ticks[ j ]; - } - } - - return value; -} - -class QwtAbstractSlider::PrivateData -{ -public: - PrivateData(): - isScrolling( false ), - isTracking( true ), - pendingValueChanged( false ), - readOnly( false ), - totalSteps( 100 ), - singleSteps( 1 ), - pageSteps( 10 ), - stepAlignment( true ), - isValid( false ), - value( 0.0 ), - wrapping( false ), - invertedControls( false ) - { - } - - bool isScrolling; - bool isTracking; - bool pendingValueChanged; - - bool readOnly; - - uint totalSteps; - uint singleSteps; - uint pageSteps; - bool stepAlignment; - - bool isValid; - double value; - - bool wrapping; - bool invertedControls; -}; - -/*! - \brief Constructor - - The scale is initialized to [0.0, 100.0], the - number of steps is set to 100 with 1 and 10 and single - an page step sizes. Step alignment is enabled. - - The initial value is invalid. - - \param parent Parent widget -*/ -QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ): - QwtAbstractScale( parent ) -{ - d_data = new QwtAbstractSlider::PrivateData; - - setScale( 0.0, 100.0 ); - setFocusPolicy( Qt::StrongFocus ); -} - -//! Destructor -QwtAbstractSlider::~QwtAbstractSlider() -{ - delete d_data; -} - -/*! - Set the value to be valid/invalid - - \param on When true, the value is invalidated - - \sa setValue() -*/ -void QwtAbstractSlider::setValid( bool on ) -{ - if ( on != d_data->isValid ) - { - d_data->isValid = on; - sliderChange(); - - Q_EMIT valueChanged( d_data->value ); - } -} - -//! \return True, when the value is invalid -bool QwtAbstractSlider::isValid() const -{ - return d_data->isValid; -} - -/*! - En/Disable read only mode - - In read only mode the slider can't be controlled by mouse - or keyboard. - - \param on Enables in case of true - \sa isReadOnly() - - \warning The focus policy is set to Qt::StrongFocus or Qt::NoFocus -*/ -void QwtAbstractSlider::setReadOnly( bool on ) -{ - if ( d_data->readOnly != on ) - { - d_data->readOnly = on; - setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus ); - - update(); - } -} - -/*! - In read only mode the slider can't be controlled by mouse - or keyboard. - - \return true if read only - \sa setReadOnly() -*/ -bool QwtAbstractSlider::isReadOnly() const -{ - return d_data->readOnly; -} - -/*! - \brief Enables or disables tracking. - - If tracking is enabled, the slider emits the valueChanged() - signal while the movable part of the slider is being dragged. - If tracking is disabled, the slider emits the valueChanged() signal - only when the user releases the slider. - - Tracking is enabled by default. - \param on \c true (enable) or \c false (disable) tracking. - - \sa isTracking(), sliderMoved() -*/ -void QwtAbstractSlider::setTracking( bool on ) -{ - d_data->isTracking = on; -} - -/*! - \return True, when tracking has been enabled - \sa setTracking() -*/ -bool QwtAbstractSlider::isTracking() const -{ - return d_data->isTracking; -} - -/*! - Mouse press event handler - \param event Mouse event -*/ -void QwtAbstractSlider::mousePressEvent( QMouseEvent *event ) -{ - if ( isReadOnly() ) - { - event->ignore(); - return; - } - - if ( !d_data->isValid || lowerBound() == upperBound() ) - return; - - d_data->isScrolling = isScrollPosition( event->pos() ); - - if ( d_data->isScrolling ) - { - d_data->pendingValueChanged = false; - - Q_EMIT sliderPressed(); - } -} - -/*! - Mouse Move Event handler - \param event Mouse event -*/ -void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event ) -{ - if ( isReadOnly() ) - { - event->ignore(); - return; - } - - if ( d_data->isValid && d_data->isScrolling ) - { - double value = scrolledTo( event->pos() ); - if ( value != d_data->value ) - { - value = boundedValue( value ); - - if ( d_data->stepAlignment ) - { - value = alignedValue( value ); - } - else - { - value = qwtAlignToScaleDiv( this, value ); - } - - if ( value != d_data->value ) - { - d_data->value = value; - - sliderChange(); - - Q_EMIT sliderMoved( d_data->value ); - - if ( d_data->isTracking ) - Q_EMIT valueChanged( d_data->value ); - else - d_data->pendingValueChanged = true; - } - } - } -} - -/*! - Mouse Release Event handler - \param event Mouse event -*/ -void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event ) -{ - if ( isReadOnly() ) - { - event->ignore(); - return; - } - - if ( d_data->isScrolling && d_data->isValid ) - { - d_data->isScrolling = false; - - if ( d_data->pendingValueChanged ) - Q_EMIT valueChanged( d_data->value ); - - Q_EMIT sliderReleased(); - } -} - -/*! - Wheel Event handler - - In/decreases the value by s number of steps. The direction - depends on the invertedControls() property. - - When the control or shift modifier is pressed the wheel delta - ( divided by 120 ) is mapped to an increment according to - pageSteps(). Otherwise it is mapped to singleSteps(). - - \param event Wheel event -*/ -void QwtAbstractSlider::wheelEvent( QWheelEvent *event ) -{ - if ( isReadOnly() ) - { - event->ignore(); - return; - } - - if ( !d_data->isValid || d_data->isScrolling ) - return; - - int numSteps = 0; - - if ( ( event->modifiers() & Qt::ControlModifier) || - ( event->modifiers() & Qt::ShiftModifier ) ) - { - // one page regardless of delta - numSteps = d_data->pageSteps; - if ( event->delta() < 0 ) - numSteps = -numSteps; - } - else - { - const int numTurns = ( event->delta() / 120 ); - numSteps = numTurns * d_data->singleSteps; - } - - if ( d_data->invertedControls ) - numSteps = -numSteps; - - const double value = incrementedValue( d_data->value, numSteps ); - if ( value != d_data->value ) - { - d_data->value = value; - sliderChange(); - - Q_EMIT sliderMoved( d_data->value ); - Q_EMIT valueChanged( d_data->value ); - } -} - -/*! - Handles key events - - QwtAbstractSlider handles the following keys: - - - Qt::Key_Left\n - Add/Subtract singleSteps() in direction to lowerBound(); - - Qt::Key_Right\n - Add/Subtract singleSteps() in direction to upperBound(); - - Qt::Key_Down\n - Subtract singleSteps(), when invertedControls() is false - - Qt::Key_Up\n - Add singleSteps(), when invertedControls() is false - - Qt::Key_PageDown\n - Subtract pageSteps(), when invertedControls() is false - - Qt::Key_PageUp\n - Add pageSteps(), when invertedControls() is false - - Qt::Key_Home\n - Set the value to the minimum() - - Qt::Key_End\n - Set the value to the maximum() - - \param event Key event - \sa isReadOnly() -*/ -void QwtAbstractSlider::keyPressEvent( QKeyEvent *event ) -{ - if ( isReadOnly() ) - { - event->ignore(); - return; - } - - if ( !d_data->isValid || d_data->isScrolling ) - return; - - int numSteps = 0; - double value = d_data->value; - - switch ( event->key() ) - { - case Qt::Key_Left: - { - numSteps = -static_cast<int>( d_data->singleSteps ); - if ( isInverted() ) - numSteps = -numSteps; - - break; - } - case Qt::Key_Right: - { - numSteps = d_data->singleSteps; - if ( isInverted() ) - numSteps = -numSteps; - - break; - } - case Qt::Key_Down: - { - numSteps = -static_cast<int>( d_data->singleSteps ); - if ( d_data->invertedControls ) - numSteps = -numSteps; - break; - } - case Qt::Key_Up: - { - numSteps = d_data->singleSteps; - if ( d_data->invertedControls ) - numSteps = -numSteps; - - break; - } - case Qt::Key_PageUp: - { - numSteps = d_data->pageSteps; - if ( d_data->invertedControls ) - numSteps = -numSteps; - break; - } - case Qt::Key_PageDown: - { - numSteps = -static_cast<int>( d_data->pageSteps ); - if ( d_data->invertedControls ) - numSteps = -numSteps; - break; - } - case Qt::Key_Home: - { - value = minimum(); - break; - } - case Qt::Key_End: - { - value = maximum(); - break; - } - default:; - { - event->ignore(); - } - } - - if ( numSteps != 0 ) - { - value = incrementedValue( d_data->value, numSteps ); - } - - if ( value != d_data->value ) - { - d_data->value = value; - sliderChange(); - - Q_EMIT sliderMoved( d_data->value ); - Q_EMIT valueChanged( d_data->value ); - } -} - -/*! - \brief Set the number of steps - - The range of the slider is divided into a number of steps from - which the value increments according to user inputs depend. - - The default setting is 100. - - \param stepCount Number of steps - - \sa totalSteps(), setSingleSteps(), setPageSteps() - */ -void QwtAbstractSlider::setTotalSteps( uint stepCount ) -{ - d_data->totalSteps = stepCount; -} - -/*! - \return Number of steps - \sa setTotalSteps(), singleSteps(), pageSteps() - */ -uint QwtAbstractSlider::totalSteps() const -{ - return d_data->totalSteps; -} - -/*! - \brief Set the number of steps for a single increment - - The range of the slider is divided into a number of steps from - which the value increments according to user inputs depend. - - \param stepCount Number of steps - - \sa singleSteps(), setTotalSteps(), setPageSteps() - */ - -void QwtAbstractSlider::setSingleSteps( uint stepCount ) -{ - d_data->singleSteps = stepCount; -} - -/*! - \return Number of steps - \sa setSingleSteps(), totalSteps(), pageSteps() - */ -uint QwtAbstractSlider::singleSteps() const -{ - return d_data->singleSteps; -} - -/*! - \brief Set the number of steps for a page increment - - The range of the slider is divided into a number of steps from - which the value increments according to user inputs depend. - - \param stepCount Number of steps - - \sa pageSteps(), setTotalSteps(), setSingleSteps() - */ - -void QwtAbstractSlider::setPageSteps( uint stepCount ) -{ - d_data->pageSteps = stepCount; -} - -/*! - \return Number of steps - \sa setPageSteps(), totalSteps(), singleSteps() - */ -uint QwtAbstractSlider::pageSteps() const -{ - return d_data->pageSteps; -} - -/*! - \brief Enable step alignment - - When step alignment is enabled values resulting from slider - movements are aligned to the step size. - - \param on Enable step alignment when true - \sa stepAlignment() -*/ -void QwtAbstractSlider::setStepAlignment( bool on ) -{ - if ( on != d_data->stepAlignment ) - { - d_data->stepAlignment = on; - } -} - -/*! - \return True, when step alignment is enabled - \sa setStepAlignment() - */ -bool QwtAbstractSlider::stepAlignment() const -{ - return d_data->stepAlignment; -} - -/*! - Set the slider to the specified value - - \param value New value - \sa setValid(), sliderChange(), valueChanged() -*/ -void QwtAbstractSlider::setValue( double value ) -{ - value = qBound( minimum(), value, maximum() ); - - const bool changed = ( d_data->value != value ) || !d_data->isValid; - - d_data->value = value; - d_data->isValid = true; - - if ( changed ) - { - sliderChange(); - Q_EMIT valueChanged( d_data->value ); - } -} - -//! Returns the current value. -double QwtAbstractSlider::value() const -{ - return d_data->value; -} - -/*! - If wrapping is true stepping up from upperBound() value will - take you to the minimum() value and vice versa. - - \param on En/Disable wrapping - \sa wrapping() -*/ -void QwtAbstractSlider::setWrapping( bool on ) -{ - d_data->wrapping = on; -} - -/*! - \return True, when wrapping is set - \sa setWrapping() - */ -bool QwtAbstractSlider::wrapping() const -{ - return d_data->wrapping; -} - -/*! - Invert wheel and key events - - Usually scrolling the mouse wheel "up" and using keys like page - up will increase the slider's value towards its maximum. - When invertedControls() is enabled the value is scrolled - towards its minimum. - - Inverting the controls might be f.e. useful for a vertical slider - with an inverted scale ( decreasing from top to bottom ). - - \param on Invert controls, when true - - \sa invertedControls(), keyEvent(), wheelEvent() - */ -void QwtAbstractSlider::setInvertedControls( bool on ) -{ - d_data->invertedControls = on; -} - -/*! - \return True, when the controls are inverted - \sa setInvertedControls() - */ -bool QwtAbstractSlider::invertedControls() const -{ - return d_data->invertedControls; -} - -/*! - Increment the slider - - The step size depends on the number of totalSteps() - - \param stepCount Number of steps - \sa setTotalSteps(), incrementedValue() - */ -void QwtAbstractSlider::incrementValue( int stepCount ) -{ - const double value = incrementedValue( - d_data->value, stepCount ); - - if ( value != d_data->value ) - { - d_data->value = value; - sliderChange(); - } -} - -/*! - Increment a value - - \param value Value - \param stepCount Number of steps - - \return Incremented value - */ -double QwtAbstractSlider::incrementedValue( - double value, int stepCount ) const -{ - if ( d_data->totalSteps == 0 ) - return value; - - const QwtTransform *transformation = - scaleMap().transformation(); - - if ( transformation == NULL ) - { - const double range = maximum() - minimum(); - value += stepCount * range / d_data->totalSteps; - } - else - { - QwtScaleMap map = scaleMap(); - map.setPaintInterval( 0, d_data->totalSteps ); - - // we need equidant steps according to - // paint device coordinates - const double range = transformation->transform( maximum() ) - - transformation->transform( minimum() ); - - const double stepSize = range / d_data->totalSteps; - - double v = transformation->transform( value ); - - v = qRound( v / stepSize ) * stepSize; - v += stepCount * range / d_data->totalSteps; - - value = transformation->invTransform( v ); - } - - value = boundedValue( value ); - - if ( d_data->stepAlignment ) - value = alignedValue( value ); - - return value; -} - -double QwtAbstractSlider::boundedValue( double value ) const -{ - const double vmin = minimum(); - const double vmax = maximum(); - - if ( d_data->wrapping && vmin != vmax ) - { - const int fullCircle = 360 * 16; - - const double pd = scaleMap().pDist(); - if ( int( pd / fullCircle ) * fullCircle == pd ) - { - // full circle scales: min and max are the same - const double range = vmax - vmin; - - if ( value < vmin ) - { - value += ::ceil( ( vmin - value ) / range ) * range; - } - else if ( value > vmax ) - { - value -= ::ceil( ( value - vmax ) / range ) * range; - } - } - else - { - if ( value < vmin ) - value = vmax; - else if ( value > vmax ) - value = vmin; - } - } - else - { - value = qBound( vmin, value, vmax ); - } - - return value; -} - -double QwtAbstractSlider::alignedValue( double value ) const -{ - if ( d_data->totalSteps == 0 ) - return value; - - double stepSize; - - if ( scaleMap().transformation() == NULL ) - { - stepSize = ( maximum() - minimum() ) / d_data->totalSteps; - if ( stepSize > 0.0 ) - { - value = lowerBound() + - qRound( ( value - lowerBound() ) / stepSize ) * stepSize; - } - } - else - { - stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps; - - if ( stepSize > 0.0 ) - { - double v = scaleMap().transform( value ); - - v = scaleMap().p1() + - qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize; - - value = scaleMap().invTransform( v ); - } - } - - if ( qAbs( stepSize ) > 1e-12 ) - { - if ( qFuzzyCompare( value + 1.0, 1.0 ) ) - { - // correct rounding error if value = 0 - value = 0.0; - } - else - { - // correct rounding error at the border - if ( qFuzzyCompare( value, upperBound() ) ) - value = upperBound(); - else if ( qFuzzyCompare( value, lowerBound() ) ) - value = lowerBound(); - } - } - - return value; -} - -/*! - Update the slider according to modifications of the scale - */ -void QwtAbstractSlider::scaleChange() -{ - const double value = qBound( minimum(), d_data->value, maximum() ); - - const bool changed = ( value != d_data->value ); - if ( changed ) - { - d_data->value = value; - } - - if ( d_data->isValid || changed ) - Q_EMIT valueChanged( d_data->value ); - - updateGeometry(); - update(); -} - -//! Calling update() -void QwtAbstractSlider::sliderChange() -{ - update(); -} diff --git a/source/third_party/qwt/qwt_analog_clock.cpp b/source/third_party/qwt/qwt_analog_clock.cpp deleted file mode 100644 index 03c482b3fa2fd06d06855b9cfa17ad1ff4051947..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_analog_clock.cpp +++ /dev/null @@ -1,244 +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/qwt_analog_clock.h" -#include "qwt/qwt_round_scale_draw.h" -#include <qmath.h> -#include <qlocale.h> - -class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw -{ -public: - QwtAnalogClockScaleDraw() - { - setSpacing( 8 ); - - enableComponent( QwtAbstractScaleDraw::Backbone, false ); - - setTickLength( QwtScaleDiv::MinorTick, 2 ); - setTickLength( QwtScaleDiv::MediumTick, 4 ); - setTickLength( QwtScaleDiv::MajorTick, 8 ); - - setPenWidth( 1 ); - } - - virtual QwtText label( double value ) const - { - if ( qFuzzyCompare( value + 1.0, 1.0 ) ) - value = 60.0 * 60.0 * 12.0; - - return QLocale().toString( qRound( value / ( 60.0 * 60.0 ) ) ); - } -}; - -/*! - Constructor - \param parent Parent widget -*/ -QwtAnalogClock::QwtAnalogClock( QWidget *parent ): - QwtDial( parent ) -{ - setWrapping( true ); - setReadOnly( true ); - - setOrigin( 270.0 ); - setScaleDraw( new QwtAnalogClockScaleDraw() ); - - setTotalSteps( 60 ); - - const int secondsPerHour = 60.0 * 60.0; - - QList<double> majorTicks; - QList<double> minorTicks; - - for ( int i = 0; i < 12; i++ ) - { - majorTicks += i * secondsPerHour; - - for ( int j = 1; j < 5; j++ ) - minorTicks += i * secondsPerHour + j * secondsPerHour / 5.0; - } - - QwtScaleDiv scaleDiv; - scaleDiv.setInterval( 0.0, 12.0 * secondsPerHour ); - scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); - scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); - setScale( scaleDiv ); - - QColor knobColor = palette().color( QPalette::Active, QPalette::Text ); - knobColor = knobColor.dark( 120 ); - - QColor handColor; - int width; - - for ( int i = 0; i < NHands; i++ ) - { - if ( i == SecondHand ) - { - width = 2; - handColor = knobColor.dark( 120 ); - } - else - { - width = 8; - handColor = knobColor; - } - - QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle( - QwtDialSimpleNeedle::Arrow, true, handColor, knobColor ); - hand->setWidth( width ); - - d_hand[i] = NULL; - setHand( static_cast<Hand>( i ), hand ); - } -} - -//! Destructor -QwtAnalogClock::~QwtAnalogClock() -{ - for ( int i = 0; i < NHands; i++ ) - delete d_hand[i]; -} - -/*! - Nop method, use setHand() instead - \sa setHand() -*/ -void QwtAnalogClock::setNeedle( QwtDialNeedle * ) -{ - // no op - return; -} - -/*! - Set a clock hand - \param hand Specifies the type of hand - \param needle Hand - \sa hand() -*/ -void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle ) -{ - if ( hand >= 0 && hand < NHands ) - { - delete d_hand[hand]; - d_hand[hand] = needle; - } -} - -/*! - \return Clock hand - \param hd Specifies the type of hand - \sa setHand() -*/ -QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) -{ - if ( hd < 0 || hd >= NHands ) - return NULL; - - return d_hand[hd]; -} - -/*! - \return Clock hand - \param hd Specifies the type of hand - \sa setHand() -*/ -const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const -{ - return const_cast<QwtAnalogClock *>( this )->hand( hd ); -} - -/*! - \brief Set the current time -*/ -void QwtAnalogClock::setCurrentTime() -{ - setTime( QTime::currentTime() ); -} - -/*! - Set a time - \param time Time to display -*/ -void QwtAnalogClock::setTime( const QTime &time ) -{ - if ( time.isValid() ) - { - setValue( ( time.hour() % 12 ) * 60.0 * 60.0 - + time.minute() * 60.0 + time.second() ); - } - else - setValid( false ); -} - -/*! - \brief Draw the needle - - A clock has no single needle but three hands instead. drawNeedle() - translates value() into directions for the hands and calls - drawHand(). - - \param painter Painter - \param center Center of the clock - \param radius Maximum length for the hands - \param dir Dummy, not used. - \param colorGroup ColorGroup - - \sa drawHand() -*/ -void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF ¢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() - qFloor(hours) * 60.0 * 60.0 ) / 60.0; - const double seconds = value() - qFloor(hours) * 60.0 * 60.0 - - qFloor(minutes) * 60.0; - - double angle[NHands]; - angle[HourHand] = 360.0 * hours / 12.0; - angle[MinuteHand] = 360.0 * minutes / 60.0; - angle[SecondHand] = 360.0 * seconds / 60.0; - - for ( int hand = 0; hand < NHands; hand++ ) - { - const double d = 360.0 - angle[hand] - origin(); - drawHand( painter, static_cast<Hand>( hand ), - center, radius, d, colorGroup ); - } - } -} - -/*! - Draw a clock hand - - \param painter Painter - \param hd Specify the type of hand - \param center Center of the clock - \param radius Maximum length for the hands - \param direction Direction of the hand in degrees, counter clockwise - \param cg ColorGroup -*/ -void QwtAnalogClock::drawHand( QPainter *painter, Hand hd, - const QPointF ¢er, double radius, double direction, - QPalette::ColorGroup cg ) const -{ - const QwtDialNeedle *needle = hand( hd ); - if ( needle ) - { - if ( hd == HourHand ) - radius = qRound( 0.8 * radius ); - - needle->draw( painter, center, radius, direction, cg ); - } -} diff --git a/source/third_party/qwt/qwt_arrow_button.cpp b/source/third_party/qwt/qwt_arrow_button.cpp deleted file mode 100644 index 2759b07d427e0bd53cfb25d458d073f3a021ee5f..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_arrow_button.cpp +++ /dev/null @@ -1,333 +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/qwt_arrow_button.h" -#include "qwt/qwt_math.h" -#include <qpainter.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qevent.h> -#include <qapplication.h> - -static const int MaxNum = 3; -static const int Margin = 2; -static const int Spacing = 1; - -class QwtArrowButton::PrivateData -{ -public: - int num; - Qt::ArrowType arrowType; -}; - -static QStyleOptionButton styleOpt( const QwtArrowButton* btn ) -{ - QStyleOptionButton option; - option.init( btn ); - option.features = QStyleOptionButton::None; - if ( btn->isFlat() ) - option.features |= QStyleOptionButton::Flat; - if ( btn->menu() ) - option.features |= QStyleOptionButton::HasMenu; - if ( btn->autoDefault() || btn->isDefault() ) - option.features |= QStyleOptionButton::AutoDefaultButton; - if ( btn->isDefault() ) - option.features |= QStyleOptionButton::DefaultButton; - if ( btn->isDown() ) - option.state |= QStyle::State_Sunken; - if ( !btn->isFlat() && !btn->isDown() ) - option.state |= QStyle::State_Raised; - - return option; -} - -/*! - \param num Number of arrows - \param arrowType see Qt::ArrowType in the Qt docs. - \param parent Parent widget -*/ -QwtArrowButton::QwtArrowButton( int num, - Qt::ArrowType arrowType, QWidget *parent ): - QPushButton( parent ) -{ - d_data = new PrivateData; - d_data->num = qBound( 1, num, MaxNum ); - d_data->arrowType = arrowType; - - setAutoRepeat( true ); - setAutoDefault( false ); - - switch ( d_data->arrowType ) - { - case Qt::LeftArrow: - case Qt::RightArrow: - setSizePolicy( QSizePolicy::Expanding, - QSizePolicy::Fixed ); - break; - default: - setSizePolicy( QSizePolicy::Fixed, - QSizePolicy::Expanding ); - } -} - -//! Destructor -QwtArrowButton::~QwtArrowButton() -{ - delete d_data; - d_data = NULL; -} - -/*! - \brief The direction of the arrows -*/ -Qt::ArrowType QwtArrowButton::arrowType() const -{ - return d_data->arrowType; -} - -/*! - \brief The number of arrows -*/ -int QwtArrowButton::num() const -{ - return d_data->num; -} - -/*! - \return the bounding rectangle for the label -*/ -QRect QwtArrowButton::labelRect() const -{ - const int m = Margin; - - QRect r = rect(); - r.setRect( r.x() + m, r.y() + m, - r.width() - 2 * m, r.height() - 2 * m ); - - if ( isDown() ) - { - QStyleOptionButton option = styleOpt( this ); - const int ph = style()->pixelMetric( - QStyle::PM_ButtonShiftHorizontal, &option, this ); - const int pv = style()->pixelMetric( - QStyle::PM_ButtonShiftVertical, &option, this ); - - r.translate( ph, pv ); - } - - return r; -} - -/*! - Paint event handler - \param event Paint event -*/ -void QwtArrowButton::paintEvent( QPaintEvent *event ) -{ - QPushButton::paintEvent( event ); - QPainter painter( this ); - drawButtonLabel( &painter ); -} - -/*! - \brief Draw the button label - - \param painter Painter - \sa The Qt Manual for QPushButton -*/ -void QwtArrowButton::drawButtonLabel( QPainter *painter ) -{ - const bool isVertical = d_data->arrowType == Qt::UpArrow || - d_data->arrowType == Qt::DownArrow; - - const QRect r = labelRect(); - QSize boundingSize = labelRect().size(); - if ( isVertical ) - boundingSize.transpose(); - - const int w = - ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum; - - QSize arrow = arrowSize( Qt::RightArrow, - QSize( w, boundingSize.height() ) ); - - if ( isVertical ) - arrow.transpose(); - - QRect contentsSize; // aligned rect where to paint all arrows - if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow ) - { - contentsSize.setWidth( d_data->num * arrow.width() - + ( d_data->num - 1 ) * Spacing ); - contentsSize.setHeight( arrow.height() ); - } - else - { - contentsSize.setWidth( arrow.width() ); - contentsSize.setHeight( d_data->num * arrow.height() - + ( d_data->num - 1 ) * Spacing ); - } - - QRect arrowRect( contentsSize ); - arrowRect.moveCenter( r.center() ); - arrowRect.setSize( arrow ); - - painter->save(); - for ( int i = 0; i < d_data->num; i++ ) - { - drawArrow( painter, arrowRect, d_data->arrowType ); - - int dx = 0; - int dy = 0; - - if ( isVertical ) - dy = arrow.height() + Spacing; - else - dx = arrow.width() + Spacing; - - arrowRect.translate( dx, dy ); - } - painter->restore(); - - if ( hasFocus() ) - { - QStyleOptionFocusRect option; - option.init( this ); - option.backgroundColor = palette().color( QPalette::Window ); - - style()->drawPrimitive( QStyle::PE_FrameFocusRect, - &option, painter, this ); - } -} - -/*! - Draw an arrow int a bounding rectangle - - \param painter Painter - \param r Rectangle where to paint the arrow - \param arrowType Arrow type -*/ -void QwtArrowButton::drawArrow( QPainter *painter, - const QRect &r, Qt::ArrowType arrowType ) const -{ - QPolygon pa( 3 ); - - switch ( arrowType ) - { - case Qt::UpArrow: - pa.setPoint( 0, r.bottomLeft() ); - pa.setPoint( 1, r.bottomRight() ); - pa.setPoint( 2, r.center().x(), r.top() ); - break; - case Qt::DownArrow: - pa.setPoint( 0, r.topLeft() ); - pa.setPoint( 1, r.topRight() ); - pa.setPoint( 2, r.center().x(), r.bottom() ); - break; - case Qt::RightArrow: - pa.setPoint( 0, r.topLeft() ); - pa.setPoint( 1, r.bottomLeft() ); - pa.setPoint( 2, r.right(), r.center().y() ); - break; - case Qt::LeftArrow: - pa.setPoint( 0, r.topRight() ); - pa.setPoint( 1, r.bottomRight() ); - pa.setPoint( 2, r.left(), r.center().y() ); - break; - default: - break; - } - - painter->save(); - - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->setPen( Qt::NoPen ); - painter->setBrush( palette().brush( QPalette::ButtonText ) ); - painter->drawPolygon( pa ); - - painter->restore(); -} - -/*! - \return a size hint -*/ -QSize QwtArrowButton::sizeHint() const -{ - const QSize hint = minimumSizeHint(); - return hint.expandedTo( QApplication::globalStrut() ); -} - -/*! - \brief Return a minimum size hint -*/ -QSize QwtArrowButton::minimumSizeHint() const -{ - const QSize asz = arrowSize( Qt::RightArrow, QSize() ); - - QSize sz( - 2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(), - 2 * Margin + asz.height() - ); - - if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow ) - sz.transpose(); - - QStyleOption styleOption; - styleOption.init( this ); - - sz = style()->sizeFromContents( QStyle::CT_PushButton, - &styleOption, sz, this ); - - return sz; -} - -/*! - Calculate the size for a arrow that fits into a rectangle of a given size - - \param arrowType Arrow type - \param boundingSize Bounding size - \return Size of the arrow -*/ -QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType, - const QSize &boundingSize ) const -{ - QSize bs = boundingSize; - if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow ) - bs.transpose(); - - const int MinLen = 2; - const QSize sz = bs.expandedTo( - QSize( MinLen, 2 * MinLen - 1 ) ); // minimum - - int w = sz.width(); - int h = 2 * w - 1; - - if ( h > sz.height() ) - { - h = sz.height(); - w = ( h + 1 ) / 2; - } - - QSize arrSize( w, h ); - if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow ) - arrSize.transpose(); - - return arrSize; -} - -/*! - \brief autoRepeat for the space keys -*/ -void QwtArrowButton::keyPressEvent( QKeyEvent *event ) -{ - if ( event->isAutoRepeat() && event->key() == Qt::Key_Space ) - Q_EMIT clicked(); - - QPushButton::keyPressEvent( event ); -} diff --git a/source/third_party/qwt/qwt_clipper.cpp b/source/third_party/qwt/qwt_clipper.cpp deleted file mode 100644 index 044da6e48642ad2ec458377047b863a0518d629c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_clipper.cpp +++ /dev/null @@ -1,510 +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/qwt_clipper.h" -#include "qwt/qwt_point_polar.h" -#include <qrect.h> -#include <string.h> -#include <stdlib.h> - -#if QT_VERSION < 0x040601 -#define qAtan(x) ::atan(x) -#endif - -namespace QwtClip -{ - // some templates used for inlining - template <class Point, typename T> class LeftEdge; - template <class Point, typename T> class RightEdge; - template <class Point, typename T> class TopEdge; - template <class Point, typename T> class BottomEdge; - - template <class Point> class PointBuffer; -} - -template <class Point, typename Value> -class QwtClip::LeftEdge -{ -public: - inline LeftEdge( Value x1, Value, Value, Value ): - d_x1( x1 ) - { - } - - inline bool isInside( const Point &p ) const - { - return p.x() >= d_x1; - } - - inline Point intersection( const Point &p1, const Point &p2 ) const - { - double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() ); - return Point( d_x1, static_cast< Value >( p2.y() + ( d_x1 - p2.x() ) * dy ) ); - } -private: - const Value d_x1; -}; - -template <class Point, typename Value> -class QwtClip::RightEdge -{ -public: - inline RightEdge( Value, Value x2, Value, Value ): - d_x2( x2 ) - { - } - - inline bool isInside( const Point &p ) const - { - return p.x() <= d_x2; - } - - inline Point intersection( const Point &p1, const Point &p2 ) const - { - double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() ); - return Point( d_x2, static_cast<Value>( p2.y() + ( d_x2 - p2.x() ) * dy ) ); - } - -private: - const Value d_x2; -}; - -template <class Point, typename Value> -class QwtClip::TopEdge -{ -public: - inline TopEdge( Value, Value, Value y1, Value ): - d_y1( y1 ) - { - } - - inline bool isInside( const Point &p ) const - { - return p.y() >= d_y1; - } - - inline Point intersection( const Point &p1, const Point &p2 ) const - { - double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() ); - return Point( static_cast<Value>( p2.x() + ( d_y1 - p2.y() ) * dx ), d_y1 ); - } - -private: - const Value d_y1; -}; - -template <class Point, typename Value> -class QwtClip::BottomEdge -{ -public: - inline BottomEdge( Value, Value, Value, Value y2 ): - d_y2( y2 ) - { - } - - inline bool isInside( const Point &p ) const - { - return p.y() <= d_y2; - } - - inline Point intersection( const Point &p1, const Point &p2 ) const - { - double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() ); - return Point( static_cast<Value>( p2.x() + ( d_y2 - p2.y() ) * dx ), d_y2 ); - } - -private: - const Value d_y2; -}; - -template<class Point> -class QwtClip::PointBuffer -{ -public: - PointBuffer( int capacity = 0 ): - m_capacity( 0 ), - m_size( 0 ), - m_buffer( NULL ) - { - if ( capacity > 0 ) - reserve( capacity ); - } - - ~PointBuffer() - { - if ( m_buffer ) - ::free( m_buffer ); - } - - inline void setPoints( int numPoints, const Point *points ) - { - reserve( numPoints ); - - m_size = numPoints; - ::memcpy( m_buffer, points, m_size * sizeof( Point ) ); - } - - inline void reset() - { - m_size = 0; - } - - inline int size() const - { - return m_size; - } - - inline Point *data() const - { - return m_buffer; - } - - inline Point &operator[]( int i ) - { - return m_buffer[i]; - } - - inline const Point &operator[]( int i ) const - { - return m_buffer[i]; - } - - inline void add( const Point &point ) - { - if ( m_capacity <= m_size ) - reserve( m_size + 1 ); - - m_buffer[m_size++] = point; - } - -private: - inline void reserve( int size ) - { - if ( m_capacity == 0 ) - m_capacity = 1; - - while ( m_capacity < size ) - m_capacity *= 2; - - m_buffer = static_cast<Point *>( - ::realloc( m_buffer, m_capacity * sizeof( Point ) ) ); - } - - int m_capacity; - int m_size; - Point *m_buffer; -}; - -using namespace QwtClip; - -template <class Polygon, class Rect, class Point, typename T> -class QwtPolygonClipper -{ -public: - QwtPolygonClipper( const Rect &clipRect ): - d_clipRect( clipRect ) - { - } - - Polygon clipPolygon( const Polygon &polygon, bool closePolygon ) const - { -#if 0 - if ( d_clipRect.contains( polygon.boundingRect() ) ) - return polygon; -#endif - - PointBuffer<Point> points1; - PointBuffer<Point> points2( qMin( 256, polygon.size() ) ); - - points1.setPoints( polygon.size(), polygon.data() ); - - clipEdge< LeftEdge<Point, T> >( closePolygon, points1, points2 ); - clipEdge< RightEdge<Point, T> >( closePolygon, points2, points1 ); - clipEdge< TopEdge<Point, T> >( closePolygon, points1, points2 ); - clipEdge< BottomEdge<Point, T> >( closePolygon, points2, points1 ); - - Polygon p; - p.resize( points1.size() ); - ::memcpy( p.data(), points1.data(), points1.size() * sizeof( Point ) ); - - return p; - } - -private: - template <class Edge> - inline void clipEdge( bool closePolygon, - PointBuffer<Point> &points, PointBuffer<Point> &clippedPoints ) const - { - clippedPoints.reset(); - - if ( points.size() < 2 ) - { - if ( points.size() == 1 ) - clippedPoints.add( points[0] ); - return; - } - - const Edge edge( d_clipRect.x(), d_clipRect.x() + d_clipRect.width(), - d_clipRect.y(), d_clipRect.y() + d_clipRect.height() ); - - int lastPos, start; - if ( closePolygon ) - { - start = 0; - lastPos = points.size() - 1; - } - else - { - start = 1; - lastPos = 0; - - if ( edge.isInside( points[0] ) ) - clippedPoints.add( points[0] ); - } - - const uint nPoints = points.size(); - for ( uint i = start; i < nPoints; i++ ) - { - const Point &p1 = points[i]; - const Point &p2 = points[lastPos]; - - if ( edge.isInside( p1 ) ) - { - if ( edge.isInside( p2 ) ) - { - clippedPoints.add( p1 ); - } - else - { - clippedPoints.add( edge.intersection( p1, p2 ) ); - clippedPoints.add( p1 ); - } - } - else - { - if ( edge.isInside( p2 ) ) - { - clippedPoints.add( edge.intersection( p1, p2 ) ); - } - } - lastPos = i; - } - } - - const Rect d_clipRect; -}; - -class QwtCircleClipper -{ -public: - QwtCircleClipper( const QRectF &r ); - QVector<QwtInterval> clipCircle( const QPointF &, double radius ) const; - -private: - enum Edge - { - Left, - Top, - Right, - Bottom, - - NEdges - }; - - QList<QPointF> cuttingPoints( - Edge, const QPointF &pos, double radius ) const; - - double toAngle( const QPointF &, const QPointF & ) const; - - const QRectF d_rect; -}; - - -QwtCircleClipper::QwtCircleClipper( const QRectF &r ): - d_rect( r ) -{ -} - -QVector<QwtInterval> QwtCircleClipper::clipCircle( - const QPointF &pos, double radius ) const -{ - QList<QPointF> points; - for ( int edge = 0; edge < NEdges; edge++ ) - points += cuttingPoints( static_cast<Edge>(edge), pos, radius ); - - QVector<QwtInterval> intv; - if ( points.size() <= 0 ) - { - QRectF cRect( 0, 0, 2 * radius, 2 * radius ); - cRect.moveCenter( pos ); - if ( d_rect.contains( cRect ) ) - intv += QwtInterval( 0.0, 2 * M_PI ); - } - else - { - QList<double> angles; - for ( int i = 0; i < points.size(); i++ ) - angles += toAngle( pos, points[i] ); - qSort( angles ); - - const int in = d_rect.contains( qwtPolar2Pos( pos, radius, - angles[0] + ( angles[1] - angles[0] ) / 2 ) ); - - if ( in ) - { - for ( int i = 0; i < angles.size() - 1; i += 2 ) - intv += QwtInterval( angles[i], angles[i+1] ); - } - else - { - for ( int i = 1; i < angles.size() - 1; i += 2 ) - intv += QwtInterval( angles[i], angles[i+1] ); - intv += QwtInterval( angles.last(), angles.first() ); - } - } - - return intv; -} - -double QwtCircleClipper::toAngle( - const QPointF &from, const QPointF &to ) const -{ - if ( from.x() == to.x() ) - return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0; - - const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) ); - - double angle = qAtan( m ); - if ( to.x() > from.x() ) - { - if ( to.y() > from.y() ) - angle = 2 * M_PI - angle; - } - else - { - if ( to.y() > from.y() ) - angle = M_PI + angle; - else - angle = M_PI - angle; - } - - return angle; -} - -QList<QPointF> QwtCircleClipper::cuttingPoints( - Edge edge, const QPointF &pos, double radius ) const -{ - QList<QPointF> points; - - if ( edge == Left || edge == Right ) - { - const double x = ( edge == Left ) ? d_rect.left() : d_rect.right(); - if ( qAbs( pos.x() - x ) < radius ) - { - const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.x() - x ) ); - const double m_y1 = pos.y() + off; - if ( m_y1 >= d_rect.top() && m_y1 <= d_rect.bottom() ) - points += QPointF( x, m_y1 ); - - const double m_y2 = pos.y() - off; - if ( m_y2 >= d_rect.top() && m_y2 <= d_rect.bottom() ) - points += QPointF( x, m_y2 ); - } - } - else - { - const double y = ( edge == Top ) ? d_rect.top() : d_rect.bottom(); - if ( qAbs( pos.y() - y ) < radius ) - { - const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.y() - y ) ); - const double x1 = pos.x() + off; - if ( x1 >= d_rect.left() && x1 <= d_rect.right() ) - points += QPointF( x1, y ); - - const double m_x2 = pos.x() - off; - if ( m_x2 >= d_rect.left() && m_x2 <= d_rect.right() ) - points += QPointF( m_x2, y ); - } - } - return points; -} - -/*! - Sutherland-Hodgman polygon clipping - - \param clipRect Clip rectangle - \param polygon Polygon - \param closePolygon True, when the polygon is closed - - \return Clipped polygon -*/ -QPolygon QwtClipper::clipPolygon( - const QRectF &clipRect, const QPolygon &polygon, bool closePolygon ) -{ - const int minX = qCeil( clipRect.left() ); - const int maxX = qFloor( clipRect.right() ); - const int minY = qCeil( clipRect.top() ); - const int maxY = qFloor( clipRect.bottom() ); - - const QRect r( minX, minY, maxX - minX, maxY - minY ); - - QwtPolygonClipper<QPolygon, QRect, QPoint, int> clipper( r ); - return clipper.clipPolygon( polygon, closePolygon ); -} -/*! - Sutherland-Hodgman polygon clipping - - \param clipRect Clip rectangle - \param polygon Polygon - \param closePolygon True, when the polygon is closed - - \return Clipped polygon -*/ -QPolygon QwtClipper::clipPolygon( - const QRect &clipRect, const QPolygon &polygon, bool closePolygon ) -{ - QwtPolygonClipper<QPolygon, QRect, QPoint, int> clipper( clipRect ); - return clipper.clipPolygon( polygon, closePolygon ); -} - -/*! - Sutherland-Hodgman polygon clipping - - \param clipRect Clip rectangle - \param polygon Polygon - \param closePolygon True, when the polygon is closed - - \return Clipped polygon -*/ -QPolygonF QwtClipper::clipPolygonF( - const QRectF &clipRect, const QPolygonF &polygon, bool closePolygon ) -{ - QwtPolygonClipper<QPolygonF, QRectF, QPointF, double> clipper( clipRect ); - return clipper.clipPolygon( polygon, closePolygon ); -} - -/*! - Circle clipping - - clipCircle() divides a circle into intervals of angles representing arcs - of the circle. When the circle is completely inside the clip rectangle - an interval [0.0, 2 * M_PI] is returned. - - \param clipRect Clip rectangle - \param center Center of the circle - \param radius Radius of the circle - - \return Arcs of the circle -*/ -QVector<QwtInterval> QwtClipper::clipCircle( const QRectF &clipRect, - const QPointF ¢er, double radius ) -{ - QwtCircleClipper clipper( clipRect ); - return clipper.clipCircle( center, radius ); -} diff --git a/source/third_party/qwt/qwt_color_map.cpp b/source/third_party/qwt/qwt_color_map.cpp deleted file mode 100644 index d0a9eae1f3d8a1a0b53746e9847c05f76e911e5e..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_color_map.cpp +++ /dev/null @@ -1,499 +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/qwt_color_map.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_interval.h" -#include <qnumeric.h> - -class QwtLinearColorMap::ColorStops -{ -public: - ColorStops(): - d_doAlpha( false ) - { - d_stops.reserve( 256 ); - } - - void insert( double pos, const QColor &color ); - QRgb rgb( QwtLinearColorMap::Mode, double pos ) const; - - QVector<double> stops() const; - -private: - - class ColorStop - { - public: - ColorStop(): - pos( 0.0 ), - rgb( 0 ) - { - }; - - ColorStop( double p, const QColor &c ): - pos( p ), - rgb( c.rgba() ) - { - r = qRed( rgb ); - g = qGreen( rgb ); - b = qBlue( rgb ); - a = qAlpha( rgb ); - - /* - when mapping a value to rgb we will have to calcualate: - - const int v = int( ( s1.v0 + ratio * s1.vStep ) + 0.5 ); - - Thus adding 0.5 ( for rounding ) can be done in advance - */ - r0 = r + 0.5; - g0 = g + 0.5; - b0 = b + 0.5; - a0 = a + 0.5; - - rStep = gStep = bStep = aStep = 0.0; - posStep = 0.0; - } - - void updateSteps( const ColorStop &nextStop ) - { - rStep = nextStop.r - r; - gStep = nextStop.g - g; - bStep = nextStop.b - b; - aStep = nextStop.a - a; - posStep = nextStop.pos - pos; - } - - double pos; - QRgb rgb; - int r, g, b, a; - - // precalculated values - double rStep, gStep, bStep, aStep; - double r0, g0, b0, a0; - double posStep; - }; - - inline int findUpper( double pos ) const; - QVector<ColorStop> d_stops; - bool d_doAlpha; -}; - -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 ... - - if ( pos < 0.0 || pos > 1.0 ) - return; - - int index; - if ( d_stops.size() == 0 ) - { - index = 0; - d_stops.resize( 1 ); - } - else - { - index = findUpper( pos ); - if ( index == d_stops.size() || - qAbs( d_stops[index].pos - pos ) >= 0.001 ) - { - d_stops.resize( d_stops.size() + 1 ); - for ( int i = d_stops.size() - 1; i > index; i-- ) - d_stops[i] = d_stops[i-1]; - } - } - - d_stops[index] = ColorStop( pos, color ); - if ( color.alpha() != 255 ) - d_doAlpha = true; - - if ( index > 0 ) - d_stops[index-1].updateSteps( d_stops[index] ); - - if ( index < d_stops.size() - 1 ) - d_stops[index].updateSteps( d_stops[index+1] ); -} - -inline QVector<double> QwtLinearColorMap::ColorStops::stops() const -{ - QVector<double> positions( d_stops.size() ); - for ( int i = 0; i < d_stops.size(); i++ ) - positions[i] = d_stops[i].pos; - return positions; -} - -inline int QwtLinearColorMap::ColorStops::findUpper( double pos ) const -{ - int index = 0; - int n = d_stops.size(); - - const ColorStop *stops = d_stops.data(); - - while ( n > 0 ) - { - const int half = n >> 1; - const int middle = index + half; - - if ( stops[middle].pos <= pos ) - { - index = middle + 1; - n -= half + 1; - } - else - n = half; - } - - return index; -} - -inline QRgb QwtLinearColorMap::ColorStops::rgb( - QwtLinearColorMap::Mode mode, double pos ) const -{ - if ( pos <= 0.0 ) - return d_stops[0].rgb; - if ( pos >= 1.0 ) - return d_stops[ d_stops.size() - 1 ].rgb; - - const int index = findUpper( pos ); - if ( mode == FixedColors ) - { - return d_stops[index-1].rgb; - } - else - { - const ColorStop &s1 = d_stops[index-1]; - - const double ratio = ( pos - s1.pos ) / ( s1.posStep ); - - const int r = int( s1.r0 + ratio * s1.rStep ); - const int g = int( s1.g0 + ratio * s1.gStep ); - const int b = int( s1.b0 + ratio * s1.bStep ); - - if ( d_doAlpha ) - { - if ( s1.aStep ) - { - const int a = int( s1.a0 + ratio * s1.aStep ); - return qRgba( r, g, b, a ); - } - else - { - return qRgba( r, g, b, s1.a ); - } - } - else - { - return qRgb( r, g, b ); - } - } -} - -//! Constructor -QwtColorMap::QwtColorMap( Format format ): - d_format( format ) -{ -} - -//! Destructor -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(). - - \param interval Range for the values - \return A color table, that can be used for a QImage -*/ -QVector<QRgb> QwtColorMap::colorTable( const QwtInterval &interval ) const -{ - QVector<QRgb> table( 256 ); - - if ( interval.isValid() ) - { - const double step = interval.width() / ( table.size() - 1 ); - for ( int i = 0; i < table.size(); i++ ) - table[i] = rgb( interval, interval.minValue() + step * i ); - } - - return table; -} - -class QwtLinearColorMap::PrivateData -{ -public: - ColorStops colorStops; - 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 ) -{ - d_data = new PrivateData; - d_data->mode = ScaledColors; - - setColorInterval( Qt::blue, Qt::yellow ); -} - -/*! - 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 for the color map -*/ -QwtLinearColorMap::QwtLinearColorMap( const QColor &color1, - const QColor &color2, QwtColorMap::Format format ): - QwtColorMap( format ) -{ - d_data = new PrivateData; - d_data->mode = ScaledColors; - setColorInterval( color1, color2 ); -} - -//! Destructor -QwtLinearColorMap::~QwtLinearColorMap() -{ - delete d_data; -} - -/*! - \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. - - \sa mode() -*/ -void QwtLinearColorMap::setMode( Mode mode ) -{ - d_data->mode = mode; -} - -/*! - \return Mode of the color map - \sa setMode() -*/ -QwtLinearColorMap::Mode QwtLinearColorMap::mode() const -{ - return d_data->mode; -} - -/*! - Set the color range - - 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 - - \sa color1(), color2() -*/ -void QwtLinearColorMap::setColorInterval( - const QColor &color1, const QColor &color2 ) -{ - d_data->colorStops = ColorStops(); - 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]. - 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 ) -{ - if ( value >= 0.0 && value <= 1.0 ) - d_data->colorStops.insert( value, color ); -} - -/*! - \return Positions of color stops in increasing order -*/ -QVector<double> 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 the second color of the color range - \sa setColorInterval() -*/ -QColor QwtLinearColorMap::color2() const -{ - return QColor( d_data->colorStops.rgb( d_data->mode, 1.0 ) ); -} - -/*! - Map a value of a given interval into a RGB value - - \param interval Range for all values - \param value Value to map into a RGB value - - \return RGB value for value -*/ -QRgb QwtLinearColorMap::rgb( - const QwtInterval &interval, double value ) const -{ - if ( qIsNaN(value) ) - return 0u; - - const double width = interval.width(); - if ( width <= 0.0 ) - return 0u; - - const double ratio = ( value - interval.minValue() ) / width; - return d_data->colorStops.rgb( d_data->mode, ratio ); -} - -/*! - \brief Map a value of a given interval into a color index - - \param interval Range for all values - \param value Value to map into a color index - - \return Index, between 0 and 255 -*/ -unsigned char QwtLinearColorMap::colorIndex( - const QwtInterval &interval, double value ) const -{ - const double width = interval.width(); - - if ( qIsNaN(value) || width <= 0.0 || value <= interval.minValue() ) - return 0; - - if ( value >= interval.maxValue() ) - return 255; - - const double ratio = ( value - interval.minValue() ) / width; - - unsigned char index; - if ( d_data->mode == FixedColors ) - index = static_cast<unsigned char>( ratio * 255 ); // always floor - else - index = static_cast<unsigned char>( ratio * 255 + 0.5 ); - - return index; -} - -class QwtAlphaColorMap::PrivateData -{ -public: - QColor color; - QRgb rgb; - QRgb rgbMax; -}; - - -/*! - Constructor - \param color Color of the map -*/ -QwtAlphaColorMap::QwtAlphaColorMap( const QColor &color ): - QwtColorMap( QwtColorMap::RGB ) -{ - d_data = new PrivateData; - setColor( color ); -} - -//! Destructor -QwtAlphaColorMap::~QwtAlphaColorMap() -{ - delete d_data; -} - -/*! - Set the color - - \param color Color - \sa color() -*/ -void QwtAlphaColorMap::setColor( const QColor &color ) -{ - d_data->color = color; - d_data->rgb = color.rgb() & qRgba( 255, 255, 255, 0 ); - d_data->rgbMax = d_data->rgb | ( 255 << 24 ); -} - -/*! - \return the color - \sa setColor() -*/ -QColor QwtAlphaColorMap::color() const -{ - return d_data->color; -} - -/*! - \brief Map a value of a given interval into a alpha value - - alpha := (value - interval.minValue()) / interval.width(); - - \param interval Range for all values - \param value Value to map into a RGB value - \return RGB value, with an alpha value -*/ -QRgb QwtAlphaColorMap::rgb( const QwtInterval &interval, double value ) const -{ - if ( qIsNaN(value) ) - return 0u; - - const double width = interval.width(); - if ( width <= 0.0 ) - return 0u; - - if ( value <= interval.minValue() ) - return d_data->rgb; - - if ( value >= interval.maxValue() ) - return d_data->rgbMax; - - const double ratio = ( value - interval.minValue() ) / width; - return d_data->rgb | ( qRound( 255 * ratio ) << 24 ); -} - -/*! - Dummy function, needed to be implemented as it is pure virtual - in QwtColorMap. Color indices make no sense in combination with - an alpha channel. - - \return Always 0 -*/ -unsigned char QwtAlphaColorMap::colorIndex( - const QwtInterval &, double ) const -{ - return 0; -} diff --git a/source/third_party/qwt/qwt_column_symbol.cpp b/source/third_party/qwt/qwt_column_symbol.cpp deleted file mode 100644 index 978054d22a0ed9fe3207308ec8bcc7ca5aaaf838..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_column_symbol.cpp +++ /dev/null @@ -1,293 +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/qwt_column_symbol.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qpalette.h> - -static void qwtDrawBox( QPainter *p, const QRectF &rect, - const QPalette &pal, double lw ) -{ - if ( lw > 0.0 ) - { - if ( rect.width() == 0.0 ) - { - p->setPen( pal.dark().color() ); - p->drawLine( rect.topLeft(), rect.bottomLeft() ); - return; - } - - if ( rect.height() == 0.0 ) - { - p->setPen( pal.dark().color() ); - p->drawLine( rect.topLeft(), rect.topRight() ); - return; - } - - lw = qMin( lw, rect.height() / 2.0 - 1.0 ); - lw = qMin( lw, rect.width() / 2.0 - 1.0 ); - - const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 ); - QPolygonF polygon( outerRect ); - - if ( outerRect.width() > 2 * lw && - outerRect.height() > 2 * lw ) - { - const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw ); - polygon = polygon.subtracted( innerRect ); - } - - p->setPen( Qt::NoPen ); - - p->setBrush( pal.dark() ); - p->drawPolygon( polygon ); - } - - const QRectF windowRect = rect.adjusted( lw, lw, -lw + 1, -lw + 1 ); - if ( windowRect.isValid() ) - p->fillRect( windowRect, pal.window() ); -} - -static void qwtDrawPanel( QPainter *painter, const QRectF &rect, - const QPalette &pal, double lw ) -{ - if ( lw > 0.0 ) - { - if ( rect.width() == 0.0 ) - { - painter->setPen( pal.window().color() ); - painter->drawLine( rect.topLeft(), rect.bottomLeft() ); - return; - } - - if ( rect.height() == 0.0 ) - { - painter->setPen( pal.window().color() ); - painter->drawLine( rect.topLeft(), rect.topRight() ); - return; - } - - lw = qMin( lw, rect.height() / 2.0 - 1.0 ); - lw = qMin( lw, rect.width() / 2.0 - 1.0 ); - - const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 ); - const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw ); - - QPolygonF lines[2]; - - lines[0] += outerRect.bottomLeft(); - lines[0] += outerRect.topLeft(); - lines[0] += outerRect.topRight(); - lines[0] += innerRect.topRight(); - lines[0] += innerRect.topLeft(); - lines[0] += innerRect.bottomLeft(); - - lines[1] += outerRect.topRight(); - lines[1] += outerRect.bottomRight(); - lines[1] += outerRect.bottomLeft(); - lines[1] += innerRect.bottomLeft(); - lines[1] += innerRect.bottomRight(); - lines[1] += innerRect.topRight(); - - painter->setPen( Qt::NoPen ); - - painter->setBrush( pal.light() ); - painter->drawPolygon( lines[0] ); - painter->setBrush( pal.dark() ); - painter->drawPolygon( lines[1] ); - } - - painter->fillRect( rect.adjusted( lw, lw, -lw + 1, -lw + 1 ), pal.window() ); -} - -class QwtColumnSymbol::PrivateData -{ -public: - PrivateData(): - style( QwtColumnSymbol::Box ), - frameStyle( QwtColumnSymbol::Raised ), - lineWidth( 2 ) - { - palette = QPalette( Qt::gray ); - } - - QwtColumnSymbol::Style style; - QwtColumnSymbol::FrameStyle frameStyle; - - QPalette palette; - int lineWidth; -}; - -/*! - Constructor - - \param style Style of the symbol - \sa setStyle(), style(), Style -*/ -QwtColumnSymbol::QwtColumnSymbol( Style style ) -{ - d_data = new PrivateData(); - d_data->style = style; -} - -//! Destructor -QwtColumnSymbol::~QwtColumnSymbol() -{ - delete d_data; -} - -/*! - Specify the symbol style - - \param style Style - \sa style(), setPalette() -*/ -void QwtColumnSymbol::setStyle( Style style ) -{ - d_data->style = style; -} - -/*! - \return Current symbol style - \sa setStyle() -*/ -QwtColumnSymbol::Style QwtColumnSymbol::style() const -{ - return d_data->style; -} - -/*! - Assign a palette for the symbol - - \param palette Palette - \sa palette(), setStyle() -*/ -void QwtColumnSymbol::setPalette( const QPalette &palette ) -{ - d_data->palette = palette; -} - -/*! - \return Current palette - \sa setPalette() -*/ -const QPalette& QwtColumnSymbol::palette() const -{ - return d_data->palette; -} - -/*! - Set the frame, that is used for the Box style. - - \param frameStyle Frame style - \sa frameStyle(), setLineWidth(), setStyle() -*/ -void QwtColumnSymbol::setFrameStyle( FrameStyle frameStyle ) -{ - d_data->frameStyle = frameStyle; -} - -/*! - \return Current frame style, that is used for the Box style. - \sa setFrameStyle(), lineWidth(), setStyle() -*/ -QwtColumnSymbol::FrameStyle QwtColumnSymbol::frameStyle() const -{ - return d_data->frameStyle; -} - -/*! - Set the line width of the frame, that is used for the Box style. - - \param width Width - \sa lineWidth(), setFrameStyle() -*/ -void QwtColumnSymbol::setLineWidth( int width ) -{ - if ( width < 0 ) - width = 0; - - d_data->lineWidth = width; -} - -/*! - \return Line width of the frame, that is used for the Box style. - \sa setLineWidth(), frameStyle(), setStyle() -*/ -int QwtColumnSymbol::lineWidth() const -{ - return d_data->lineWidth; -} - -/*! - Draw the symbol depending on its style. - - \param painter Painter - \param rect Directed rectangle - - \sa drawBox() -*/ -void QwtColumnSymbol::draw( QPainter *painter, - const QwtColumnRect &rect ) const -{ - painter->save(); - - switch ( d_data->style ) - { - case QwtColumnSymbol::Box: - { - drawBox( painter, rect ); - break; - } - default:; - } - - painter->restore(); -} - -/*! - Draw the symbol when it is in Box style. - - \param painter Painter - \param rect Directed rectangle - - \sa draw() -*/ -void QwtColumnSymbol::drawBox( QPainter *painter, - const QwtColumnRect &rect ) const -{ - QRectF r = rect.toRect(); - if ( QwtPainter::roundingAlignment( painter ) ) - { - r.setLeft( qRound( r.left() ) ); - r.setRight( qRound( r.right() ) ); - r.setTop( qRound( r.top() ) ); - r.setBottom( qRound( r.bottom() ) ); - } - - switch ( d_data->frameStyle ) - { - case QwtColumnSymbol::Raised: - { - qwtDrawPanel( painter, r, d_data->palette, d_data->lineWidth ); - break; - } - case QwtColumnSymbol::Plain: - { - qwtDrawBox( painter, r, d_data->palette, d_data->lineWidth ); - break; - } - default: - { - painter->fillRect( r, d_data->palette.window() ); - } - } -} diff --git a/source/third_party/qwt/qwt_compass.cpp b/source/third_party/qwt/qwt_compass.cpp deleted file mode 100644 index 9305f031f1fea5e712267e2131276461911adb67..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_compass.cpp +++ /dev/null @@ -1,308 +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/qwt_compass.h" -#include "qwt/qwt_compass_rose.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_scale_draw.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_dial_needle.h" -#include <qpainter.h> -#include <qpixmap.h> -#include <qevent.h> - -/*! - \brief Constructor - - Initializes a label map for multiples of 45 degrees - */ -QwtCompassScaleDraw::QwtCompassScaleDraw() -{ - enableComponent( QwtAbstractScaleDraw::Backbone, false ); - enableComponent( QwtAbstractScaleDraw::Ticks, false ); - - d_labelMap.insert( 0.0, QString::fromLatin1( "N" ) ); - d_labelMap.insert( 45.0, QString::fromLatin1( "NE" ) ); - d_labelMap.insert( 90.0, QString::fromLatin1( "E" ) ); - d_labelMap.insert( 135.0, QString::fromLatin1( "SE" ) ); - d_labelMap.insert( 180.0, QString::fromLatin1( "S" ) ); - d_labelMap.insert( 225.0, QString::fromLatin1( "SW" ) ); - d_labelMap.insert( 270.0, QString::fromLatin1( "W" ) ); - d_labelMap.insert( 315.0, QString::fromLatin1( "NW" ) ); - -#if 0 - d_labelMap.insert( 22.5, QString::fromLatin1( "NNE" ) ); - d_labelMap.insert( 67.5, QString::fromLatin1( "NEE" ) ); - d_labelMap.insert( 112.5, QString::fromLatin1( "SEE" ) ); - d_labelMap.insert( 157.5, QString::fromLatin1( "SSE" ) ); - d_labelMap.insert( 202.5, QString::fromLatin1( "SSW" ) ); - d_labelMap.insert( 247.5, QString::fromLatin1( "SWW" ) ); - d_labelMap.insert( 292.5, QString::fromLatin1( "NWW" ) ); - d_labelMap.insert( 337.5, QString::fromLatin1( "NNW" ) ); -#endif -} - -/*! - \brief Constructor - - \param map Value to label map - */ -QwtCompassScaleDraw::QwtCompassScaleDraw( const QMap<double, QString> &map ): - d_labelMap( map ) -{ - enableComponent( QwtAbstractScaleDraw::Backbone, false ); - enableComponent( QwtAbstractScaleDraw::Ticks, false ); -} - -/*! - \brief Set a map, mapping values to labels - \param map Value to label map - - The values of the major ticks are found by looking into this - map. The default map consists of the labels N, NE, E, SE, S, SW, W, NW. - - \warning The map will have no effect for values that are no major - tick values. Major ticks can be changed by QwtScaleDraw::setScale - - \sa labelMap(), scaleDraw(), setScale() -*/ -void QwtCompassScaleDraw::setLabelMap( const QMap<double, QString> &map ) -{ - d_labelMap = map; -} - - -/*! - \return map, mapping values to labels - \sa setLabelMap() -*/ -QMap<double, QString> QwtCompassScaleDraw::labelMap() const -{ - return d_labelMap; -} - -/*! - Map a value to a corresponding label - - \param value Value that will be mapped - - label() looks in the labelMap() for a corresponding label for value - or returns an null text. - - \return Label, or QString::null - \sa labelMap(), setLabelMap() -*/ - -QwtText QwtCompassScaleDraw::label( double value ) const -{ - if ( qFuzzyCompare( value + 1.0, 1.0 ) ) - value = 0.0; - - if ( value < 0.0 ) - value += 360.0; - - if ( d_labelMap.contains( value ) ) - return d_labelMap[value]; - - return QwtText(); -} - -class QwtCompass::PrivateData -{ -public: - PrivateData(): - rose( NULL ) - { - } - - ~PrivateData() - { - delete rose; - } - - QwtCompassRose *rose; -}; - -/*! - \brief Constructor - \param parent Parent widget - - 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 ) -{ - d_data = new PrivateData; - - setScaleDraw( new QwtCompassScaleDraw() ); - - setOrigin( 270.0 ); - setWrapping( true ); - - setScaleMaxMajor( 36 ); - setScaleMaxMinor( 10 ); - - setScale( 0.0, 360.0 ); // degrees as default - setTotalSteps( 360 ); -} - -//! Destructor -QwtCompass::~QwtCompass() -{ - delete d_data; -} - - -/*! - 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 QPointF ¢er, double radius ) const -{ - QPalette::ColorGroup cg; - if ( isEnabled() ) - cg = hasFocus() ? QPalette::Active : QPalette::Inactive; - else - cg = QPalette::Disabled; - - double north = origin(); - if ( isValid() ) - { - if ( mode() == RotateScale ) - north -= value(); - } - - const int margin = 4; - 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 QPointF ¢er, - double radius, double north, QPalette::ColorGroup cg ) const -{ - if ( d_data->rose ) - d_data->rose->draw( painter, center, radius, north, cg ); -} - -/*! - Set a rose for the compass - \param rose Compass rose - \warning The rose will be deleted, when a different rose is - set or in ~QwtCompass - \sa rose() -*/ -void QwtCompass::setRose( QwtCompassRose *rose ) -{ - if ( rose != d_data->rose ) - { - if ( d_data->rose ) - delete d_data->rose; - - d_data->rose = rose; - update(); - } -} - -/*! - \return rose - \sa setRose() -*/ -const QwtCompassRose *QwtCompass::rose() const -{ - return d_data->rose; -} - -/*! - \return rose - \sa setRose() -*/ -QwtCompassRose *QwtCompass::rose() -{ - return d_data->rose; -} - -/*! - Handles key events - - Beside the keys described in QwtDial::keyPressEvent numbers - from 1-9 (without 5) set the direction according to their - position on the num pad. - - \sa isReadOnly() -*/ -void QwtCompass::keyPressEvent( QKeyEvent *kev ) -{ - if ( isReadOnly() ) - return; - -#if 0 - if ( kev->key() == Key_5 ) - { - invalidate(); // signal ??? - return; - } -#endif - - double newValue = value(); - - if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 ) - { - if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 ) - return; - - switch ( kev->key() ) - { - case Qt::Key_6: - newValue = 180.0 * 0.0; - break; - case Qt::Key_3: - newValue = 180.0 * 0.25; - break; - case Qt::Key_2: - newValue = 180.0 * 0.5; - break; - case Qt::Key_1: - newValue = 180.0 * 0.75; - break; - case Qt::Key_4: - newValue = 180.0 * 1.0; - break; - case Qt::Key_7: - newValue = 180.0 * 1.25; - break; - case Qt::Key_8: - newValue = 180.0 * 1.5; - break; - case Qt::Key_9: - newValue = 180.0 * 1.75; - break; - } - newValue -= origin(); - setValue( newValue ); - } - else - { - QwtDial::keyPressEvent( kev ); - } -} diff --git a/source/third_party/qwt/qwt_compass_rose.cpp b/source/third_party/qwt/qwt_compass_rose.cpp deleted file mode 100644 index b81e09181abcb54e8979979dc23b433f046963c3..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_compass_rose.cpp +++ /dev/null @@ -1,269 +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/qwt_compass_rose.h" -#include "qwt/qwt_point_polar.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> - -static QPointF qwtIntersection( - QPointF p11, QPointF p12, QPointF p21, QPointF p22 ) -{ - const QLineF line1( p11, p12 ); - const QLineF line2( p21, p22 ); - - QPointF pos; - if ( line1.intersect( line2, &pos ) == QLineF::NoIntersection ) - return QPointF(); - - 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_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; - palette.setColor( QPalette::Dark, dark ); - palette.setColor( QPalette::Light, light ); - - setPalette( palette ); -} - -//! Destructor -QwtSimpleCompassRose::~QwtSimpleCompassRose() -{ - delete d_data; -} - -/*! - Set the Factor how to shrink the thorns with each level - The default value is 0.9. - - \param factor Shrink factor - \sa shrinkFactor() -*/ -void QwtSimpleCompassRose::setShrinkFactor( double factor ) -{ - d_data->shrinkFactor = factor; -} - -/*! - \return Factor how to shrink the thorns with each level - \sa setShrinkFactor() -*/ -double QwtSimpleCompassRose::shrinkFactor() const -{ - return d_data->shrinkFactor; -} - -/*! - Draw the rose - - \param painter Painter - \param center Center point - \param radius Radius of the rose - \param north Position - \param cg Color group -*/ -void QwtSimpleCompassRose::draw( QPainter *painter, const QPointF ¢er, - double radius, double north, QPalette::ColorGroup cg ) const -{ - QPalette pal = palette(); - pal.setCurrentColorGroup( cg ); - - drawRose( painter, pal, center, radius, north, d_data->width, - d_data->numThorns, d_data->numThornLevels, d_data->shrinkFactor ); -} - -/*! - Draw the rose - - \param painter Painter - \param palette Palette - \param center Center of the rose - \param radius Radius of the rose - \param north Position pointing to north - \param width Width of the rose - \param numThorns Number of thorns - \param numThornLevels Number of thorn levels - \param shrinkFactor Factor to shrink the thorns with each level -*/ -void QwtSimpleCompassRose::drawRose( - QPainter *painter, - const QPalette &palette, - const QPointF ¢er, double radius, double north, double width, - int numThorns, int numThornLevels, double shrinkFactor ) -{ - if ( numThorns < 4 ) - numThorns = 4; - - if ( numThorns % 4 ) - numThorns += 4 - numThorns % 4; - - if ( numThornLevels <= 0 ) - numThornLevels = numThorns / 4; - - if ( shrinkFactor >= 1.0 ) - shrinkFactor = 1.0; - - if ( shrinkFactor <= 0.5 ) - shrinkFactor = 0.5; - - painter->save(); - - painter->setPen( Qt::NoPen ); - - for ( int j = 1; j <= numThornLevels; j++ ) - { - double step = qPow( 2.0, j ) * M_PI / numThorns; - if ( step > M_PI_2 ) - break; - - double r = radius; - for ( int k = 0; k < 3; k++ ) - { - if ( j + k < numThornLevels ) - r *= shrinkFactor; - } - - double leafWidth = r * width; - if ( 2.0 * M_PI / step > 32 ) - leafWidth = 16; - - const double origin = qwtRadians( north ); - for ( double angle = origin; - angle < 2.0 * M_PI + origin; angle += step ) - { - const QPointF p = qwtPolar2Pos( center, r, angle ); - const QPointF p1 = qwtPolar2Pos( center, leafWidth, angle + M_PI_2 ); - const QPointF p2 = qwtPolar2Pos( center, leafWidth, angle - M_PI_2 ); - const QPointF p3 = qwtPolar2Pos( center, r, angle + step / 2.0 ); - const QPointF p4 = qwtPolar2Pos( center, r, angle - step / 2.0 ); - - QPainterPath darkPath; - darkPath.moveTo( center ); - darkPath.lineTo( p ); - darkPath.lineTo( qwtIntersection( center, p3, p1, p ) ); - - painter->setBrush( palette.brush( QPalette::Dark ) ); - painter->drawPath( darkPath ); - - QPainterPath lightPath; - lightPath.moveTo( center ); - lightPath.lineTo( p ); - lightPath.lineTo( qwtIntersection( center, p4, p2, p ) ); - - painter->setBrush( palette.brush( QPalette::Light ) ); - painter->drawPath( lightPath ); - } - } - painter->restore(); -} - -/*! - Set the width of the rose heads. Lower value make thinner heads. - The range is limited from 0.03 to 0.4. - - \param width Width -*/ -void QwtSimpleCompassRose::setWidth( double width ) -{ - d_data->width = width; - if ( d_data->width < 0.03 ) - d_data->width = 0.03; - - if ( d_data->width > 0.4 ) - d_data->width = 0.4; -} - -/*! - \return Width of the rose - \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 - - \param numThorns Number of thorns - \sa numThorns(), setNumThornLevels() -*/ -void QwtSimpleCompassRose::setNumThorns( int numThorns ) -{ - if ( numThorns < 4 ) - numThorns = 4; - - if ( numThorns % 4 ) - numThorns += 4 - numThorns % 4; - - d_data->numThorns = numThorns; -} - -/*! - \return Number of thorns - \sa setNumThorns(), setNumThornLevels() -*/ -int QwtSimpleCompassRose::numThorns() const -{ - return d_data->numThorns; -} - -/*! - Set the of thorns levels - - \param numThornLevels Number of thorns levels - \sa setNumThorns(), numThornLevels() -*/ -void QwtSimpleCompassRose::setNumThornLevels( int numThornLevels ) -{ - d_data->numThornLevels = numThornLevels; -} - -/*! - \return Number of thorn levels - \sa setNumThorns(), setNumThornLevels() -*/ -int QwtSimpleCompassRose::numThornLevels() const -{ - return d_data->numThornLevels; -} diff --git a/source/third_party/qwt/qwt_counter.cpp b/source/third_party/qwt/qwt_counter.cpp deleted file mode 100644 index cdaa28d54720d6a4b2e7715f1ee7cfd1c247dddb..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_counter.cpp +++ /dev/null @@ -1,785 +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/qwt_arrow_button.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_counter.h" -#include <qlayout.h> -#include <qlineedit.h> -#include <qvalidator.h> -#include <qevent.h> -#include <qstyle.h> - -class QwtCounter::PrivateData -{ -public: - PrivateData(): - minimum( 0.0 ), - maximum( 0.0 ), - singleStep( 1.0 ), - isValid( false ), - value( 0.0 ), - wrapping( false ) - { - increment[Button1] = 1; - increment[Button2] = 10; - increment[Button3] = 100; - } - - QwtArrowButton *buttonDown[ButtonCnt]; - QwtArrowButton *buttonUp[ButtonCnt]; - QLineEdit *valueEdit; - - int increment[ButtonCnt]; - int numButtons; - - double minimum; - double maximum; - double singleStep; - - bool isValid; - double value; - - bool wrapping; -}; - -/*! - The counter is initialized with a range is set to [0.0, 1.0] with - 0.01 as single step size. The value is invalid. - - The default number of buttons is set to 2. The default increments are: - \li Button 1: 1 step - \li Button 2: 10 steps - \li Button 3: 100 steps - - \param parent - */ -QwtCounter::QwtCounter( QWidget *parent ): - QWidget( parent ) -{ - initCounter(); -} - -void QwtCounter::initCounter() -{ - d_data = new PrivateData; - - QHBoxLayout *layout = new QHBoxLayout( this ); - layout->setSpacing( 0 ); - layout->setMargin( 0 ); - - for ( int i = ButtonCnt - 1; i >= 0; i-- ) - { - QwtArrowButton *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() ) ); - - 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 ); - - connect( d_data->valueEdit, SIGNAL( editingFinished() ), - SLOT( textChanged() ) ); - - layout->setStretchFactor( d_data->valueEdit, 10 ); - - for ( int i = 0; i < ButtonCnt; i++ ) - { - QwtArrowButton *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() ) ); - - d_data->buttonUp[i] = btn; - } - - setNumButtons( 2 ); - setRange( 0.0, 1.0 ); - setSingleStep( 0.001 ); - setValue( 0.0 ); - - setSizePolicy( - QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) ); - - setFocusProxy( d_data->valueEdit ); - setFocusPolicy( Qt::StrongFocus ); -} - -//! Destructor -QwtCounter::~QwtCounter() -{ - delete d_data; -} - -/*! - Set the counter to be in valid/invalid state - - When the counter is set to invalid, no numbers are displayed and - the buttons are disabled. - - \param on If true the counter will be set as valid - - \sa setValue(), isValid() -*/ -void QwtCounter::setValid( bool on ) -{ - if ( on != d_data->isValid ) - { - d_data->isValid = on; - - updateButtons(); - - if ( d_data->isValid ) - { - showNumber( value() ); - Q_EMIT valueChanged( value() ); - } - else - { - d_data->valueEdit->setText( QString::null ); - } - } -} - -/*! - \return True, if the value is valid - \sa setValid(), setValue() - */ -bool QwtCounter::isValid() const -{ - return d_data->isValid; -} - -/*! - \brief Allow/disallow the user to manually edit the value - - \param on True disable editing - \sa isReadOnly() -*/ -void QwtCounter::setReadOnly( bool on ) -{ - d_data->valueEdit->setReadOnly( on ); -} - -/*! - \return True, when the line line edit is read only. (default is no) - \sa setReadOnly() - */ -bool QwtCounter::isReadOnly() const -{ - return d_data->valueEdit->isReadOnly(); -} - -/*! - \brief Set a new value without adjusting to the step raster - - The state of the counter is set to be valid. - - \param value New value - - \sa isValid(), value(), valueChanged() - \warning The value is clipped when it lies outside the range. -*/ - -void QwtCounter::setValue( double value ) -{ - const double vmin = qMin( d_data->minimum, d_data->maximum ); - const double vmax = qMax( d_data->minimum, d_data->maximum ); - - value = qBound( vmin, value, vmax ); - - if ( !d_data->isValid || value != d_data->value ) - { - d_data->isValid = true; - d_data->value = value; - - showNumber( value ); - updateButtons(); - - Q_EMIT valueChanged( value ); - } -} - -/*! - \return Current value of the counter - \sa setValue(), valueChanged() - */ -double QwtCounter::value() const -{ - return d_data->value; -} - -/*! - \brief Set the minimum and maximum values - - The maximum is adjusted if necessary to ensure that the range remains valid. - The value might be modified to be inside of the range. - - \param min Minimum value - \param max Maximum value - - \sa minimum(), maximum() - */ -void QwtCounter::setRange( double min, double max ) -{ - max = qMax( min, max ); - - if ( d_data->maximum == max && d_data->minimum == min ) - return; - - d_data->minimum = min; - d_data->maximum = max; - - setSingleStep( singleStep() ); - - const double value = qBound( min, d_data->value, max ); - - if ( value != d_data->value ) - { - d_data->value = value; - - if ( d_data->isValid ) - { - showNumber( value ); - Q_EMIT valueChanged( value ); - } - } - - updateButtons(); -} - -/*! - Set the minimum value of the range - - \param value Minimum value - \sa setRange(), setMaximum(), minimum() - - \note The maximum is adjusted if necessary to ensure that the range remains valid. -*/ -void QwtCounter::setMinimum( double value ) -{ - setRange( value, maximum() ); -} - -/*! - \return The minimum of the range - \sa setRange(), setMinimum(), maximum() -*/ -double QwtCounter::minimum() const -{ - return d_data->minimum; -} - -/*! - Set the maximum value of the range - - \param value Maximum value - \sa setRange(), setMinimum(), maximum() -*/ -void QwtCounter::setMaximum( double value ) -{ - setRange( minimum(), value ); -} - -/*! - \return The maximum of the range - \sa setRange(), setMaximum(), minimum() -*/ -double QwtCounter::maximum() const -{ - return d_data->maximum; -} - -/*! - \brief Set the step size of the counter - - A value <= 0.0 disables stepping - - \param stepSize Single step size - \sa singleStep() -*/ -void QwtCounter::setSingleStep( double stepSize ) -{ - d_data->singleStep = qMax( stepSize, 0.0 ); -} - -/*! - \return Single step size - \sa setSingleStep() - */ -double QwtCounter::singleStep() const -{ - return d_data->singleStep; -} - -/*! - \brief En/Disable wrapping - - If wrapping is true stepping up from maximum() value will take - you to the minimum() value and vice versa. - - \param on En/Disable wrapping - \sa wrapping() - */ -void QwtCounter::setWrapping( bool on ) -{ - d_data->wrapping = on; -} - -/*! - \return True, when wrapping is set - \sa setWrapping() - */ -bool QwtCounter::wrapping() const -{ - return d_data->wrapping; -} - -/*! - Specify the number of buttons on each side of the label - - \param numButtons Number of buttons - \sa numButtons() -*/ -void QwtCounter::setNumButtons( int numButtons ) -{ - if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt ) - return; - - for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) - { - if ( i < numButtons ) - { - d_data->buttonDown[i]->show(); - d_data->buttonUp[i]->show(); - } - else - { - d_data->buttonDown[i]->hide(); - d_data->buttonUp[i]->hide(); - } - } - - d_data->numButtons = numButtons; -} - -/*! - \return The number of buttons on each side of the widget. - \sa setNumButtons() -*/ -int QwtCounter::numButtons() const -{ - return d_data->numButtons; -} - -/*! - Specify the number of steps by which the value - is incremented or decremented when a specified button - is pushed. - - \param button Button index - \param numSteps Number of steps - - \sa incSteps() -*/ -void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps ) -{ - if ( button >= 0 && button < QwtCounter::ButtonCnt ) - d_data->increment[ button ] = numSteps; -} - -/*! - \return The number of steps by which a specified button increments the value - or 0 if the button is invalid. - \param button Button index - - \sa setIncSteps() -*/ -int QwtCounter::incSteps( QwtCounter::Button button ) const -{ - if ( button >= 0 && button < QwtCounter::ButtonCnt ) - return d_data->increment[ button ]; - - return 0; -} - - -/*! - Set the number of increment steps for button 1 - \param nSteps Number of steps -*/ -void QwtCounter::setStepButton1( int nSteps ) -{ - setIncSteps( QwtCounter::Button1, nSteps ); -} - -//! returns the number of increment steps for button 1 -int QwtCounter::stepButton1() const -{ - return incSteps( QwtCounter::Button1 ); -} - -/*! - Set the number of increment steps for button 2 - \param nSteps Number of steps -*/ -void QwtCounter::setStepButton2( int nSteps ) -{ - setIncSteps( QwtCounter::Button2, nSteps ); -} - -//! returns the number of increment steps for button 2 -int QwtCounter::stepButton2() const -{ - return incSteps( QwtCounter::Button2 ); -} - -/*! - Set the number of increment steps for button 3 - \param nSteps Number of steps -*/ -void QwtCounter::setStepButton3( int nSteps ) -{ - setIncSteps( QwtCounter::Button3, nSteps ); -} - -//! returns the number of increment steps for button 3 -int QwtCounter::stepButton3() const -{ - return incSteps( QwtCounter::Button3 ); -} - -//! Set from lineedit -void QwtCounter::textChanged() -{ - bool converted = false; - - const double value = d_data->valueEdit->text().toDouble( &converted ); - if ( converted ) - setValue( value ); -} - -/*! - Handle QEvent::PolishRequest events - \param event Event - \return see QWidget::event() -*/ -bool QwtCounter::event( QEvent *event ) -{ - if ( event->type() == QEvent::PolishRequest ) - { - const int w = d_data->valueEdit->fontMetrics().width( "W" ) + 8; - for ( int i = 0; i < ButtonCnt; i++ ) - { - d_data->buttonDown[i]->setMinimumWidth( w ); - d_data->buttonUp[i]->setMinimumWidth( w ); - } - } - - return QWidget::event( event ); -} - -/*! - Handle key events - - - Ctrl + Qt::Key_Home\n - Step to minimum() - - Ctrl + Qt::Key_End\n - Step to maximum() - - Qt::Key_Up\n - Increment by incSteps(QwtCounter::Button1) - - Qt::Key_Down\n - Decrement by incSteps(QwtCounter::Button1) - - Qt::Key_PageUp\n - Increment by incSteps(QwtCounter::Button2) - - Qt::Key_PageDown\n - Decrement by incSteps(QwtCounter::Button2) - - Shift + Qt::Key_PageUp\n - Increment by incSteps(QwtCounter::Button3) - - Shift + Qt::Key_PageDown\n - Decrement by incSteps(QwtCounter::Button3) - - \param event Key event -*/ -void QwtCounter::keyPressEvent ( QKeyEvent *event ) -{ - bool accepted = true; - - switch ( event->key() ) - { - case Qt::Key_Home: - { - if ( event->modifiers() & Qt::ControlModifier ) - setValue( minimum() ); - else - accepted = false; - break; - } - case Qt::Key_End: - { - if ( event->modifiers() & Qt::ControlModifier ) - setValue( maximum() ); - else - accepted = false; - break; - } - case Qt::Key_Up: - { - incrementValue( d_data->increment[0] ); - break; - } - case Qt::Key_Down: - { - incrementValue( -d_data->increment[0] ); - break; - } - case Qt::Key_PageUp: - case Qt::Key_PageDown: - { - int increment = d_data->increment[0]; - if ( d_data->numButtons >= 2 ) - increment = d_data->increment[1]; - if ( d_data->numButtons >= 3 ) - { - if ( event->modifiers() & Qt::ShiftModifier ) - increment = d_data->increment[2]; - } - if ( event->key() == Qt::Key_PageDown ) - increment = -increment; - incrementValue( increment ); - break; - } - default: - { - accepted = false; - } - } - - if ( accepted ) - { - event->accept(); - return; - } - - QWidget::keyPressEvent ( event ); -} - -/*! - Handle wheel events - \param event Wheel event -*/ -void QwtCounter::wheelEvent( QWheelEvent *event ) -{ - event->accept(); - - if ( d_data->numButtons <= 0 ) - return; - - int increment = d_data->increment[0]; - if ( d_data->numButtons >= 2 ) - { - if ( event->modifiers() & Qt::ControlModifier ) - increment = d_data->increment[1]; - } - if ( d_data->numButtons >= 3 ) - { - if ( event->modifiers() & Qt::ShiftModifier ) - increment = d_data->increment[2]; - } - - for ( int i = 0; i < d_data->numButtons; i++ ) - { - if ( d_data->buttonDown[i]->geometry().contains( event->pos() ) || - d_data->buttonUp[i]->geometry().contains( event->pos() ) ) - { - increment = d_data->increment[i]; - } - } - - const int wheel_delta = 120; - -#if 1 - int delta = event->delta(); - if ( delta >= 2 * wheel_delta ) - delta /= 2; // Never saw an abs(delta) < 240 -#endif - - incrementValue( delta / wheel_delta * increment ); -} - -void QwtCounter::incrementValue( int numSteps ) -{ - const double min = d_data->minimum; - const double max = d_data->maximum; - double stepSize = d_data->singleStep; - - if ( !d_data->isValid || min >= max || stepSize <= 0.0 ) - return; - - -#if 1 - stepSize = qMax( stepSize, 1.0e-10 * ( max - min ) ); -#endif - - double value = d_data->value + numSteps * stepSize; - - if ( d_data->wrapping ) - { - const double range = max - min; - - if ( value < min ) - { - value += ::ceil( ( min - value ) / range ) * range; - } - else if ( value > max ) - { - value -= ::ceil( ( value - max ) / range ) * range; - } - } - else - { - value = qBound( min, value, max ); - } - - value = min + qRound( ( value - min ) / stepSize ) * stepSize; - - if ( stepSize > 1e-12 ) - { - if ( qFuzzyCompare( value + 1.0, 1.0 ) ) - { - // correct rounding error if value = 0 - value = 0.0; - } - else if ( qFuzzyCompare( value, max ) ) - { - // correct rounding error at the border - value = max; - } - } - - if ( value != d_data->value ) - { - d_data->value = value; - showNumber( d_data->value ); - updateButtons(); - - Q_EMIT valueChanged( d_data->value ); - } -} - - -/*! - \brief Update buttons according to the current value - - When the QwtCounter under- or over-flows, the focus is set to the smallest - up- or down-button and counting is disabled. - - Counting is re-enabled on a button release event (mouse or space bar). -*/ -void QwtCounter::updateButtons() -{ - if ( d_data->isValid ) - { - // 1. save enabled state of the smallest down- and up-button - // 2. change enabled state on under- or over-flow - - for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) - { - d_data->buttonDown[i]->setEnabled( value() > minimum() ); - d_data->buttonUp[i]->setEnabled( value() < maximum() ); - } - } - else - { - for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) - { - d_data->buttonDown[i]->setEnabled( false ); - d_data->buttonUp[i]->setEnabled( false ); - } - } -} -/*! - Display number string - - \param number Number -*/ -void QwtCounter::showNumber( double number ) -{ - QString text; - text.setNum( number ); - - const int cursorPos = d_data->valueEdit->cursorPosition(); - d_data->valueEdit->setText( text ); - d_data->valueEdit->setCursorPosition( cursorPos ); -} - -//! Button clicked -void QwtCounter::btnClicked() -{ - for ( int i = 0; i < ButtonCnt; i++ ) - { - if ( d_data->buttonUp[i] == sender() ) - incrementValue( d_data->increment[i] ); - - if ( d_data->buttonDown[i] == sender() ) - incrementValue( -d_data->increment[i] ); - } -} - -//! Button released -void QwtCounter::btnReleased() -{ - Q_EMIT buttonReleased( value() ); -} - -//! A size hint -QSize QwtCounter::sizeHint() const -{ - QString tmp; - - int w = tmp.setNum( minimum() ).length(); - int w1 = tmp.setNum( maximum() ).length(); - if ( w1 > w ) - w = w1; - w1 = tmp.setNum( minimum() + singleStep() ).length(); - if ( w1 > w ) - w = w1; - w1 = tmp.setNum( maximum() - singleStep() ).length(); - if ( w1 > w ) - w = w1; - - tmp.fill( '9', w ); - - QFontMetrics fm( d_data->valueEdit->font() ); - w = fm.width( tmp ) + 2; - if ( d_data->valueEdit->hasFrame() ) - 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 = qMin( QWidget::sizeHint().height(), - d_data->valueEdit->minimumSizeHint().height() ); - return QSize( w, h ); -} diff --git a/source/third_party/qwt/qwt_curve_fitter.cpp b/source/third_party/qwt/qwt_curve_fitter.cpp deleted file mode 100644 index b7afe2072a7031c93784e1ce257bce1cf8264078..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_curve_fitter.cpp +++ /dev/null @@ -1,453 +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/qwt_curve_fitter.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_spline.h" -#include <qstack.h> -#include <qvector.h> - -#if QT_VERSION < 0x040601 -#define qFabs(x) ::fabs(x) -#endif - -//! Constructor -QwtCurveFitter::QwtCurveFitter() -{ -} - -//! Destructor -QwtCurveFitter::~QwtCurveFitter() -{ -} - -class QwtSplineCurveFitter::PrivateData -{ -public: - PrivateData(): - fitMode( QwtSplineCurveFitter::Auto ), - splineSize( 250 ) - { - } - - QwtSpline spline; - QwtSplineCurveFitter::FitMode fitMode; - int splineSize; -}; - -//! Constructor -QwtSplineCurveFitter::QwtSplineCurveFitter() -{ - d_data = new PrivateData; -} - -//! Destructor -QwtSplineCurveFitter::~QwtSplineCurveFitter() -{ - delete d_data; -} - -/*! - Select the algorithm used for building the spline - - \param mode Mode representing a spline algorithm - \sa fitMode() -*/ -void QwtSplineCurveFitter::setFitMode( FitMode mode ) -{ - d_data->fitMode = mode; -} - -/*! - \return Mode representing a spline algorithm - \sa setFitMode() -*/ -QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const -{ - return d_data->fitMode; -} - -/*! - Assign a spline - - \param spline Spline - \sa spline() -*/ -void QwtSplineCurveFitter::setSpline( const QwtSpline &spline ) -{ - d_data->spline = spline; - d_data->spline.reset(); -} - -/*! - \return Spline - \sa setSpline() -*/ -const QwtSpline &QwtSplineCurveFitter::spline() const -{ - return d_data->spline; -} - -/*! - \return Spline - \sa setSpline() -*/ -QwtSpline &QwtSplineCurveFitter::spline() -{ - return d_data->spline; -} - -/*! - 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 = qMax( splineSize, 10 ); -} - -/*! - \return Spline size - \sa setSplineSize() -*/ -int QwtSplineCurveFitter::splineSize() const -{ - return d_data->splineSize; -} - -/*! - Find a curve which has the best fit to a series of data points - - \param points Series of data points - \return Curve points -*/ -QPolygonF QwtSplineCurveFitter::fitCurve( const QPolygonF &points ) const -{ - const int size = points.size(); - if ( size <= 2 ) - return points; - - FitMode fitMode = d_data->fitMode; - if ( fitMode == Auto ) - { - fitMode = Spline; - - const QPointF *p = points.data(); - for ( int i = 1; i < size; i++ ) - { - if ( p[i].x() <= p[i-1].x() ) - { - fitMode = ParametricSpline; - break; - } - }; - } - - if ( fitMode == ParametricSpline ) - return fitParametric( points ); - else - return fitSpline( points ); -} - -QPolygonF QwtSplineCurveFitter::fitSpline( const QPolygonF &points ) const -{ - d_data->spline.setPoints( points ); - if ( !d_data->spline.isValid() ) - return points; - - QPolygonF fittedPoints( d_data->splineSize ); - - const double x1 = points[0].x(); - const double x2 = points[int( points.size() - 1 )].x(); - const double dx = x2 - x1; - const double delta = dx / ( d_data->splineSize - 1 ); - - for ( int i = 0; i < d_data->splineSize; i++ ) - { - QPointF &p = fittedPoints[i]; - - const double v = x1 + i * delta; - const double sv = d_data->spline.value( v ); - - p.setX( v ); - p.setY( sv ); - } - d_data->spline.reset(); - - return fittedPoints; -} - -QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const -{ - int i; - const int size = points.size(); - - QPolygonF fittedPoints( d_data->splineSize ); - QPolygonF splinePointsX( size ); - QPolygonF splinePointsY( size ); - - const QPointF *p = points.data(); - QPointF *spX = splinePointsX.data(); - QPointF *spY = splinePointsY.data(); - - double param = 0.0; - for ( i = 0; i < size; i++ ) - { - const double x = p[i].x(); - const double y = p[i].y(); - if ( i > 0 ) - { - const double delta = qSqrt( qwtSqr( x - spX[i-1].y() ) - + qwtSqr( y - spY[i-1].y() ) ); - param += qMax( delta, 1.0 ); - } - spX[i].setX( param ); - spX[i].setY( x ); - spY[i].setX( param ); - spY[i].setY( y ); - } - - 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++ ) - { - const double dtmp = i * deltaX; - fittedPoints[i].setX( d_data->spline.value( dtmp ) ); - } - - 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++ ) - { - const double dtmp = i * deltaY; - fittedPoints[i].setY( d_data->spline.value( dtmp ) ); - } - - return fittedPoints; -} - -class QwtWeedingCurveFitter::PrivateData -{ -public: - PrivateData(): - tolerance( 1.0 ), - chunkSize( 0 ) - { - } - - double tolerance; - uint chunkSize; -}; - -class QwtWeedingCurveFitter::Line -{ -public: - Line( int i1 = 0, int i2 = 0 ): - from( i1 ), - to( i2 ) - { - } - - int from; - int to; -}; - -/*! - Constructor - - \param tolerance Tolerance - \sa setTolerance(), tolerance() -*/ -QwtWeedingCurveFitter::QwtWeedingCurveFitter( double tolerance ) -{ - d_data = new PrivateData; - setTolerance( tolerance ); -} - -//! Destructor -QwtWeedingCurveFitter::~QwtWeedingCurveFitter() -{ - delete d_data; -} - -/*! - Assign the tolerance - - The tolerance is the maximum distance, that is acceptable - between the original curve and the smoothed curve. - - Increasing the tolerance will reduce the number of the - resulting points. - - \param tolerance Tolerance - - \sa tolerance() -*/ -void QwtWeedingCurveFitter::setTolerance( double tolerance ) -{ - d_data->tolerance = qMax( tolerance, 0.0 ); -} - -/*! - \return Tolerance - \sa setTolerance() -*/ -double QwtWeedingCurveFitter::tolerance() const -{ - return d_data->tolerance; -} - -/*! - Limit the number of points passed to a run of the algorithm - - The runtime of the Douglas Peucker algorithm increases non linear - with the number of points. For a chunk size > 0 the polygon - is split into pieces passed to the algorithm one by one. - - \param numPoints Maximum for the number of points passed to the algorithm - - \sa chunkSize() -*/ -void QwtWeedingCurveFitter::setChunkSize( uint numPoints ) -{ - if ( numPoints > 0 ) - numPoints = qMax( numPoints, 3U ); - - d_data->chunkSize = numPoints; -} - -/*! - - \return Maximum for the number of points passed to a run - of the algorithm - or 0, when unlimited - \sa setChunkSize() -*/ -uint QwtWeedingCurveFitter::chunkSize() const -{ - return d_data->chunkSize; -} - -/*! - \param points Series of data points - \return Curve points -*/ -QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const -{ - QPolygonF fittedPoints; - - if ( d_data->chunkSize == 0 ) - { - fittedPoints = simplify( points ); - } - else - { - for ( int i = 0; i < points.size(); i += d_data->chunkSize ) - { - const QPolygonF p = points.mid( i, d_data->chunkSize ); - fittedPoints += simplify( p ); - } - } - - return fittedPoints; -} - -QPolygonF QwtWeedingCurveFitter::simplify( const QPolygonF &points ) const -{ - const double toleranceSqr = d_data->tolerance * d_data->tolerance; - - QStack<Line> stack; - stack.reserve( 500 ); - - const QPointF *p = points.data(); - const int nPoints = points.size(); - - QVector<bool> usePoint( nPoints, false ); - - stack.push( Line( 0, nPoints - 1 ) ); - - while ( !stack.isEmpty() ) - { - const Line r = stack.pop(); - - // initialize line segment - const double vecX = p[r.to].x() - p[r.from].x(); - const double vecY = p[r.to].y() - p[r.from].y(); - - const double vecLength = qSqrt( vecX * vecX + vecY * vecY ); - - const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0; - const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0; - - double maxDistSqr = 0.0; - int nVertexIndexMaxDistance = r.from + 1; - for ( int i = r.from + 1; i < r.to; i++ ) - { - //compare to anchor - const double fromVecX = p[i].x() - p[r.from].x(); - const double fromVecY = p[i].y() - p[r.from].y(); - - double distToSegmentSqr; - if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) - { - distToSegmentSqr = fromVecX * fromVecX + fromVecY * fromVecY; - } - else - { - const double toVecX = p[i].x() - p[r.to].x(); - const double toVecY = p[i].y() - p[r.to].y(); - const double toVecLength = toVecX * toVecX + toVecY * toVecY; - - const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY ); - if ( s < 0.0 ) - { - distToSegmentSqr = toVecLength; - } - else - { - distToSegmentSqr = qFabs( toVecLength - s * s ); - } - } - - if ( maxDistSqr < distToSegmentSqr ) - { - maxDistSqr = distToSegmentSqr; - nVertexIndexMaxDistance = i; - } - } - if ( maxDistSqr <= toleranceSqr ) - { - usePoint[r.from] = true; - usePoint[r.to] = true; - } - else - { - stack.push( Line( r.from, nVertexIndexMaxDistance ) ); - stack.push( Line( nVertexIndexMaxDistance, r.to ) ); - } - } - - QPolygonF stripped; - for ( int i = 0; i < nPoints; i++ ) - { - if ( usePoint[i] ) - stripped += p[i]; - } - - return stripped; -} diff --git a/source/third_party/qwt/qwt_date.cpp b/source/third_party/qwt/qwt_date.cpp deleted file mode 100644 index c52ab49d04cd8a11e9ebfc560dd26f8a4768d3f8..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_date.cpp +++ /dev/null @@ -1,760 +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/qwt_date.h" -#include <qdebug.h> -#include <qlocale.h> -#include <math.h> -#include <limits> -#include <limits.h> - -#if QT_VERSION >= 0x050000 - -typedef qint64 QwtJulianDay; -static const QwtJulianDay minJulianDayD = Q_INT64_C( -784350574879 ); -static const QwtJulianDay maxJulianDayD = Q_INT64_C( 784354017364 ); - -#else - -// QDate stores the Julian day as unsigned int, but -// but it is QDate::fromJulianDay( int ). That's why -// we have the range [ 1, INT_MAX ] -typedef int QwtJulianDay; -static const QwtJulianDay minJulianDayD = 1; -static const QwtJulianDay maxJulianDayD = std::numeric_limits<int>::max(); - -#endif - -static QString qwtExpandedFormat( const QString & format, - const QDateTime &dateTime, QwtDate::Week0Type week0Type ) -{ - const int week = QwtDate::weekNumber( dateTime.date(), week0Type ); - - QString weekNo; - weekNo.setNum( week ); - - QString weekNoWW; - if ( weekNo.length() == 1 ) - weekNoWW += "0"; - - weekNoWW += weekNo; - - QString fmt = format; - fmt.replace( "ww", weekNoWW ); - fmt.replace( "w", weekNo ); - - if ( week == 1 && dateTime.date().month() != 1 ) - { - // in case of week 1, we might need to increment the year - - static QString s_yyyy = "yyyy"; - static QString s_yy = "yy"; - - // week 1 might start in the previous year - - bool doReplaceYear = fmt.contains( s_yy ); - - if ( doReplaceYear ) - { - if ( fmt.contains( 'M' ) ) - { - // in case of also having 'M' we have a conflict about - // which year to show - - doReplaceYear = false; - } - else - { - // in case of also having 'd' or 'dd' we have a conflict about - // which year to show - - int numD = 0; - - for ( int i = 0; i < fmt.size(); i++ ) - { - if ( fmt[i] == 'd' ) - { - numD++; - } - else - { - if ( numD > 0 && numD <= 2 ) - break; - - numD = 0; - } - } - - if ( numD > 0 && numD <= 2 ) - doReplaceYear = false; - } - } - - if ( doReplaceYear ) - { - const QDate dt( dateTime.date().year() + 1, 1, 1 ); - - if ( fmt.contains( s_yyyy ) ) - { - fmt.replace( s_yyyy, dt.toString( s_yyyy ) ); - } - else - { - fmt.replace( s_yy, dt.toString( s_yyyy ) ); - } - } - } - - return fmt; -} - -static inline Qt::DayOfWeek qwtFirstDayOfWeek() -{ -#if QT_VERSION >= 0x040800 - return QLocale().firstDayOfWeek(); -#else - - switch( QLocale().country() ) - { - case QLocale::Maldives: - return Qt::Friday; - - case QLocale::Afghanistan: - case QLocale::Algeria: - case QLocale::Bahrain: - case QLocale::Djibouti: - case QLocale::Egypt: - case QLocale::Eritrea: - case QLocale::Ethiopia: - case QLocale::Iran: - case QLocale::Iraq: - case QLocale::Jordan: - case QLocale::Kenya: - case QLocale::Kuwait: - case QLocale::LibyanArabJamahiriya: - case QLocale::Morocco: - case QLocale::Oman: - case QLocale::Qatar: - case QLocale::SaudiArabia: - case QLocale::Somalia: - case QLocale::Sudan: - case QLocale::Tunisia: - case QLocale::Yemen: - return Qt::Saturday; - - case QLocale::AmericanSamoa: - case QLocale::Argentina: - case QLocale::Azerbaijan: - case QLocale::Botswana: - case QLocale::Canada: - case QLocale::China: - case QLocale::FaroeIslands: - case QLocale::Georgia: - case QLocale::Greenland: - case QLocale::Guam: - case QLocale::HongKong: - case QLocale::Iceland: - case QLocale::India: - case QLocale::Ireland: - case QLocale::Israel: - case QLocale::Jamaica: - case QLocale::Japan: - case QLocale::Kyrgyzstan: - case QLocale::Lao: - case QLocale::Malta: - case QLocale::MarshallIslands: - case QLocale::Macau: - case QLocale::Mongolia: - case QLocale::NewZealand: - case QLocale::NorthernMarianaIslands: - case QLocale::Pakistan: - case QLocale::Philippines: - case QLocale::RepublicOfKorea: - case QLocale::Singapore: - case QLocale::SyrianArabRepublic: - case QLocale::Taiwan: - case QLocale::Thailand: - case QLocale::TrinidadAndTobago: - case QLocale::UnitedStates: - case QLocale::UnitedStatesMinorOutlyingIslands: - case QLocale::USVirginIslands: - case QLocale::Uzbekistan: - case QLocale::Zimbabwe: - return Qt::Sunday; - - default: - return Qt::Monday; - } -#endif -} - -static inline void qwtFloorTime( - QwtDate::IntervalType intervalType, QDateTime &dt ) -{ - // when dt is inside the special hour where DST is ending - // an hour is no unique. Therefore we have to - // use UTC time. - - const Qt::TimeSpec timeSpec = dt.timeSpec(); - - if ( timeSpec == Qt::LocalTime ) - dt = dt.toTimeSpec( Qt::UTC ); - - const QTime t = dt.time(); - switch( intervalType ) - { - case QwtDate::Second: - { - dt.setTime( QTime( t.hour(), t.minute(), t.second() ) ); - break; - } - case QwtDate::Minute: - { - dt.setTime( QTime( t.hour(), t.minute(), 0 ) ); - break; - } - case QwtDate::Hour: - { - dt.setTime( QTime( t.hour(), 0, 0 ) ); - break; - } - default: - break; - } - - if ( timeSpec == Qt::LocalTime ) - dt = dt.toTimeSpec( Qt::LocalTime ); -} - -static inline QDateTime qwtToTimeSpec( - const QDateTime &dt, Qt::TimeSpec spec ) -{ - if ( dt.timeSpec() == spec ) - return dt; - - const qint64 jd = dt.date().toJulianDay(); - if ( jd < 0 || jd >= INT_MAX ) - { - // the conversion between local time and UTC - // is internally limited. To avoid - // overflows we simply ignore the difference - // for those dates - - QDateTime dt2 = dt; - dt2.setTimeSpec( spec ); - return dt2; - } - - return dt.toTimeSpec( spec ); -} - -static inline double qwtToJulianDay( int year, int month, int day ) -{ - // code from QDate but using doubles to avoid overflows - // for large values - - const int m1 = ( month - 14 ) / 12; - const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12; - const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 ); - - return ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2 - - ::floor( ( 3 * y1 ) / 4 ) + day - 32075; -} - -static inline qint64 qwtFloorDiv64( qint64 a, int b ) -{ - if ( a < 0 ) - a -= b - 1; - - return a / b; -} - -static inline qint64 qwtFloorDiv( int a, int b ) -{ - if ( a < 0 ) - a -= b - 1; - - return a / b; -} - -static inline QDate qwtToDate( int year, int month = 1, int day = 1 ) -{ -#if QT_VERSION >= 0x050000 - return QDate( year, month, day ); -#else - if ( year > 100000 ) - { - // code from QDate but using doubles to avoid overflows - // for large values - - const int m1 = ( month - 14 ) / 12; - const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12; - const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 ); - - const double jd = ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2 - - ::floor( ( 3 * y1 ) / 4 ) + day - 32075; - - if ( jd > maxJulianDayD ) - { - qWarning() << "qwtToDate: overflow"; - return QDate(); - } - - return QDate::fromJulianDay( static_cast<QwtJulianDay>( jd ) ); - } - else - { - return QDate( year, month, day ); - } -#endif -} - -/*! - Translate from double to QDateTime - - \param value Number of milliseconds since the epoch, - 1970-01-01T00:00:00 UTC - \param timeSpec Time specification - \return Datetime value - - \sa toDouble(), QDateTime::setMSecsSinceEpoch() - \note The return datetime for Qt::OffsetFromUTC will be Qt::UTC - */ -QDateTime QwtDate::toDateTime( double value, Qt::TimeSpec timeSpec ) -{ - const int msecsPerDay = 86400000; - - const double days = static_cast<qint64>( ::floor( value / msecsPerDay ) ); - - const double jd = QwtDate::JulianDayForEpoch + days; - if ( ( jd > maxJulianDayD ) || ( jd < minJulianDayD ) ) - { - qWarning() << "QwtDate::toDateTime: overflow"; - return QDateTime(); - } - - const QDate d = QDate::fromJulianDay( static_cast<QwtJulianDay>( jd ) ); - - const int msecs = static_cast<int>( value - days * msecsPerDay ); - - static const QTime timeNull( 0, 0, 0, 0 ); - - QDateTime dt( d, timeNull.addMSecs( msecs ), Qt::UTC ); - - if ( timeSpec == Qt::LocalTime ) - dt = qwtToTimeSpec( dt, timeSpec ); - - return dt; -} - -/*! - Translate from QDateTime to double - - \param dateTime Datetime value - \return Number of milliseconds since 1970-01-01T00:00:00 UTC has passed. - - \sa toDateTime(), QDateTime::toMSecsSinceEpoch() - \warning For values very far below or above 1970-01-01 UTC rounding errors - will happen due to the limited significance of a double. - */ -double QwtDate::toDouble( const QDateTime &dateTime ) -{ - const int msecsPerDay = 86400000; - - const QDateTime dt = qwtToTimeSpec( dateTime, Qt::UTC ); - - const double days = dt.date().toJulianDay() - QwtDate::JulianDayForEpoch; - - const QTime time = dt.time(); - const double secs = 3600.0 * time.hour() + - 60.0 * time.minute() + time.second(); - - return days * msecsPerDay + time.msec() + 1000.0 * secs; -} - -/*! - Ceil a datetime according the interval type - - \param dateTime Datetime value - \param intervalType Interval type, how to ceil. - F.e. when intervalType = QwtDate::Months, the result - will be ceiled to the next beginning of a month - \return Ceiled datetime - \sa floor() - */ -QDateTime QwtDate::ceil( const QDateTime &dateTime, IntervalType intervalType ) -{ - if ( dateTime.date() >= QwtDate::maxDate() ) - return dateTime; - - QDateTime dt = dateTime; - - switch ( intervalType ) - { - case QwtDate::Millisecond: - { - break; - } - case QwtDate::Second: - { - qwtFloorTime( QwtDate::Second, dt ); - if ( dt < dateTime ) - dt = dt.addSecs( 1 ); - - break; - } - case QwtDate::Minute: - { - qwtFloorTime( QwtDate::Minute, dt ); - if ( dt < dateTime ) - dt = dt.addSecs( 60 ); - - break; - } - case QwtDate::Hour: - { - qwtFloorTime( QwtDate::Hour, dt ); - if ( dt < dateTime ) - dt = dt.addSecs( 3600 ); - - break; - } - case QwtDate::Day: - { - dt.setTime( QTime( 0, 0 ) ); - if ( dt < dateTime ) - dt = dt.addDays( 1 ); - - break; - } - case QwtDate::Week: - { - dt.setTime( QTime( 0, 0 ) ); - if ( dt < dateTime ) - dt = dt.addDays( 1 ); - - int days = qwtFirstDayOfWeek() - dt.date().dayOfWeek(); - if ( days < 0 ) - days += 7; - - dt = dt.addDays( days ); - - break; - } - case QwtDate::Month: - { - dt.setTime( QTime( 0, 0 ) ); - dt.setDate( qwtToDate( dateTime.date().year(), - dateTime.date().month() ) ); - - if ( dt < dateTime ) - dt = dt.addMonths( 1 ); - - break; - } - case QwtDate::Year: - { - dt.setTime( QTime( 0, 0 ) ); - - const QDate d = dateTime.date(); - - int year = d.year(); - if ( d.month() > 1 || d.day() > 1 || !dateTime.time().isNull() ) - year++; - - if ( year == 0 ) - year++; // there is no year 0 - - dt.setDate( qwtToDate( year ) ); - break; - } - } - - return dt; -} - -/*! - Floor a datetime according the interval type - - \param dateTime Datetime value - \param intervalType Interval type, how to ceil. - F.e. when intervalType = QwtDate::Months, - the result will be ceiled to the next - beginning of a month - \return Floored datetime - \sa floor() - */ -QDateTime QwtDate::floor( const QDateTime &dateTime, - IntervalType intervalType ) -{ - if ( dateTime.date() <= QwtDate::minDate() ) - return dateTime; - - QDateTime dt = dateTime; - - switch ( intervalType ) - { - case QwtDate::Millisecond: - { - break; - } - case QwtDate::Second: - case QwtDate::Minute: - case QwtDate::Hour: - { - qwtFloorTime( intervalType, dt ); - break; - } - case QwtDate::Day: - { - dt.setTime( QTime( 0, 0 ) ); - break; - } - case QwtDate::Week: - { - dt.setTime( QTime( 0, 0 ) ); - - int days = dt.date().dayOfWeek() - qwtFirstDayOfWeek(); - if ( days < 0 ) - days += 7; - - dt = dt.addDays( -days ); - - break; - } - case QwtDate::Month: - { - dt.setTime( QTime( 0, 0 ) ); - - const QDate date = qwtToDate( dt.date().year(), - dt.date().month() ); - dt.setDate( date ); - - break; - } - case QwtDate::Year: - { - dt.setTime( QTime( 0, 0 ) ); - - const QDate date = qwtToDate( dt.date().year() ); - dt.setDate( date ); - - break; - } - } - - return dt; -} - -/*! - Minimum for the supported date range - - The range of valid dates depends on how QDate stores the - Julian day internally. - - - For Qt4 it is "Tue Jan 2 -4713" - - For Qt5 it is "Thu Jan 1 -2147483648" - - \return minimum of the date range - \sa maxDate() - */ -QDate QwtDate::minDate() -{ - static QDate date; - if ( !date.isValid() ) - date = QDate::fromJulianDay( minJulianDayD ); - - return date; -} - -/*! - Maximum for the supported date range - - The range of valid dates depends on how QDate stores the - Julian day internally. - - - For Qt4 it is "Tue Jun 3 5874898" - - For Qt5 it is "Tue Dec 31 2147483647" - - \return maximum of the date range - \sa minDate() - \note The maximum differs between Qt4 and Qt5 - */ -QDate QwtDate::maxDate() -{ - static QDate date; - if ( !date.isValid() ) - date = QDate::fromJulianDay( maxJulianDayD ); - - return date; -} - -/*! - \brief Date of the first day of the first week for a year - - The first day of a week depends on the current locale - ( QLocale::firstDayOfWeek() ). - - \param year Year - \param type Option how to identify the first week - \return First day of week 0 - - \sa QLocale::firstDayOfWeek(), weekNumber() - */ -QDate QwtDate::dateOfWeek0( int year, Week0Type type ) -{ - const Qt::DayOfWeek firstDayOfWeek = qwtFirstDayOfWeek(); - - QDate dt0( year, 1, 1 ); - - // floor to the first day of the week - int days = dt0.dayOfWeek() - firstDayOfWeek; - if ( days < 0 ) - days += 7; - - dt0 = dt0.addDays( -days ); - - if ( type == QwtDate::FirstThursday ) - { - // according to ISO 8601 the first week is defined - // by the first thursday. - - int d = Qt::Thursday - firstDayOfWeek; - if ( d < 0 ) - d += 7; - - if ( dt0.addDays( d ).year() < year ) - dt0 = dt0.addDays( 7 ); - } - - return dt0; -} - -/*! - Find the week number of a date - - - QwtDate::FirstThursday\n - Corresponding to ISO 8601 ( see QDate::weekNumber() ). - - - QwtDate::FirstDay\n - Number of weeks that have begun since dateOfWeek0(). - - \param date Date - \param type Option how to identify the first week - - \return Week number, starting with 1 - */ -int QwtDate::weekNumber( const QDate &date, Week0Type type ) -{ - int weekNo; - - if ( type == QwtDate::FirstDay ) - { - QDate day0; - - if ( date.month() == 12 && date.day() >= 24 ) - { - // week 1 usually starts in the previous years. - // and we have to check if we are already there - - day0 = dateOfWeek0( date.year() + 1, type ); - if ( day0.daysTo( date ) < 0 ) - day0 = dateOfWeek0( date.year(), type ); - } - else - { - day0 = dateOfWeek0( date.year(), type ); - } - - weekNo = day0.daysTo( date ) / 7 + 1; - } - else - { - weekNo = date.weekNumber(); - } - - return weekNo; -} - -/*! - Offset in seconds from Coordinated Universal Time - - The offset depends on the time specification of dateTime: - - - Qt::UTC - 0, dateTime has no offset - - Qt::OffsetFromUTC - returns dateTime.utcOffset() - - Qt::LocalTime: - number of seconds from the UTC - - For Qt::LocalTime the offset depends on the timezone and - daylight savings. - - \param dateTime Datetime value - \return Offset in seconds - */ -int QwtDate::utcOffset( const QDateTime &dateTime ) -{ - int seconds = 0; - - switch( dateTime.timeSpec() ) - { - case Qt::UTC: - { - break; - } - case Qt::OffsetFromUTC: - { - seconds = dateTime.utcOffset(); - break; - } - default: - { - const QDateTime dt1( dateTime.date(), dateTime.time(), Qt::UTC ); - seconds = dateTime.secsTo( dt1 ); - } - } - - return seconds; -} - -/*! - Translate a datetime into a string - - Beside the format expressions documented in QDateTime::toString() - the following expressions are supported: - - - w\n - week number: ( 1 - 53 ) - - ww\n - week number with a leading zero ( 01 - 53 ) - - As week 1 usually starts in the previous year a special rule - is applied for formats, where the year is expected to match the - week number - even if the date belongs to the previous year. - - \param dateTime Datetime value - \param format Format string - \param week0Type Specification of week 0 - - \return Datetime string - \sa QDateTime::toString(), weekNumber(), QwtDateScaleDraw - */ -QString QwtDate::toString( const QDateTime &dateTime, - const QString & format, Week0Type week0Type ) -{ - QString fmt = format; - if ( fmt.contains( 'w' ) ) - { - fmt = qwtExpandedFormat( fmt, dateTime, week0Type ); - } - - return dateTime.toString( fmt ); -} diff --git a/source/third_party/qwt/qwt_date_scale_draw.cpp b/source/third_party/qwt/qwt_date_scale_draw.cpp deleted file mode 100644 index e4c46cc2221d44fd65707df5e1105ed940bccf02..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_date_scale_draw.cpp +++ /dev/null @@ -1,278 +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/qwt_date_scale_draw.h" - -class QwtDateScaleDraw::PrivateData -{ -public: - PrivateData( Qt::TimeSpec spec ): - timeSpec( spec ), - utcOffset( 0 ), - week0Type( QwtDate::FirstThursday ) - { - dateFormats[ QwtDate::Millisecond ] = "hh:mm:ss:zzz\nddd dd MMM yyyy"; - dateFormats[ QwtDate::Second ] = "hh:mm:ss\nddd dd MMM yyyy"; - dateFormats[ QwtDate::Minute ] = "hh:mm\nddd dd MMM yyyy"; - dateFormats[ QwtDate::Hour ] = "hh:mm\nddd dd MMM yyyy"; - dateFormats[ QwtDate::Day ] = "ddd dd MMM yyyy"; - dateFormats[ QwtDate::Week ] = "Www yyyy"; - dateFormats[ QwtDate::Month ] = "MMM yyyy"; - dateFormats[ QwtDate::Year ] = "yyyy"; - } - - Qt::TimeSpec timeSpec; - int utcOffset; - QwtDate::Week0Type week0Type; - QString dateFormats[ QwtDate::Year + 1 ]; -}; - -/*! - \brief Constructor - - The default setting is to display tick labels for the - given time specification. The first week of a year is defined like - for QwtDate::FirstThursday. - - \param timeSpec Time specification - - \sa setTimeSpec(), setWeek0Type() - */ -QwtDateScaleDraw::QwtDateScaleDraw( Qt::TimeSpec timeSpec ) -{ - d_data = new PrivateData( timeSpec ); -} - -//! Destructor -QwtDateScaleDraw::~QwtDateScaleDraw() -{ - delete d_data; -} - -/*! - Set the time specification used for the tick labels - - \param timeSpec Time specification - \sa timeSpec(), setUtcOffset(), toDateTime() - */ -void QwtDateScaleDraw::setTimeSpec( Qt::TimeSpec timeSpec ) -{ - d_data->timeSpec = timeSpec; -} - -/*! - \return Time specification used for the tick labels - \sa setTimeSpec(), utcOffset(), toDateTime() - */ -Qt::TimeSpec QwtDateScaleDraw::timeSpec() const -{ - return d_data->timeSpec; -} - -/*! - Set the offset in seconds from Coordinated Universal Time - - \param seconds Offset in seconds - - \note The offset has no effect beside for the time specification - Qt::OffsetFromUTC. - - \sa QDate::utcOffset(), setTimeSpec(), toDateTime() - */ -void QwtDateScaleDraw::setUtcOffset( int seconds ) -{ - d_data->utcOffset = seconds; -} - -/*! - \return Offset in seconds from Coordinated Universal Time - \note The offset has no effect beside for the time specification - Qt::OffsetFromUTC. - - \sa QDate::setUtcOffset(), setTimeSpec(), toDateTime() - */ -int QwtDateScaleDraw::utcOffset() const -{ - return d_data->utcOffset; -} - -/*! - Sets how to identify the first week of a year. - - \param week0Type Mode how to identify the first week of a year - - \sa week0Type(). - \note week0Type has no effect beside for intervals classified as - QwtDate::Week. - */ -void QwtDateScaleDraw::setWeek0Type( QwtDate::Week0Type week0Type ) -{ - d_data->week0Type = week0Type; -} - -/*! - \return Setting how to identify the first week of a year. - \sa setWeek0Type() - */ -QwtDate::Week0Type QwtDateScaleDraw::week0Type() const -{ - return d_data->week0Type; -} - -/*! - Set the default format string for an datetime interval type - - \param intervalType Interval type - \param format Default format string - - \sa dateFormat(), dateFormatOfDate(), QwtDate::toString() - */ -void QwtDateScaleDraw::setDateFormat( - QwtDate::IntervalType intervalType, const QString &format ) -{ - if ( intervalType >= QwtDate::Millisecond && - intervalType <= QwtDate::Year ) - { - d_data->dateFormats[ intervalType ] = format; - } -} - -/*! - \param intervalType Interval type - \return Default format string for an datetime interval type - \sa setDateFormat(), dateFormatOfDate() - */ -QString QwtDateScaleDraw::dateFormat( - QwtDate::IntervalType intervalType ) const -{ - if ( intervalType >= QwtDate::Millisecond && - intervalType <= QwtDate::Year ) - { - return d_data->dateFormats[ intervalType ]; - } - - return QString::null; -} - -/*! - Format string for the representation of a datetime - - dateFormatOfDate() is intended to be overloaded for - situations, where formats are individual for specific - datetime values. - - The default setting ignores dateTime and return - the default format for the interval type. - - \param dateTime Datetime value - \param intervalType Interval type - \return Format string - - \sa setDateFormat(), QwtDate::toString() - */ -QString QwtDateScaleDraw::dateFormatOfDate( const QDateTime &dateTime, - QwtDate::IntervalType intervalType ) const -{ - Q_UNUSED( dateTime ) - - if ( intervalType >= QwtDate::Millisecond && - intervalType <= QwtDate::Year ) - { - return d_data->dateFormats[ intervalType ]; - } - - return d_data->dateFormats[ QwtDate::Second ]; -} - -/*! - \brief Convert a value into its representing label - - The value is converted to a datetime value using toDateTime() - and converted to a plain text using QwtDate::toString(). - - \param value Value - \return Label string. - - \sa dateFormatOfDate() -*/ -QwtText QwtDateScaleDraw::label( double value ) const -{ - const QDateTime dt = toDateTime( value ); - const QString fmt = dateFormatOfDate( - dt, intervalType( scaleDiv() ) ); - - return QwtDate::toString( dt, fmt, d_data->week0Type ); -} - -/*! - Find the less detailed datetime unit, where no rounding - errors happen. - - \param scaleDiv Scale division - \return Interval type - - \sa dateFormatOfDate() - */ -QwtDate::IntervalType QwtDateScaleDraw::intervalType( - const QwtScaleDiv &scaleDiv ) const -{ - int intvType = QwtDate::Year; - - bool alignedToWeeks = true; - - const QList<double> ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick ); - for ( int i = 0; i < ticks.size(); i++ ) - { - const QDateTime dt = toDateTime( ticks[i] ); - for ( int j = QwtDate::Second; j <= intvType; j++ ) - { - const QDateTime dt0 = QwtDate::floor( dt, - static_cast<QwtDate::IntervalType>( j ) ); - - if ( dt0 != dt ) - { - if ( j == QwtDate::Week ) - { - alignedToWeeks = false; - } - else - { - intvType = j - 1; - break; - } - } - } - - if ( intvType == QwtDate::Millisecond ) - break; - } - - if ( intvType == QwtDate::Week && !alignedToWeeks ) - intvType = QwtDate::Day; - - return static_cast<QwtDate::IntervalType>( intvType ); -} - -/*! - Translate a double value into a QDateTime object. - - \return QDateTime object initialized with timeSpec() and utcOffset(). - \sa timeSpec(), utcOffset(), QwtDate::toDateTime() - */ -QDateTime QwtDateScaleDraw::toDateTime( double value ) const -{ - QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec ); - if ( d_data->timeSpec == Qt::OffsetFromUTC ) - { - dt = dt.addSecs( d_data->utcOffset ); - dt.setUtcOffset( d_data->utcOffset ); - } - - return dt; -} diff --git a/source/third_party/qwt/qwt_date_scale_engine.cpp b/source/third_party/qwt/qwt_date_scale_engine.cpp deleted file mode 100644 index 2ded7ee73f0c495e2e9fb77ccbbb6f0462df065e..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_date_scale_engine.cpp +++ /dev/null @@ -1,1309 +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/qwt_date_scale_engine.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_transform.h" -#include <qdatetime.h> -#include <limits.h> - -static inline double qwtMsecsForType( QwtDate::IntervalType type ) -{ - static const double msecs[] = - { - 1.0, - 1000.0, - 60.0 * 1000.0, - 3600.0 * 1000.0, - 24.0 * 3600.0 * 1000.0, - 7.0 * 24.0 * 3600.0 * 1000.0, - 30.0 * 24.0 * 3600.0 * 1000.0, - 365.0 * 24.0 * 3600.0 * 1000.0, - }; - - if ( type < 0 || type >= static_cast<int>( sizeof( msecs ) / sizeof( msecs[0] ) ) ) - return 1.0; - - return msecs[ type ]; -} - -static inline int qwtAlignValue( - double value, double stepSize, bool up ) -{ - double d = value / stepSize; - d = up ? ::ceil( d ) : ::floor( d ); - - return static_cast<int>( d * stepSize ); -} - -static double qwtIntervalWidth( const QDateTime &minDate, - const QDateTime &maxDate, QwtDate::IntervalType intervalType ) -{ - switch( intervalType ) - { - case QwtDate::Millisecond: - { - const double secsTo = minDate.secsTo( maxDate ); - const double msecs = maxDate.time().msec() - - minDate.time().msec(); - - return secsTo * 1000 + msecs; - } - case QwtDate::Second: - { - return minDate.secsTo( maxDate ); - } - case QwtDate::Minute: - { - const double secsTo = minDate.secsTo( maxDate ); - return ::floor( secsTo / 60 ); - } - case QwtDate::Hour: - { - const double secsTo = minDate.secsTo( maxDate ); - return ::floor( secsTo / 3600 ); - } - case QwtDate::Day: - { - return minDate.daysTo( maxDate ); - } - case QwtDate::Week: - { - return ::floor( minDate.daysTo( maxDate ) / 7.0 ); - } - case QwtDate::Month: - { - const double years = - double( maxDate.date().year() ) - minDate.date().year(); - - int months = maxDate.date().month() - minDate.date().month(); - if ( maxDate.date().day() < minDate.date().day() ) - months--; - - return years * 12 + months; - } - case QwtDate::Year: - { - double years = - double( maxDate.date().year() ) - minDate.date().year(); - - if ( maxDate.date().month() < minDate.date().month() ) - years -= 1.0; - - return years; - } - } - - return 0.0; -} - -static double qwtRoundedIntervalWidth( - const QDateTime &minDate, const QDateTime &maxDate, - QwtDate::IntervalType intervalType ) -{ - const QDateTime minD = QwtDate::floor( minDate, intervalType ); - const QDateTime maxD = QwtDate::ceil( maxDate, intervalType ); - - return qwtIntervalWidth( minD, maxD, intervalType ); -} - -static inline int qwtStepCount( int intervalSize, int maxSteps, - const int limits[], size_t numLimits ) -{ - for ( uint i = 0; i < numLimits; i++ ) - { - const int numSteps = intervalSize / limits[ i ]; - - if ( numSteps > 1 && numSteps <= maxSteps && - numSteps * limits[ i ] == intervalSize ) - { - return numSteps; - } - } - - return 0; -} - -static int qwtStepSize( int intervalSize, int maxSteps, uint base ) -{ - if ( maxSteps <= 0 ) - return 0; - - if ( maxSteps > 2 ) - { - for ( int numSteps = maxSteps; numSteps > 1; numSteps-- ) - { - const double stepSize = double( intervalSize ) / numSteps; - - const double p = ::floor( ::log( stepSize ) / ::log( double( base ) ) ); - const double fraction = qPow( base, p ); - - for ( uint n = base; n >= 1; n /= 2 ) - { - if ( qFuzzyCompare( stepSize, n * fraction ) ) - return qRound( stepSize ); - - if ( n == 3 && ( base % 2 ) == 0 ) - { - if ( qFuzzyCompare( stepSize, 2 * fraction ) ) - return qRound( stepSize ); - } - } - } - } - - return 0; -} - -static int qwtDivideInterval( double intervalSize, int numSteps, - const int limits[], size_t numLimits ) -{ - const int v = qCeil( intervalSize / double( numSteps ) ); - - for ( uint i = 0; i < numLimits - 1; i++ ) - { - if ( v <= limits[i] ) - return limits[i]; - } - - return limits[ numLimits - 1 ]; -} - -static double qwtDivideScale( double intervalSize, int numSteps, - QwtDate::IntervalType intervalType ) -{ - if ( intervalType != QwtDate::Day ) - { - if ( ( intervalSize > numSteps ) && - ( intervalSize <= 2 * numSteps ) ) - { - return 2.0; - } - } - - double stepSize; - - switch( intervalType ) - { - case QwtDate::Second: - case QwtDate::Minute: - { - static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; - - stepSize = qwtDivideInterval( intervalSize, numSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - break; - } - case QwtDate::Hour: - { - static int limits[] = { 1, 2, 3, 4, 6, 12, 24 }; - - stepSize = qwtDivideInterval( intervalSize, numSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - break; - } - case QwtDate::Day: - { - const double v = intervalSize / double( numSteps ); - if ( v <= 5.0 ) - stepSize = qCeil( v ); - else - stepSize = qCeil( v / 7 ) * 7; - - break; - } - case QwtDate::Week: - { - static int limits[] = { 1, 2, 4, 8, 12, 26, 52 }; - - stepSize = qwtDivideInterval( intervalSize, numSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - break; - } - case QwtDate::Month: - { - static int limits[] = { 1, 2, 3, 4, 6, 12 }; - - stepSize = qwtDivideInterval( intervalSize, numSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - break; - } - case QwtDate::Year: - case QwtDate::Millisecond: - default: - { - stepSize = QwtScaleArithmetic::divideInterval( - intervalSize, numSteps, 10 ); - } - } - - return stepSize; -} - -static double qwtDivideMajorStep( double stepSize, int maxMinSteps, - QwtDate::IntervalType intervalType ) -{ - double minStepSize = 0.0; - - switch( intervalType ) - { - case QwtDate::Second: - { - minStepSize = qwtStepSize( stepSize, maxMinSteps, 10 ); - if ( minStepSize == 0.0 ) - minStepSize = 0.5 * stepSize; - - break; - } - case QwtDate::Minute: - { - static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; - - int numSteps; - - if ( stepSize > maxMinSteps ) - { - numSteps = qwtStepCount( stepSize, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - } - else - { - numSteps = qwtStepCount( stepSize * 60, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - } - - if ( numSteps > 0 ) - minStepSize = double( stepSize ) / numSteps; - - break; - } - case QwtDate::Hour: - { - int numSteps = 0; - - if ( stepSize > maxMinSteps ) - { - static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 }; - - numSteps = qwtStepCount( stepSize, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - } - else - { - static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; - - numSteps = qwtStepCount( stepSize * 60, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - } - - if ( numSteps > 0 ) - minStepSize = double( stepSize ) / numSteps; - - break; - } - case QwtDate::Day: - { - int numSteps = 0; - - if ( stepSize > maxMinSteps ) - { - static int limits[] = { 1, 2, 3, 7, 14, 28 }; - - numSteps = qwtStepCount( stepSize, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - } - else - { - static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 }; - - numSteps = qwtStepCount( stepSize * 24, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - } - - if ( numSteps > 0 ) - minStepSize = double( stepSize ) / numSteps; - - break; - } - case QwtDate::Week: - { - const int daysInStep = stepSize * 7; - - if ( maxMinSteps >= daysInStep ) - { - // we want to have one tick per day - minStepSize = 1.0 / 7.0; - } - else - { - // when the stepSize is more than a week we want to - // have a tick for each week - - const int stepSizeInWeeks = stepSize; - - if ( stepSizeInWeeks <= maxMinSteps ) - { - minStepSize = 1; - } - else - { - minStepSize = QwtScaleArithmetic::divideInterval( - stepSizeInWeeks, maxMinSteps, 10 ); - } - } - break; - } - case QwtDate::Month: - { - // fractions of months doesn't make any sense - - if ( stepSize < maxMinSteps ) - maxMinSteps = static_cast<int>( stepSize ); - - static int limits[] = { 1, 2, 3, 4, 6, 12 }; - - int numSteps = qwtStepCount( stepSize, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - if ( numSteps > 0 ) - minStepSize = double( stepSize ) / numSteps; - - break; - } - case QwtDate::Year: - { - if ( stepSize >= maxMinSteps ) - { - minStepSize = QwtScaleArithmetic::divideInterval( - stepSize, maxMinSteps, 10 ); - } - else - { - // something in months - - static int limits[] = { 1, 2, 3, 4, 6, 12 }; - - int numSteps = qwtStepCount( 12 * stepSize, maxMinSteps, - limits, sizeof( limits ) / sizeof( int ) ); - - if ( numSteps > 0 ) - minStepSize = double( stepSize ) / numSteps; - } - - break; - } - default: - break; - } - - if ( intervalType != QwtDate::Month - && minStepSize == 0.0 ) - { - minStepSize = 0.5 * stepSize; - } - - return minStepSize; -} - -static QList<double> qwtDstTicks( const QDateTime &dateTime, - int secondsMajor, int secondsMinor ) -{ - if ( secondsMinor <= 0 ) - QList<double>(); - - QDateTime minDate = dateTime.addSecs( -secondsMajor ); - minDate = QwtDate::floor( minDate, QwtDate::Hour ); - - const double utcOffset = QwtDate::utcOffset( dateTime ); - - // find the hours where daylight saving time happens - - double dstMin = QwtDate::toDouble( minDate ); - while ( minDate < dateTime && - QwtDate::utcOffset( minDate ) != utcOffset ) - { - minDate = minDate.addSecs( 3600 ); - dstMin += 3600 * 1000.0; - } - - QList<double> ticks; - for ( int i = 0; i < 3600; i += secondsMinor ) - ticks += dstMin + i * 1000.0; - - return ticks; -} - -static QwtScaleDiv qwtDivideToSeconds( - const QDateTime &minDate, const QDateTime &maxDate, - double stepSize, int maxMinSteps, - QwtDate::IntervalType intervalType ) -{ - // calculate the min step size - double minStepSize = 0; - - if ( maxMinSteps > 1 ) - { - minStepSize = qwtDivideMajorStep( stepSize, - maxMinSteps, intervalType ); - } - - bool daylightSaving = false; - if ( minDate.timeSpec() == Qt::LocalTime ) - { - daylightSaving = intervalType > QwtDate::Hour; - if ( intervalType == QwtDate::Hour ) - { - daylightSaving = stepSize > 1; - } - } - - const double s = qwtMsecsForType( intervalType ) / 1000; - const int secondsMajor = static_cast<int>( stepSize * s ); - const double secondsMinor = minStepSize * s; - - // UTC excludes daylight savings. So from the difference - // of a date and its UTC counterpart we can find out - // the daylight saving hours - - const double utcOffset = QwtDate::utcOffset( minDate ); - double dstOff = 0; - - QList<double> majorTicks; - QList<double> mediumTicks; - QList<double> minorTicks; - - for ( QDateTime dt = minDate; dt <= maxDate; - dt = dt.addSecs( secondsMajor ) ) - { - if ( !dt.isValid() ) - break; - - double majorValue = QwtDate::toDouble( dt ); - - if ( daylightSaving ) - { - const double offset = utcOffset - QwtDate::utcOffset( dt ); - majorValue += offset * 1000.0; - - if ( offset > dstOff ) - { - // we add some minor ticks for the DST hour, - // otherwise the ticks will be unaligned: 0, 2, 3, 5 ... - minorTicks += qwtDstTicks( - dt, secondsMajor, qRound( secondsMinor ) ); - } - - dstOff = offset; - } - - if ( majorTicks.isEmpty() || majorTicks.last() != majorValue ) - majorTicks += majorValue; - - if ( secondsMinor > 0.0 ) - { - const int numMinorSteps = qFloor( secondsMajor / secondsMinor ); - - for ( int i = 1; i < numMinorSteps; i++ ) - { - const QDateTime mt = dt.addMSecs( - qRound64( i * secondsMinor * 1000 ) ); - - double minorValue = QwtDate::toDouble( mt ); - if ( daylightSaving ) - { - const double offset = utcOffset - QwtDate::utcOffset( mt ); - minorValue += offset * 1000.0; - } - - if ( minorTicks.isEmpty() || minorTicks.last() != minorValue ) - { - const bool isMedium = ( numMinorSteps % 2 == 0 ) - && ( i != 1 ) && ( i == numMinorSteps / 2 ); - - if ( isMedium ) - mediumTicks += minorValue; - else - minorTicks += minorValue; - } - } - } - } - - QwtScaleDiv scaleDiv; - - scaleDiv.setInterval( QwtDate::toDouble( minDate ), - QwtDate::toDouble( maxDate ) ); - - scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); - scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks ); - scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); - - return scaleDiv; -} - -static QwtScaleDiv qwtDivideToMonths( - QDateTime &minDate, const QDateTime &maxDate, - double stepSize, int maxMinSteps ) -{ - // months are intervals with non - // equidistant ( in ms ) steps: we have to build the - // scale division manually - - int minStepDays = 0; - int minStepSize = 0.0; - - if ( maxMinSteps > 1 ) - { - if ( stepSize == 1 ) - { - if ( maxMinSteps >= 30 ) - minStepDays = 1; - else if ( maxMinSteps >= 6 ) - minStepDays = 5; - else if ( maxMinSteps >= 3 ) - minStepDays = 10; - else - minStepDays = 15; - } - else - { - minStepSize = qwtDivideMajorStep( - stepSize, maxMinSteps, QwtDate::Month ); - } - } - - QList<double> majorTicks; - QList<double> mediumTicks; - QList<double> minorTicks; - - for ( QDateTime dt = minDate; - dt <= maxDate; dt = dt.addMonths( stepSize ) ) - { - if ( !dt.isValid() ) - break; - - majorTicks += QwtDate::toDouble( dt ); - - if ( minStepDays > 0 ) - { - for ( int days = minStepDays; - days < 30; days += minStepDays ) - { - const double tick = QwtDate::toDouble( dt.addDays( days ) ); - - if ( days == 15 && minStepDays != 15 ) - mediumTicks += tick; - else - minorTicks += tick; - } - } - else if ( minStepSize > 0.0 ) - { - const int numMinorSteps = qRound( stepSize / (double) minStepSize ); - - for ( int i = 1; i < numMinorSteps; i++ ) - { - const double minorValue = - QwtDate::toDouble( dt.addMonths( i * minStepSize ) ); - - if ( ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 ) ) - mediumTicks += minorValue; - else - minorTicks += minorValue; - } - } - } - - QwtScaleDiv scaleDiv; - scaleDiv.setInterval( QwtDate::toDouble( minDate ), - QwtDate::toDouble( maxDate ) ); - - scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); - scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks ); - scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); - - return scaleDiv; -} - -static QwtScaleDiv qwtDivideToYears( - const QDateTime &minDate, const QDateTime &maxDate, - double stepSize, int maxMinSteps ) -{ - QList<double> majorTicks; - QList<double> mediumTicks; - QList<double> minorTicks; - - double minStepSize = 0.0; - - if ( maxMinSteps > 1 ) - { - minStepSize = qwtDivideMajorStep( - stepSize, maxMinSteps, QwtDate::Year ); - } - - int numMinorSteps = 0; - if ( minStepSize > 0.0 ) - numMinorSteps = qFloor( stepSize / minStepSize ); - - bool dateBC = minDate.date().year() < -1; - - for ( QDateTime dt = minDate; dt <= maxDate; - dt = dt.addYears( stepSize ) ) - { - if ( dateBC && dt.date().year() > 1 ) - { - // there is no year 0 in the Julian calendar - dt = dt.addYears( -1 ); - dateBC = false; - } - - if ( !dt.isValid() ) - break; - - majorTicks += QwtDate::toDouble( dt ); - - for ( int i = 1; i < numMinorSteps; i++ ) - { - QDateTime tickDate; - - const double years = qRound( i * minStepSize ); - if ( years >= INT_MAX / 12 ) - { - tickDate = dt.addYears( years ); - } - else - { - tickDate = dt.addMonths( qRound( years * 12 ) ); - } - - const bool isMedium = ( numMinorSteps > 2 ) && - ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 ); - - const double minorValue = QwtDate::toDouble( tickDate ); - if ( isMedium ) - mediumTicks += minorValue; - else - minorTicks += minorValue; - } - - if ( QwtDate::maxDate().addYears( -stepSize ) < dt.date() ) - { - break; - } - } - - QwtScaleDiv scaleDiv; - scaleDiv.setInterval( QwtDate::toDouble( minDate ), - QwtDate::toDouble( maxDate ) ); - - scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); - scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks ); - scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); - - return scaleDiv; -} - -class QwtDateScaleEngine::PrivateData -{ -public: - PrivateData( Qt::TimeSpec spec ): - timeSpec( spec ), - utcOffset( 0 ), - week0Type( QwtDate::FirstThursday ), - maxWeeks( 4 ) - { - } - - Qt::TimeSpec timeSpec; - int utcOffset; - QwtDate::Week0Type week0Type; - int maxWeeks; -}; - - -/*! - \brief Constructor - - The engine is initialized to build scales for the - given time specification. It classifies intervals > 4 weeks - as >= Qt::Month. The first week of a year is defined like - for QwtDate::FirstThursday. - - \param timeSpec Time specification - - \sa setTimeSpec(), setMaxWeeks(), setWeek0Type() - */ -QwtDateScaleEngine::QwtDateScaleEngine( Qt::TimeSpec timeSpec ): - QwtLinearScaleEngine( 10 ) -{ - d_data = new PrivateData( timeSpec ); -} - -//! Destructor -QwtDateScaleEngine::~QwtDateScaleEngine() -{ - delete d_data; -} - -/*! - Set the time specification used by the engine - - \param timeSpec Time specification - \sa timeSpec(), setUtcOffset(), toDateTime() - */ -void QwtDateScaleEngine::setTimeSpec( Qt::TimeSpec timeSpec ) -{ - d_data->timeSpec = timeSpec; -} - -/*! - \return Time specification used by the engine - \sa setTimeSpec(), utcOffset(), toDateTime() - */ -Qt::TimeSpec QwtDateScaleEngine::timeSpec() const -{ - return d_data->timeSpec; -} - -/*! - Set the offset in seconds from Coordinated Universal Time - - \param seconds Offset in seconds - - \note The offset has no effect beside for the time specification - Qt::OffsetFromUTC. - - \sa QDate::utcOffset(), setTimeSpec(), toDateTime() - */ -void QwtDateScaleEngine::setUtcOffset( int seconds ) -{ - d_data->utcOffset = seconds; -} - -/*! - \return Offset in seconds from Coordinated Universal Time - \note The offset has no effect beside for the time specification - Qt::OffsetFromUTC. - - \sa QDate::setUtcOffset(), setTimeSpec(), toDateTime() - */ -int QwtDateScaleEngine::utcOffset() const -{ - return d_data->utcOffset; -} - -/*! - Sets how to identify the first week of a year. - - \param week0Type Mode how to identify the first week of a year - - \sa week0Type(), setMaxWeeks() - \note week0Type has no effect beside for intervals classified as - QwtDate::Week. - */ -void QwtDateScaleEngine::setWeek0Type( QwtDate::Week0Type week0Type ) -{ - d_data->week0Type = week0Type; -} - -/*! - \return Setting how to identify the first week of a year. - \sa setWeek0Type(), maxWeeks() - */ -QwtDate::Week0Type QwtDateScaleEngine::week0Type() const -{ - return d_data->week0Type; -} - -/*! - Set a upper limit for the number of weeks, when an interval - can be classified as Qt::Week. - - The default setting is 4 weeks. - - \param weeks Upper limit for the number of weeks - - \note In business charts a year is often devided - into weeks [1-52] - \sa maxWeeks(), setWeek0Type() - */ -void QwtDateScaleEngine::setMaxWeeks( int weeks ) -{ - d_data->maxWeeks = qMax( weeks, 0 ); -} - -/*! - \return Upper limit for the number of weeks, when an interval - can be classified as Qt::Week. - \sa setMaxWeeks(), week0Type() - */ -int QwtDateScaleEngine::maxWeeks() const -{ - return d_data->maxWeeks; -} - -/*! - Classification of a date/time interval division - - \param minDate Minimum ( = earlier ) of the interval - \param maxDate Maximum ( = later ) of the interval - \param maxSteps Maximum for the number of steps - - \return Interval classification - */ -QwtDate::IntervalType QwtDateScaleEngine::intervalType( - const QDateTime &minDate, const QDateTime &maxDate, - int maxSteps ) const -{ - const double jdMin = minDate.date().toJulianDay(); - const double jdMax = maxDate.date().toJulianDay(); - - if ( ( jdMax - jdMin ) / 365 > maxSteps ) - return QwtDate::Year; - - const int months = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Month ); - if ( months > maxSteps * 6 ) - return QwtDate::Year; - - const int days = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Day ); - const int weeks = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Week ); - - if ( weeks > d_data->maxWeeks ) - { - if ( days > 4 * maxSteps * 7 ) - return QwtDate::Month; - } - - if ( days > maxSteps * 7 ) - return QwtDate::Week; - - const int hours = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Hour ); - if ( hours > maxSteps * 24 ) - return QwtDate::Day; - - const int seconds = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Second ); - - if ( seconds >= maxSteps * 3600 ) - return QwtDate::Hour; - - if ( seconds >= maxSteps * 60 ) - return QwtDate::Minute; - - if ( seconds >= maxSteps ) - return QwtDate::Second; - - return QwtDate::Millisecond; -} - -/*! - Align and divide an interval - - The algorithm aligns and divides the interval into steps. - - Datetime interval divisions are usually not equidistant and the - calculated stepSize can only be used as an approximation - for the steps calculated by divideScale(). - - \param maxNumSteps Max. number of steps - \param x1 First limit of the interval (In/Out) - \param x2 Second limit of the interval (In/Out) - \param stepSize Step size (Out) - - \sa QwtScaleEngine::setAttribute() -*/ -void QwtDateScaleEngine::autoScale( int maxNumSteps, - double &x1, double &x2, double &stepSize ) const -{ - stepSize = 0.0; - - QwtInterval interval( x1, x2 ); - interval = interval.normalized(); - - interval.setMinValue( interval.minValue() - lowerMargin() ); - interval.setMaxValue( interval.maxValue() + upperMargin() ); - - if ( testAttribute( QwtScaleEngine::Symmetric ) ) - interval = interval.symmetrize( reference() ); - - if ( testAttribute( QwtScaleEngine::IncludeReference ) ) - interval = interval.extend( reference() ); - - if ( interval.width() == 0.0 ) - interval = buildInterval( interval.minValue() ); - - const QDateTime from = toDateTime( interval.minValue() ); - const QDateTime to = toDateTime( interval.maxValue() ); - - if ( from.isValid() && to.isValid() ) - { - if ( maxNumSteps < 1 ) - maxNumSteps = 1; - - const QwtDate::IntervalType intvType = - intervalType( from, to, maxNumSteps ); - - const double width = qwtIntervalWidth( from, to, intvType ); - - const double stepWidth = qwtDivideScale( width, maxNumSteps, intvType ); - if ( stepWidth != 0.0 && !testAttribute( QwtScaleEngine::Floating ) ) - { - const QDateTime d1 = alignDate( from, stepWidth, intvType, false ); - const QDateTime d2 = alignDate( to, stepWidth, intvType, true ); - - interval.setMinValue( QwtDate::toDouble( d1 ) ); - interval.setMaxValue( QwtDate::toDouble( d2 ) ); - } - - stepSize = stepWidth * qwtMsecsForType( intvType ); - } - - x1 = interval.minValue(); - x2 = interval.maxValue(); - - if ( testAttribute( QwtScaleEngine::Inverted ) ) - { - qSwap( x1, x2 ); - stepSize = -stepSize; - } -} - -/*! - \brief Calculate a scale division for a date/time interval - - \param x1 First interval limit - \param x2 Second interval limit - \param maxMajorSteps Maximum for the number of major steps - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size. If stepSize == 0, the scaleEngine - calculates one. - \return Calculated scale division -*/ -QwtScaleDiv QwtDateScaleEngine::divideScale( double x1, double x2, - int maxMajorSteps, int maxMinorSteps, double stepSize ) const -{ - if ( maxMajorSteps < 1 ) - maxMajorSteps = 1; - - const double min = qMin( x1, x2 ); - const double max = qMax( x1, x2 ); - - const QDateTime from = toDateTime( min ); - const QDateTime to = toDateTime( max ); - - if ( from == to ) - return QwtScaleDiv(); - - stepSize = qAbs( stepSize ); - if ( stepSize > 0.0 ) - { - // as interval types above hours are not equidistant - // ( even days might have 23/25 hours because of daylight saving ) - // the stepSize is used as a hint only - - maxMajorSteps = qCeil( ( max - min ) / stepSize ); - } - - const QwtDate::IntervalType intvType = - intervalType( from, to, maxMajorSteps ); - - QwtScaleDiv scaleDiv; - - if ( intvType == QwtDate::Millisecond ) - { - // for milliseconds and below we can use the decimal system - scaleDiv = QwtLinearScaleEngine::divideScale( min, max, - maxMajorSteps, maxMinorSteps, stepSize ); - } - else - { - const QDateTime minDate = QwtDate::floor( from, intvType ); - const QDateTime maxDate = QwtDate::ceil( to, intvType ); - - scaleDiv = buildScaleDiv( minDate, maxDate, - maxMajorSteps, maxMinorSteps, intvType ); - - // scaleDiv has been calculated from an extended interval - // adjusted to the step size. We have to shrink it again. - - scaleDiv = scaleDiv.bounded( min, max ); - } - - if ( x1 > x2 ) - scaleDiv.invert(); - - return scaleDiv; -} - -QwtScaleDiv QwtDateScaleEngine::buildScaleDiv( - const QDateTime &minDate, const QDateTime &maxDate, - int maxMajorSteps, int maxMinorSteps, - QwtDate::IntervalType intervalType ) const -{ - // calculate the step size - const double stepSize = qwtDivideScale( - qwtIntervalWidth( minDate, maxDate, intervalType ), - maxMajorSteps, intervalType ); - - // align minDate to the step size - QDateTime dt0 = alignDate( minDate, stepSize, intervalType, false ); - if ( !dt0.isValid() ) - { - // the floored date is out of the range of a - // QDateTime - we ceil instead. - dt0 = alignDate( minDate, stepSize, intervalType, true ); - } - - QwtScaleDiv scaleDiv; - - if ( intervalType <= QwtDate::Week ) - { - scaleDiv = qwtDivideToSeconds( dt0, maxDate, - stepSize, maxMinorSteps, intervalType ); - } - else - { - if( intervalType == QwtDate::Month ) - { - scaleDiv = qwtDivideToMonths( dt0, maxDate, - stepSize, maxMinorSteps ); - } - else if ( intervalType == QwtDate::Year ) - { - scaleDiv = qwtDivideToYears( dt0, maxDate, - stepSize, maxMinorSteps ); - } - } - - - return scaleDiv; -} - -/*! - Align a date/time value for a step size - - For Qt::Day alignments there is no "natural day 0" - - instead the first day of the year is used to avoid jumping - major ticks positions when panning a scale. For other alignments - ( f.e according to the first day of the month ) alignDate() - has to be overloaded. - - \param dateTime Date/time value - \param stepSize Step size - \param intervalType Interval type - \param up When true dateTime is ceiled - otherwise it is floored - - \return Aligned date/time value - */ -QDateTime QwtDateScaleEngine::alignDate( - const QDateTime &dateTime, double stepSize, - QwtDate::IntervalType intervalType, bool up ) const -{ - // what about: (year == 1582 && month == 10 && day > 4 && day < 15) ?? - - QDateTime dt = dateTime; - - if ( dateTime.timeSpec() == Qt::OffsetFromUTC ) - { - dt.setUtcOffset( 0 ); - } - - switch( intervalType ) - { - case QwtDate::Millisecond: - { - const int ms = qwtAlignValue( - dt.time().msec(), stepSize, up ) ; - - dt = QwtDate::floor( dateTime, QwtDate::Second ); - dt = dt.addMSecs( ms ); - - break; - } - case QwtDate::Second: - { - int second = dt.time().second(); - if ( up ) - { - if ( dt.time().msec() > 0 ) - second++; - } - - const int s = qwtAlignValue( second, stepSize, up ); - - dt = QwtDate::floor( dt, QwtDate::Minute ); - dt = dt.addSecs( s ); - - break; - } - case QwtDate::Minute: - { - int minute = dt.time().minute(); - if ( up ) - { - if ( dt.time().msec() > 0 || dt.time().second() > 0 ) - minute++; - } - - const int m = qwtAlignValue( minute, stepSize, up ); - - dt = QwtDate::floor( dt, QwtDate::Hour ); - dt = dt.addSecs( m * 60 ); - - break; - } - case QwtDate::Hour: - { - int hour = dt.time().hour(); - if ( up ) - { - if ( dt.time().msec() > 0 || dt.time().second() > 0 - || dt.time().minute() > 0 ) - { - hour++; - } - } - const int h = qwtAlignValue( hour, stepSize, up ); - - dt = QwtDate::floor( dt, QwtDate::Day ); - dt = dt.addSecs( h * 3600 ); - - break; - } - case QwtDate::Day: - { - // What date do we expect f.e. from an alignment of 5 days ?? - // Aligning them to the beginning of the year avoids at least - // jumping major ticks when panning - - int day = dt.date().dayOfYear(); - if ( up ) - { - if ( dt.time() > QTime( 0, 0 ) ) - day++; - } - - const int d = qwtAlignValue( day, stepSize, up ); - - dt = QwtDate::floor( dt, QwtDate::Year ); - dt = dt.addDays( d - 1 ); - - break; - } - case QwtDate::Week: - { - const QDate date = QwtDate::dateOfWeek0( - dt.date().year(), d_data->week0Type ); - - int numWeeks = date.daysTo( dt.date() ) / 7; - if ( up ) - { - if ( dt.time() > QTime( 0, 0 ) || - date.daysTo( dt.date() ) % 7 ) - { - numWeeks++; - } - } - - const int d = qwtAlignValue( numWeeks, stepSize, up ) * 7; - - dt = QwtDate::floor( dt, QwtDate::Day ); - dt.setDate( date ); - dt = dt.addDays( d ); - - break; - } - case QwtDate::Month: - { - int month = dt.date().month(); - if ( up ) - { - if ( dt.date().day() > 1 || - dt.time() > QTime( 0, 0 ) ) - { - month++; - } - } - - const int m = qwtAlignValue( month - 1, stepSize, up ); - - dt = QwtDate::floor( dt, QwtDate::Year ); - dt = dt.addMonths( m ); - - break; - } - case QwtDate::Year: - { - int year = dateTime.date().year(); - if ( up ) - { - if ( dateTime.date().dayOfYear() > 1 || - dt.time() > QTime( 0, 0 ) ) - { - year++; - } - } - - const int y = qwtAlignValue( year, stepSize, up ); - - dt = QwtDate::floor( dt, QwtDate::Day ); - if ( y == 0 ) - { - // there is no year 0 in the Julian calendar - dt.setDate( QDate( stepSize, 1, 1 ).addYears( -stepSize ) ); - } - else - { - dt.setDate( QDate( y, 1, 1 ) ); - } - - break; - } - } - - if ( dateTime.timeSpec() == Qt::OffsetFromUTC ) - { - dt.setUtcOffset( dateTime.utcOffset() ); - } - - return dt; -} - -/*! - Translate a double value into a QDateTime object. - - For QDateTime result is bounded by QwtDate::minDate() and QwtDate::maxDate() - - \return QDateTime object initialized with timeSpec() and utcOffset(). - \sa timeSpec(), utcOffset(), QwtDate::toDateTime() - */ -QDateTime QwtDateScaleEngine::toDateTime( double value ) const -{ - QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec ); - if ( !dt.isValid() ) - { - const QDate date = ( value <= 0.0 ) - ? QwtDate::minDate() : QwtDate::maxDate(); - - dt = QDateTime( date, QTime( 0, 0 ), d_data->timeSpec ); - } - - if ( d_data->timeSpec == Qt::OffsetFromUTC ) - { - dt = dt.addSecs( d_data->utcOffset ); - dt.setUtcOffset( d_data->utcOffset ); - } - - return dt; -} - diff --git a/source/third_party/qwt/qwt_dial.cpp b/source/third_party/qwt/qwt_dial.cpp deleted file mode 100644 index 950139964aad0ee8b82706872f10ab77afd3a205..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_dial.cpp +++ /dev/null @@ -1,871 +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/qwt_dial.h" -#include "qwt/qwt_dial_needle.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_scale_engine.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_round_scale_draw.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qpalette.h> -#include <qpixmap.h> -#include <qevent.h> -#include <qalgorithms.h> -#include <qmath.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qapplication.h> - -static inline double qwtAngleDist( double a1, double a2 ) -{ - double dist = qAbs( a2 - a1 ); - if ( dist > 360.0 ) - dist -= 360.0; - - return dist; -} - -static inline bool qwtIsOnArc( double angle, double min, double max ) -{ - if ( min < max ) - { - return ( angle >= min ) && ( angle <= max ); - } - else - { - return ( angle >= min ) || ( angle <= max ); - } -} - -static inline double qwtBoundedAngle( double min, double angle, double max ) -{ - double from = qwtNormalizeDegrees( min ); - double to = qwtNormalizeDegrees( max ); - - double a; - - if ( qwtIsOnArc( angle, from, to ) ) - { - a = angle; - if ( a < min ) - a += 360.0; - } - else - { - if ( qwtAngleDist( angle, from ) < - qwtAngleDist( angle, to ) ) - { - a = min; - } - else - { - a = max; - } - } - - return a; -} - -class QwtDial::PrivateData -{ -public: - PrivateData(): - frameShadow( Sunken ), - lineWidth( 0 ), - mode( RotateNeedle ), - origin( 90.0 ), - minScaleArc( 0.0 ), - maxScaleArc( 0.0 ), - needle( NULL ), - arcOffset( 0.0 ), - mouseOffset( 0.0 ) - { - } - - ~PrivateData() - { - delete needle; - } - Shadow frameShadow; - int lineWidth; - - QwtDial::Mode mode; - - double origin; - double minScaleArc; - double maxScaleArc; - - QwtDialNeedle *needle; - - double arcOffset; - double mouseOffset; - - QPixmap pixmapCache; -}; - -/*! - \brief Constructor - \param parent Parent widget - - Create a dial widget with no needle. The scale is initialized - to [ 0.0, 360.0 ] and 360 steps ( QwtAbstractSlider::setTotalSteps() ). - The origin of the scale is at 90°, - - The value is set to 0.0. - - The default mode is QwtDial::RotateNeedle. -*/ -QwtDial::QwtDial( QWidget* parent ): - QwtAbstractSlider( parent ) -{ - d_data = new PrivateData; - - setFocusPolicy( Qt::TabFocus ); - - QPalette p = palette(); - for ( int i = 0; i < QPalette::NColorGroups; i++ ) - { - const QPalette::ColorGroup colorGroup = - static_cast<QPalette::ColorGroup>( i ); - - // Base: background color of the circle inside the frame. - // WindowText: background color of the circle inside the scale - - p.setColor( colorGroup, QPalette::WindowText, - p.color( colorGroup, QPalette::Base ) ); - } - setPalette( p ); - - QwtRoundScaleDraw* scaleDraw = new QwtRoundScaleDraw(); - scaleDraw->setRadius( 0 ); - - setScaleDraw( scaleDraw ); - - setScaleArc( 0.0, 360.0 ); // scale as a full circle - - setScaleMaxMajor( 10 ); - setScaleMaxMinor( 5 ); - - setValue( 0.0 ); -} - -//! Destructor -QwtDial::~QwtDial() -{ - delete d_data; -} - -/*! - Sets the frame shadow value from the frame style. - - \param shadow Frame shadow - \sa setLineWidth(), QFrame::setFrameShadow() -*/ -void QwtDial::setFrameShadow( Shadow shadow ) -{ - if ( shadow != d_data->frameShadow ) - { - invalidateCache(); - - d_data->frameShadow = shadow; - if ( lineWidth() > 0 ) - update(); - } -} - -/*! - \return Frame shadow - /sa setFrameShadow(), lineWidth(), QFrame::frameShadow() -*/ -QwtDial::Shadow QwtDial::frameShadow() const -{ - return d_data->frameShadow; -} - -/*! - Sets the line width of the frame - - \param lineWidth Line width - \sa setFrameShadow() -*/ -void QwtDial::setLineWidth( int lineWidth ) -{ - if ( lineWidth < 0 ) - lineWidth = 0; - - if ( d_data->lineWidth != lineWidth ) - { - invalidateCache(); - - d_data->lineWidth = lineWidth; - update(); - } -} - -/*! - \return Line width of the frame - \sa setLineWidth(), frameShadow(), lineWidth() -*/ -int QwtDial::lineWidth() const -{ - return d_data->lineWidth; -} - -/*! - \return bounding rectangle of the circle inside the frame - \sa setLineWidth(), scaleInnerRect(), boundingRect() -*/ -QRect QwtDial::innerRect() const -{ - const int lw = lineWidth(); - return boundingRect().adjusted( lw, lw, -lw, -lw ); -} - -/*! - \return bounding rectangle of the dial including the frame - \sa setLineWidth(), scaleInnerRect(), innerRect() -*/ -QRect QwtDial::boundingRect() const -{ - const QRect cr = contentsRect(); - - const double dim = qMin( cr.width(), cr.height() ); - - QRect inner( 0, 0, dim, dim ); - inner.moveCenter( cr.center() ); - - return inner; -} - -/*! - \return rectangle inside the scale - \sa setLineWidth(), boundingRect(), innerRect() -*/ -QRect QwtDial::scaleInnerRect() const -{ - QRect rect = innerRect(); - - const QwtAbstractScaleDraw *sd = scaleDraw(); - if ( sd ) - { - int scaleDist = qCeil( sd->extent( font() ) ); - scaleDist++; // margin - - rect.adjust( scaleDist, scaleDist, -scaleDist, -scaleDist ); - } - - return rect; -} - -/*! - \brief Change the mode of the dial. - \param mode New mode - - In case of QwtDial::RotateNeedle 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 ) -{ - if ( mode != d_data->mode ) - { - invalidateCache(); - - d_data->mode = mode; - sliderChange(); - } -} - -/*! - \return Mode of the dial. - \sa setMode(), origin(), setScaleArc(), value() -*/ -QwtDial::Mode QwtDial::mode() const -{ - return d_data->mode; -} - -/*! - Invalidate the internal caches used to speed up repainting - */ -void QwtDial::invalidateCache() -{ - d_data->pixmapCache = QPixmap(); -} - -/*! - Paint the dial - \param event Paint event -*/ -void QwtDial::paintEvent( QPaintEvent *event ) -{ - QPainter painter( this ); - painter.setClipRegion( event->region() ); - - QStyleOption opt; - opt.init(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); - - if ( d_data->mode == QwtDial::RotateScale ) - { - painter.save(); - painter.setRenderHint( QPainter::Antialiasing, true ); - - drawContents( &painter ); - - painter.restore(); - } - - const QRect r = contentsRect(); - if ( r.size() != d_data->pixmapCache.size() ) - { - d_data->pixmapCache = QwtPainter::backingStore( this, r.size() ); - d_data->pixmapCache.fill( Qt::transparent ); - - QPainter p( &d_data->pixmapCache ); - p.setRenderHint( QPainter::Antialiasing, true ); - p.translate( -r.topLeft() ); - - if ( d_data->mode != QwtDial::RotateScale ) - drawContents( &p ); - - if ( lineWidth() > 0 ) - drawFrame( &p ); - - if ( d_data->mode != QwtDial::RotateNeedle ) - drawNeedle( &p ); - } - - painter.drawPixmap( r.topLeft(), d_data->pixmapCache ); - - if ( d_data->mode == QwtDial::RotateNeedle ) - drawNeedle( &painter ); - - if ( hasFocus() ) - drawFocusIndicator( &painter ); -} - -/*! - Draw the focus indicator - \param painter Painter -*/ -void QwtDial::drawFocusIndicator( QPainter *painter ) const -{ - QwtPainter::drawFocusRect( painter, this, boundingRect() ); -} - -/*! - Draw the frame around the dial - - \param painter Painter - \sa lineWidth(), frameShadow() -*/ -void QwtDial::drawFrame( QPainter *painter ) -{ - QwtPainter::drawRoundFrame( painter, boundingRect(), - palette(), lineWidth(), d_data->frameShadow ); -} - -/*! - \brief Draw the contents inside the frame - - 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(), innerRect(), - scaleInnerRect(), QWidget::setPalette() -*/ -void QwtDial::drawContents( QPainter *painter ) const -{ - if ( testAttribute( Qt::WA_NoSystemBackground ) || - palette().brush( QPalette::Base ) != - palette().brush( QPalette::Window ) ) - { - const QRectF br = boundingRect(); - - painter->save(); - painter->setPen( Qt::NoPen ); - painter->setBrush( palette().brush( QPalette::Base ) ); - painter->drawEllipse( br ); - painter->restore(); - } - - const QRectF insideScaleRect = scaleInnerRect(); - if ( palette().brush( QPalette::WindowText ) != - palette().brush( QPalette::Base ) ) - { - painter->save(); - painter->setPen( Qt::NoPen ); - painter->setBrush( palette().brush( QPalette::WindowText ) ); - painter->drawEllipse( insideScaleRect ); - painter->restore(); - } - - const QPointF center = insideScaleRect.center(); - const double radius = 0.5 * insideScaleRect.width(); - - painter->save(); - drawScale( painter, center, radius ); - painter->restore(); - - painter->save(); - drawScaleContents( painter, center, radius ); - painter->restore(); -} - -/*! - Draw the needle - - \param painter Painter - \param center Center of the dial - \param radius Length for the needle - \param direction Direction of the needle in degrees, counter clockwise - \param colorGroup ColorGroup -*/ -void QwtDial::drawNeedle( QPainter *painter, const QPointF ¢er, - double radius, double direction, QPalette::ColorGroup colorGroup ) const -{ - if ( d_data->needle ) - { - direction = 360.0 - direction; // counter clockwise - d_data->needle->draw( painter, center, radius, direction, colorGroup ); - } -} - -void QwtDial::drawNeedle( QPainter *painter ) const -{ - if ( !isValid() ) - return; - - QPalette::ColorGroup colorGroup; - if ( isEnabled() ) - colorGroup = hasFocus() ? QPalette::Active : QPalette::Inactive; - else - colorGroup = QPalette::Disabled; - - const QRectF sr = scaleInnerRect(); - - painter->save(); - painter->setRenderHint( QPainter::Antialiasing, true ); - drawNeedle( painter, sr.center(), 0.5 * sr.width(), - scaleMap().transform( value() ) + 270.0, colorGroup ); - painter->restore(); -} - -/*! - Draw the scale - - \param painter Painter - \param center Center of the dial - \param radius Radius of the scale -*/ -void QwtDial::drawScale( QPainter *painter, - const QPointF ¢er, double radius ) const -{ - QwtRoundScaleDraw *sd = const_cast<QwtRoundScaleDraw *>( scaleDraw() ); - if ( sd == NULL ) - return; - - sd->setRadius( radius ); - sd->moveCenter( center ); - - QPalette pal = palette(); - - const QColor textColor = pal.color( QPalette::Text ); - pal.setColor( QPalette::WindowText, textColor ); // ticks, backbone - - painter->setFont( font() ); - painter->setPen( QPen( textColor, sd->penWidth() ) ); - - painter->setBrush( Qt::red ); - sd->draw( painter, pal ); -} - -/*! - 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 -{ - Q_UNUSED(painter); - Q_UNUSED(center); - Q_UNUSED(radius); -} - -/*! - Set a needle for the dial - - \param needle Needle - - \warning The needle will be deleted, when a different needle is - set or in ~QwtDial() -*/ -void QwtDial::setNeedle( QwtDialNeedle *needle ) -{ - if ( needle != d_data->needle ) - { - if ( d_data->needle ) - delete d_data->needle; - - d_data->needle = needle; - update(); - } -} - -/*! - \return needle - \sa setNeedle() -*/ -const QwtDialNeedle *QwtDial::needle() const -{ - return d_data->needle; -} - -/*! - \return needle - \sa setNeedle() -*/ -QwtDialNeedle *QwtDial::needle() -{ - return d_data->needle; -} - -//! \return the scale draw -QwtRoundScaleDraw *QwtDial::scaleDraw() -{ - return static_cast<QwtRoundScaleDraw *>( abstractScaleDraw() ); -} - -//! \return the scale draw -const QwtRoundScaleDraw *QwtDial::scaleDraw() const -{ - return static_cast<const QwtRoundScaleDraw *>( abstractScaleDraw() ); -} - -/*! - Set an individual scale draw - - The motivation for setting a scale draw is often - to overload QwtRoundScaleDraw::label() to return - individual tick labels. - - \param scaleDraw Scale draw - \warning The previous scale draw is deleted -*/ -void QwtDial::setScaleDraw( QwtRoundScaleDraw *scaleDraw ) -{ - setAbstractScaleDraw( scaleDraw ); - sliderChange(); -} - -/*! - Change the arc of the scale - - \param minArc Lower limit - \param maxArc Upper limit - - \sa minScaleArc(), maxScaleArc() -*/ -void QwtDial::setScaleArc( double minArc, double maxArc ) -{ - if ( minArc != 360.0 && minArc != -360.0 ) - minArc = ::fmod( minArc, 360.0 ); - if ( maxArc != 360.0 && maxArc != -360.0 ) - maxArc = ::fmod( maxArc, 360.0 ); - - double minScaleArc = qMin( minArc, maxArc ); - double maxScaleArc = qMax( minArc, maxArc ); - - if ( maxScaleArc - minScaleArc > 360.0 ) - maxScaleArc = minScaleArc + 360.0; - - if ( ( minScaleArc != d_data->minScaleArc ) || - ( maxScaleArc != d_data->maxScaleArc ) ) - { - d_data->minScaleArc = minScaleArc; - d_data->maxScaleArc = maxScaleArc; - - invalidateCache(); - sliderChange(); - } -} - -/*! - Set the lower limit for the scale arc - - \param min Lower limit of the scale arc - \sa setScaleArc(), setMaxScaleArc() - */ -void QwtDial::setMinScaleArc( double min ) -{ - setScaleArc( min, d_data->maxScaleArc ); -} - -/*! - \return Lower limit of the scale arc - \sa setScaleArc() -*/ -double QwtDial::minScaleArc() const -{ - return d_data->minScaleArc; -} - -/*! - Set the upper limit for the scale arc - - \param max Upper limit of the scale arc - \sa setScaleArc(), setMinScaleArc() - */ -void QwtDial::setMaxScaleArc( double max ) -{ - setScaleArc( d_data->minScaleArc, max ); -} - -/*! - \return Upper limit of the scale arc - \sa setScaleArc() -*/ -double QwtDial::maxScaleArc() const -{ - return d_data->maxScaleArc; -} - -/*! - \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 ) -{ - invalidateCache(); - - d_data->origin = origin; - sliderChange(); -} - -/*! - The origin is the angle where scale and needle is relative to. - - \return Origin of the dial - \sa setOrigin() -*/ -double QwtDial::origin() const -{ - return d_data->origin; -} - -/*! - \return Size hint - \sa minimumSizeHint() -*/ -QSize QwtDial::sizeHint() const -{ - int sh = 0; - if ( scaleDraw() ) - sh = qCeil( scaleDraw()->extent( font() ) ); - - const int d = 6 * sh + 2 * lineWidth(); - - QSize hint( d, d ); - if ( !isReadOnly() ) - hint = hint.expandedTo( QApplication::globalStrut() ); - - return hint; -} - -/*! - \return Minimum size hint - \sa sizeHint() -*/ -QSize QwtDial::minimumSizeHint() const -{ - int sh = 0; - if ( scaleDraw() ) - sh = qCeil( scaleDraw()->extent( font() ) ); - - const int d = 3 * sh + 2 * lineWidth(); - - return QSize( d, d ); -} - -/*! - \brief Determine what to do when the user presses a mouse button. - - \param pos Mouse position - - \retval True, when the inner circle contains pos - \sa scrolledTo() -*/ -bool QwtDial::isScrollPosition( const QPoint &pos ) const -{ - const QRegion region( innerRect(), QRegion::Ellipse ); - if ( region.contains( pos ) && ( pos != innerRect().center() ) ) - { - double angle = QLineF( rect().center(), pos ).angle(); - if ( d_data->mode == QwtDial::RotateScale ) - angle = 360.0 - angle; - - double valueAngle = - qwtNormalizeDegrees( 90.0 - scaleMap().transform( value() ) ); - - d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle ); - d_data->arcOffset = scaleMap().p1(); - - return true; - } - - return false; -} - -/*! - \brief Determine the value for a new position of the - slider handle. - - \param pos Mouse position - - \return Value for the mouse position - \sa isScrollPosition() -*/ -double QwtDial::scrolledTo( const QPoint &pos ) const -{ - double angle = QLineF( rect().center(), pos ).angle(); - if ( d_data->mode == QwtDial::RotateScale ) - { - angle += scaleMap().p1() - d_data->arcOffset; - angle = 360.0 - angle; - } - - angle = qwtNormalizeDegrees( angle - d_data->mouseOffset ); - angle = qwtNormalizeDegrees( 90.0 - angle ); - - if ( scaleMap().pDist() >= 360.0 ) - { - if ( angle < scaleMap().p1() ) - angle += 360.0; - - if ( !wrapping() ) - { - double boundedAngle = angle; - - const double arc = angle - scaleMap().transform( value() ); - if ( qAbs( arc ) > 180.0 ) - { - boundedAngle = ( arc > 0 ) - ? scaleMap().p1() : scaleMap().p2(); - } - - d_data->mouseOffset += ( boundedAngle - angle ); - - angle = boundedAngle; - } - } - else - { - const double boundedAngle = - qwtBoundedAngle( scaleMap().p1(), angle, scaleMap().p2() ); - - if ( !wrapping() ) - d_data->mouseOffset += ( boundedAngle - angle ); - - angle = boundedAngle; - } - - return scaleMap().invTransform( angle ); -} - -/*! - Change Event handler - \param event Change event - - Invalidates internal paint caches if necessary -*/ -void QwtDial::changeEvent( QEvent *event ) -{ - switch( event->type() ) - { - case QEvent::EnabledChange: - case QEvent::FontChange: - case QEvent::StyleChange: - case QEvent::PaletteChange: - case QEvent::LanguageChange: - case QEvent::LocaleChange: - { - invalidateCache(); - break; - } - default: - break; - } - - QwtAbstractSlider::changeEvent( event ); -} - -/*! - Wheel Event handler - \param event Wheel event -*/ -void QwtDial::wheelEvent( QWheelEvent *event ) -{ - const QRegion region( innerRect(), QRegion::Ellipse ); - if ( region.contains( event->pos() ) ) - QwtAbstractSlider::wheelEvent( event ); -} - -void QwtDial::setAngleRange( double angle, double span ) -{ - QwtRoundScaleDraw *sd = const_cast<QwtRoundScaleDraw *>( scaleDraw() ); - if ( sd ) - { - angle = qwtNormalizeDegrees( angle - 270.0 ); - sd->setAngleRange( angle, angle + span ); - } -} - -/*! - Invalidate the internal caches and call - QwtAbstractSlider::scaleChange() - */ -void QwtDial::scaleChange() -{ - invalidateCache(); - QwtAbstractSlider::scaleChange(); -} - -void QwtDial::sliderChange() -{ - setAngleRange( d_data->origin + d_data->minScaleArc, - d_data->maxScaleArc - d_data->minScaleArc ); - - if ( mode() == RotateScale ) - { - const double arc = scaleMap().transform( value() ) - scaleMap().p1(); - setAngleRange( d_data->origin - arc, - d_data->maxScaleArc - d_data->minScaleArc ); - } - - QwtAbstractSlider::sliderChange(); -} diff --git a/source/third_party/qwt/qwt_dial_needle.cpp b/source/third_party/qwt/qwt_dial_needle.cpp deleted file mode 100644 index e8e663d1f67b98962e65ff20a4278d7a417d3939..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_dial_needle.cpp +++ /dev/null @@ -1,440 +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/qwt_dial_needle.h" -#include "qwt/qwt_global.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include <qapplication.h> -#include <qpainter.h> - -#if QT_VERSION < 0x040601 -#define qFastSin(x) qSin(x) -#define qFastCos(x) qCos(x) -#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 * qFastCos( angle ); - const double y = radius * qFastSin( 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() ) -{ -} - -//! Destructor -QwtDialNeedle::~QwtDialNeedle() -{ -} - -/*! - Sets the palette for the needle. - - \param palette New Palette -*/ -void QwtDialNeedle::setPalette( const QPalette &palette ) -{ - d_palette = palette; -} - -/*! - \return the palette of the needle. -*/ -const QPalette &QwtDialNeedle::palette() const -{ - return d_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 QwtDialNeedle::draw( QPainter *painter, - const QPointF ¢er, double length, double direction, - QPalette::ColorGroup colorGroup ) const -{ - painter->save(); - - painter->translate( center ); - painter->rotate( -direction ); - - drawNeedle( painter, length, colorGroup ); - - painter->restore(); -} - -//! 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 ); - - if ( sunken ) - qSwap( c1, c2 ); - - QRectF rect( 0.0, 0.0, width, width ); - rect.moveCenter( painter->combinedTransform().map( QPointF() ) ); - - 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 ); - - painter->save(); - - painter->resetTransform(); - - painter->setPen( QPen( gradient, 1 ) ); - painter->setBrush( brush ); - painter->drawEllipse( rect ); - - painter->restore(); -} - -/*! - Constructor - - \param style Style - \param hasKnob With/Without knob - \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 ) -{ - QPalette palette; - palette.setColor( QPalette::Mid, mid ); - palette.setColor( QPalette::Base, base ); - - setPalette( palette ); -} - -/*! - Set the width of the needle - \param width Width - \sa width() -*/ -void QwtDialSimpleNeedle::setWidth( double width ) -{ - d_width = width; -} - -/*! - \return the width of the needle - \sa setWidth() -*/ -double QwtDialSimpleNeedle::width() const -{ - return d_width; -} - -/*! - Draw the needle - - \param painter Painter - \param length Length of the needle - \param colorGroup Color group, used for painting -*/ -void QwtDialSimpleNeedle::drawNeedle( QPainter *painter, - double length, QPalette::ColorGroup colorGroup ) const -{ - double knobWidth = 0.0; - double width = d_width; - - if ( d_style == Arrow ) - { - 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 - { - if ( width <= 0.0 ) - width = 5.0; - - QPen pen ( palette().brush( colorGroup, QPalette::Mid ), width ); - pen.setCapStyle( Qt::FlatCap ); - - painter->setPen( pen ); - painter->drawLine( QPointF( 0.0, 0.0 ), QPointF( length, 0.0 ) ); - - knobWidth = qMax( width * 3.0, 5.0 ); - } - - if ( d_hasKnob && knobWidth > 0.0 ) - { - drawKnob( painter, knobWidth, - palette().brush( colorGroup, QPalette::Base ), false ); - } -} - -//! Constructor -QwtCompassMagnetNeedle::QwtCompassMagnetNeedle( Style style, - const QColor &light, const QColor &dark ): - d_style( style ) -{ - QPalette palette; - palette.setColor( QPalette::Light, light ); - palette.setColor( QPalette::Dark, dark ); - palette.setColor( QPalette::Base, Qt::gray ); - - setPalette( palette ); -} - -/*! - Draw the needle - - \param painter Painter - \param length Length of the needle - \param colorGroup Color group, used for painting -*/ -void QwtCompassMagnetNeedle::drawNeedle( QPainter *painter, - double length, QPalette::ColorGroup colorGroup ) const -{ - if ( d_style == ThinStyle ) - { - 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 - { - qwtDrawTriangleNeedle( painter, palette(), colorGroup, length ); - } -} - -/*! - 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 ) -{ - QPalette palette; - palette.setColor( QPalette::Light, light ); - palette.setColor( QPalette::Dark, dark ); - - setPalette( palette ); -} - -/*! - Draw the needle - - \param painter Painter - \param length Length of the needle - \param colorGroup Color group, used for painting -*/ -void QwtCompassWindArrow::drawNeedle( QPainter *painter, - double length, QPalette::ColorGroup colorGroup ) const -{ - if ( d_style == Style1 ) - qwtDrawStyle1Needle( painter, palette(), colorGroup, length ); - else - qwtDrawStyle2Needle( painter, palette(), colorGroup, length ); -} diff --git a/source/third_party/qwt/qwt_dyngrid_layout.cpp b/source/third_party/qwt/qwt_dyngrid_layout.cpp deleted file mode 100644 index 438ceaec2ce395f1c5fdf9076e3c057419d2750c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_dyngrid_layout.cpp +++ /dev/null @@ -1,591 +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/qwt_dyngrid_layout.h" -#include "qwt/qwt_math.h" -#include <qvector.h> -#include <qlist.h> - -class QwtDynGridLayout::PrivateData -{ -public: - PrivateData(): - isDirty( true ) - { - } - - void updateLayoutCache(); - - mutable QList<QLayoutItem*> itemList; - - uint maxColumns; - uint numRows; - uint numColumns; - - Qt::Orientations expanding; - - bool isDirty; - QVector<QSize> itemSizeHints; -}; - -void QwtDynGridLayout::PrivateData::updateLayoutCache() -{ - itemSizeHints.resize( itemList.count() ); - - int index = 0; - - for ( QList<QLayoutItem*>::iterator it = itemList.begin(); - it != itemList.end(); ++it, index++ ) - { - itemSizeHints[ index ] = ( *it )->sizeHint(); - } - - isDirty = false; -} - -/*! - \param parent Parent widget - \param margin Margin - \param spacing Spacing -*/ - -QwtDynGridLayout::QwtDynGridLayout( QWidget *parent, - int margin, int spacing ): - QLayout( parent ) -{ - init(); - - setSpacing( spacing ); - setMargin( margin ); -} - -/*! - \param spacing Spacing -*/ - -QwtDynGridLayout::QwtDynGridLayout( int spacing ) -{ - init(); - setSpacing( spacing ); -} - -/*! - Initialize the layout with default values. -*/ -void QwtDynGridLayout::init() -{ - d_data = new QwtDynGridLayout::PrivateData; - d_data->maxColumns = d_data->numRows = d_data->numColumns = 0; - d_data->expanding = 0; -} - -//! Destructor - -QwtDynGridLayout::~QwtDynGridLayout() -{ - for ( int i = 0; i < d_data->itemList.size(); i++ ) - delete d_data->itemList[i]; - - delete d_data; -} - -//! Invalidate all internal caches -void QwtDynGridLayout::invalidate() -{ - d_data->isDirty = true; - QLayout::invalidate(); -} - -/*! - Limit the number of columns. - \param maxColumns upper limit, 0 means unlimited - \sa maxColumns() -*/ -void QwtDynGridLayout::setMaxColumns( uint maxColumns ) -{ - d_data->maxColumns = maxColumns; -} - -/*! - \brief Return the upper limit for the number of columns. - - 0 means unlimited, what is the default. - - \return Upper limit for the number of columns - \sa setMaxColumns() -*/ -uint QwtDynGridLayout::maxColumns() const -{ - return d_data->maxColumns; -} - -/*! - \brief Add an item to the next free position. - \param item Layout item - */ -void QwtDynGridLayout::addItem( QLayoutItem *item ) -{ - d_data->itemList.append( item ); - invalidate(); -} - -/*! - \return true if this layout is empty. -*/ -bool QwtDynGridLayout::isEmpty() const -{ - return d_data->itemList.isEmpty(); -} - -/*! - \return number of layout items -*/ -uint QwtDynGridLayout::itemCount() const -{ - return d_data->itemList.count(); -} - -/*! - Find the item at a specific index - - \param index Index - \return Item at a specific index - \sa takeAt() -*/ -QLayoutItem *QwtDynGridLayout::itemAt( int index ) const -{ - if ( index < 0 || index >= d_data->itemList.count() ) - return NULL; - - return d_data->itemList.at( index ); -} - -/*! - Find the item at a specific index and remove it from the layout - - \param index Index - \return Layout item, removed from the layout - \sa itemAt() -*/ -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 Number of items in the layout -int QwtDynGridLayout::count() const -{ - return d_data->itemList.count(); -} - -/*! - 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 - to grow in both dimensions. The default value is 0. - - \param expanding Or'd orientations - \sa expandingDirections() -*/ -void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding ) -{ - d_data->expanding = expanding; -} - -/*! - \brief 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 - to grow in both dimensions. - - \return Orientations, where the layout expands - \sa setExpandingDirections() -*/ -Qt::Orientations QwtDynGridLayout::expandingDirections() const -{ - return d_data->expanding; -} - -/*! - Reorganizes columns and rows and resizes managed items within - a rectangle. - - \param rect Layout geometry -*/ -void QwtDynGridLayout::setGeometry( const QRect &rect ) -{ - QLayout::setGeometry( rect ); - - if ( isEmpty() ) - return; - - d_data->numColumns = columnsForWidth( rect.width() ); - d_data->numRows = itemCount() / d_data->numColumns; - if ( itemCount() % d_data->numColumns ) - d_data->numRows++; - - QList<QRect> itemGeometries = layoutItems( rect, d_data->numColumns ); - - int index = 0; - for ( QList<QLayoutItem*>::iterator it = d_data->itemList.begin(); - it != d_data->itemList.end(); ++it ) - { - ( *it )->setGeometry( itemGeometries[index] ); - index++; - } -} - -/*! - \brief Calculate the number of columns for a given width. - - The calculation tries to use as many columns as possible - ( limited by maxColumns() ) - - \param width Available width for all columns - \return Number of columns for a given width - - \sa maxColumns(), setMaxColumns() -*/ -uint QwtDynGridLayout::columnsForWidth( int width ) const -{ - if ( isEmpty() ) - return 0; - - uint maxColumns = itemCount(); - if ( d_data->maxColumns > 0 ) - maxColumns = qMin( d_data->maxColumns, maxColumns ); - - if ( maxRowWidth( maxColumns ) <= width ) - return maxColumns; - - for ( uint numColumns = 2; numColumns <= maxColumns; numColumns++ ) - { - const int rowWidth = maxRowWidth( numColumns ); - if ( rowWidth > width ) - return numColumns - 1; - } - - return 1; // At least 1 column -} - -/*! - Calculate the width of a layout for a given number of - columns. - - \param numColumns Given number of columns - \param itemWidth Array of the width hints for all items -*/ -int QwtDynGridLayout::maxRowWidth( int numColumns ) const -{ - int col; - - QVector<int> colWidth( numColumns ); - for ( col = 0; col < numColumns; col++ ) - colWidth[col] = 0; - - if ( d_data->isDirty ) - d_data->updateLayoutCache(); - - for ( int index = 0; - index < d_data->itemSizeHints.count(); index++ ) - { - col = index % numColumns; - colWidth[col] = qMax( colWidth[col], - d_data->itemSizeHints[int( index )].width() ); - } - - int rowWidth = 2 * margin() + ( numColumns - 1 ) * spacing(); - for ( col = 0; col < numColumns; col++ ) - rowWidth += colWidth[col]; - - return rowWidth; -} - -/*! - \return the maximum width of all layout items -*/ -int QwtDynGridLayout::maxItemWidth() const -{ - if ( isEmpty() ) - return 0; - - if ( d_data->isDirty ) - d_data->updateLayoutCache(); - - int w = 0; - for ( int i = 0; i < d_data->itemSizeHints.count(); i++ ) - { - const int itemW = d_data->itemSizeHints[i].width(); - if ( itemW > w ) - w = itemW; - } - - return w; -} - -/*! - Calculate the geometries of the layout items for a layout - with numColumns columns and a given rectangle. - - \param rect Rect where to place the items - \param numColumns Number of columns - \return item geometries -*/ - -QList<QRect> QwtDynGridLayout::layoutItems( const QRect &rect, - uint numColumns ) const -{ - QList<QRect> itemGeometries; - if ( numColumns == 0 || isEmpty() ) - return itemGeometries; - - uint numRows = itemCount() / numColumns; - if ( numColumns % itemCount() ) - numRows++; - - if ( numRows == 0 ) - return itemGeometries; - - QVector<int> rowHeight( numRows ); - QVector<int> colWidth( numColumns ); - - layoutGrid( numColumns, rowHeight, colWidth ); - - bool expandH, expandV; - expandH = expandingDirections() & Qt::Horizontal; - expandV = expandingDirections() & Qt::Vertical; - - if ( expandH || expandV ) - stretchGrid( rect, numColumns, rowHeight, colWidth ); - - const int maxColumns = d_data->maxColumns; - d_data->maxColumns = numColumns; - const QRect alignedRect = alignmentRect( rect ); - d_data->maxColumns = maxColumns; - - const int xOffset = expandH ? 0 : alignedRect.x(); - const int yOffset = expandV ? 0 : alignedRect.y(); - - QVector<int> colX( numColumns ); - QVector<int> rowY( numRows ); - - const int xySpace = spacing(); - - rowY[0] = yOffset + margin(); - for ( uint r = 1; r < numRows; r++ ) - rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace; - - colX[0] = xOffset + margin(); - for ( uint c = 1; c < numColumns; 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 / numColumns; - const int col = i % numColumns; - - QRect itemGeometry( colX[col], rowY[row], - colWidth[col], rowHeight[row] ); - itemGeometries.append( itemGeometry ); - } - - return itemGeometries; -} - - -/*! - Calculate the dimensions for the columns and rows for a grid - of numColumns columns. - - \param numColumns Number of columns. - \param rowHeight Array where to fill in the calculated row heights. - \param colWidth Array where to fill in the calculated column widths. -*/ - -void QwtDynGridLayout::layoutGrid( uint numColumns, - QVector<int>& rowHeight, QVector<int>& colWidth ) const -{ - if ( numColumns <= 0 ) - return; - - if ( d_data->isDirty ) - d_data->updateLayoutCache(); - - for ( int index = 0; index < d_data->itemSizeHints.count(); index++ ) - { - const int row = index / numColumns; - const int col = index % numColumns; - - const QSize &size = d_data->itemSizeHints[int( index )]; - - rowHeight[row] = ( col == 0 ) - ? size.height() : qMax( rowHeight[row], size.height() ); - colWidth[col] = ( row == 0 ) - ? size.width() : qMax( colWidth[col], size.width() ); - } -} - -/*! - \return true: QwtDynGridLayout implements heightForWidth(). - \sa heightForWidth() -*/ -bool QwtDynGridLayout::hasHeightForWidth() const -{ - return true; -} - -/*! - \return The preferred height for this layout, given a width. - \sa hasHeightForWidth() -*/ -int QwtDynGridLayout::heightForWidth( int width ) const -{ - if ( isEmpty() ) - return 0; - - const uint numColumns = columnsForWidth( width ); - uint numRows = itemCount() / numColumns; - if ( itemCount() % numColumns ) - numRows++; - - QVector<int> rowHeight( numRows ); - QVector<int> colWidth( numColumns ); - - layoutGrid( numColumns, rowHeight, colWidth ); - - int h = 2 * margin() + ( numRows - 1 ) * spacing(); - for ( uint row = 0; row < numRows; row++ ) - h += rowHeight[row]; - - return h; -} - -/*! - Stretch columns in case of expanding() & QSizePolicy::Horizontal and - rows in case of expanding() & QSizePolicy::Vertical to fill the entire - rect. Rows and columns are stretched with the same factor. - - \param rect Bounding rectangle - \param numColumns Number of columns - \param rowHeight Array to be filled with the calculated row heights - \param colWidth Array to be filled with the calculated column widths - - \sa setExpanding(), expanding() -*/ -void QwtDynGridLayout::stretchGrid( const QRect &rect, - uint numColumns, QVector<int>& rowHeight, QVector<int>& colWidth ) const -{ - if ( numColumns == 0 || isEmpty() ) - return; - - bool expandH, expandV; - expandH = expandingDirections() & Qt::Horizontal; - expandV = expandingDirections() & Qt::Vertical; - - if ( expandH ) - { - int xDelta = rect.width() - 2 * margin() - ( numColumns - 1 ) * spacing(); - for ( uint col = 0; col < numColumns; col++ ) - xDelta -= colWidth[col]; - - if ( xDelta > 0 ) - { - for ( uint col = 0; col < numColumns; col++ ) - { - const int space = xDelta / ( numColumns - col ); - colWidth[col] += space; - xDelta -= space; - } - } - } - - if ( expandV ) - { - uint numRows = itemCount() / numColumns; - if ( itemCount() % numColumns ) - numRows++; - - int yDelta = rect.height() - 2 * margin() - ( numRows - 1 ) * spacing(); - for ( uint row = 0; row < numRows; row++ ) - yDelta -= rowHeight[row]; - - if ( yDelta > 0 ) - { - for ( uint row = 0; row < numRows; row++ ) - { - const int space = yDelta / ( numRows - row ); - rowHeight[row] += space; - yDelta -= space; - } - } - } -} - -/*! - Return the size hint. If maxColumns() > 0 it is the size for - a grid with maxColumns() columns, otherwise it is the size for - a grid with only one row. - - \return Size hint - \sa maxColumns(), setMaxColumns() -*/ -QSize QwtDynGridLayout::sizeHint() const -{ - if ( isEmpty() ) - return QSize(); - - uint numColumns = itemCount(); - if ( d_data->maxColumns > 0 ) - numColumns = qMin( d_data->maxColumns, numColumns ); - - uint numRows = itemCount() / numColumns; - if ( itemCount() % numColumns ) - numRows++; - - QVector<int> rowHeight( numRows ); - QVector<int> colWidth( numColumns ); - - layoutGrid( numColumns, rowHeight, colWidth ); - - int h = 2 * margin() + ( numRows - 1 ) * spacing(); - for ( uint row = 0; row < numRows; row++ ) - h += rowHeight[row]; - - int w = 2 * margin() + ( numColumns - 1 ) * spacing(); - for ( uint col = 0; col < numColumns; col++ ) - w += colWidth[col]; - - return QSize( w, h ); -} - -/*! - \return Number of rows of the current layout. - \sa numColumns() - \warning The number of rows might change whenever the geometry changes -*/ -uint QwtDynGridLayout::numRows() const -{ - return d_data->numRows; -} - -/*! - \return Number of columns of the current layout. - \sa numRows() - \warning The number of columns might change whenever the geometry changes -*/ -uint QwtDynGridLayout::numColumns() const -{ - return d_data->numColumns; -} diff --git a/source/third_party/qwt/qwt_event_pattern.cpp b/source/third_party/qwt/qwt_event_pattern.cpp deleted file mode 100644 index d805cb2e483f901318f32456d8b631812a68836c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_event_pattern.cpp +++ /dev/null @@ -1,265 +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/qwt_event_pattern.h" -#include <qevent.h> - -/*! - Constructor - - \sa MousePatternCode, KeyPatternCode -*/ - -QwtEventPattern::QwtEventPattern(): - d_mousePattern( MousePatternCount ), - d_keyPattern( KeyPatternCount ) -{ - initKeyPattern(); - initMousePattern( 3 ); -} - -//! Destructor -QwtEventPattern::~QwtEventPattern() -{ -} - -/*! - Set default mouse patterns, depending on the number of mouse buttons - - \param numButtons Number of mouse buttons ( <= 3 ) - \sa MousePatternCode -*/ -void QwtEventPattern::initMousePattern( int numButtons ) -{ - d_mousePattern.resize( MousePatternCount ); - - switch ( numButtons ) - { - case 1: - { - setMousePattern( MouseSelect1, Qt::LeftButton ); - setMousePattern( MouseSelect2, Qt::LeftButton, Qt::ControlModifier ); - setMousePattern( MouseSelect3, Qt::LeftButton, Qt::AltModifier ); - break; - } - case 2: - { - setMousePattern( MouseSelect1, Qt::LeftButton ); - setMousePattern( MouseSelect2, Qt::RightButton ); - setMousePattern( MouseSelect3, Qt::LeftButton, Qt::AltModifier ); - break; - } - default: - { - setMousePattern( MouseSelect1, Qt::LeftButton ); - setMousePattern( MouseSelect2, Qt::RightButton ); - setMousePattern( MouseSelect3, Qt::MidButton ); - } - } - - setMousePattern( MouseSelect4, d_mousePattern[MouseSelect1].button, - d_mousePattern[MouseSelect1].modifiers | Qt::ShiftModifier ); - - setMousePattern( MouseSelect5, d_mousePattern[MouseSelect2].button, - d_mousePattern[MouseSelect2].modifiers | Qt::ShiftModifier ); - - setMousePattern( MouseSelect6, d_mousePattern[MouseSelect3].button, - d_mousePattern[MouseSelect3].modifiers | Qt::ShiftModifier ); -} - -/*! - Set default mouse patterns. - - \sa KeyPatternCode -*/ -void QwtEventPattern::initKeyPattern() -{ - d_keyPattern.resize( KeyPatternCount ); - - 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( KeyRedo, Qt::Key_Plus ); - setKeyPattern( KeyUndo, Qt::Key_Minus ); - setKeyPattern( KeyHome, Qt::Key_Escape ); -} - -/*! - Change one mouse pattern - - \param pattern Index of the pattern - \param button Button - \param modifiers Keyboard modifiers - - \sa QMouseEvent -*/ -void QwtEventPattern::setMousePattern( MousePatternCode pattern, - Qt::MouseButton button, Qt::KeyboardModifiers modifiers ) -{ - if ( pattern >= 0 && pattern < MousePatternCount ) - { - d_mousePattern[ pattern ].button = button; - d_mousePattern[ pattern ].modifiers = modifiers; - } -} - -/*! - Change one key pattern - - \param pattern Index of the pattern - \param key Key - \param modifiers Keyboard modifiers - - \sa QKeyEvent -*/ -void QwtEventPattern::setKeyPattern( KeyPatternCode pattern, - int key, Qt::KeyboardModifiers modifiers ) -{ - if ( pattern >= 0 && pattern < KeyPatternCount ) - { - d_keyPattern[ pattern ].key = key; - d_keyPattern[ pattern ].modifiers = modifiers; - } -} - -//! Change the mouse event patterns -void QwtEventPattern::setMousePattern( const QVector<MousePattern> &pattern ) -{ - d_mousePattern = pattern; -} - -//! Change the key event patterns -void QwtEventPattern::setKeyPattern( const QVector<KeyPattern> &pattern ) -{ - d_keyPattern = pattern; -} - -//! \return Mouse pattern -const QVector<QwtEventPattern::MousePattern> & -QwtEventPattern::mousePattern() const -{ - return d_mousePattern; -} - -//! \return Key pattern -const QVector<QwtEventPattern::KeyPattern> & -QwtEventPattern::keyPattern() const -{ - return d_keyPattern; -} - -//! \return Mouse pattern -QVector<QwtEventPattern::MousePattern> &QwtEventPattern::mousePattern() -{ - return d_mousePattern; -} - -//! \return Key pattern -QVector<QwtEventPattern::KeyPattern> &QwtEventPattern::keyPattern() -{ - return d_keyPattern; -} - -/*! - \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 code Index of the event pattern - \param event Mouse event - \return true if matches - - \sa keyMatch() -*/ -bool QwtEventPattern::mouseMatch( MousePatternCode code, - const QMouseEvent *event ) const -{ - if ( code >= 0 && code < MousePatternCount ) - return mouseMatch( d_mousePattern[ code ], event ); - - return false; -} - -/*! - \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 event Mouse event - \return true if matches - - \sa keyMatch() -*/ - -bool QwtEventPattern::mouseMatch( const MousePattern &pattern, - const QMouseEvent *event ) const -{ - if ( event == NULL ) - return false; - - const MousePattern mousePattern( event->button(), event->modifiers() ); - return mousePattern == 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 code Index of the event pattern - \param event Key event - \return true if matches - - \sa mouseMatch() -*/ -bool QwtEventPattern::keyMatch( KeyPatternCode code, - const QKeyEvent *event ) const -{ - if ( code >= 0 && code < KeyPatternCount ) - return keyMatch( d_keyPattern[ code ], event ); - - return false; -} - -/*! - \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 event Key event - \return true if matches - - \sa mouseMatch() -*/ - -bool QwtEventPattern::keyMatch( - const KeyPattern &pattern, const QKeyEvent *event ) const -{ - if ( event == NULL ) - return false; - - const KeyPattern keyPattern( event->key(), event->modifiers() ); - return keyPattern == pattern; -} diff --git a/source/third_party/qwt/qwt_graphic.cpp b/source/third_party/qwt/qwt_graphic.cpp deleted file mode 100644 index 9e04311889ef178b9e5da25bed4f12dd5f33ef14..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_graphic.cpp +++ /dev/null @@ -1,1009 +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/qwt_graphic.h" -#include "qwt/qwt_painter_command.h" -#include <qvector.h> -#include <qpainter.h> -#include <qpaintengine.h> -#include <qimage.h> -#include <qpixmap.h> -#include <qpainterpath.h> -#include <qmath.h> - -static bool qwtHasScalablePen( const QPainter *painter ) -{ - const QPen pen = painter->pen(); - - bool scalablePen = false; - - if ( pen.style() != Qt::NoPen && pen.brush().style() != Qt::NoBrush ) - { - scalablePen = !pen.isCosmetic(); - if ( !scalablePen && pen.widthF() == 0.0 ) - { - const QPainter::RenderHints hints = painter->renderHints(); - if ( hints.testFlag( QPainter::NonCosmeticDefaultPen ) ) - scalablePen = true; - } - } - - return scalablePen; -} - -static QRectF qwtStrokedPathRect( - const QPainter *painter, const QPainterPath &path ) -{ - QPainterPathStroker stroker; - stroker.setWidth( painter->pen().widthF() ); - stroker.setCapStyle( painter->pen().capStyle() ); - stroker.setJoinStyle( painter->pen().joinStyle() ); - stroker.setMiterLimit( painter->pen().miterLimit() ); - - QRectF rect; - if ( qwtHasScalablePen( painter ) ) - { - QPainterPath stroke = stroker.createStroke(path); - rect = painter->transform().map(stroke).boundingRect(); - } - else - { - QPainterPath mappedPath = painter->transform().map(path); - mappedPath = stroker.createStroke( mappedPath ); - - rect = mappedPath.boundingRect(); - } - - return rect; -} - -static inline void qwtExecCommand( - QPainter *painter, const QwtPainterCommand &cmd, - QwtGraphic::RenderHints renderHints, - const QTransform &transform, - const QTransform *initialTransform ) -{ - switch( cmd.type() ) - { - case QwtPainterCommand::Path: - { - bool doMap = false; - - if ( renderHints.testFlag( QwtGraphic::RenderPensUnscaled ) - && painter->transform().isScaling() ) - { - bool isCosmetic = painter->pen().isCosmetic(); - if ( isCosmetic && painter->pen().widthF() == 0.0 ) - { - QPainter::RenderHints hints = painter->renderHints(); - if ( hints.testFlag( QPainter::NonCosmeticDefaultPen ) ) - isCosmetic = false; - } - - doMap = !isCosmetic; - } - - if ( doMap ) - { - const QTransform tr = painter->transform(); - - painter->resetTransform(); - - QPainterPath path = tr.map( *cmd.path() ); - if ( initialTransform ) - { - painter->setTransform( *initialTransform ); - path = initialTransform->inverted().map( path ); - } - - painter->drawPath( path ); - - painter->setTransform( tr ); - } - else - { - painter->drawPath( *cmd.path() ); - } - break; - } - case QwtPainterCommand::Pixmap: - { - const QwtPainterCommand::PixmapData *data = cmd.pixmapData(); - painter->drawPixmap( data->rect, data->pixmap, data->subRect ); - break; - } - case QwtPainterCommand::Image: - { - const QwtPainterCommand::ImageData *data = cmd.imageData(); - painter->drawImage( data->rect, data->image, - data->subRect, data->flags ); - break; - } - case QwtPainterCommand::State: - { - const QwtPainterCommand::StateData *data = cmd.stateData(); - - if ( data->flags & QPaintEngine::DirtyPen ) - painter->setPen( data->pen ); - - if ( data->flags & QPaintEngine::DirtyBrush ) - painter->setBrush( data->brush ); - - if ( data->flags & QPaintEngine::DirtyBrushOrigin ) - painter->setBrushOrigin( data->brushOrigin ); - - if ( data->flags & QPaintEngine::DirtyFont ) - painter->setFont( data->font ); - - if ( data->flags & QPaintEngine::DirtyBackground ) - { - painter->setBackgroundMode( data->backgroundMode ); - painter->setBackground( data->backgroundBrush ); - } - - if ( data->flags & QPaintEngine::DirtyTransform ) - { - painter->setTransform( data->transform * transform ); - } - - if ( data->flags & QPaintEngine::DirtyClipEnabled ) - painter->setClipping( data->isClipEnabled ); - - if ( data->flags & QPaintEngine::DirtyClipRegion) - { - painter->setClipRegion( data->clipRegion, - data->clipOperation ); - } - - if ( data->flags & QPaintEngine::DirtyClipPath ) - { - painter->setClipPath( data->clipPath, data->clipOperation ); - } - - if ( data->flags & QPaintEngine::DirtyHints) - { - const QPainter::RenderHints hints = data->renderHints; - - painter->setRenderHint( QPainter::Antialiasing, - hints.testFlag( QPainter::Antialiasing ) ); - - painter->setRenderHint( QPainter::TextAntialiasing, - hints.testFlag( QPainter::TextAntialiasing ) ); - - painter->setRenderHint( QPainter::SmoothPixmapTransform, - hints.testFlag( QPainter::SmoothPixmapTransform ) ); - - painter->setRenderHint( QPainter::HighQualityAntialiasing, - hints.testFlag( QPainter::HighQualityAntialiasing ) ); - - painter->setRenderHint( QPainter::NonCosmeticDefaultPen, - hints.testFlag( QPainter::NonCosmeticDefaultPen ) ); - } - - if ( data->flags & QPaintEngine::DirtyCompositionMode) - painter->setCompositionMode( data->compositionMode ); - - if ( data->flags & QPaintEngine::DirtyOpacity) - painter->setOpacity( data->opacity ); - - break; - } - default: - break; - } - -} - -class QwtGraphic::PathInfo -{ -public: - PathInfo(): - d_scalablePen( false ) - { - // QVector needs a default constructor - } - - PathInfo( const QRectF &pointRect, - const QRectF &boundingRect, bool scalablePen ): - d_pointRect( pointRect ), - d_boundingRect( boundingRect ), - d_scalablePen( scalablePen ) - { - } - - inline QRectF scaledBoundingRect( double sx, double sy, - bool scalePens ) const - { - if ( sx == 1.0 && sy == 1.0 ) - return d_boundingRect; - - QTransform transform; - transform.scale( sx, sy ); - - QRectF rect; - if ( scalePens && d_scalablePen ) - { - rect = transform.mapRect( d_boundingRect ); - } - else - { - rect = transform.mapRect( d_pointRect ); - - const double l = qAbs( d_pointRect.left() - d_boundingRect.left() ); - const double r = qAbs( d_pointRect.right() - d_boundingRect.right() ); - const double t = qAbs( d_pointRect.top() - d_boundingRect.top() ); - const double b = qAbs( d_pointRect.bottom() - d_boundingRect.bottom() ); - - rect.adjust( -l, -t, r, b ); - } - - return rect; - } - - inline double scaleFactorX( const QRectF& pathRect, - const QRectF &targetRect, bool scalePens ) const - { - if ( pathRect.width() <= 0.0 ) - return 0.0; - - const QPointF p0 = d_pointRect.center(); - - const double l = qAbs( pathRect.left() - p0.x() ); - const double r = qAbs( pathRect.right() - p0.x() ); - - const double w = 2.0 * qMin( l, r ) - * targetRect.width() / pathRect.width(); - - double sx; - if ( scalePens && d_scalablePen ) - { - sx = w / d_boundingRect.width(); - } - else - { - const double pw = qMax( - qAbs( d_boundingRect.left() - d_pointRect.left() ), - qAbs( d_boundingRect.right() - d_pointRect.right() ) ); - - sx = ( w - 2 * pw ) / d_pointRect.width(); - } - - return sx; - } - - inline double scaleFactorY( const QRectF& pathRect, - const QRectF &targetRect, bool scalePens ) const - { - if ( pathRect.height() <= 0.0 ) - return 0.0; - - const QPointF p0 = d_pointRect.center(); - - const double t = qAbs( pathRect.top() - p0.y() ); - const double b = qAbs( pathRect.bottom() - p0.y() ); - - const double h = 2.0 * qMin( t, b ) - * targetRect.height() / pathRect.height(); - - double sy; - if ( scalePens && d_scalablePen ) - { - sy = h / d_boundingRect.height(); - } - else - { - const double pw = - qMax( qAbs( d_boundingRect.top() - d_pointRect.top() ), - qAbs( d_boundingRect.bottom() - d_pointRect.bottom() ) ); - - sy = ( h - 2 * pw ) / d_pointRect.height(); - } - - return sy; - } - -private: - QRectF d_pointRect; - QRectF d_boundingRect; - bool d_scalablePen; -}; - -class QwtGraphic::PrivateData -{ -public: - PrivateData(): - boundingRect( 0.0, 0.0, -1.0, -1.0 ), - pointRect( 0.0, 0.0, -1.0, -1.0 ), - initialTransform( NULL ) - { - } - - QSizeF defaultSize; - QVector<QwtPainterCommand> commands; - QVector<QwtGraphic::PathInfo> pathInfos; - - QRectF boundingRect; - QRectF pointRect; - - QwtGraphic::RenderHints renderHints; - QTransform *initialTransform; -}; - -/*! - \brief Constructor - - Initializes a null graphic - \sa isNull() - */ -QwtGraphic::QwtGraphic(): - QwtNullPaintDevice() -{ - setMode( QwtNullPaintDevice::PathMode ); - d_data = new PrivateData; -} - -/*! - \brief Copy constructor - - \param other Source - \sa operator=() - */ -QwtGraphic::QwtGraphic( const QwtGraphic &other ): - QwtNullPaintDevice() -{ - setMode( other.mode() ); - d_data = new PrivateData( *other.d_data ); -} - -//! Destructor -QwtGraphic::~QwtGraphic() -{ - delete d_data; -} - -/*! - \brief Assignment operator - - \param other Source - \return A reference of this object - */ -QwtGraphic& QwtGraphic::operator=(const QwtGraphic &other) -{ - setMode( other.mode() ); - *d_data = *other.d_data; - - return *this; -} - -/*! - \brief Clear all stored commands - \sa isNull() - */ -void QwtGraphic::reset() -{ - d_data->commands.clear(); - d_data->pathInfos.clear(); - - d_data->boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); - d_data->pointRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); - d_data->defaultSize = QSizeF(); - -} - -/*! - \return True, when no painter commands have been stored - \sa isEmpty(), commands() -*/ -bool QwtGraphic::isNull() const -{ - return d_data->commands.isEmpty(); -} - -/*! - \return True, when the bounding rectangle is empty - \sa boundingRect(), isNull() -*/ -bool QwtGraphic::isEmpty() const -{ - return d_data->boundingRect.isEmpty(); -} - -/*! - Toggle an render hint - - \param hint Render hint - \param on true/false - - \sa testRenderHint(), RenderHint -*/ -void QwtGraphic::setRenderHint( RenderHint hint, bool on ) -{ - if ( on ) - d_data->renderHints |= hint; - else - d_data->renderHints &= ~hint; -} - -/*! - Test a render hint - - \param hint Render hint - \return true/false - \sa setRenderHint(), RenderHint -*/ -bool QwtGraphic::testRenderHint( RenderHint hint ) const -{ - return d_data->renderHints.testFlag( hint ); -} - -/*! - The bounding rectangle is the controlPointRect() - extended by the areas needed for rendering the outlines - with unscaled pens. - - \return Bounding rectangle of the graphic - \sa controlPointRect(), scaledBoundingRect() - */ -QRectF QwtGraphic::boundingRect() const -{ - if ( d_data->boundingRect.width() < 0 ) - return QRectF(); - - return d_data->boundingRect; -} - -/*! - The control point rectangle is the bounding rectangle - of all control points of the paths and the target - rectangles of the images/pixmaps. - - \return Control point rectangle - \sa boundingRect(), scaledBoundingRect() - */ -QRectF QwtGraphic::controlPointRect() const -{ - if ( d_data->pointRect.width() < 0 ) - return QRectF(); - - return d_data->pointRect; -} - -/*! - \brief Calculate the target rectangle for scaling the graphic - - \param sx Horizontal scaling factor - \param sy Vertical scaling factor - - \note In case of paths that are painted with a cosmetic pen - ( see QPen::isCosmetic() ) the target rectangle is different to - multiplying the bounding rectangle. - - \return Scaled bounding rectangle - \sa boundingRect(), controlPointRect() - */ -QRectF QwtGraphic::scaledBoundingRect( double sx, double sy ) const -{ - if ( sx == 1.0 && sy == 1.0 ) - return d_data->boundingRect; - - QTransform transform; - transform.scale( sx, sy ); - - QRectF rect = transform.mapRect( d_data->pointRect ); - - for ( int i = 0; i < d_data->pathInfos.size(); i++ ) - { - rect |= d_data->pathInfos[i].scaledBoundingRect( sx, sy, - !d_data->renderHints.testFlag( RenderPensUnscaled ) ); - } - - return rect; -} - -//! \return Ceiled defaultSize() -QSize QwtGraphic::sizeMetrics() const -{ - const QSizeF sz = defaultSize(); - return QSize( qCeil( sz.width() ), qCeil( sz.height() ) ); -} - -/*! - \brief Set a default size - - The default size is used in all methods rendering the graphic, - where no size is explicitly specified. Assigning an empty size - means, that the default size will be calculated from the bounding - rectangle. - - The default setting is an empty size. - - \param size Default size - - \sa defaultSize(), boundingRect() - */ -void QwtGraphic::setDefaultSize( const QSizeF &size ) -{ - const double w = qMax( qreal( 0.0 ), size.width() ); - const double h = qMax( qreal( 0.0 ), size.height() ); - - d_data->defaultSize = QSizeF( w, h ); -} - -/*! - \brief Default size - - When a non empty size has been assigned by setDefaultSize() this - size will be returned. Otherwise the default size is the size - of the bounding rectangle. - - The default size is used in all methods rendering the graphic, - where no size is explicitly specified. - - \return Default size - \sa setDefaultSize(), boundingRect() - */ -QSizeF QwtGraphic::defaultSize() const -{ - if ( !d_data->defaultSize.isEmpty() ) - return d_data->defaultSize; - - return boundingRect().size(); -} - -/*! - \brief Replay all recorded painter commands - \param painter Qt painter - */ -void QwtGraphic::render( QPainter *painter ) const -{ - if ( isNull() ) - return; - - const int numCommands = d_data->commands.size(); - const QwtPainterCommand *commands = d_data->commands.constData(); - - const QTransform transform = painter->transform(); - - painter->save(); - - for ( int i = 0; i < numCommands; i++ ) - { - qwtExecCommand( painter, commands[i], - d_data->renderHints, transform, d_data->initialTransform ); - } - - painter->restore(); -} - -/*! - \brief Replay all recorded painter commands - - The graphic is scaled to fit into the rectangle - of the given size starting at ( 0, 0 ). - - \param painter Qt painter - \param size Size for the scaled graphic - \param aspectRatioMode Mode how to scale - See Qt::AspectRatioMode - */ -void QwtGraphic::render( QPainter *painter, const QSizeF &size, - Qt::AspectRatioMode aspectRatioMode ) const -{ - const QRectF r( 0.0, 0.0, size.width(), size.height() ); - render( painter, r, aspectRatioMode ); -} - -/*! - \brief Replay all recorded painter commands - - The graphic is scaled to fit into the given rectangle - - \param painter Qt painter - \param rect Rectangle for the scaled graphic - \param aspectRatioMode Mode how to scale - See Qt::AspectRatioMode - */ -void QwtGraphic::render( QPainter *painter, const QRectF &rect, - Qt::AspectRatioMode aspectRatioMode ) const -{ - if ( isEmpty() || rect.isEmpty() ) - return; - - double sx = 1.0; - double sy = 1.0; - - if ( d_data->pointRect.width() > 0.0 ) - sx = rect.width() / d_data->pointRect.width(); - - if ( d_data->pointRect.height() > 0.0 ) - sy = rect.height() / d_data->pointRect.height(); - - const bool scalePens = - !d_data->renderHints.testFlag( RenderPensUnscaled ); - - for ( int i = 0; i < d_data->pathInfos.size(); i++ ) - { - const PathInfo info = d_data->pathInfos[i]; - - const double ssx = info.scaleFactorX( - d_data->pointRect, rect, scalePens ); - - if ( ssx > 0.0 ) - sx = qMin( sx, ssx ); - - const double ssy = info.scaleFactorY( - d_data->pointRect, rect, scalePens ); - - if ( ssy > 0.0 ) - sy = qMin( sy, ssy ); - } - - if ( aspectRatioMode == Qt::KeepAspectRatio ) - { - const double s = qMin( sx, sy ); - sx = s; - sy = s; - } - else if ( aspectRatioMode == Qt::KeepAspectRatioByExpanding ) - { - const double s = qMax( sx, sy ); - sx = s; - sy = s; - } - - QTransform tr; - tr.translate( rect.center().x() - 0.5 * sx * d_data->pointRect.width(), - rect.center().y() - 0.5 * sy * d_data->pointRect.height() ); - tr.scale( sx, sy ); - tr.translate( -d_data->pointRect.x(), -d_data->pointRect.y() ); - - const QTransform transform = painter->transform(); - if ( !scalePens && transform.isScaling() ) - { - // we don't want to scale pens according to sx/sy, - // but we want to apply the scaling from the - // painter transformation later - - d_data->initialTransform = new QTransform(); - d_data->initialTransform->scale( transform.m11(), transform.m22() ); - } - - painter->setTransform( tr, true ); - render( painter ); - - painter->setTransform( transform ); - - delete d_data->initialTransform; - d_data->initialTransform = NULL; -} - -/*! - \brief Replay all recorded painter commands - - The graphic is scaled to the defaultSize() and aligned - to a position. - - \param painter Qt painter - \param pos Reference point, where to render - \param alignment Flags how to align the target rectangle - to pos. - */ -void QwtGraphic::render( QPainter *painter, - const QPointF &pos, Qt::Alignment alignment ) const -{ - QRectF r( pos, defaultSize() ); - - if ( alignment & Qt::AlignLeft ) - { - r.moveLeft( pos.x() ); - } - else if ( alignment & Qt::AlignHCenter ) - { - r.moveCenter( QPointF( pos.x(), r.center().y() ) ); - } - else if ( alignment & Qt::AlignRight ) - { - r.moveRight( pos.x() ); - } - - if ( alignment & Qt::AlignTop ) - { - r.moveTop( pos.y() ); - } - else if ( alignment & Qt::AlignVCenter ) - { - r.moveCenter( QPointF( r.center().x(), pos.y() ) ); - } - else if ( alignment & Qt::AlignBottom ) - { - r.moveBottom( pos.y() ); - } - - render( painter, r ); -} - -/*! - \brief Convert the graphic to a QPixmap - - All pixels of the pixmap get initialized by Qt::transparent - before the graphic is scaled and rendered on it. - - The size of the pixmap is the default size ( ceiled to integers ) - of the graphic. - - \return The graphic as pixmap in default size - \sa defaultSize(), toImage(), render() - */ -QPixmap QwtGraphic::toPixmap() const -{ - if ( isNull() ) - return QPixmap(); - - const QSizeF sz = defaultSize(); - - const int w = qCeil( sz.width() ); - const int h = qCeil( sz.height() ); - - QPixmap pixmap( w, h ); - pixmap.fill( Qt::transparent ); - - const QRectF r( 0.0, 0.0, sz.width(), sz.height() ); - - QPainter painter( &pixmap ); - render( &painter, r, Qt::KeepAspectRatio ); - painter.end(); - - return pixmap; -} - -/*! - \brief Convert the graphic to a QPixmap - - All pixels of the pixmap get initialized by Qt::transparent - before the graphic is scaled and rendered on it. - - \param size Size of the image - \param aspectRatioMode Aspect ratio how to scale the graphic - - \return The graphic as pixmap - \sa toImage(), render() - */ -QPixmap QwtGraphic::toPixmap( const QSize &size, - Qt::AspectRatioMode aspectRatioMode ) const -{ - QPixmap pixmap( size ); - pixmap.fill( Qt::transparent ); - - const QRect r( 0, 0, size.width(), size.height() ); - - QPainter painter( &pixmap ); - render( &painter, r, aspectRatioMode ); - painter.end(); - - return pixmap; -} - -/*! - \brief Convert the graphic to a QImage - - All pixels of the image get initialized by 0 ( transparent ) - before the graphic is scaled and rendered on it. - - The format of the image is QImage::Format_ARGB32_Premultiplied. - - \param size Size of the image - \param aspectRatioMode Aspect ratio how to scale the graphic - - \return The graphic as image - \sa toPixmap(), render() - */ -QImage QwtGraphic::toImage( const QSize &size, - Qt::AspectRatioMode aspectRatioMode ) const -{ - QImage image( size, QImage::Format_ARGB32_Premultiplied ); - image.fill( 0 ); - - const QRect r( 0, 0, size.width(), size.height() ); - - QPainter painter( &image ); - render( &painter, r, aspectRatioMode ); - painter.end(); - - return image; -} - -/*! - \brief Convert the graphic to a QImage - - All pixels of the image get initialized by 0 ( transparent ) - before the graphic is scaled and rendered on it. - - The format of the image is QImage::Format_ARGB32_Premultiplied. - - The size of the image is the default size ( ceiled to integers ) - of the graphic. - - \return The graphic as image in default size - \sa defaultSize(), toPixmap(), render() - */ -QImage QwtGraphic::toImage() const -{ - if ( isNull() ) - return QImage(); - - const QSizeF sz = defaultSize(); - - const int w = qCeil( sz.width() ); - const int h = qCeil( sz.height() ); - - QImage image( w, h, QImage::Format_ARGB32 ); - image.fill( 0 ); - - const QRect r( 0, 0, sz.width(), sz.height() ); - - QPainter painter( &image ); - render( &painter, r, Qt::KeepAspectRatio ); - painter.end(); - - return image; -} - -/*! - Store a path command in the command list - - \param path Painter path - \sa QPaintEngine::drawPath() -*/ -void QwtGraphic::drawPath( const QPainterPath &path ) -{ - const QPainter *painter = paintEngine()->painter(); - if ( painter == NULL ) - return; - - d_data->commands += QwtPainterCommand( path ); - - if ( !path.isEmpty() ) - { - const QPainterPath scaledPath = painter->transform().map( path ); - - QRectF pointRect = scaledPath.boundingRect(); - QRectF boundingRect = pointRect; - - if ( painter->pen().style() != Qt::NoPen - && painter->pen().brush().style() != Qt::NoBrush ) - { - boundingRect = qwtStrokedPathRect( painter, path ); - } - - updateControlPointRect( pointRect ); - updateBoundingRect( boundingRect ); - - d_data->pathInfos += PathInfo( pointRect, - boundingRect, qwtHasScalablePen( painter ) ); - } -} - -/*! - \brief Store a pixmap command in the command list - - \param rect target rectangle - \param pixmap Pixmap to be painted - \param subRect Reactangle of the pixmap to be painted - - \sa QPaintEngine::drawPixmap() -*/ -void QwtGraphic::drawPixmap( const QRectF &rect, - const QPixmap &pixmap, const QRectF &subRect ) -{ - const QPainter *painter = paintEngine()->painter(); - if ( painter == NULL ) - return; - - d_data->commands += QwtPainterCommand( rect, pixmap, subRect ); - - const QRectF r = painter->transform().mapRect( rect ); - updateControlPointRect( r ); - updateBoundingRect( r ); -} - -/*! - \brief Store a image command in the command list - - \param rect traget rectangle - \param image Image to be painted - \param subRect Reactangle of the pixmap to be painted - \param flags Image conversion flags - - \sa QPaintEngine::drawImage() - */ -void QwtGraphic::drawImage( const QRectF &rect, const QImage &image, - const QRectF &subRect, Qt::ImageConversionFlags flags) -{ - const QPainter *painter = paintEngine()->painter(); - if ( painter == NULL ) - return; - - d_data->commands += QwtPainterCommand( rect, image, subRect, flags ); - - const QRectF r = painter->transform().mapRect( rect ); - - updateControlPointRect( r ); - updateBoundingRect( r ); -} - -/*! - \brief Store a state command in the command list - - \param state State to be stored - \sa QPaintEngine::updateState() - */ -void QwtGraphic::updateState( const QPaintEngineState &state) -{ - d_data->commands += QwtPainterCommand( state ); -} - -void QwtGraphic::updateBoundingRect( const QRectF &rect ) -{ - QRectF br = rect; - - const QPainter *painter = paintEngine()->painter(); - if ( painter && painter->hasClipping() ) - { - QRectF cr = painter->clipRegion().boundingRect(); - cr = painter->transform().mapRect( cr ); - - br &= cr; - } - - if ( d_data->boundingRect.width() < 0 ) - d_data->boundingRect = br; - else - d_data->boundingRect |= br; -} - -void QwtGraphic::updateControlPointRect( const QRectF &rect ) -{ - if ( d_data->pointRect.width() < 0.0 ) - d_data->pointRect = rect; - else - d_data->pointRect |= rect; -} - -/*! - \return List of recorded paint commands - \sa setCommands() - */ -const QVector< QwtPainterCommand > &QwtGraphic::commands() const -{ - return d_data->commands; -} - -/*! - \brief Append paint commands - - \param commands Paint commands - \sa commands() - */ -void QwtGraphic::setCommands( QVector< QwtPainterCommand > &commands ) -{ - reset(); - - const int numCommands = commands.size(); - if ( numCommands <= 0 ) - return; - - // to calculate a proper bounding rectangle we don't simply copy - // the commands. - - const QwtPainterCommand *cmds = commands.constData(); - - QPainter painter( this ); - for ( int i = 0; i < numCommands; i++ ) - qwtExecCommand( &painter, cmds[i], RenderHints(), QTransform(), NULL ); - - painter.end(); -} diff --git a/source/third_party/qwt/qwt_interval.cpp b/source/third_party/qwt/qwt_interval.cpp deleted file mode 100644 index 5652c4db1bd44d8f853d113f1c01249af9164df5..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_interval.cpp +++ /dev/null @@ -1,354 +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/qwt_interval.h" -#include "qwt/qwt_math.h" -#include <qalgorithms.h> - -/*! - \brief Normalize the limits of the interval - - If maxValue() < minValue() the limits will be inverted. - \return Normalized interval - - \sa isValid(), inverted() -*/ -QwtInterval QwtInterval::normalized() const -{ - if ( d_minValue > d_maxValue ) - { - return inverted(); - } - if ( d_minValue == d_maxValue && d_borderFlags == ExcludeMinimum ) - { - return inverted(); - } - - return *this; -} - -/*! - Invert the limits of the interval - \return Inverted interval - \sa normalized() -*/ -QwtInterval QwtInterval::inverted() const -{ - BorderFlags borderFlags = IncludeBorders; - if ( d_borderFlags & ExcludeMinimum ) - borderFlags |= ExcludeMaximum; - if ( d_borderFlags & ExcludeMaximum ) - borderFlags |= ExcludeMinimum; - - return QwtInterval( d_maxValue, d_minValue, borderFlags ); -} - -/*! - Test if a value is inside an interval - - \param value Value - \return true, if value >= minValue() && value <= maxValue() -*/ -bool QwtInterval::contains( double value ) const -{ - if ( !isValid() ) - return false; - - if ( value < d_minValue || value > d_maxValue ) - return false; - - if ( value == d_minValue && d_borderFlags & ExcludeMinimum ) - return false; - - if ( value == d_maxValue && d_borderFlags & ExcludeMaximum ) - return false; - - return true; -} - -//! Unite 2 intervals -QwtInterval QwtInterval::unite( const QwtInterval &other ) const -{ - /* - If one of the intervals is invalid return the other one. - If both are invalid return an invalid default interval - */ - if ( !isValid() ) - { - if ( !other.isValid() ) - return QwtInterval(); - else - return other; - } - if ( !other.isValid() ) - return *this; - - QwtInterval united; - BorderFlags flags = IncludeBorders; - - // minimum - if ( d_minValue < other.minValue() ) - { - united.setMinValue( d_minValue ); - flags &= d_borderFlags & ExcludeMinimum; - } - else if ( other.minValue() < d_minValue ) - { - united.setMinValue( other.minValue() ); - flags &= other.borderFlags() & ExcludeMinimum; - } - else // d_minValue == other.minValue() - { - united.setMinValue( d_minValue ); - flags &= ( d_borderFlags & other.borderFlags() ) & ExcludeMinimum; - } - - // maximum - if ( d_maxValue > other.maxValue() ) - { - united.setMaxValue( d_maxValue ); - flags &= d_borderFlags & ExcludeMaximum; - } - else if ( other.maxValue() > d_maxValue ) - { - united.setMaxValue( other.maxValue() ); - flags &= other.borderFlags() & ExcludeMaximum; - } - else // d_maxValue == other.maxValue() ) - { - united.setMaxValue( d_maxValue ); - flags &= d_borderFlags & other.borderFlags() & ExcludeMaximum; - } - - united.setBorderFlags( flags ); - return united; -} - -/*! - \brief Intersect 2 intervals - - \param other Interval to be intersect with - \return Intersection - */ -QwtInterval QwtInterval::intersect( const QwtInterval &other ) const -{ - if ( !other.isValid() || !isValid() ) - return QwtInterval(); - - 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() ) - { - qSwap( i1, i2 ); - } - else if ( i1.minValue() == i2.minValue() ) - { - if ( i1.borderFlags() & ExcludeMinimum ) - qSwap( i1, i2 ); - } - - if ( i1.maxValue() < i2.minValue() ) - { - return QwtInterval(); - } - - if ( i1.maxValue() == i2.minValue() ) - { - if ( i1.borderFlags() & ExcludeMaximum || - i2.borderFlags() & ExcludeMinimum ) - { - return QwtInterval(); - } - } - - QwtInterval intersected; - BorderFlags flags = IncludeBorders; - - intersected.setMinValue( i2.minValue() ); - flags |= i2.borderFlags() & ExcludeMinimum; - - if ( i1.maxValue() < i2.maxValue() ) - { - intersected.setMaxValue( i1.maxValue() ); - flags |= i1.borderFlags() & ExcludeMaximum; - } - else if ( i2.maxValue() < i1.maxValue() ) - { - intersected.setMaxValue( i2.maxValue() ); - flags |= i2.borderFlags() & ExcludeMaximum; - } - else // i1.maxValue() == i2.maxValue() - { - intersected.setMaxValue( i1.maxValue() ); - flags |= i1.borderFlags() & i2.borderFlags() & ExcludeMaximum; - } - - intersected.setBorderFlags( flags ); - return intersected; -} - -/*! - \brief Unite this interval with the given interval. - - \param other Interval to be united with - \return This interval - */ -QwtInterval& QwtInterval::operator|=( const QwtInterval &other ) -{ - *this = *this | other; - return *this; -} - -/*! - \brief Intersect this interval with the given interval. - - \param other Interval to be intersected with - \return This interval - */ -QwtInterval& QwtInterval::operator&=( const QwtInterval &other ) -{ - *this = *this & other; - return *this; -} - -/*! - \brief Test if two intervals overlap - - \param other Interval - \return True, when the intervals are intersecting -*/ -bool QwtInterval::intersects( const QwtInterval &other ) const -{ - if ( !isValid() || !other.isValid() ) - return false; - - 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() ) - { - qSwap( i1, i2 ); - } - else if ( i1.minValue() == i2.minValue() && - i1.borderFlags() & ExcludeMinimum ) - { - qSwap( i1, i2 ); - } - - if ( i1.maxValue() > i2.minValue() ) - { - return true; - } - if ( i1.maxValue() == i2.minValue() ) - { - return !( ( i1.borderFlags() & ExcludeMaximum ) || - ( i2.borderFlags() & ExcludeMinimum ) ); - } - return false; -} - -/*! - Adjust the limit that is closer to value, so that value becomes - the center of the interval. - - \param value Center - \return Interval with value as center -*/ -QwtInterval QwtInterval::symmetrize( double value ) const -{ - if ( !isValid() ) - return *this; - - const double delta = - qMax( qAbs( value - d_maxValue ), qAbs( value - d_minValue ) ); - - return QwtInterval( value - delta, value + delta ); -} - -/*! - Limit the interval, keeping the border modes - - \param lowerBound Lower limit - \param upperBound Upper limit - - \return Limited interval -*/ -QwtInterval QwtInterval::limited( double lowerBound, double upperBound ) const -{ - if ( !isValid() || lowerBound > upperBound ) - return QwtInterval(); - - double minValue = qMax( d_minValue, lowerBound ); - minValue = qMin( minValue, upperBound ); - - double maxValue = qMax( d_maxValue, lowerBound ); - maxValue = qMin( maxValue, upperBound ); - - return QwtInterval( minValue, maxValue, d_borderFlags ); -} - -/*! - \brief Extend the interval - - If value is below minValue(), value becomes the lower limit. - If value is above maxValue(), value becomes the upper limit. - - extend() has no effect for invalid intervals - - \param value Value - \return extended interval - - \sa isValid() -*/ -QwtInterval QwtInterval::extend( double value ) const -{ - if ( !isValid() ) - return *this; - - return QwtInterval( qMin( value, d_minValue ), - qMax( value, d_maxValue ), d_borderFlags ); -} - -/*! - 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/source/third_party/qwt/qwt_interval_symbol.cpp b/source/third_party/qwt/qwt_interval_symbol.cpp deleted file mode 100644 index 8c7d43349d66b1c15aa8a60d97cfe3277aae3bc2..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_interval_symbol.cpp +++ /dev/null @@ -1,319 +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/qwt_interval_symbol.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_math.h" -#include <qpainter.h> - -#if QT_VERSION < 0x040601 -#define qAtan2(y, x) ::atan2(y, x) -#define qFastSin(x) qSin(x) -#define qFastCos(x) qCos(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; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtIntervalSymbol::setPen( const QColor &color, - qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - 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 = qFastCos( angle ) * dw2; - const double sy = qFastSin( 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 double cx = qFastCos( angle ) * dw2; - const double sy = qFastSin( 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/source/third_party/qwt/qwt_knob.cpp b/source/third_party/qwt/qwt_knob.cpp deleted file mode 100644 index ded9e2890ed0fd1efbd3867ad05be5db2133c49d..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_knob.cpp +++ /dev/null @@ -1,855 +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/qwt_knob.h" -#include "qwt/qwt_round_scale_draw.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include <qpainter.h> -#include <qpalette.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qevent.h> -#include <qmath.h> -#include <qapplication.h> - -#if QT_VERSION < 0x040601 -#define qAtan2(y, x) ::atan2(y, x) -#define qFabs(x) ::fabs(x) -#define qFastCos(x) qCos(x) -#define qFastSin(x) qSin(x) -#endif - -static QSize qwtKnobSizeHint( const QwtKnob *knob, int min ) -{ - int knobWidth = knob->knobWidth(); - if ( knobWidth <= 0 ) - knobWidth = qMax( 3 * knob->markerSize(), min ); - - // Add the scale radial thickness to the knobWidth - const int extent = qCeil( knob->scaleDraw()->extent( knob->font() ) ); - const int d = 2 * ( extent + 4 ) + knobWidth; - - int left, right, top, bottom; - knob->getContentsMargins( &left, &top, &right, &bottom ); - - return QSize( d + left + right, d + top + bottom ); -} - -static inline double qwtToScaleAngle( double angle ) -{ - // the map is counter clockwise with the origin - // at 90° using angles from -180° -> 180° - - double a = 90.0 - angle; - if ( a <= -180.0 ) - a += 360.0; - else if ( a >= 180.0 ) - a -= 360.0; - - return a; -} - -static double qwtToDegrees( double value ) -{ - return qwtNormalizeDegrees( 90.0 - value ); -} - -class QwtKnob::PrivateData -{ -public: - PrivateData(): - knobStyle( QwtKnob::Raised ), - markerStyle( QwtKnob::Notch ), - borderWidth( 2 ), - borderDist( 4 ), - scaleDist( 4 ), - maxScaleTicks( 11 ), - knobWidth( 0 ), - alignment( Qt::AlignCenter ), - markerSize( 8 ), - totalAngle( 270.0 ), - mouseOffset( 0.0 ) - { - } - - QwtKnob::KnobStyle knobStyle; - QwtKnob::MarkerStyle markerStyle; - - int borderWidth; - int borderDist; - int scaleDist; - int maxScaleTicks; - int knobWidth; - Qt::Alignment alignment; - int markerSize; - - double totalAngle; - - double mouseOffset; -}; - -/*! - \brief Constructor - - Construct a knob with an angle of 270°. The style is - QwtKnob::Raised and the marker style is QwtKnob::Notch. - The width of the knob is set to 50 pixels. - - \param parent Parent widget - - \sa setTotalAngle() -*/ -QwtKnob::QwtKnob( QWidget* parent ): - QwtAbstractSlider( parent ) -{ - d_data = new PrivateData; - - setScaleDraw( new QwtRoundScaleDraw() ); - - setTotalAngle( 270.0 ); - - setScale( 0.0, 10.0 ); - setValue( 0.0 ); - - setSizePolicy( QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding ); -} - -//! Destructor -QwtKnob::~QwtKnob() -{ - delete d_data; -} - -/*! - \brief Set the knob type - - \param knobStyle Knob type - \sa knobStyle(), setBorderWidth() -*/ -void QwtKnob::setKnobStyle( KnobStyle knobStyle ) -{ - if ( d_data->knobStyle != knobStyle ) - { - d_data->knobStyle = knobStyle; - update(); - } -} - -/*! - \return Marker type of the knob - \sa setKnobStyle(), setBorderWidth() -*/ -QwtKnob::KnobStyle QwtKnob::knobStyle() const -{ - 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; -} - -/*! - \brief Set the total angle by which the knob can be turned - \param angle Angle in degrees. - - The angle has to be between [10, 360] degrees. Angles above - 360 ( so that the knob can be turned several times around its axis ) - have to be set using setNumTurns(). - - The default angle is 270 degrees. - - \sa totalAngle(), setNumTurns() -*/ -void QwtKnob::setTotalAngle ( double angle ) -{ - angle = qBound( 10.0, angle, 360.0 ); - - if ( angle != d_data->totalAngle ) - { - d_data->totalAngle = angle; - - scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle, - 0.5 * d_data->totalAngle ); - - updateGeometry(); - update(); - } -} - -/*! - \return the total angle - \sa setTotalAngle(), setNumTurns(), numTurns() - */ -double QwtKnob::totalAngle() const -{ - return d_data->totalAngle; -} - -/*! - \brief Set the number of turns - - When numTurns > 1 the knob can be turned several times around its axis - - otherwise the total angle is floored to 360°. - - \sa numTurns(), totalAngle(), setTotalAngle() -*/ - -void QwtKnob::setNumTurns( int numTurns ) -{ - numTurns = qMax( numTurns, 1 ); - - if ( numTurns == 1 && d_data->totalAngle <= 360.0 ) - return; - - const double angle = numTurns * 360.0; - if ( angle != d_data->totalAngle ) - { - d_data->totalAngle = angle; - - scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle, - 0.5 * d_data->totalAngle ); - - updateGeometry(); - update(); - } -} - -/*! - \return Number of turns. - - When the total angle is below 360° numTurns() is ceiled to 1. - \sa setNumTurns(), setTotalAngle(), totalAngle() - */ -int QwtKnob::numTurns() const -{ - return qCeil( d_data->totalAngle / 360.0 ); -} - -/*! - Change the scale draw of the knob - - For changing the labels of the scales, it - is necessary to derive from QwtRoundScaleDraw and - overload QwtRoundScaleDraw::label(). - - \sa scaleDraw() -*/ -void QwtKnob::setScaleDraw( QwtRoundScaleDraw *scaleDraw ) -{ - setAbstractScaleDraw( scaleDraw ); - setTotalAngle( d_data->totalAngle ); - - updateGeometry(); - update(); -} - -/*! - \return the scale draw of the knob - \sa setScaleDraw() -*/ -const QwtRoundScaleDraw *QwtKnob::scaleDraw() const -{ - return static_cast<const QwtRoundScaleDraw *>( abstractScaleDraw() ); -} - -/*! - \return the scale draw of the knob - \sa setScaleDraw() -*/ -QwtRoundScaleDraw *QwtKnob::scaleDraw() -{ - return static_cast<QwtRoundScaleDraw *>( abstractScaleDraw() ); -} - -/*! - Calculate the bounding rectangle of the knob without the scale - - \return Bounding rectangle of the knob - \sa knobWidth(), alignment(), QWidget::contentsRect() - */ -QRect QwtKnob::knobRect() const -{ - const QRect cr = contentsRect(); - - const int extent = qCeil( scaleDraw()->extent( font() ) ); - const int d = extent + d_data->scaleDist; - - int w = d_data->knobWidth; - if ( w <= 0 ) - { - const int dim = qMin( cr.width(), cr.height() ); - - w = dim - 2 * ( d ); - w = qMax( 0, w ); - } - - QRect r( 0, 0, w, w ); - - if ( d_data->alignment & Qt::AlignLeft ) - { - r.moveLeft( cr.left() + d ); - } - else if ( d_data->alignment & Qt::AlignRight ) - { - r.moveRight( cr.right() - d ); - } - else - { - r.moveCenter( QPoint( cr.center().x(), r.center().y() ) ); - } - - if ( d_data->alignment & Qt::AlignTop ) - { - r.moveTop( cr.top() + d ); - } - else if ( d_data->alignment & Qt::AlignBottom ) - { - r.moveBottom( cr.bottom() - d ); - } - else - { - r.moveCenter( QPoint( r.center().x(), cr.center().y() ) ); - } - - return r; -} - -/*! - \brief Determine what to do when the user presses a mouse button. - - \param pos Mouse position - - \retval True, when pos is inside the circle of the knob. - \sa scrolledTo() -*/ -bool QwtKnob::isScrollPosition( const QPoint &pos ) const -{ - const QRect kr = knobRect(); - - const QRegion region( kr, QRegion::Ellipse ); - if ( region.contains( pos ) && ( pos != kr.center() ) ) - { - const double angle = QLineF( kr.center(), pos ).angle(); - const double valueAngle = qwtToDegrees( scaleMap().transform( value() ) ); - - d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle ); - - return true; - } - - return false; -} - -/*! - \brief Determine the value for a new position of the mouse - - \param pos Mouse position - - \return Value for the mouse position - \sa isScrollPosition() -*/ -double QwtKnob::scrolledTo( const QPoint &pos ) const -{ - double angle = QLineF( rect().center(), pos ).angle(); - angle = qwtNormalizeDegrees( angle - d_data->mouseOffset ); - - if ( scaleMap().pDist() > 360.0 ) - { - angle = qwtToDegrees( angle ); - - const double v = scaleMap().transform( value() ); - - int numTurns = qFloor( ( v - scaleMap().p1() ) / 360.0 ); - - double valueAngle = qwtNormalizeDegrees( v ); - if ( qAbs( valueAngle - angle ) > 180.0 ) - { - numTurns += ( angle > valueAngle ) ? -1 : 1; - } - - angle += scaleMap().p1() + numTurns * 360.0; - - if ( !wrapping() ) - { - const double boundedAngle = - qBound( scaleMap().p1(), angle, scaleMap().p2() ); - - d_data->mouseOffset += ( boundedAngle - angle ); - angle = boundedAngle; - } - } - else - { - angle = qwtToScaleAngle( angle ); - - double boundedAngle = qBound( scaleMap().p1(), angle, scaleMap().p2() ); - - if ( !wrapping() ) - { - const double currentAngle = scaleMap().transform( value() ); - - if ( ( currentAngle > 90.0 ) && ( boundedAngle < -90.0 ) ) - boundedAngle = scaleMap().p2(); - else if ( ( currentAngle < -90.0 ) && ( boundedAngle > 90.0 ) ) - boundedAngle = scaleMap().p1(); - - d_data->mouseOffset += ( boundedAngle - angle ); - } - - angle = boundedAngle; - } - - return scaleMap().invTransform( angle ); -} - -/*! - Handle QEvent::StyleChange and QEvent::FontChange; - \param event Change event -*/ -void QwtKnob::changeEvent( QEvent *event ) -{ - switch( event->type() ) - { - case QEvent::StyleChange: - case QEvent::FontChange: - { - updateGeometry(); - update(); - break; - } - default: - break; - } -} - -/*! - Repaint the knob - \param event Paint event -*/ -void QwtKnob::paintEvent( QPaintEvent *event ) -{ - const QRectF knobRect = this->knobRect(); - - 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 ( !knobRect.contains( event->region().boundingRect() ) ) - { - scaleDraw()->setRadius( 0.5 * knobRect.width() + d_data->scaleDist ); - scaleDraw()->moveCenter( knobRect.center() ); - - scaleDraw()->draw( &painter, palette() ); - } - - drawKnob( &painter, knobRect ); - - drawMarker( &painter, knobRect, - qwtNormalizeDegrees( scaleMap().transform( value() ) ) ); - - painter.setRenderHint( QPainter::Antialiasing, false ); - - if ( hasFocus() ) - drawFocusIndicator( &painter ); -} - -/*! - \brief Draw the knob - - \param painter painter - \param knobRect Bounding rectangle of the knob (without scale) -*/ -void QwtKnob::drawKnob( QPainter *painter, const QRectF &knobRect ) const -{ - 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 ) - { - 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 ); - } - - QBrush brush; - switch( d_data->knobStyle ) - { - case QwtKnob::Raised: - { - double off = 0.3 * knobRect.width(); - QRadialGradient gradient( knobRect.center(), - knobRect.width(), knobRect.topLeft() + QPointF( off, off ) ); - - gradient.setColorAt( 0.0, palette().color( QPalette::Midlight ) ); - gradient.setColorAt( 1.0, palette().color( QPalette::Button ) ); - - brush = QBrush( gradient ); - - break; - } - case QwtKnob::Styled: - { - QRadialGradient gradient(knobRect.center().x() - knobRect.width() / 3, - knobRect.center().y() - knobRect.height() / 2, - knobRect.width() * 1.3, - knobRect.center().x(), - knobRect.center().y() - knobRect.height() / 2); - - const QColor c = palette().color( QPalette::Button ); - gradient.setColorAt(0, c.lighter(110)); - gradient.setColorAt(qreal(0.5), c); - gradient.setColorAt(qreal(0.501), c.darker(102)); - gradient.setColorAt(1, c.darker(115)); - - 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; - } - case QwtKnob::Flat: - 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 painter Painter - \param rect Bounding rectangle of the knob without scale - \param angle Angle of the marker in degrees - ( clockwise, 0 at the 12 o'clock position ) -*/ -void QwtKnob::drawMarker( QPainter *painter, - const QRectF &rect, double angle ) const -{ - if ( d_data->markerStyle == NoMarker || !isValid() ) - return; - - const double radians = qwtRadians( angle ); - const double sinA = -qFastSin( radians ); - const double cosA = qFastCos( radians ); - - const double xm = rect.center().x(); - const double ym = rect.center().y(); - const double margin = 4.0; - - double radius = 0.5 * ( rect.width() - d_data->borderWidth ) - margin; - if ( radius < 1.0 ) - radius = 1.0; - - int markerSize = d_data->markerSize; - if ( markerSize <= 0 ) - markerSize = qRound( 0.4 * radius ); - - switch ( d_data->markerStyle ) - { - case Notch: - case Nub: - { - const double dotWidth = - qMin( double( 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: - { - const double dotWidth = - qMin( double( 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 ); - } - - break; - } - case Tick: - { - const double rb = qMax( radius - markerSize, 1.0 ); - const double re = radius; - - const QLineF 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 ); - - break; - } - case Triangle: - { - const double rb = qMax( radius - 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::ButtonText ) ); - painter->drawPolygon( polygon ); - - painter->resetTransform(); - - break; - } - default: - break; - } -} - -/*! - Draw the focus indicator - \param painter Painter -*/ -void QwtKnob::drawFocusIndicator( QPainter *painter ) const -{ - const QRect cr = contentsRect(); - - int w = d_data->knobWidth; - if ( w <= 0 ) - { - w = qMin( cr.width(), cr.height() ); - } - else - { - const int extent = qCeil( scaleDraw()->extent( font() ) ); - w += 2 * ( extent + d_data->scaleDist ); - } - - QRect focusRect( 0, 0, w, w ); - focusRect.moveCenter( cr.center() ); - - QwtPainter::drawFocusRect( painter, this, focusRect ); -} - -/*! - \brief Set the alignment of the knob - - Similar to a QLabel::alignment() the flags decide how - to align the knob inside of contentsRect(). - - The default setting is Qt::AlignCenter - - \param alignment Or'd alignment flags - - \sa alignment(), setKnobWidth(), knobRect() - */ -void QwtKnob::setAlignment( Qt::Alignment alignment ) -{ - if ( d_data->alignment != alignment ) - { - d_data->alignment = alignment; - update(); - } -} - -/*! - \return Alignment of the knob inside of contentsRect() - \sa setAlignment(), knobWidth(), knobRect() - */ -Qt::Alignment QwtKnob::alignment() const -{ - return d_data->alignment; -} - -/*! - \brief Change the knob's width. - - Setting a fixed value for the diameter of the knob - is helpful for aligning several knobs in a row. - - \param width New width - - \sa knobWidth(), setAlignment() - \note Modifies the sizePolicy() -*/ -void QwtKnob::setKnobWidth( int width ) -{ - width = qMax( width, 0 ); - - if ( width != d_data->knobWidth ) - { - QSizePolicy::Policy policy; - if ( width > 0 ) - policy = QSizePolicy::Minimum; - else - policy = QSizePolicy::MinimumExpanding; - - setSizePolicy( policy, policy ); - - d_data->knobWidth = width; - - updateGeometry(); - update(); - } -} - -//! Return the width of the knob -int QwtKnob::knobWidth() const -{ - return d_data->knobWidth; -} - -/*! - \brief Set the knob's border width - \param borderWidth new border width -*/ -void QwtKnob::setBorderWidth( int borderWidth ) -{ - d_data->borderWidth = qMax( borderWidth, 0 ); - - updateGeometry(); - update(); -} - -//! Return the border width -int QwtKnob::borderWidth() const -{ - return d_data->borderWidth; -} - -/*! - \brief Set the size of the marker - - When setting a size <= 0 the marker will - automatically scaled to 40% of the radius of the knob. - - \sa markerSize(), markerStyle() -*/ -void QwtKnob::setMarkerSize( int size ) -{ - if ( d_data->markerSize != size ) - { - d_data->markerSize = size; - update(); - } -} - -/*! - \return Marker size - \sa setMarkerSize() - */ -int QwtKnob::markerSize() const -{ - return d_data->markerSize; -} - -/*! - \return sizeHint() -*/ -QSize QwtKnob::sizeHint() const -{ - const QSize hint = qwtKnobSizeHint( this, 50 ); - return hint.expandedTo( QApplication::globalStrut() ); -} - -/*! - \return Minimum size hint - \sa sizeHint() -*/ -QSize QwtKnob::minimumSizeHint() const -{ - return qwtKnobSizeHint( this, 20 ); -} diff --git a/source/third_party/qwt/qwt_legend.cpp b/source/third_party/qwt/qwt_legend.cpp deleted file mode 100644 index df13195f0eff82b8b9b0c5f31b73588c4feef7c2..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_legend.cpp +++ /dev/null @@ -1,811 +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/qwt_legend.h" -#include "qwt/qwt_legend_label.h" -#include "qwt/qwt_dyngrid_layout.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_plot_item.h" -#include "qwt/qwt_painter.h" -#include <qapplication.h> -#include <qscrollbar.h> -#include <qscrollarea.h> -#include <qpainter.h> -#include <qstyle.h> -#include <qstyleoption.h> - -class QwtLegendMap -{ -public: - inline bool isEmpty() const { return d_entries.isEmpty(); } - - void insert( const QVariant &, const QList<QWidget *> & ); - void remove( const QVariant & ); - - void removeWidget( const QWidget * ); - - QList<QWidget *> legendWidgets( const QVariant & ) const; - QVariant itemInfo( const QWidget * ) const; - -private: - // we don't know anything about itemInfo and therefore don't have - // any key that can be used for a map or hashtab. - // But a simple linear list is o.k. here, as we will never have - // more than a few entries. - - class Entry - { - public: - QVariant itemInfo; - QList<QWidget *> widgets; - }; - - QList< Entry > d_entries; -}; - -void QwtLegendMap::insert( const QVariant &itemInfo, - const QList<QWidget *> &widgets ) -{ - for ( int i = 0; i < d_entries.size(); i++ ) - { - Entry &entry = d_entries[i]; - if ( entry.itemInfo == itemInfo ) - { - entry.widgets = widgets; - return; - } - } - - Entry newEntry; - newEntry.itemInfo = itemInfo; - newEntry.widgets = widgets; - - d_entries += newEntry; -} - -void QwtLegendMap::remove( const QVariant &itemInfo ) -{ - for ( int i = 0; i < d_entries.size(); i++ ) - { - Entry &entry = d_entries[i]; - if ( entry.itemInfo == itemInfo ) - { - d_entries.removeAt( i ); - return; - } - } -} - -void QwtLegendMap::removeWidget( const QWidget *widget ) -{ - QWidget *w = const_cast<QWidget *>( widget ); - - for ( int i = 0; i < d_entries.size(); i++ ) - d_entries[ i ].widgets.removeAll( w ); -} - -QVariant QwtLegendMap::itemInfo( const QWidget *widget ) const -{ - if ( widget != NULL ) - { - QWidget *w = const_cast<QWidget *>( widget ); - - for ( int i = 0; i < d_entries.size(); i++ ) - { - const Entry &entry = d_entries[i]; - if ( entry.widgets.indexOf( w ) >= 0 ) - return entry.itemInfo; - } - } - - return QVariant(); -} - -QList<QWidget *> QwtLegendMap::legendWidgets( const QVariant &itemInfo ) const -{ - if ( itemInfo.isValid() ) - { - for ( int i = 0; i < d_entries.size(); i++ ) - { - const Entry &entry = d_entries[i]; - if ( entry.itemInfo == itemInfo ) - return entry.widgets; - } - } - - return QList<QWidget *>(); -} - -class QwtLegend::PrivateData -{ -public: - PrivateData(): - itemMode( QwtLegendData::ReadOnly ), - view( NULL ) - { - } - - QwtLegendData::Mode itemMode; - QwtLegendMap itemMap; - - class LegendView; - LegendView *view; -}; - -class QwtLegend::PrivateData::LegendView: public QScrollArea -{ -public: - LegendView( QWidget *parent ): - QScrollArea( parent ) - { - 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 event( QEvent *event ) - { - if ( event->type() == QEvent::PolishRequest ) - { - setFocusPolicy( Qt::NoFocus ); - } - - if ( event->type() == QEvent::Resize ) - { - // adjust the size to en/disable the scrollbars - // before QScrollArea adjusts the viewport size - - const QRect cr = contentsRect(); - - int w = cr.width(); - int h = contentsWidget->heightForWidth( cr.width() ); - if ( h > w ) - { - w -= verticalScrollBar()->sizeHint().width(); - h = contentsWidget->heightForWidth( w ); - } - - contentsWidget->resize( w, h ); - } - - return QScrollArea::event( event ); - } - - virtual bool viewportEvent( QEvent *event ) - { - bool ok = QScrollArea::viewportEvent( event ); - - if ( event->type() == QEvent::Resize ) - { - layoutContents(); - } - return ok; - } - - 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(); - - int vw = cw; - int vh = ch; - - if ( w > vw ) - vh -= sbHeight; - - if ( h > vh ) - { - vw -= sbWidth; - if ( w > vw && vh == ch ) - vh -= sbHeight; - } - return QSize( vw, vh ); - } - - void layoutContents() - { - const QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>( - contentsWidget->layout() ); - if ( tl == NULL ) - return; - - const QSize visibleSize = viewport()->contentsRect().size(); - - const int minW = int( tl->maxItemWidth() ) + 2 * tl->margin(); - - int w = qMax( visibleSize.width(), minW ); - int h = qMax( tl->heightForWidth( w ), visibleSize.height() ); - - const int vpWidth = viewportSize( w, h ).width(); - if ( w > vpWidth ) - { - w = qMax( vpWidth, minW ); - h = qMax( tl->heightForWidth( w ), visibleSize.height() ); - } - - contentsWidget->resize( w, h ); - } - - QWidget *contentsWidget; -}; - -/*! - Constructor - \param parent Parent widget -*/ -QwtLegend::QwtLegend( QWidget *parent ): - QwtAbstractLegend( parent ) -{ - setFrameStyle( NoFrame ); - - d_data = new QwtLegend::PrivateData; - - d_data->view = new QwtLegend::PrivateData::LegendView( this ); - d_data->view->setObjectName( "QwtLegendView" ); - d_data->view->setFrameStyle( NoFrame ); - - QwtDynGridLayout *gridLayout = new QwtDynGridLayout( - d_data->view->contentsWidget ); - gridLayout->setAlignment( Qt::AlignHCenter | Qt::AlignTop ); - - d_data->view->contentsWidget->installEventFilter( this ); - - QVBoxLayout *layout = new QVBoxLayout( this ); - layout->setContentsMargins( 0, 0, 0, 0 ); - layout->addWidget( d_data->view ); -} - -//! Destructor -QwtLegend::~QwtLegend() -{ - delete d_data; -} - -/*! - \brief Set the maximum number of entries in a row - - F.e when the maximum is set to 1 all items are aligned - vertically. 0 means unlimited - - \param numColums Maximum number of entries in a row - - \sa maxColumns(), QwtDynGridLayout::setMaxColumns() - */ -void QwtLegend::setMaxColumns( uint numColums ) -{ - QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>( - d_data->view->contentsWidget->layout() ); - if ( tl ) - tl->setMaxColumns( numColums ); -} - -/*! - \return Maximum number of entries in a row - \sa setMaxColumns(), QwtDynGridLayout::maxColumns() - */ -uint QwtLegend::maxColumns() const -{ - uint maxCols = 0; - - const QwtDynGridLayout *tl = qobject_cast<const QwtDynGridLayout *>( - d_data->view->contentsWidget->layout() ); - if ( tl ) - maxCols = tl->maxColumns(); - - return maxCols; -} - -/*! - \brief Set the default mode for legend labels - - Legend labels will be constructed according to the - attributes in a QwtLegendData object. When it doesn't - contain a value for the QwtLegendData::ModeRole the - label will be initialized with the default mode of the legend. - - \param mode Default item mode - - \sa itemMode(), QwtLegendData::value(), QwtPlotItem::legendData() - \note Changing the mode doesn't have any effect on existing labels. - */ -void QwtLegend::setDefaultItemMode( QwtLegendData::Mode mode ) -{ - d_data->itemMode = mode; -} - -/*! - \return Default item mode - \sa setDefaultItemMode() -*/ -QwtLegendData::Mode QwtLegend::defaultItemMode() const -{ - return d_data->itemMode; -} - -/*! - 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 -*/ -QWidget *QwtLegend::contentsWidget() -{ - return d_data->view->contentsWidget; -} - -/*! - \return Horizontal scrollbar - \sa verticalScrollBar() -*/ -QScrollBar *QwtLegend::horizontalScrollBar() const -{ - return d_data->view->horizontalScrollBar(); -} - -/*! - \return Vertical scrollbar - \sa horizontalScrollBar() -*/ -QScrollBar *QwtLegend::verticalScrollBar() const -{ - return d_data->view->verticalScrollBar(); -} - -/*! - 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; -} - -/*! - \brief Update the entries for an item - - \param itemInfo Info for an item - \param data List of legend entry attributes for the item - */ -void QwtLegend::updateLegend( const QVariant &itemInfo, - const QList<QwtLegendData> &data ) -{ - QList<QWidget *> widgetList = legendWidgets( itemInfo ); - - if ( widgetList.size() != data.size() ) - { - QLayout *contentsLayout = d_data->view->contentsWidget->layout(); - - while ( widgetList.size() > data.size() ) - { - QWidget *w = widgetList.takeLast(); - - contentsLayout->removeWidget( w ); - - // updates might be triggered by signals from the legend widget - // itself. So we better don't delete it here. - - w->hide(); - w->deleteLater(); - } - - for ( int i = widgetList.size(); i < data.size(); i++ ) - { - QWidget *widget = createWidget( data[i] ); - - if ( contentsLayout ) - contentsLayout->addWidget( widget ); - - if ( isVisible() ) - { - // QLayout does a delayed show, with the effect, that - // the size hint will be wrong, when applications - // call replot() right after changing the list - // of plot items. So we better do the show now. - - widget->setVisible( true ); - } - - widgetList += widget; - } - - if ( widgetList.isEmpty() ) - { - d_data->itemMap.remove( itemInfo ); - } - else - { - d_data->itemMap.insert( itemInfo, widgetList ); - } - - updateTabOrder(); - } - - for ( int i = 0; i < data.size(); i++ ) - updateWidget( widgetList[i], data[i] ); -} - -/*! - \brief Create a widget to be inserted into the legend - - The default implementation returns a QwtLegendLabel. - - \param data Attributes of the legend entry - \return Widget representing data on the legend - - \note updateWidget() will called soon after createWidget() - with the same attributes. - */ -QWidget *QwtLegend::createWidget( const QwtLegendData &data ) const -{ - Q_UNUSED( data ); - - QwtLegendLabel *label = new QwtLegendLabel(); - label->setItemMode( defaultItemMode() ); - - connect( label, SIGNAL( clicked() ), SLOT( itemClicked() ) ); - connect( label, SIGNAL( checked( bool ) ), SLOT( itemChecked( bool ) ) ); - - return label; -} - -/*! - \brief Update the widget - - \param widget Usually a QwtLegendLabel - \param data Attributes to be displayed - - \sa createWidget() - \note When widget is no QwtLegendLabel updateWidget() does nothing. - */ -void QwtLegend::updateWidget( QWidget *widget, const QwtLegendData &data ) -{ - QwtLegendLabel *label = qobject_cast<QwtLegendLabel *>( widget ); - if ( label ) - { - label->setData( data ); - if ( !data.value( QwtLegendData::ModeRole ).isValid() ) - { - // use the default mode, when there is no specific - // hint from the legend data - - label->setItemMode( defaultItemMode() ); - } - } -} - -void QwtLegend::updateTabOrder() -{ - QLayout *contentsLayout = d_data->view->contentsWidget->layout(); - if ( contentsLayout ) - { - // set tab focus chain - - QWidget *w = NULL; - - for ( int i = 0; i < contentsLayout->count(); i++ ) - { - QLayoutItem *item = contentsLayout->itemAt( i ); - if ( w && item->widget() ) - QWidget::setTabOrder( w, item->widget() ); - - w = item->widget(); - } - } -} - -//! Return a size hint. -QSize QwtLegend::sizeHint() const -{ - QSize hint = d_data->view->contentsWidget->sizeHint(); - hint += QSize( 2 * frameWidth(), 2 * frameWidth() ); - - return hint; -} - -/*! - \return The preferred height, for a width. - \param width Width -*/ -int QwtLegend::heightForWidth( int width ) const -{ - width -= 2 * frameWidth(); - - int h = d_data->view->contentsWidget->heightForWidth( width ); - if ( h >= 0 ) - h += 2 * frameWidth(); - - return h; -} - - -/*! - Handle QEvent::ChildRemoved andQEvent::LayoutRequest events - for the contentsWidget(). - - \param object Object to be filtered - \param event Event - - \return Forwarded to QwtAbstractLegend::eventFilter() -*/ -bool QwtLegend::eventFilter( QObject *object, QEvent *event ) -{ - if ( object == d_data->view->contentsWidget ) - { - switch ( event->type() ) - { - case QEvent::ChildRemoved: - { - const QChildEvent *ce = - static_cast<const QChildEvent *>(event); - if ( ce->child()->isWidgetType() ) - { - QWidget *w = static_cast< QWidget * >( ce->child() ); - d_data->itemMap.removeWidget( w ); - } - break; - } - case QEvent::LayoutRequest: - { - d_data->view->layoutContents(); - - if ( parentWidget() && parentWidget()->layout() == NULL ) - { - /* - We want the parent widget ( usually QwtPlot ) to recalculate - its layout, when the contentsWidget has changed. But - because of the scroll view we have to forward the LayoutRequest - event manually. - - We don't use updateGeometry() because it doesn't post LayoutRequest - events when the legend is 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 ) ); - } - break; - } - default: - break; - } - } - - return QwtAbstractLegend::eventFilter( object, event ); -} - -/*! - Called internally when the legend has been clicked on. - Emits a clicked() signal. -*/ -void QwtLegend::itemClicked() -{ - QWidget *w = qobject_cast<QWidget *>( sender() ); - if ( w ) - { - const QVariant itemInfo = d_data->itemMap.itemInfo( w ); - if ( itemInfo.isValid() ) - { - const QList<QWidget *> widgetList = - d_data->itemMap.legendWidgets( itemInfo ); - - const int index = widgetList.indexOf( w ); - if ( index >= 0 ) - Q_EMIT clicked( itemInfo, index ); - } - } -} - -/*! - Called internally when the legend has been checked - Emits a checked() signal. -*/ -void QwtLegend::itemChecked( bool on ) -{ - QWidget *w = qobject_cast<QWidget *>( sender() ); - if ( w ) - { - const QVariant itemInfo = d_data->itemMap.itemInfo( w ); - if ( itemInfo.isValid() ) - { - const QList<QWidget *> widgetList = - d_data->itemMap.legendWidgets( itemInfo ); - - const int index = widgetList.indexOf( w ); - if ( index >= 0 ) - Q_EMIT checked( itemInfo, on, index ); - } - } -} - -/*! - Render the legend into a given rectangle. - - \param painter Painter - \param rect Bounding rectangle - \param fillBackground When true, fill rect with the widget background - - \sa renderLegend() is used by QwtPlotRenderer - not by QwtLegend itself -*/ -void QwtLegend::renderLegend( QPainter *painter, - const QRectF &rect, bool fillBackground ) const -{ - if ( d_data->itemMap.isEmpty() ) - return; - - if ( fillBackground ) - { - if ( autoFillBackground() || - testAttribute( Qt::WA_StyledBackground ) ) - { - QwtPainter::drawBackgound( painter, rect, this ); - } - } - - const QwtDynGridLayout *legendLayout = - qobject_cast<QwtDynGridLayout *>( contentsWidget()->layout() ); - if ( legendLayout == NULL ) - return; - - int left, right, top, bottom; - getContentsMargins( &left, &top, &right, &bottom ); - - QRect layoutRect; - layoutRect.setLeft( qCeil( rect.left() ) + left ); - layoutRect.setTop( qCeil( rect.top() ) + top ); - layoutRect.setRight( qFloor( rect.right() ) - right ); - layoutRect.setBottom( qFloor( rect.bottom() ) - bottom ); - - uint numCols = legendLayout->columnsForWidth( layoutRect.width() ); - QList<QRect> itemRects = - legendLayout->layoutItems( layoutRect, numCols ); - - int index = 0; - - for ( int i = 0; i < legendLayout->count(); i++ ) - { - QLayoutItem *item = legendLayout->itemAt( i ); - QWidget *w = item->widget(); - if ( w ) - { - painter->save(); - - painter->setClipRect( itemRects[index], Qt::IntersectClip ); - renderItem( painter, w, itemRects[index], fillBackground ); - - index++; - painter->restore(); - } - } -} - -/*! - Render a legend entry into a given rectangle. - - \param painter Painter - \param widget Widget representing a legend entry - \param rect Bounding rectangle - \param fillBackground When true, fill rect with the widget background - - \note When widget is not derived from QwtLegendLabel renderItem - does nothing beside the background -*/ -void QwtLegend::renderItem( QPainter *painter, - const QWidget *widget, const QRectF &rect, bool fillBackground ) const -{ - if ( fillBackground ) - { - if ( widget->autoFillBackground() || - widget->testAttribute( Qt::WA_StyledBackground ) ) - { - QwtPainter::drawBackgound( painter, rect, widget ); - } - } - - const QwtLegendLabel *label = qobject_cast<const QwtLegendLabel *>( widget ); - if ( label ) - { - // icon - - const QwtGraphic &icon = label->data().icon(); - const QSizeF sz = icon.defaultSize(); - - const QRectF iconRect( rect.x() + label->margin(), - rect.center().y() - 0.5 * sz.height(), - sz.width(), sz.height() ); - - icon.render( painter, iconRect, Qt::KeepAspectRatio ); - - // title - - QRectF titleRect = rect; - titleRect.setX( iconRect.right() + 2 * label->spacing() ); - - painter->setFont( label->font() ); - painter->setPen( label->palette().color( QPalette::Text ) ); - const_cast< QwtLegendLabel *>( label )->drawText( painter, titleRect ); - } -} - -/*! - \return List of widgets associated to a item - \param itemInfo Info about an item - \sa legendWidget(), itemInfo(), QwtPlot::itemToInfo() - */ -QList<QWidget *> QwtLegend::legendWidgets( const QVariant &itemInfo ) const -{ - return d_data->itemMap.legendWidgets( itemInfo ); -} - -/*! - \return First widget in the list of widgets associated to an item - \param itemInfo Info about an item - \sa itemInfo(), QwtPlot::itemToInfo() - \note Almost all types of items have only one widget -*/ -QWidget *QwtLegend::legendWidget( const QVariant &itemInfo ) const -{ - const QList<QWidget *> list = d_data->itemMap.legendWidgets( itemInfo ); - if ( list.isEmpty() ) - return NULL; - - return list[0]; -} - -/*! - Find the item that is associated to a widget - - \param widget Widget on the legend - \return Associated item info - \sa legendWidget() - */ -QVariant QwtLegend::itemInfo( const QWidget *widget ) const -{ - return d_data->itemMap.itemInfo( widget ); -} - -//! \return True, when no item is inserted -bool QwtLegend::isEmpty() const -{ - return d_data->itemMap.isEmpty(); -} - -/*! - Return the extent, that is needed for the scrollbars - - \param orientation Orientation ( - \return The width of the vertical scrollbar for Qt::Horizontal and v.v. - */ -int QwtLegend::scrollExtent( Qt::Orientation orientation ) const -{ - int extent = 0; - - if ( orientation == Qt::Horizontal ) - extent = verticalScrollBar()->sizeHint().width(); - else - extent = horizontalScrollBar()->sizeHint().height(); - - return extent; -} - diff --git a/source/third_party/qwt/qwt_legend_data.cpp b/source/third_party/qwt/qwt_legend_data.cpp deleted file mode 100644 index d4852ef1302232b1a7370184b3b2a60225c8fee7..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_legend_data.cpp +++ /dev/null @@ -1,129 +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/qwt_legend_data.h" - -//! Constructor -QwtLegendData::QwtLegendData() -{ -} - -//! Destructor -QwtLegendData::~QwtLegendData() -{ -} - -/*! - Set the legend attributes - - QwtLegendData actually is a QMap<int, QVariant> with some - convenience interfaces - - \param map Values - \sa values() - */ -void QwtLegendData::setValues( const QMap<int, QVariant> &map ) -{ - d_map = map; -} - -/*! - \return Legend attributes - \sa setValues() - */ -const QMap<int, QVariant> &QwtLegendData::values() const -{ - return d_map; -} - -/*! - \param role Attribute role - \return True, when the internal map has an entry for role - */ -bool QwtLegendData::hasRole( int role ) const -{ - return d_map.contains( role ); -} - -/*! - Set an attribute value - - \param role Attribute role - \param data Attribute value - - \sa value() - */ -void QwtLegendData::setValue( int role, const QVariant &data ) -{ - d_map[role] = data; -} - -/*! - \param role Attribute role - \return Attribute value for a specific role - */ -QVariant QwtLegendData::value( int role ) const -{ - if ( !d_map.contains( role ) ) - return QVariant(); - - return d_map[role]; -} - -//! \return True, when the internal map is empty -bool QwtLegendData::isValid() const -{ - return !d_map.isEmpty(); -} - -//! \return Value of the TitleRole attribute -QwtText QwtLegendData::title() const -{ - QwtText text; - - const QVariant titleValue = value( QwtLegendData::TitleRole ); - if ( titleValue.canConvert<QwtText>() ) - { - text = qvariant_cast<QwtText>( titleValue ); - } - else if ( titleValue.canConvert<QString>() ) - { - text.setText( qvariant_cast<QString>( titleValue ) ); - } - - return text; -} - -//! \return Value of the IconRole attribute -QwtGraphic QwtLegendData::icon() const -{ - const QVariant iconValue = value( QwtLegendData::IconRole ); - - QwtGraphic graphic; - if ( iconValue.canConvert<QwtGraphic>() ) - { - graphic = qvariant_cast<QwtGraphic>( iconValue ); - } - - return graphic; -} - -//! \return Value of the ModeRole attribute -QwtLegendData::Mode QwtLegendData::mode() const -{ - const QVariant modeValue = value( QwtLegendData::ModeRole ); - if ( modeValue.canConvert<int>() ) - { - const int mode = qvariant_cast<int>( modeValue ); - return static_cast<QwtLegendData::Mode>( mode ); - } - - return QwtLegendData::ReadOnly; -} - diff --git a/source/third_party/qwt/qwt_legend_label.cpp b/source/third_party/qwt/qwt_legend_label.cpp deleted file mode 100644 index f99646140a5bae8c5be5b09b1774cc9b5b81a102..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_legend_label.cpp +++ /dev/null @@ -1,421 +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/qwt_legend_label.h" -#include "qwt/qwt_legend_data.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_symbol.h" -#include "qwt/qwt_graphic.h" -#include <qpainter.h> -#include <qdrawutil.h> -#include <qstyle.h> -#include <qpen.h> -#include <qevent.h> -#include <qstyleoption.h> -#include <qapplication.h> - -static const int ButtonFrame = 2; -static const int Margin = 2; - -static QSize buttonShift( const QwtLegendLabel *w ) -{ - QStyleOption option; - option.init( w ); - - const int ph = w->style()->pixelMetric( - QStyle::PM_ButtonShiftHorizontal, &option, w ); - const int pv = w->style()->pixelMetric( - QStyle::PM_ButtonShiftVertical, &option, w ); - return QSize( ph, pv ); -} - -class QwtLegendLabel::PrivateData -{ -public: - PrivateData(): - itemMode( QwtLegendData::ReadOnly ), - isDown( false ), - spacing( Margin ) - { - } - - QwtLegendData::Mode itemMode; - QwtLegendData legendData; - bool isDown; - - QPixmap icon; - - int spacing; -}; - -/*! - Set the attributes of the legend label - - \param legendData Attributes of the label - \sa data() - */ -void QwtLegendLabel::setData( const QwtLegendData &legendData ) -{ - d_data->legendData = legendData; - - const bool doUpdate = updatesEnabled(); - setUpdatesEnabled( false ); - - setText( legendData.title() ); - setIcon( legendData.icon().toPixmap() ); - - if ( legendData.hasRole( QwtLegendData::ModeRole ) ) - setItemMode( legendData.mode() ); - - if ( doUpdate ) - { - setUpdatesEnabled( true ); - update(); - } -} - -/*! - \return Attributes of the label - \sa setData(), QwtPlotItem::legendData() - */ -const QwtLegendData &QwtLegendLabel::data() const -{ - return d_data->legendData; -} - -/*! - \param parent Parent widget -*/ -QwtLegendLabel::QwtLegendLabel( QWidget *parent ): - QwtTextLabel( parent ) -{ - d_data = new PrivateData; - setMargin( Margin ); - setIndent( Margin ); -} - -//! Destructor -QwtLegendLabel::~QwtLegendLabel() -{ - delete d_data; - d_data = NULL; -} - -/*! - Set the text to the legend item - - \param text Text label - \sa QwtTextLabel::text() -*/ -void QwtLegendLabel::setText( const QwtText &text ) -{ - const int flags = Qt::AlignLeft | Qt::AlignVCenter - | Qt::TextExpandTabs | Qt::TextWordWrap; - - QwtText txt = text; - txt.setRenderFlags( flags ); - - QwtTextLabel::setText( txt ); -} - -/*! - Set the item mode - The default is QwtLegendData::ReadOnly - - \param mode Item mode - \sa itemMode() -*/ -void QwtLegendLabel::setItemMode( QwtLegendData::Mode mode ) -{ - if ( mode != d_data->itemMode ) - { - d_data->itemMode = mode; - d_data->isDown = false; - - setFocusPolicy( ( mode != QwtLegendData::ReadOnly ) - ? Qt::TabFocus : Qt::NoFocus ); - setMargin( ButtonFrame + Margin ); - - updateGeometry(); - } -} - -/*! - \return Item mode - \sa setItemMode() -*/ -QwtLegendData::Mode QwtLegendLabel::itemMode() const -{ - return d_data->itemMode; -} - -/*! - Assign the icon - - \param icon Pixmap representing a plot item - - \sa icon(), QwtPlotItem::legendIcon() -*/ -void QwtLegendLabel::setIcon( const QPixmap &icon ) -{ - d_data->icon = icon; - - int indent = margin() + d_data->spacing; - if ( icon.width() > 0 ) - indent += icon.width() + d_data->spacing; - - setIndent( indent ); -} - -/*! - \return Pixmap representing a plot item - \sa setIcon() -*/ -QPixmap QwtLegendLabel::icon() const -{ - return d_data->icon; -} - -/*! - \brief Change the spacing between icon and text - - \param spacing Spacing - \sa spacing(), QwtTextLabel::margin() -*/ -void QwtLegendLabel::setSpacing( int spacing ) -{ - spacing = qMax( spacing, 0 ); - if ( spacing != d_data->spacing ) - { - d_data->spacing = spacing; - - int indent = margin() + d_data->spacing; - if ( d_data->icon.width() > 0 ) - indent += d_data->icon.width() + d_data->spacing; - - setIndent( indent ); - } -} - -/*! - \return Spacing between icon and text - \sa setSpacing(), QwtTextLabel::margin() -*/ -int QwtLegendLabel::spacing() const -{ - return d_data->spacing; -} - -/*! - Check/Uncheck a the item - - \param on check/uncheck - \sa setItemMode() -*/ -void QwtLegendLabel::setChecked( bool on ) -{ - if ( d_data->itemMode == QwtLegendData::Checkable ) - { - const bool isBlocked = signalsBlocked(); - blockSignals( true ); - - setDown( on ); - - blockSignals( isBlocked ); - } -} - -//! Return true, if the item is checked -bool QwtLegendLabel::isChecked() const -{ - return d_data->itemMode == QwtLegendData::Checkable && isDown(); -} - -//! Set the item being down -void QwtLegendLabel::setDown( bool down ) -{ - if ( down == d_data->isDown ) - return; - - d_data->isDown = down; - update(); - - if ( d_data->itemMode == QwtLegendData::Clickable ) - { - if ( d_data->isDown ) - Q_EMIT pressed(); - else - { - Q_EMIT released(); - Q_EMIT clicked(); - } - } - - if ( d_data->itemMode == QwtLegendData::Checkable ) - Q_EMIT checked( d_data->isDown ); -} - -//! Return true, if the item is down -bool QwtLegendLabel::isDown() const -{ - return d_data->isDown; -} - -//! Return a size hint -QSize QwtLegendLabel::sizeHint() const -{ - QSize sz = QwtTextLabel::sizeHint(); - sz.setHeight( qMax( sz.height(), d_data->icon.height() + 4 ) ); - - if ( d_data->itemMode != QwtLegendData::ReadOnly ) - { - sz += buttonShift( this ); - sz = sz.expandedTo( QApplication::globalStrut() ); - } - - return sz; -} - -//! Paint event -void QwtLegendLabel::paintEvent( QPaintEvent *e ) -{ - 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->icon.isNull() ) - { - QRect iconRect = cr; - iconRect.setX( iconRect.x() + margin() ); - if ( d_data->itemMode != QwtLegendData::ReadOnly ) - iconRect.setX( iconRect.x() + ButtonFrame ); - - iconRect.setSize( d_data->icon.size() ); - iconRect.moveCenter( QPoint( iconRect.center().x(), cr.center().y() ) ); - - painter.drawPixmap( iconRect, d_data->icon ); - } - - painter.restore(); -} - -//! Handle mouse press events -void QwtLegendLabel::mousePressEvent( QMouseEvent *e ) -{ - if ( e->button() == Qt::LeftButton ) - { - switch ( d_data->itemMode ) - { - case QwtLegendData::Clickable: - { - setDown( true ); - return; - } - case QwtLegendData::Checkable: - { - setDown( !isDown() ); - return; - } - default:; - } - } - QwtTextLabel::mousePressEvent( e ); -} - -//! Handle mouse release events -void QwtLegendLabel::mouseReleaseEvent( QMouseEvent *e ) -{ - if ( e->button() == Qt::LeftButton ) - { - switch ( d_data->itemMode ) - { - case QwtLegendData::Clickable: - { - setDown( false ); - return; - } - case QwtLegendData::Checkable: - { - return; // do nothing, but accept - } - default:; - } - } - QwtTextLabel::mouseReleaseEvent( e ); -} - -//! Handle key press events -void QwtLegendLabel::keyPressEvent( QKeyEvent *e ) -{ - if ( e->key() == Qt::Key_Space ) - { - switch ( d_data->itemMode ) - { - case QwtLegendData::Clickable: - { - if ( !e->isAutoRepeat() ) - setDown( true ); - return; - } - case QwtLegendData::Checkable: - { - if ( !e->isAutoRepeat() ) - setDown( !isDown() ); - return; - } - default:; - } - } - - QwtTextLabel::keyPressEvent( e ); -} - -//! Handle key release events -void QwtLegendLabel::keyReleaseEvent( QKeyEvent *e ) -{ - if ( e->key() == Qt::Key_Space ) - { - switch ( d_data->itemMode ) - { - case QwtLegendData::Clickable: - { - if ( !e->isAutoRepeat() ) - setDown( false ); - return; - } - case QwtLegendData::Checkable: - { - return; // do nothing, but accept - } - default:; - } - } - - QwtTextLabel::keyReleaseEvent( e ); -} diff --git a/source/third_party/qwt/qwt_magnifier.cpp b/source/third_party/qwt/qwt_magnifier.cpp deleted file mode 100644 index 40c6c41047315f94924cad6a9e6bd8568b736b40..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_magnifier.cpp +++ /dev/null @@ -1,492 +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/qwt_magnifier.h" -#include "qwt/qwt_math.h" -#include <qevent.h> -#include <qwidget.h> - -class QwtMagnifier::PrivateData -{ -public: - PrivateData(): - isEnabled( false ), - wheelFactor( 0.9 ), - wheelModifiers( Qt::NoModifier ), - mouseFactor( 0.95 ), - mouseButton( Qt::RightButton ), - mouseButtonModifiers( Qt::NoModifier ), - keyFactor( 0.9 ), - zoomInKey( Qt::Key_Plus ), - zoomInKeyModifiers( Qt::NoModifier ), - zoomOutKey( Qt::Key_Minus ), - zoomOutKeyModifiers( Qt::NoModifier ), - mousePressed( false ) - { - } - - bool isEnabled; - - double wheelFactor; - Qt::KeyboardModifiers wheelModifiers; - - double mouseFactor; - - Qt::MouseButton mouseButton; - Qt::KeyboardModifiers mouseButtonModifiers; - - double keyFactor; - - int zoomInKey; - Qt::KeyboardModifiers zoomInKeyModifiers; - - int zoomOutKey; - Qt::KeyboardModifiers zoomOutKeyModifiers; - - bool mousePressed; - bool hasMouseTracking; - QPoint mousePos; -}; - -/*! - Constructor - \param parent Widget to be magnified -*/ -QwtMagnifier::QwtMagnifier( QWidget *parent ): - QObject( parent ) -{ - d_data = new PrivateData(); - setEnabled( true ); -} - -//! Destructor -QwtMagnifier::~QwtMagnifier() -{ - delete d_data; -} - -/*! - \brief En/disable the magnifier - - 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 QwtMagnifier::setEnabled( bool on ) -{ - if ( d_data->isEnabled != on ) - { - d_data->isEnabled = on; - - QObject *o = parent(); - if ( o ) - { - if ( d_data->isEnabled ) - o->installEventFilter( this ); - else - o->removeEventFilter( this ); - } - } -} - -/*! - \return true when enabled, false otherwise - \sa setEnabled(), eventFilter() -*/ -bool QwtMagnifier::isEnabled() const -{ - return d_data->isEnabled; -} - -/*! - \brief Change the wheel factor - - The wheel factor defines the ratio between the current range - on the parent widget and the zoomed range for each step of the wheel. - - Use values > 1 for magnification (i.e. 2.0) and values < 1 for - scaling down (i.e. 1/2.0 = 0.5). You can use this feature for - inverting the direction of the wheel. - - The default value is 0.9. - - \param factor Wheel factor - \sa wheelFactor(), setWheelButtonState(), - setMouseFactor(), setKeyFactor() -*/ -void QwtMagnifier::setWheelFactor( double factor ) -{ - d_data->wheelFactor = factor; -} - -/*! - \return Wheel factor - \sa setWheelFactor() -*/ -double QwtMagnifier::wheelFactor() const -{ - return d_data->wheelFactor; -} - -/*! - Assign keyboard modifiers for zooming in/out using the wheel. - The default modifiers are Qt::NoModifiers. - - \param modifiers Keyboard modifiers - \sa wheelModifiers() -*/ -void QwtMagnifier::setWheelModifiers( Qt::KeyboardModifiers modifiers ) -{ - d_data->wheelModifiers = modifiers; -} - -/*! - \return Wheel modifiers - \sa setWheelModifiers() -*/ -Qt::KeyboardModifiers QwtMagnifier::wheelModifiers() const -{ - return d_data->wheelModifiers; -} - -/*! - \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 ) -{ - d_data->mouseFactor = factor; -} - -/*! - \return Mouse factor - \sa setMouseFactor() -*/ -double QwtMagnifier::mouseFactor() const -{ - return d_data->mouseFactor; -} - -/*! - Assign the mouse button, that is used for zooming in/out. - The default value is Qt::RightButton. - - \param button Button - \param modifiers Keyboard modifiers - - \sa getMouseButton() -*/ -void QwtMagnifier::setMouseButton( - Qt::MouseButton button, Qt::KeyboardModifiers modifiers ) -{ - d_data->mouseButton = button; - d_data->mouseButtonModifiers = modifiers; -} - -//! \sa setMouseButton() -void QwtMagnifier::getMouseButton( - Qt::MouseButton &button, Qt::KeyboardModifiers &modifiers ) const -{ - button = d_data->mouseButton; - modifiers = d_data->mouseButtonModifiers; -} - -/*! - \brief Change the key factor - - 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 ) -{ - d_data->keyFactor = factor; -} - -/*! - \return Key factor - \sa setKeyFactor() -*/ -double QwtMagnifier::keyFactor() const -{ - return d_data->keyFactor; -} - -/*! - Assign the key, that is used for zooming in. - The default combination is Qt::Key_Plus + Qt::NoModifier. - - \param key - \param modifiers - \sa getZoomInKey(), setZoomOutKey() -*/ -void QwtMagnifier::setZoomInKey( int key, - Qt::KeyboardModifiers modifiers ) -{ - d_data->zoomInKey = key; - d_data->zoomInKeyModifiers = modifiers; -} - -/*! - \brief Retrieve the settings of the zoom in key - - \param key Key code, see Qt::Key - \param modifiers Keyboard modifiers - - \sa setZoomInKey() -*/ -void QwtMagnifier::getZoomInKey( int &key, - Qt::KeyboardModifiers &modifiers ) const -{ - key = d_data->zoomInKey; - modifiers = d_data->zoomInKeyModifiers; -} - -/*! - Assign the key, that is used for zooming out. - The default combination is Qt::Key_Minus + Qt::NoModifier. - - \param key - \param modifiers - \sa getZoomOutKey(), setZoomOutKey() -*/ -void QwtMagnifier::setZoomOutKey( int key, - Qt::KeyboardModifiers modifiers ) -{ - d_data->zoomOutKey = key; - d_data->zoomOutKeyModifiers = modifiers; -} - -/*! - \brief Retrieve the settings of the zoom out key - - \param key Key code, see Qt::Key - \param modifiers Keyboard modifiers - - \sa setZoomOutKey() -*/ -void QwtMagnifier::getZoomOutKey( int &key, - Qt::KeyboardModifiers &modifiers ) const -{ - key = d_data->zoomOutKey; - modifiers = d_data->zoomOutKeyModifiers; -} - -/*! - \brief Event filter - - When isEnabled() is true, the mouse events of the - observed widget are filtered. - - \param object Object to be filtered - \param event Event - - \return Forwarded to QObject::eventFilter() - - \sa widgetMousePressEvent(), widgetMouseReleaseEvent(), - widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent() - widgetKeyReleaseEvent() -*/ -bool QwtMagnifier::eventFilter( QObject *object, QEvent *event ) -{ - if ( object && object == parent() ) - { - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - widgetMousePressEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseMove: - { - widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseButtonRelease: - { - widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::Wheel: - { - widgetWheelEvent( static_cast<QWheelEvent *>( event ) ); - break; - } - case QEvent::KeyPress: - { - widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) ); - break; - } - case QEvent::KeyRelease: - { - widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) ); - break; - } - default:; - } - } - return QObject::eventFilter( object, event ); -} - -/*! - Handle a mouse press event for the observed widget. - - \param mouseEvent Mouse event - \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent() -*/ -void QwtMagnifier::widgetMousePressEvent( QMouseEvent *mouseEvent ) -{ - if ( parentWidget() == NULL ) - return; - - if ( ( mouseEvent->button() != d_data->mouseButton ) || - ( mouseEvent->modifiers() != d_data->mouseButtonModifiers ) ) - { - return; - } - - d_data->hasMouseTracking = parentWidget()->hasMouseTracking(); - - 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 *mouseEvent ) -{ - Q_UNUSED( mouseEvent ); - - if ( d_data->mousePressed && parentWidget() ) - { - d_data->mousePressed = false; - parentWidget()->setMouseTracking( d_data->hasMouseTracking ); - } -} - -/*! - Handle a mouse move event for the observed widget. - - \param mouseEvent Mouse event - \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), -*/ -void QwtMagnifier::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) -{ - if ( !d_data->mousePressed ) - return; - - 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 ); - } - - d_data->mousePos = mouseEvent->pos(); -} - -/*! - Handle a wheel event for the observed widget. - - \param wheelEvent Wheel event - \sa eventFilter() -*/ -void QwtMagnifier::widgetWheelEvent( QWheelEvent *wheelEvent ) -{ - if ( wheelEvent->modifiers() != d_data->wheelModifiers ) - { - 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 = qPow( d_data->wheelFactor, - qAbs( wheelEvent->delta() / 120.0 ) ); - - if ( wheelEvent->delta() > 0 ) - f = 1 / f; - - rescale( f ); - } -} - -/*! - Handle a key press event for the observed widget. - - \param keyEvent Key event - \sa eventFilter(), widgetKeyReleaseEvent() -*/ -void QwtMagnifier::widgetKeyPressEvent( QKeyEvent *keyEvent ) -{ - if ( keyEvent->key() == d_data->zoomInKey && - keyEvent->modifiers() == d_data->zoomInKeyModifiers ) - { - rescale( d_data->keyFactor ); - } - else if ( keyEvent->key() == d_data->zoomOutKey && - keyEvent->modifiers() == d_data->zoomOutKeyModifiers ) - { - rescale( 1.0 / d_data->keyFactor ); - } -} - -/*! - Handle a key release event for the observed widget. - - \param keyEvent Key event - \sa eventFilter(), widgetKeyReleaseEvent() -*/ -void QwtMagnifier::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) -{ - Q_UNUSED( keyEvent ); -} - -//! \return Parent widget, where the rescaling happens -QWidget *QwtMagnifier::parentWidget() -{ - return qobject_cast<QWidget *>( parent() ); -} - -//! \return Parent widget, where the rescaling happens -const QWidget *QwtMagnifier::parentWidget() const -{ - return qobject_cast<const QWidget *>( parent() ); -} - diff --git a/source/third_party/qwt/qwt_math.cpp b/source/third_party/qwt/qwt_math.cpp deleted file mode 100644 index 877f120e0d9d3a06bd85d306d8d98aa4326184af..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_math.cpp +++ /dev/null @@ -1,74 +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/qwt_math.h" - -/*! - \brief Find the smallest value in an array - \param array Pointer to an array - \param size Array size -*/ -double qwtGetMin( const double *array, int size ) -{ - if ( size <= 0 ) - return 0.0; - - double rv = array[0]; - for ( int i = 1; i < size; i++ ) - rv = qMin( rv, array[i] ); - - return rv; -} - - -/*! - \brief Find the largest value in an array - \param array Pointer to an array - \param size Array size -*/ -double qwtGetMax( const double *array, int size ) -{ - if ( size <= 0 ) - return 0.0; - - double rv = array[0]; - for ( int i = 1; i < size; i++ ) - rv = qMax( rv, array[i] ); - - return rv; -} - -/*! - \brief Normalize an angle to be int the range [0.0, 2 * PI[ - \param radians Angle in radians - \return Normalized angle in radians -*/ -double qwtNormalizeRadians( double radians ) -{ - double a = ::fmod( radians, 2.0 * M_PI ); - if ( a < 0.0 ) - a += 2.0 * M_PI; - - return a; - -} - -/*! - \brief Normalize an angle to be int the range [0.0, 360.0[ - \param radians Angle in degrees - \return Normalized angle in degrees -*/ -double qwtNormalizeDegrees( double degrees ) -{ - double a = ::fmod( degrees, 360.0 ); - if ( a < 0.0 ) - a += 360.0; - - return a; -} diff --git a/source/third_party/qwt/qwt_matrix_raster_data.cpp b/source/third_party/qwt/qwt_matrix_raster_data.cpp deleted file mode 100644 index 5d7cc69e62e32d8f933f9b28e0c3d72317b85462..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_matrix_raster_data.cpp +++ /dev/null @@ -1,298 +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/qwt_matrix_raster_data.h" -#include <qnumeric.h> -#include <qmath.h> - -class QwtMatrixRasterData::PrivateData -{ -public: - PrivateData(): - resampleMode(QwtMatrixRasterData::NearestNeighbour), - numColumns(0) - { - } - - inline double value(int row, int col) const - { - return values.data()[ row * numColumns + col ]; - } - - QwtMatrixRasterData::ResampleMode resampleMode; - - QVector<double> values; - int numColumns; - int 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<double> &values, int numColumns ) -{ - d_data->values = values; - d_data->numColumns = qMax( numColumns, 0 ); - update(); -} - -/*! - \return Value matrix - \sa setValueMatrix(), numColumns(), numRows(), setInterval() -*/ -const QVector<double> QwtMatrixRasterData::valueMatrix() const -{ - return d_data->values; -} - -/*! - \brief Change a single value in the matrix - - \param row Row index - \param col Column index - \param value New value - - \sa value(), setValueMatrix() -*/ -void QwtMatrixRasterData::setValue( int row, int col, double value ) -{ - if ( row >= 0 && row < d_data->numRows && - col >= 0 && col < d_data->numColumns ) - { - const int index = row * d_data->numColumns + col; - d_data->values.data()[ index ] = value; - } -} - -/*! - \return Number of columns of the value matrix - \sa valueMatrix(), numRows(), setValueMatrix() -*/ -int QwtMatrixRasterData::numColumns() const -{ - return d_data->numColumns; -} - -/*! - \return Number of rows of the value matrix - \sa valueMatrix(), numColumns(), setValueMatrix() -*/ -int QwtMatrixRasterData::numRows() const -{ - return d_data->numRows; -} - -/*! - \brief Calculate the pixel hint - - pixelHint() returns the geometry of a pixel, that can be used - to calculate the resolution and alignment of the plot item, that is - representing the data. - - - 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. - - \param area Requested area, ignored - \return Calculated hint - - \sa ResampleMode, setMatrix(), setInterval() -*/ -QRectF QwtMatrixRasterData::pixelHint( const QRectF &area ) const -{ - Q_UNUSED( area ) - - 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 >= static_cast<int>( d_data->numColumns ) ) - col2 = col1; - - if ( row1 < 0 ) - row1 = row2; - else if ( row2 >= static_cast<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: - { - int row = int( (y - yInterval.minValue() ) / d_data->dy ); - int col = int( (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/source/third_party/qwt/qwt_null_paintdevice.cpp b/source/third_party/qwt/qwt_null_paintdevice.cpp deleted file mode 100644 index e7c77aa14081b62bb233f967c8d69629ad43f536..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_null_paintdevice.cpp +++ /dev/null @@ -1,593 +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/qwt_null_paintdevice.h" -#include <qpaintengine.h> -#include <qpixmap.h> - -class QwtNullPaintDevice::PrivateData -{ -public: - PrivateData(): - mode( QwtNullPaintDevice::NormalMode ) - { - } - - QwtNullPaintDevice::Mode mode; -}; - -class QwtNullPaintDevice::PaintEngine: public QPaintEngine -{ -public: - PaintEngine(); - - 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 *nullDevice(); -}; - -QwtNullPaintDevice::PaintEngine::PaintEngine(): - QPaintEngine( QPaintEngine::AllFeatures ) -{ -} - -bool QwtNullPaintDevice::PaintEngine::begin( QPaintDevice * ) -{ - setActive( true ); - return true; -} - -bool QwtNullPaintDevice::PaintEngine::end() -{ - setActive( false ); - return true; -} - -QPaintEngine::Type QwtNullPaintDevice::PaintEngine::type() const -{ - return QPaintEngine::User; -} - -void QwtNullPaintDevice::PaintEngine::drawRects( - const QRect *rects, int rectCount) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawRects( rects, rectCount ); - return; - } - - device->drawRects( rects, rectCount ); -} - -void QwtNullPaintDevice::PaintEngine::drawRects( - const QRectF *rects, int rectCount) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawRects( rects, rectCount ); - return; - } - - device->drawRects( rects, rectCount ); -} - -void QwtNullPaintDevice::PaintEngine::drawLines( - const QLine *lines, int lineCount) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawLines( lines, lineCount ); - return; - } - - device->drawLines( lines, lineCount ); -} - -void QwtNullPaintDevice::PaintEngine::drawLines( - const QLineF *lines, int lineCount) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawLines( lines, lineCount ); - return; - } - - device->drawLines( lines, lineCount ); -} - -void QwtNullPaintDevice::PaintEngine::drawEllipse( - const QRectF &rect) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawEllipse( rect ); - return; - } - - device->drawEllipse( rect ); -} - -void QwtNullPaintDevice::PaintEngine::drawEllipse( - const QRect &rect) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawEllipse( rect ); - return; - } - - device->drawEllipse( rect ); -} - - -void QwtNullPaintDevice::PaintEngine::drawPath( - const QPainterPath &path) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - device->drawPath( path ); -} - -void QwtNullPaintDevice::PaintEngine::drawPoints( - const QPointF *points, int pointCount) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawPoints( points, pointCount ); - return; - } - - device->drawPoints( points, pointCount ); -} - -void QwtNullPaintDevice::PaintEngine::drawPoints( - const QPoint *points, int pointCount) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawPoints( points, pointCount ); - return; - } - - device->drawPoints( points, pointCount ); -} - -void QwtNullPaintDevice::PaintEngine::drawPolygon( - const QPointF *points, int pointCount, PolygonDrawMode mode) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() == QwtNullPaintDevice::PathMode ) - { - QPainterPath path; - - if ( pointCount > 0 ) - { - path.moveTo( points[0] ); - for ( int i = 1; i < pointCount; i++ ) - path.lineTo( points[i] ); - - if ( mode != PolylineMode ) - path.closeSubpath(); - } - - device->drawPath( path ); - return; - } - - device->drawPolygon( points, pointCount, mode ); -} - -void QwtNullPaintDevice::PaintEngine::drawPolygon( - const QPoint *points, int pointCount, PolygonDrawMode mode) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() == QwtNullPaintDevice::PathMode ) - { - QPainterPath path; - - if ( pointCount > 0 ) - { - path.moveTo( points[0] ); - for ( int i = 1; i < pointCount; i++ ) - path.lineTo( points[i] ); - - if ( mode != PolylineMode ) - path.closeSubpath(); - } - - device->drawPath( path ); - return; - } - - device->drawPolygon( points, pointCount, mode ); -} - -void QwtNullPaintDevice::PaintEngine::drawPixmap( - const QRectF &rect, const QPixmap &pm, const QRectF &subRect ) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - device->drawPixmap( rect, pm, subRect ); -} - -void QwtNullPaintDevice::PaintEngine::drawTextItem( - const QPointF &pos, const QTextItem &textItem) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawTextItem( pos, textItem ); - return; - } - - device->drawTextItem( pos, textItem ); -} - -void QwtNullPaintDevice::PaintEngine::drawTiledPixmap( - const QRectF &rect, const QPixmap &pixmap, - const QPointF &subRect) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - if ( device->mode() != QwtNullPaintDevice::NormalMode ) - { - QPaintEngine::drawTiledPixmap( rect, pixmap, subRect ); - return; - } - - device->drawTiledPixmap( rect, pixmap, subRect ); -} - -void QwtNullPaintDevice::PaintEngine::drawImage( - const QRectF &rect, const QImage &image, - const QRectF &subRect, Qt::ImageConversionFlags flags) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - device->drawImage( rect, image, subRect, flags ); -} - -void QwtNullPaintDevice::PaintEngine::updateState( - const QPaintEngineState &state) -{ - QwtNullPaintDevice *device = nullDevice(); - if ( device == NULL ) - return; - - device->updateState( state ); -} - -inline QwtNullPaintDevice *QwtNullPaintDevice::PaintEngine::nullDevice() -{ - if ( !isActive() ) - return NULL; - - return static_cast<QwtNullPaintDevice *>( paintDevice() ); -} - -//! Constructor -QwtNullPaintDevice::QwtNullPaintDevice(): - d_engine( NULL ) -{ - d_data = new PrivateData; -} - -//! Destructor -QwtNullPaintDevice::~QwtNullPaintDevice() -{ - delete d_engine; - delete d_data; -} - -/*! - Set the render mode - - \param mode New mode - \sa mode() - */ -void QwtNullPaintDevice::setMode( Mode mode ) -{ - d_data->mode = mode; -} - -/*! - \return Render mode - \sa setMode() -*/ -QwtNullPaintDevice::Mode QwtNullPaintDevice::mode() const -{ - return d_data->mode; -} - -//! See QPaintDevice::paintEngine() -QPaintEngine *QwtNullPaintDevice::paintEngine() const -{ - if ( d_engine == NULL ) - { - QwtNullPaintDevice *that = - const_cast< QwtNullPaintDevice * >( this ); - - that->d_engine = new PaintEngine(); - } - - return d_engine; -} - -/*! - See QPaintDevice::metric() - - \param deviceMetric Type of metric - \return Metric information for the given paint device metric. - - \sa sizeMetrics() -*/ -int QwtNullPaintDevice::metric( PaintDeviceMetric deviceMetric ) const -{ - int value; - - switch ( deviceMetric ) - { - case PdmWidth: - { - value = sizeMetrics().width(); - break; - } - case PdmHeight: - { - value = sizeMetrics().height(); - break; - } - case PdmNumColors: - { - value = 0xffffffff; - break; - } - case PdmDepth: - { - value = 32; - break; - } - case PdmPhysicalDpiX: - case PdmPhysicalDpiY: - case PdmDpiY: - case PdmDpiX: - { - value = 72; - break; - } - case PdmWidthMM: - { - value = qRound( metric( PdmWidth ) * 25.4 / metric( PdmDpiX ) ); - break; - } - case PdmHeightMM: - { - value = qRound( metric( PdmHeight ) * 25.4 / metric( PdmDpiY ) ); - break; - } - 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/source/third_party/qwt/qwt_painter.cpp b/source/third_party/qwt/qwt_painter.cpp deleted file mode 100644 index f9a461a272ab3983c1d5c819ca5d74b4ad8c8d4c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_painter.cpp +++ /dev/null @@ -1,1298 +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/qwt_painter.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_clipper.h" -#include "qwt/qwt_color_map.h" -#include "qwt/qwt_scale_map.h" -#include <qwindowdefs.h> -#include <qwidget.h> -#include <qframe.h> -#include <qrect.h> -#include <qpainter.h> -#include <qpalette.h> -#include <qpaintdevice.h> -#include <qpixmap.h> -#include <qstyle.h> -#include <qtextdocument.h> -#include <qabstracttextdocumentlayout.h> -#include <qstyleoption.h> -#include <qpaintengine.h> -#include <qapplication.h> -#include <qdesktopwidget.h> - -#if QT_VERSION >= 0x050000 -#include <qwindow.h> -#endif - -#if QT_VERSION < 0x050000 - -#ifdef Q_WS_X11 -#include <qx11info_x11.h> -#endif - -#endif - -bool QwtPainter::d_polylineSplitting = true; -bool QwtPainter::d_roundingAlignment = true; - -static inline bool qwtIsClippingNeeded( - const QPainter *painter, QRectF &clipRect ) -{ - bool doClipping = false; - const QPaintEngine *pe = painter->paintEngine(); - if ( pe && pe->type() == QPaintEngine::SVG ) - { - // The SVG paint engine ignores any clipping, - - if ( painter->hasClipping() ) - { - doClipping = true; - clipRect = painter->clipRegion().boundingRect(); - } - } - - return doClipping; -} - -template <class T> -static inline void qwtDrawPolyline( QPainter *painter, - const T *points, int pointCount, bool polylineSplitting ) -{ - bool doSplit = false; - if ( polylineSplitting ) - { - 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; - } - } - - if ( doSplit ) - { - const int splitSize = 6; - - 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 ); - } -} - -static inline QSize qwtScreenResolution() -{ - static QSize screenResolution; - if ( !screenResolution.isValid() ) - { - QDesktopWidget *desktop = QApplication::desktop(); - if ( desktop ) - { - screenResolution.setWidth( desktop->logicalDpiX() ); - screenResolution.setHeight( desktop->logicalDpiY() ); - } - } - - return screenResolution; -} - -static inline void qwtUnscaleFont( QPainter *painter ) -{ - if ( painter->font().pixelSize() >= 0 ) - return; - - const QSize screenResolution = qwtScreenResolution(); - - 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() ); - - painter->setFont( pixelFont ); - } -} - -/*! - Check is the application is running with the X11 graphics system - that has some special capabilities that can be used for incremental - painting to a widget. - - \return True, when the graphics system is X11 -*/ -bool QwtPainter::isX11GraphicsSystem() -{ - static int onX11 = -1; - if ( onX11 < 0 ) - { - QPixmap pm( 1, 1 ); - QPainter painter( &pm ); - - onX11 = ( painter.paintEngine()->type() == QPaintEngine::X11 ) ? 1 : 0; - } - - return onX11 == 1; -} - -/*! - 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. - - If we have an integer based paint engine it is also - checked if the painter has a transformation matrix, - that rotates or scales. - - \param painter Painter - \return true, when the painter is aligning - - \sa setRoundingAlignment() -*/ -bool QwtPainter::isAligning( QPainter *painter ) -{ - if ( painter && painter->isActive() ) - { - switch ( painter->paintEngine()->type() ) - { - case QPaintEngine::Pdf: - case QPaintEngine::SVG: - return false; - - default:; - } - - const QTransform tr = painter->transform(); - if ( tr.isRotating() || tr.isScaling() ) - { - // we might have to check translations too - return false; - } - } - - return true; -} - -/*! - Enable whether coordinates should be rounded, before they are painted - to a paint engine that floors to integer values. For other paint engines - ( PDF, SVG ) this flag has no effect. - QwtPainter stores this flag only, the rounding itself is done in - the painting code ( f.e the plot items ). - - The default setting is true. - - \sa roundingAlignment(), isAligning() -*/ -void QwtPainter::setRoundingAlignment( bool enable ) -{ - d_roundingAlignment = enable; -} - -/*! - \brief En/Disable line splitting for the raster paint engine - - In some Qt versions the raster paint engine paints polylines of many points - much faster when they are split in smaller chunks: f.e all supported Qt versions - >= Qt 5.0 when drawing an antialiased polyline with a pen width >=2. - - The default setting is true. - - \sa polylineSplitting() -*/ -void QwtPainter::setPolylineSplitting( bool enable ) -{ - d_polylineSplitting = enable; -} - -//! Wrapper for QPainter::drawPath() -void QwtPainter::drawPath( QPainter *painter, const QPainterPath &path ) -{ - painter->drawPath( path ); -} - -//! 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 = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping ) - { - if ( !clipRect.intersects( r ) ) - return; - - if ( !clipRect.contains( r ) ) - { - fillRect( painter, r & clipRect, painter->brush() ); - - painter->save(); - painter->setBrush( Qt::NoBrush ); - drawPolyline( painter, QPolygonF( r ) ); - painter->restore(); - - return; - } - } - - painter->drawRect( r ); -} - -//! Wrapper for QPainter::fillRect() -void QwtPainter::fillRect( QPainter *painter, - const QRectF &rect, const QBrush &brush ) -{ - if ( !rect.isValid() ) - return; - - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - /* - Performance of Qt4 is horrible for a non trivial brush. Without - clipping expect minutes or hours for repainting large rectangles - (might result from zooming) - */ - - if ( deviceClipping ) - clipRect &= painter->window(); - else - clipRect = painter->window(); - - if ( painter->hasClipping() ) - clipRect &= painter->clipRegion().boundingRect(); - - QRectF r = rect; - if ( deviceClipping ) - r = r.intersected( clipRect ); - - if ( r.isValid() ) - painter->fillRect( r, brush ); -} - -//! Wrapper for QPainter::drawPie() -void QwtPainter::drawPie( QPainter *painter, const QRectF &rect, - int a, int alen ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - if ( deviceClipping && !clipRect.contains( rect ) ) - return; - - painter->drawPie( rect, a, alen ); -} - -//! Wrapper for QPainter::drawEllipse() -void QwtPainter::drawEllipse( QPainter *painter, const QRectF &rect ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping && !clipRect.contains( rect ) ) - return; - - painter->drawEllipse( rect ); -} - -//! Wrapper for QPainter::drawText() -void QwtPainter::drawText( QPainter *painter, double x, double y, - const QString &text ) -{ - drawText( painter, QPointF( x, y ), text ); -} - -//! Wrapper for QPainter::drawText() -void QwtPainter::drawText( QPainter *painter, const QPointF &pos, - const QString &text ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping && !clipRect.contains( pos ) ) - return; - - - painter->save(); - qwtUnscaleFont( painter ); - painter->drawText( pos, text ); - painter->restore(); -} - -//! Wrapper for QPainter::drawText() -void QwtPainter::drawText( QPainter *painter, - double x, double y, double w, double h, - int flags, const QString &text ) -{ - drawText( painter, QRectF( x, y, w, h ), flags, text ); -} - -//! Wrapper for QPainter::drawText() -void QwtPainter::drawText( QPainter *painter, const QRectF &rect, - int flags, const QString &text ) -{ - painter->save(); - qwtUnscaleFont( painter ); - painter->drawText( rect, flags, text ); - painter->restore(); -} - -#ifndef QT_NO_RICHTEXT - -/*! - 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 -*/ -void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect, - int flags, const QTextDocument &text ) -{ - QTextDocument *txt = text.clone(); - - painter->save(); - - QRectF unscaledRect = rect; - - if ( painter->font().pixelSize() < 0 ) - { - const QSize res = qwtScreenResolution(); - - const QPaintDevice *pd = painter->device(); - if ( pd->logicalDpiX() != res.width() || - pd->logicalDpiY() != res.height() ) - { - QTransform transform; - transform.scale( res.width() / double( pd->logicalDpiX() ), - res.height() / double( pd->logicalDpiY() )); - - painter->setWorldTransform( transform, true ); - unscaledRect = transform.inverted().mapRect(rect); - } - } - - txt->setDefaultFont( painter->font() ); - txt->setPageSize( QSizeF( unscaledRect.width(), QWIDGETSIZE_MAX ) ); - - QAbstractTextDocumentLayout* layout = txt->documentLayout(); - - const double height = layout->documentSize().height(); - double y = unscaledRect.y(); - if ( flags & Qt::AlignBottom ) - y += ( unscaledRect.height() - height ); - else if ( flags & Qt::AlignVCenter ) - y += ( unscaledRect.height() - height ) / 2; - - QAbstractTextDocumentLayout::PaintContext context; - context.palette.setColor( QPalette::Text, painter->pen().color() ); - - painter->translate( unscaledRect.x(), y ); - layout->draw( painter, context ); - - painter->restore(); - delete txt; -} - -#endif // !QT_NO_RICHTEXT - - -//! Wrapper for QPainter::drawLine() -void QwtPainter::drawLine( QPainter *painter, - const QPointF &p1, const QPointF &p2 ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping && - !( clipRect.contains( p1 ) && clipRect.contains( p2 ) ) ) - { - QPolygonF polygon; - polygon += p1; - polygon += p2; - drawPolyline( painter, polygon ); - return; - } - - painter->drawLine( p1, p2 ); -} - -//! Wrapper for QPainter::drawPolygon() -void QwtPainter::drawPolygon( QPainter *painter, const QPolygonF &polygon ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( 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 = qwtIsClippingNeeded( painter, clipRect ); - - QPolygonF cpa = polygon; - if ( deviceClipping ) - cpa = QwtClipper::clipPolygonF( clipRect, cpa ); - - qwtDrawPolyline<QPointF>( 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 = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping ) - { - QPolygonF polygon( pointCount ); - ::memcpy( polygon.data(), points, pointCount * sizeof( QPointF ) ); - - polygon = QwtClipper::clipPolygonF( clipRect, polygon ); - qwtDrawPolyline<QPointF>( painter, - polygon.constData(), polygon.size(), d_polylineSplitting ); - } - else - { - qwtDrawPolyline<QPointF>( painter, points, pointCount, d_polylineSplitting ); - } -} - -//! Wrapper for QPainter::drawPolygon() -void QwtPainter::drawPolygon( QPainter *painter, const QPolygon &polygon ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - QPolygon cpa = polygon; - if ( deviceClipping ) - cpa = QwtClipper::clipPolygon( clipRect, polygon ); - - painter->drawPolygon( cpa ); -} - -//! Wrapper for QPainter::drawPolyline() -void QwtPainter::drawPolyline( QPainter *painter, const QPolygon &polygon ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - QPolygon cpa = polygon; - if ( deviceClipping ) - cpa = QwtClipper::clipPolygon( clipRect, cpa ); - - qwtDrawPolyline<QPoint>( painter, - cpa.constData(), cpa.size(), d_polylineSplitting ); -} - -//! Wrapper for QPainter::drawPolyline() -void QwtPainter::drawPolyline( QPainter *painter, - const QPoint *points, int pointCount ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping ) - { - QPolygon polygon( pointCount ); - ::memcpy( polygon.data(), points, pointCount * sizeof( QPoint ) ); - - polygon = QwtClipper::clipPolygon( clipRect, polygon ); - qwtDrawPolyline<QPoint>( painter, - polygon.constData(), polygon.size(), d_polylineSplitting ); - } - else - qwtDrawPolyline<QPoint>( painter, points, pointCount, d_polylineSplitting ); -} - -//! Wrapper for QPainter::drawPoint() -void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping && !clipRect.contains( pos ) ) - return; - - painter->drawPoint( pos ); -} - -//! Wrapper for QPainter::drawPoint() -void QwtPainter::drawPoint( QPainter *painter, const QPoint &pos ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping ) - { - const int minX = qCeil( clipRect.left() ); - const int maxX = qFloor( clipRect.right() ); - const int minY = qCeil( clipRect.top() ); - const int maxY = qFloor( clipRect.bottom() ); - - if ( pos.x() < minX || pos.x() > maxX - || pos.y() < minY || pos.y() > maxY ) - { - return; - } - } - - painter->drawPoint( pos ); -} - -//! Wrapper for QPainter::drawPoints() -void QwtPainter::drawPoints( QPainter *painter, - const QPoint *points, int pointCount ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping ) - { - const int minX = qCeil( clipRect.left() ); - const int maxX = qFloor( clipRect.right() ); - const int minY = qCeil( clipRect.top() ); - const int maxY = qFloor( clipRect.bottom() ); - - const QRect r( minX, minY, maxX - minX, maxY - minY ); - - QPolygon clippedPolygon( pointCount ); - QPoint *clippedData = clippedPolygon.data(); - - int numClippedPoints = 0; - for ( int i = 0; i < pointCount; i++ ) - { - if ( r.contains( points[i] ) ) - clippedData[ numClippedPoints++ ] = points[i]; - } - painter->drawPoints( clippedData, numClippedPoints ); - } - else - { - painter->drawPoints( points, pointCount ); - } -} - -//! Wrapper for QPainter::drawPoints() -void QwtPainter::drawPoints( QPainter *painter, - const QPointF *points, int pointCount ) -{ - QRectF clipRect; - const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); - - if ( deviceClipping ) - { - QPolygonF clippedPolygon( pointCount ); - QPointF *clippedData = clippedPolygon.data(); - - int numClippedPoints = 0; - for ( int i = 0; i < pointCount; i++ ) - { - if ( clipRect.contains( points[i] ) ) - clippedData[ numClippedPoints++ ] = points[i]; - } - painter->drawPoints( clippedData, numClippedPoints ); - } - else - { - painter->drawPoints( points, pointCount ); - } -} - -//! Wrapper for QPainter::drawImage() -void QwtPainter::drawImage( QPainter *painter, - const QRectF &rect, const QImage &image ) -{ - const QRect alignedRect = rect.toAlignedRect(); - - if ( alignedRect != rect ) - { - const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); - - painter->save(); - painter->setClipRect( clipRect, Qt::IntersectClip ); - painter->drawImage( alignedRect, image ); - painter->restore(); - } - else - { - painter->drawImage( alignedRect, image ); - } -} - -//! Wrapper for QPainter::drawPixmap() -void QwtPainter::drawPixmap( QPainter *painter, - const QRectF &rect, const QPixmap &pixmap ) -{ - const QRect alignedRect = rect.toAlignedRect(); - - if ( alignedRect != rect ) - { - 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 - { - painter->drawPixmap( alignedRect, pixmap ); - } -} - -//! Draw a focus rectangle on a widget using its style. -void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget ) -{ - drawFocusRect( painter, widget, widget->rect() ); -} - -//! Draw a focus rectangle on a widget using its style. -void QwtPainter::drawFocusRect( QPainter *painter, const 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 round frame - - \param painter Painter - \param rect Frame rectangle - \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::drawRoundFrame( QPainter *painter, - const QRectF &rect, const QPalette &palette, - int lineWidth, int frameStyle ) -{ - 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; - - const double lw2 = 0.5 * lineWidth; - QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 ); - - QBrush brush; - - if ( style != Plain ) - { - QColor c1 = palette.color( QPalette::Light ); - QColor c2 = palette.color( QPalette::Dark ); - - if ( style == 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 - gradient.setColorAt( 1.0, c2 ); - - brush = QBrush( gradient ); - } - else // Plain - { - brush = palette.brush( QPalette::WindowText ); - } - - painter->save(); - - painter->setPen( QPen( brush, lineWidth ) ); - painter->setBrush( Qt::NoBrush ); - - painter->drawEllipse( r ); - - painter->restore(); -} - -/*! - Draw a rectangular frame - - \param painter Painter - \param rect Frame rectangle - \param palette Palette - \param foregroundRole Foreground role used for QFrame::Plain - \param frameWidth Frame width - \param midLineWidth Used for QFrame::Box - \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow -*/ -void QwtPainter::drawFrame( QPainter *painter, const QRectF &rect, - const QPalette &palette, QPalette::ColorRole foregroundRole, - int frameWidth, int midLineWidth, int frameStyle ) -{ - if ( frameWidth <= 0 || rect.isEmpty() ) - return; - - const int shadow = frameStyle & QFrame::Shadow_Mask; - - painter->save(); - - if ( shadow == QFrame::Plain ) - { - const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); - const QRectF innerRect = outerRect.adjusted( - frameWidth, frameWidth, -frameWidth, -frameWidth ); - - QPainterPath path; - path.addRect( outerRect ); - path.addRect( innerRect ); - - painter->setPen( Qt::NoPen ); - painter->setBrush( palette.color( foregroundRole ) ); - - painter->drawPath( path ); - } - else - { - const int shape = frameStyle & QFrame::Shape_Mask; - - if ( shape == QFrame::Box ) - { - const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); - const QRectF midRect1 = outerRect.adjusted( - frameWidth, frameWidth, -frameWidth, -frameWidth ); - const QRectF midRect2 = midRect1.adjusted( - midLineWidth, midLineWidth, -midLineWidth, -midLineWidth ); - - const QRectF innerRect = midRect2.adjusted( - frameWidth, frameWidth, -frameWidth, -frameWidth ); - - QPainterPath path1; - path1.moveTo( outerRect.bottomLeft() ); - path1.lineTo( outerRect.topLeft() ); - path1.lineTo( outerRect.topRight() ); - path1.lineTo( midRect1.topRight() ); - path1.lineTo( midRect1.topLeft() ); - path1.lineTo( midRect1.bottomLeft() ); - - QPainterPath path2; - path2.moveTo( outerRect.bottomLeft() ); - path2.lineTo( outerRect.bottomRight() ); - path2.lineTo( outerRect.topRight() ); - path2.lineTo( midRect1.topRight() ); - path2.lineTo( midRect1.bottomRight() ); - path2.lineTo( midRect1.bottomLeft() ); - - QPainterPath path3; - path3.moveTo( midRect2.bottomLeft() ); - path3.lineTo( midRect2.topLeft() ); - path3.lineTo( midRect2.topRight() ); - path3.lineTo( innerRect.topRight() ); - path3.lineTo( innerRect.topLeft() ); - path3.lineTo( innerRect.bottomLeft() ); - - QPainterPath path4; - path4.moveTo( midRect2.bottomLeft() ); - path4.lineTo( midRect2.bottomRight() ); - path4.lineTo( midRect2.topRight() ); - path4.lineTo( innerRect.topRight() ); - path4.lineTo( innerRect.bottomRight() ); - path4.lineTo( innerRect.bottomLeft() ); - - QPainterPath path5; - path5.addRect( midRect1 ); - path5.addRect( midRect2 ); - - painter->setPen( Qt::NoPen ); - - QBrush brush1 = palette.dark().color(); - QBrush brush2 = palette.light().color(); - - if ( shadow == QFrame::Raised ) - qSwap( brush1, brush2 ); - - painter->setBrush( brush1 ); - painter->drawPath( path1 ); - painter->drawPath( path4 ); - - painter->setBrush( brush2 ); - painter->drawPath( path2 ); - painter->drawPath( path3 ); - - painter->setBrush( palette.mid() ); - painter->drawPath( path5 ); - } -#if 0 - // qDrawWinPanel doesn't result in something nice - // on a scalable document like PDF. Better draw a - // Panel. - - else if ( shape == QFrame::WinPanel ) - { - painter->setRenderHint( QPainter::NonCosmeticDefaultPen, true ); - qDrawWinPanel ( painter, rect.toRect(), palette, - frameStyle & QFrame::Sunken ); - } - else if ( shape == QFrame::StyledPanel ) - { - } -#endif - else - { - const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); - const QRectF innerRect = outerRect.adjusted( - frameWidth - 1.0, frameWidth - 1.0, - -( frameWidth - 1.0 ), -( frameWidth - 1.0 ) ); - - QPainterPath path1; - path1.moveTo( outerRect.bottomLeft() ); - path1.lineTo( outerRect.topLeft() ); - path1.lineTo( outerRect.topRight() ); - path1.lineTo( innerRect.topRight() ); - path1.lineTo( innerRect.topLeft() ); - path1.lineTo( innerRect.bottomLeft() ); - - - QPainterPath path2; - path2.moveTo( outerRect.bottomLeft() ); - path2.lineTo( outerRect.bottomRight() ); - path2.lineTo( outerRect.topRight() ); - path2.lineTo( innerRect.topRight() ); - path2.lineTo( innerRect.bottomRight() ); - path2.lineTo( innerRect.bottomLeft() ); - - painter->setPen( Qt::NoPen ); - - QBrush brush1 = palette.dark().color(); - QBrush brush2 = palette.light().color(); - - if ( shadow == QFrame::Raised ) - qSwap( brush1, brush2 ); - - painter->setBrush( brush1 ); - painter->drawPath( path1 ); - - painter->setBrush( brush2 ); - painter->drawPath( path2 ); - } - - } - - painter->restore(); -} - -/*! - Draw a rectangular 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.setCapStyle( Qt::FlatCap ); - arcPen.setWidth( lineWidth ); - - QPen linePen; - linePen.setCapStyle( Qt::FlatCap ); - 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 QRectF &rect ) -{ - QVector<QRgb> colorTable; - if ( colorMap.format() == QwtColorMap::Indexed ) - colorTable = colorMap.colorTable( interval ); - - QColor c; - - 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() ); - pixmap.fill( Qt::transparent ); - - QPainter pmPainter( &pixmap ); - pmPainter.translate( -devRect.x(), -devRect.y() ); - - if ( orientation == Qt::Horizontal ) - { - QwtScaleMap sMap = scaleMap; - sMap.setPaintInterval( rect.left(), rect.right() ); - - for ( int x = devRect.left(); x <= devRect.right(); x++ ) - { - const double value = sMap.invTransform( x ); - - if ( colorMap.format() == QwtColorMap::RGB ) - c.setRgba( colorMap.rgb( interval, value ) ); - else - c = colorTable[colorMap.colorIndex( interval, value )]; - - pmPainter.setPen( c ); - pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() ); - } - } - else // Vertical - { - QwtScaleMap sMap = scaleMap; - sMap.setPaintInterval( rect.bottom(), rect.top() ); - - for ( int y = devRect.top(); y <= devRect.bottom(); y++ ) - { - const double value = sMap.invTransform( y ); - - if ( colorMap.format() == QwtColorMap::RGB ) - c.setRgba( colorMap.rgb( interval, value ) ); - else - c = colorTable[colorMap.colorIndex( interval, value )]; - - pmPainter.setPen( c ); - pmPainter.drawLine( devRect.left(), y, devRect.right(), y ); - } - } - pmPainter.end(); - - drawPixmap( painter, rect, pixmap ); -} - -static inline void qwtFillRect( const QWidget *widget, QPainter *painter, - const QRect &rect, const QBrush &brush) -{ - if ( brush.style() == Qt::TexturePattern ) - { - painter->save(); - - painter->setClipRect( rect ); - painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); - - painter->restore(); - } - else if ( brush.gradient() ) - { - painter->save(); - - painter->setClipRect( rect ); - painter->fillRect(0, 0, widget->width(), - widget->height(), brush); - - painter->restore(); - } - else - { - painter->fillRect(rect, brush); - } -} - -/*! - Fill a pixmap with the content of a widget - - In Qt >= 5.0 QPixmap::fill() is a nop, in Qt 4.x it is buggy - for backgrounds with gradients. Thus fillPixmap() offers - an alternative implementation. - - \param widget Widget - \param pixmap Pixmap to be filled - \param offset Offset - - \sa QPixmap::fill() - */ -void QwtPainter::fillPixmap( const QWidget *widget, - QPixmap &pixmap, const QPoint &offset ) -{ - const QRect rect( offset, pixmap.size() ); - - QPainter painter( &pixmap ); - painter.translate( -offset ); - - const QBrush autoFillBrush = - widget->palette().brush( widget->backgroundRole() ); - - if ( !( widget->autoFillBackground() && autoFillBrush.isOpaque() ) ) - { - const QBrush bg = widget->palette().brush( QPalette::Window ); - qwtFillRect( widget, &painter, rect, bg); - } - - if ( widget->autoFillBackground() ) - qwtFillRect( widget, &painter, rect, autoFillBrush); - - if ( widget->testAttribute(Qt::WA_StyledBackground) ) - { - painter.setClipRegion( rect ); - - QStyleOption opt; - opt.initFrom( widget ); - widget->style()->drawPrimitive( QStyle::PE_Widget, - &opt, &painter, widget ); - } -} - -/*! - Fill rect with the background of a widget - - \param painter Painter - \param rect Rectangle to be filled - \param widget Widget - - \sa QStyle::PE_Widget, QWidget::backgroundRole() - */ -void QwtPainter::drawBackgound( QPainter *painter, - const QRectF &rect, const QWidget *widget ) -{ - if ( widget->testAttribute( Qt::WA_StyledBackground ) ) - { - QStyleOption opt; - opt.initFrom( widget ); - opt.rect = rect.toAlignedRect(); - - widget->style()->drawPrimitive( - QStyle::PE_Widget, &opt, painter, widget); - } - else - { - const QBrush brush = - widget->palette().brush( widget->backgroundRole() ); - - painter->fillRect( rect, brush ); - } -} - -/*! - \return A pixmap that can be used as backing store - - \param widget Widget, for which the backinstore is intended - \param size Size of the pixmap - */ -QPixmap QwtPainter::backingStore( QWidget *widget, const QSize &size ) -{ - QPixmap pm; - -#define QWT_HIGH_DPI 1 - -#if QT_VERSION >= 0x050000 && QWT_HIGH_DPI - qreal pixelRatio = 1.0; - - if ( widget && widget->windowHandle() ) - { -#if QT_VERSION < 0x050100 - pixelRatio = widget->windowHandle()->devicePixelRatio(); -#else - pixelRatio = widget->devicePixelRatio(); -#endif - } - else - { - if ( qApp ) - pixelRatio = qApp->devicePixelRatio(); - } - - pm = QPixmap( size * pixelRatio ); - pm.setDevicePixelRatio( pixelRatio ); -#else - Q_UNUSED( widget ) - pm = QPixmap( size ); -#endif - -#if QT_VERSION < 0x050000 -#ifdef Q_WS_X11 - if ( widget && isX11GraphicsSystem() ) - { - if ( pm.x11Info().screen() != widget->x11Info().screen() ) - pm.x11SetScreen( widget->x11Info().screen() ); - } -#endif -#endif - - return pm; -} - diff --git a/source/third_party/qwt/qwt_painter_command.cpp b/source/third_party/qwt/qwt_painter_command.cpp deleted file mode 100644 index 951f4681868968eca75f75cda663fa424f0916d7..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_painter_command.cpp +++ /dev/null @@ -1,237 +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/qwt_painter_command.h" - -//! Construct an invalid command -QwtPainterCommand::QwtPainterCommand(): - d_type( Invalid ) -{ -} - -//! Copy constructor -QwtPainterCommand::QwtPainterCommand( const QPainterPath &path ): - d_type( Path ) -{ - d_path = new QPainterPath( path ); -} - -/*! - Constructor for Pixmap paint operation - - \param rect Target rectangle - \param pixmap Pixmap - \param subRect Rectangle inside the pixmap - - \sa QPainter::drawPixmap() - */ -QwtPainterCommand::QwtPainterCommand( const QRectF &rect, - const QPixmap &pixmap, const QRectF& subRect ): - d_type( Pixmap ) -{ - d_pixmapData = new PixmapData(); - d_pixmapData->rect = rect; - d_pixmapData->pixmap = pixmap; - d_pixmapData->subRect = subRect; -} - -/*! - Constructor for Image paint operation - - \param rect Target rectangle - \param image Image - \param subRect Rectangle inside the image - \param flags Conversion flags - - \sa QPainter::drawImage() - */ -QwtPainterCommand::QwtPainterCommand( const QRectF &rect, - const QImage &image, const QRectF& subRect, - Qt::ImageConversionFlags flags ): - d_type( Image ) -{ - d_imageData = new ImageData(); - d_imageData->rect = rect; - d_imageData->image = image; - d_imageData->subRect = subRect; - d_imageData->flags = flags; -} - -/*! - Constructor for State paint operation - \param state Paint engine state - */ -QwtPainterCommand::QwtPainterCommand( const QPaintEngineState &state ): - d_type( State ) -{ - d_stateData = new StateData(); - - d_stateData->flags = state.state(); - - if ( d_stateData->flags & QPaintEngine::DirtyPen ) - d_stateData->pen = state.pen(); - - if ( d_stateData->flags & QPaintEngine::DirtyBrush ) - d_stateData->brush = state.brush(); - - if ( d_stateData->flags & QPaintEngine::DirtyBrushOrigin ) - d_stateData->brushOrigin = state.brushOrigin(); - - if ( d_stateData->flags & QPaintEngine::DirtyFont ) - d_stateData->font = state.font(); - - if ( d_stateData->flags & QPaintEngine::DirtyBackground ) - { - d_stateData->backgroundMode = state.backgroundMode(); - d_stateData->backgroundBrush = state.backgroundBrush(); - } - - if ( d_stateData->flags & QPaintEngine::DirtyTransform ) - d_stateData->transform = state.transform(); - - if ( d_stateData->flags & QPaintEngine::DirtyClipEnabled ) - d_stateData->isClipEnabled = state.isClipEnabled(); - - if ( d_stateData->flags & QPaintEngine::DirtyClipRegion ) - { - d_stateData->clipRegion = state.clipRegion(); - d_stateData->clipOperation = state.clipOperation(); - } - - if ( d_stateData->flags & QPaintEngine::DirtyClipPath ) - { - d_stateData->clipPath = state.clipPath(); - d_stateData->clipOperation = state.clipOperation(); - } - - if ( d_stateData->flags & QPaintEngine::DirtyHints ) - d_stateData->renderHints = state.renderHints(); - - if ( d_stateData->flags & QPaintEngine::DirtyCompositionMode ) - d_stateData->compositionMode = state.compositionMode(); - - if ( d_stateData->flags & QPaintEngine::DirtyOpacity ) - d_stateData->opacity = state.opacity(); -} - -/*! - Copy constructor - \param other Command to be copied - - */ -QwtPainterCommand::QwtPainterCommand(const QwtPainterCommand &other) -{ - copy( other ); -} - -//! Destructor -QwtPainterCommand::~QwtPainterCommand() -{ - reset(); -} - -/*! - Assignment operator - - \param other Command to be copied - \return Modified command - */ -QwtPainterCommand &QwtPainterCommand::operator=(const QwtPainterCommand &other) -{ - reset(); - copy( other ); - - return *this; -} - -void QwtPainterCommand::copy( const QwtPainterCommand &other ) -{ - d_type = other.d_type; - - switch( other.d_type ) - { - case Path: - { - d_path = new QPainterPath( *other.d_path ); - break; - } - case Pixmap: - { - d_pixmapData = new PixmapData( *other.d_pixmapData ); - break; - } - case Image: - { - d_imageData = new ImageData( *other.d_imageData ); - break; - } - case State: - { - d_stateData = new StateData( *other.d_stateData ); - break; - } - default: - break; - } -} - -void QwtPainterCommand::reset() -{ - switch( d_type ) - { - case Path: - { - delete d_path; - break; - } - case Pixmap: - { - delete d_pixmapData; - break; - } - case Image: - { - delete d_imageData; - break; - } - case State: - { - delete d_stateData; - break; - } - default: - break; - } - - d_type = Invalid; -} - -//! \return Painter path to be painted -QPainterPath *QwtPainterCommand::path() -{ - return d_path; -} - -//! \return Attributes how to paint a QPixmap -QwtPainterCommand::PixmapData* QwtPainterCommand::pixmapData() -{ - return d_pixmapData; -} - -//! \return Attributes how to paint a QImage -QwtPainterCommand::ImageData* QwtPainterCommand::imageData() -{ - return d_imageData; -} - -//! \return Attributes of a state change -QwtPainterCommand::StateData* QwtPainterCommand::stateData() -{ - return d_stateData; -} diff --git a/source/third_party/qwt/qwt_panner.cpp b/source/third_party/qwt/qwt_panner.cpp deleted file mode 100644 index 61205f16c481c35649e01d7fdac189a740dc7ecb..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_panner.cpp +++ /dev/null @@ -1,538 +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/qwt_panner.h" -#include "qwt/qwt_picker.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qpixmap.h> -#include <qevent.h> -#include <qcursor.h> -#include <qbitmap.h> - -static QVector<QwtPicker *> qwtActivePickers( QWidget *w ) -{ - QVector<QwtPicker *> pickers; - - QObjectList children = w->children(); - for ( int i = 0; i < children.size(); i++ ) - { - QwtPicker *picker = qobject_cast<QwtPicker *>( children[i] ); - if ( picker && picker->isEnabled() ) - pickers += picker; - } - - return pickers; -} - -class QwtPanner::PrivateData -{ -public: - PrivateData(): - button( Qt::LeftButton ), - buttonModifiers( Qt::NoModifier ), - abortKey( Qt::Key_Escape ), - abortKeyModifiers( Qt::NoModifier ), -#ifndef QT_NO_CURSOR - cursor( NULL ), - restoreCursor( NULL ), - hasCursor( false ), -#endif - isEnabled( false ) - { - orientations = Qt::Vertical | Qt::Horizontal; - } - - ~PrivateData() - { -#ifndef QT_NO_CURSOR - delete cursor; - delete restoreCursor; -#endif - } - - Qt::MouseButton button; - Qt::KeyboardModifiers buttonModifiers; - - int abortKey; - Qt::KeyboardModifiers abortKeyModifiers; - - QPoint initialPos; - QPoint pos; - - QPixmap pixmap; - QBitmap contentsMask; - -#ifndef QT_NO_CURSOR - QCursor *cursor; - QCursor *restoreCursor; - bool hasCursor; -#endif - bool isEnabled; - Qt::Orientations orientations; -}; - -/*! - Creates an panner that is enabled for the left mouse button. - - \param parent Parent widget to be panned -*/ -QwtPanner::QwtPanner( QWidget *parent ): - QWidget( parent ) -{ - d_data = new PrivateData(); - - setAttribute( Qt::WA_TransparentForMouseEvents ); - setAttribute( Qt::WA_NoSystemBackground ); - setFocusPolicy( Qt::NoFocus ); - hide(); - - setEnabled( true ); -} - -//! Destructor -QwtPanner::~QwtPanner() -{ - delete d_data; -} - -/*! - Change the mouse button and modifiers used for panning - The defaults are Qt::LeftButton and Qt::NoModifier -*/ -void QwtPanner::setMouseButton( Qt::MouseButton button, - Qt::KeyboardModifiers modifiers ) -{ - d_data->button = button; - d_data->buttonModifiers = modifiers; -} - -//! Get mouse button and modifiers used for panning -void QwtPanner::getMouseButton( Qt::MouseButton &button, - Qt::KeyboardModifiers &modifiers ) const -{ - button = d_data->button; - modifiers = d_data->buttonModifiers; -} - -/*! - Change the abort key - The defaults are Qt::Key_Escape and Qt::NoModifiers - - \param key Key ( See Qt::Keycode ) - \param modifiers Keyboard modifiers -*/ -void QwtPanner::setAbortKey( int key, - Qt::KeyboardModifiers modifiers ) -{ - d_data->abortKey = key; - d_data->abortKeyModifiers = modifiers; -} - -//! Get the abort key and modifiers -void QwtPanner::getAbortKey( int &key, - Qt::KeyboardModifiers &modifiers ) const -{ - key = d_data->abortKey; - modifiers = d_data->abortKeyModifiers; -} - -/*! - Change the cursor, that is active while panning - The default is the cursor of the parent widget. - - \param cursor New cursor - - \sa setCursor() -*/ -#ifndef QT_NO_CURSOR -void QwtPanner::setCursor( const QCursor &cursor ) -{ - d_data->cursor = new QCursor( cursor ); -} -#endif - -/*! - \return Cursor that is active while panning - \sa setCursor() -*/ -#ifndef QT_NO_CURSOR -const QCursor QwtPanner::cursor() const -{ - if ( d_data->cursor ) - return *d_data->cursor; - - if ( parentWidget() ) - return parentWidget()->cursor(); - - return QCursor(); -} -#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 ) -{ - if ( d_data->isEnabled != on ) - { - d_data->isEnabled = on; - - QWidget *w = parentWidget(); - if ( w ) - { - if ( d_data->isEnabled ) - { - w->installEventFilter( this ); - } - else - { - w->removeEventFilter( this ); - hide(); - } - } - } -} - -/*! - 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 ) -{ - d_data->orientations = o; -} - -//! Return the orientation, where paning is enabled -Qt::Orientations QwtPanner::orientations() const -{ - return d_data->orientations; -} - -/*! - \return True if an orientation is enabled - \sa orientations(), setOrientations() -*/ -bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const -{ - return d_data->orientations & o; -} - -/*! - \return true when enabled, false otherwise - \sa setEnabled, eventFilter() -*/ -bool QwtPanner::isEnabled() const -{ - return d_data->isEnabled; -} - -/*! - \brief Paint event - - Repaint the grabbed pixmap on its current position and - fill the empty spaces by the background of the parent widget. - - \param pe Paint event -*/ -void QwtPanner::paintEvent( QPaintEvent *pe ) -{ - 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 ) ); - - QPixmap pm( size() ); - QwtPainter::fillPixmap( parentWidget(), pm ); - - 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.end(); - - 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. - \return Grabbed pixmap -*/ -QPixmap QwtPanner::grab() const -{ -#if QT_VERSION >= 0x050000 - return parentWidget()->grab( parentWidget()->rect() ); -#else - return QPixmap::grabWidget( parentWidget() ); -#endif -} - -/*! - \brief Event filter - - When isEnabled() is true mouse events of the - observed widget are filtered. - - \param object Object to be filtered - \param event Event - - \return Always false, beside for paint events for the - parent widget. - - \sa widgetMousePressEvent(), widgetMouseReleaseEvent(), - widgetMouseMoveEvent() -*/ -bool QwtPanner::eventFilter( QObject *object, QEvent *event ) -{ - if ( object == NULL || object != parentWidget() ) - return false; - - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - widgetMousePressEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseMove: - { - widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseButtonRelease: - { - widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::KeyPress: - { - widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) ); - break; - } - case QEvent::KeyRelease: - { - widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) ); - break; - } - case QEvent::Paint: - { - if ( isVisible() ) - return true; - break; - } - default:; - } - - return false; -} - -/*! - Handle a mouse press event for the observed widget. - - \param mouseEvent Mouse event - \sa eventFilter(), widgetMouseReleaseEvent(), - widgetMouseMoveEvent(), -*/ -void QwtPanner::widgetMousePressEvent( QMouseEvent *mouseEvent ) -{ - if ( ( mouseEvent->button() != d_data->button ) - || ( mouseEvent->modifiers() != d_data->buttonModifiers ) ) - { - return; - } - - QWidget *w = parentWidget(); - if ( w == NULL ) - return; - -#ifndef QT_NO_CURSOR - showCursor( true ); -#endif - - d_data->initialPos = d_data->pos = mouseEvent->pos(); - - setGeometry( parentWidget()->rect() ); - - // We don't want to grab the picker ! - QVector<QwtPicker *> pickers = qwtActivePickers( parentWidget() ); - for ( int i = 0; i < pickers.size(); i++ ) - pickers[i]->setEnabled( false ); - - d_data->pixmap = grab(); - d_data->contentsMask = contentsMask(); - - for ( int i = 0; i < pickers.size(); i++ ) - pickers[i]->setEnabled( true ); - - show(); -} - -/*! - Handle a mouse move event for the observed widget. - - \param mouseEvent Mouse event - \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent() -*/ -void QwtPanner::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) -{ - if ( !isVisible() ) - return; - - 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 ) ) - { - d_data->pos = pos; - update(); - - 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 mouseEvent Mouse event - \sa eventFilter(), widgetMousePressEvent(), - widgetMouseMoveEvent(), -*/ -void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) -{ - if ( isVisible() ) - { - hide(); -#ifndef QT_NO_CURSOR - showCursor( false ); -#endif - - 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 ) - { - Q_EMIT panned( d_data->pos.x() - d_data->initialPos.x(), - d_data->pos.y() - d_data->initialPos.y() ); - } - } -} - -/*! - Handle a key press event for the observed widget. - - \param keyEvent Key event - \sa eventFilter(), widgetKeyReleaseEvent() -*/ -void QwtPanner::widgetKeyPressEvent( QKeyEvent *keyEvent ) -{ - if ( ( keyEvent->key() == d_data->abortKey ) - && ( keyEvent->modifiers() == d_data->abortKeyModifiers ) ) - { - hide(); - -#ifndef QT_NO_CURSOR - showCursor( false ); -#endif - d_data->pixmap = QPixmap(); - } -} - -/*! - Handle a key release event for the observed widget. - - \param keyEvent Key event - \sa eventFilter(), widgetKeyReleaseEvent() -*/ -void QwtPanner::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) -{ - Q_UNUSED( keyEvent ); -} - -#ifndef QT_NO_CURSOR -void QwtPanner::showCursor( bool on ) -{ - if ( on == d_data->hasCursor ) - return; - - QWidget *w = parentWidget(); - if ( w == NULL || d_data->cursor == NULL ) - return; - - d_data->hasCursor = on; - - if ( on ) - { - if ( w->testAttribute( Qt::WA_SetCursor ) ) - { - delete d_data->restoreCursor; - d_data->restoreCursor = new QCursor( w->cursor() ); - } - w->setCursor( *d_data->cursor ); - } - else - { - if ( d_data->restoreCursor ) - { - w->setCursor( *d_data->restoreCursor ); - delete d_data->restoreCursor; - d_data->restoreCursor = NULL; - } - else - w->unsetCursor(); - } -} -#endif diff --git a/source/third_party/qwt/qwt_picker.cpp b/source/third_party/qwt/qwt_picker.cpp deleted file mode 100644 index 5ae5ef13578ee96966c53dd6de11eefe396f3bc2..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_picker.cpp +++ /dev/null @@ -1,1593 +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/qwt_picker.h" -#include "qwt/qwt_picker_machine.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_widget_overlay.h" -#include <qapplication.h> -#include <qevent.h> -#include <qpainter.h> -#include <qframe.h> -#include <qcursor.h> -#include <qbitmap.h> -#include <qpointer.h> -#include <qpaintengine.h> -#include <qmath.h> - -static inline QRegion qwtMaskRegion( const QRect &r, int penWidth ) -{ - const int pw = qMax( penWidth, 1 ); - const int pw2 = penWidth / 2; - - int x1 = r.left() - pw2; - int x2 = r.right() + 1 + pw2 + ( pw % 2 ); - - int y1 = r.top() - pw2; - int y2 = r.bottom() + 1 + pw2 + ( pw % 2 ); - - QRegion region; - - region += QRect( x1, y1, x2 - x1, pw ); - region += QRect( x1, y1, pw, y2 - y1 ); - region += QRect( x1, y2 - pw, x2 - x1, pw ); - region += QRect( x2 - pw, y1, pw, y2 - y1 ); - - return region; -} - -static inline QRegion qwtMaskRegion( const QLine &l, int penWidth ) -{ - const int pw = qMax( penWidth, 1 ); - const int pw2 = penWidth / 2; - - QRegion region; - - if ( l.x1() == l.x2() ) - { - region += QRect( l.x1() - pw2, l.y1(), - pw, l.y2() ).normalized(); - } - else if ( l.y1() == l.y2() ) - { - region += QRect( l.x1(), l.y1() - pw2, - l.x2(), pw ).normalized(); - } - - return region; -} - -class QwtPickerRubberband: public QwtWidgetOverlay -{ -public: - QwtPickerRubberband( QwtPicker *, QWidget * ); - -protected: - virtual void drawOverlay( QPainter * ) const; - virtual QRegion maskHint() const; - - QwtPicker *d_picker; -}; - -class QwtPickerTracker: public QwtWidgetOverlay -{ -public: - QwtPickerTracker( QwtPicker *, QWidget * ); - -protected: - virtual void drawOverlay( QPainter * ) const; - virtual QRegion maskHint() const; - - QwtPicker *d_picker; -}; - - -class QwtPicker::PrivateData -{ -public: - PrivateData(): - enabled( false ), - stateMachine( NULL ), - resizeMode( QwtPicker::Stretch ), - rubberBand( QwtPicker::NoRubberBand ), - trackerMode( QwtPicker::AlwaysOff ), - isActive( false ), - trackerPosition( -1, -1 ), - mouseTracking( false ), - openGL( false ) - { - } - - bool enabled; - - QwtPickerMachine *stateMachine; - - QwtPicker::ResizeMode resizeMode; - - QwtPicker::RubberBand rubberBand; - QPen rubberBandPen; - - QwtPicker::DisplayMode trackerMode; - QPen trackerPen; - QFont trackerFont; - - QPolygon pickedPoints; - bool isActive; - QPoint trackerPosition; - - bool mouseTracking; // used to save previous value - - QPointer< QwtPickerRubberband > rubberBandOverlay; - QPointer< QwtPickerTracker> trackerOverlay; - - bool openGL; -}; - -QwtPickerRubberband::QwtPickerRubberband( - QwtPicker *picker, QWidget *parent ): - QwtWidgetOverlay( parent ), - d_picker( picker ) -{ - setMaskMode( QwtWidgetOverlay::MaskHint ); -} - -QRegion QwtPickerRubberband::maskHint() const -{ - return d_picker->rubberBandMask(); -} - -void QwtPickerRubberband::drawOverlay( QPainter *painter ) const -{ - painter->setPen( d_picker->rubberBandPen() ); - d_picker->drawRubberBand( painter ); -} - -QwtPickerTracker::QwtPickerTracker( - QwtPicker *picker, QWidget *parent ): - QwtWidgetOverlay( parent ), - d_picker( picker ) -{ - setMaskMode( QwtWidgetOverlay::MaskHint ); -} - -QRegion QwtPickerTracker::maskHint() const -{ - return d_picker->trackerRect( font() ); -} - -void QwtPickerTracker::drawOverlay( QPainter *painter ) const -{ - painter->setPen( d_picker->trackerPen() ); - d_picker->drawTracker( painter ); -} - -/*! - Constructor - - Creates an picker that is enabled, but without a state machine. - rubber band and tracker are disabled. - - \param parent Parent widget, that will be observed - */ - -QwtPicker::QwtPicker( QWidget *parent ): - QObject( parent ) -{ - init( parent, NoRubberBand, AlwaysOff ); -} - -/*! - Constructor - - \param rubberBand Rubber band style - \param trackerMode Tracker mode - \param parent Parent widget, that will be observed - */ -QwtPicker::QwtPicker( RubberBand rubberBand, - DisplayMode trackerMode, QWidget *parent ): - QObject( parent ) -{ - init( parent, rubberBand, trackerMode ); -} - -//! Destructor -QwtPicker::~QwtPicker() -{ - setMouseTracking( false ); - - delete d_data->stateMachine; - delete d_data->rubberBandOverlay; - delete d_data->trackerOverlay; - - delete d_data; -} - -//! Initialize the picker - used by the constructors -void QwtPicker::init( QWidget *parent, - RubberBand rubberBand, DisplayMode trackerMode ) -{ - d_data = new PrivateData; - - d_data->rubberBand = rubberBand; - - if ( parent ) - { - if ( parent->focusPolicy() == Qt::NoFocus ) - parent->setFocusPolicy( Qt::WheelFocus ); - - d_data->openGL = parent->inherits( "QGLWidget" ); - d_data->trackerFont = parent->font(); - d_data->mouseTracking = parent->hasMouseTracking(); - - setEnabled( true ); - } - - setTrackerMode( trackerMode ); -} - -/*! - Set a state machine and delete the previous one - - \param stateMachine State machine - \sa stateMachine() -*/ -void QwtPicker::setStateMachine( QwtPickerMachine *stateMachine ) -{ - if ( d_data->stateMachine != stateMachine ) - { - reset(); - - delete d_data->stateMachine; - d_data->stateMachine = stateMachine; - - if ( d_data->stateMachine ) - d_data->stateMachine->reset(); - } -} - -/*! - \return Assigned state machine - \sa setStateMachine() -*/ -QwtPickerMachine *QwtPicker::stateMachine() -{ - 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 -QWidget *QwtPicker::parentWidget() -{ - QObject *obj = parent(); - if ( obj && obj->isWidgetType() ) - return static_cast<QWidget *>( obj ); - - return NULL; -} - -//! Return the parent widget, where the selection happens -const QWidget *QwtPicker::parentWidget() const -{ - QObject *obj = parent(); - if ( obj && obj->isWidgetType() ) - return static_cast< const QWidget *>( obj ); - - return NULL; -} - -/*! - Set the rubber band style - - \param rubberBand Rubber band style - The default value is NoRubberBand. - - \sa rubberBand(), RubberBand, setRubberBandPen() -*/ -void QwtPicker::setRubberBand( RubberBand rubberBand ) -{ - d_data->rubberBand = rubberBand; -} - -/*! - \return Rubber band style - \sa setRubberBand(), RubberBand, rubberBandPen() -*/ -QwtPicker::RubberBand QwtPicker::rubberBand() const -{ - return d_data->rubberBand; -} - -/*! - \brief Set the display mode of the tracker. - - A tracker displays information about current position of - the cursor as a string. The display mode controls - 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 - for the observed widget. - \sa trackerMode(), DisplayMode -*/ - -void QwtPicker::setTrackerMode( DisplayMode mode ) -{ - if ( d_data->trackerMode != mode ) - { - d_data->trackerMode = mode; - 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. - - The resize mode controls what to do with the selected points of an active - selection when the observed widget is resized. - - Stretch means the points are scaled according to the new - size, KeepSize means the points remain unchanged. - - The default mode is Stretch. - - \param mode Resize mode - \sa resizeMode(), ResizeMode -*/ -void QwtPicker::setResizeMode( ResizeMode mode ) -{ - d_data->resizeMode = mode; -} - -/*! - \return Resize mode - \sa setResizeMode(), ResizeMode -*/ - -QwtPicker::ResizeMode QwtPicker::resizeMode() const -{ - return d_data->resizeMode; -} - -/*! - \brief En/disable the picker - - When enabled is true an event filter is installed for - the observed widget, otherwise the event filter is removed. - - \param enabled true or false - \sa isEnabled(), eventFilter() -*/ -void QwtPicker::setEnabled( bool enabled ) -{ - if ( d_data->enabled != enabled ) - { - d_data->enabled = enabled; - - QWidget *w = parentWidget(); - if ( w ) - { - if ( enabled ) - w->installEventFilter( this ); - else - w->removeEventFilter( this ); - } - - updateDisplay(); - } -} - -/*! - \return true when enabled, false otherwise - \sa setEnabled(), eventFilter() -*/ - -bool QwtPicker::isEnabled() const -{ - return d_data->enabled; -} - -/*! - Set the font for the tracker - - \param font Tracker font - \sa trackerFont(), setTrackerMode(), setTrackerPen() -*/ -void QwtPicker::setTrackerFont( const QFont &font ) -{ - if ( font != d_data->trackerFont ) - { - d_data->trackerFont = font; - updateDisplay(); - } -} - -/*! - \return Tracker font - \sa setTrackerFont(), trackerMode(), trackerPen() -*/ - -QFont QwtPicker::trackerFont() const -{ - return d_data->trackerFont; -} - -/*! - Set the pen for the tracker - - \param pen Tracker pen - \sa trackerPen(), setTrackerMode(), setTrackerFont() -*/ -void QwtPicker::setTrackerPen( const QPen &pen ) -{ - if ( pen != d_data->trackerPen ) - { - d_data->trackerPen = pen; - updateDisplay(); - } -} - -/*! - \return Tracker pen - \sa setTrackerPen(), trackerMode(), trackerFont() -*/ -QPen QwtPicker::trackerPen() const -{ - return d_data->trackerPen; -} - -/*! - Set the pen for the rubberband - - \param pen Rubber band pen - \sa rubberBandPen(), setRubberBand() -*/ -void QwtPicker::setRubberBandPen( const QPen &pen ) -{ - if ( pen != d_data->rubberBandPen ) - { - d_data->rubberBandPen = pen; - updateDisplay(); - } -} - -/*! - \return Rubber band pen - \sa setRubberBandPen(), rubberBand() -*/ -QPen QwtPicker::rubberBandPen() const -{ - return d_data->rubberBandPen; -} - -/*! - \brief Return the label for a position - - In case of HLineRubberBand the label is the value of the - y position, in case of VLineRubberBand the value of the x position. - Otherwise the label contains x and y position separated by a ',' . - - The format for the string conversion is "%d". - - \param pos Position - \return Converted position as string -*/ - -QwtText QwtPicker::trackerText( const QPoint &pos ) const -{ - QString label; - - switch ( rubberBand() ) - { - case HLineRubberBand: - label.sprintf( "%d", pos.y() ); - break; - case VLineRubberBand: - label.sprintf( "%d", pos.x() ); - break; - default: - label.sprintf( "%d, %d", pos.x(), pos.y() ); - } - return label; -} - -/*! - Calculate the mask for the rubber band overlay - - \return Region for the mask - \sa QWidget::setMask() - */ -QRegion QwtPicker::rubberBandMask() const -{ - QRegion mask; - - if ( !isActive() || rubberBand() == NoRubberBand || - rubberBandPen().style() == Qt::NoPen ) - { - return mask; - } - - const QPolygon pa = adjustedPoints( d_data->pickedPoints ); - - QwtPickerMachine::SelectionType selectionType = - QwtPickerMachine::NoSelection; - - if ( d_data->stateMachine ) - selectionType = d_data->stateMachine->selectionType(); - - switch ( selectionType ) - { - case QwtPickerMachine::NoSelection: - case QwtPickerMachine::PointSelection: - { - if ( pa.count() < 1 ) - return mask; - - const QPoint pos = pa[0]; - const int pw = rubberBandPen().width(); - - const QRect pRect = pickArea().boundingRect().toRect(); - switch ( rubberBand() ) - { - case VLineRubberBand: - { - mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), - pos.x(), pRect.bottom() ), pw ); - break; - } - case HLineRubberBand: - { - mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), - pRect.right(), pos.y() ), pw ); - break; - } - case CrossRubberBand: - { - mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), - pos.x(), pRect.bottom() ), pw ); - mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), - pRect.right(), pos.y() ), pw ); - break; - } - default: - break; - } - break; - } - case QwtPickerMachine::RectSelection: - { - if ( pa.count() < 2 ) - return mask; - - const int pw = rubberBandPen().width(); - - switch ( rubberBand() ) - { - case RectRubberBand: - { - const QRect r = QRect( pa.first(), pa.last() ); - mask = qwtMaskRegion( r.normalized(), pw ); - break; - } - case EllipseRubberBand: - { - const QRect r = QRect( pa.first(), pa.last() ); - mask += r.adjusted( -pw, -pw, pw, pw ); - break; - } - default: - break; - } - break; - } - case QwtPickerMachine::PolygonSelection: - { - const int pw = rubberBandPen().width(); - if ( pw <= 1 ) - { - // because of the join style we better - // return a mask for a pen width <= 1 only - - const int off = 2 * pw; - const QRect r = pa.boundingRect(); - mask += r.adjusted( -off, -off, off, off ); - } - break; - } - default: - break; - } - - return mask; -} - -/*! - Draw a rubber band, depending on rubberBand() - - \param painter Painter, initialized with a clip region - - \sa rubberBand(), RubberBand -*/ - -void QwtPicker::drawRubberBand( QPainter *painter ) const -{ - if ( !isActive() || rubberBand() == NoRubberBand || - rubberBandPen().style() == Qt::NoPen ) - { - return; - } - - const QPolygon pa = adjustedPoints( d_data->pickedPoints ); - - QwtPickerMachine::SelectionType selectionType = - QwtPickerMachine::NoSelection; - - if ( d_data->stateMachine ) - selectionType = d_data->stateMachine->selectionType(); - - switch ( selectionType ) - { - case QwtPickerMachine::NoSelection: - case QwtPickerMachine::PointSelection: - { - if ( pa.count() < 1 ) - return; - - const QPoint pos = pa[0]; - - const QRect pRect = pickArea().boundingRect().toRect(); - 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; - } - case QwtPickerMachine::RectSelection: - { - if ( pa.count() < 2 ) - return; - - const QRect rect = QRect( pa.first(), pa.last() ).normalized(); - switch ( rubberBand() ) - { - case EllipseRubberBand: - { - QwtPainter::drawEllipse( painter, rect ); - break; - } - case RectRubberBand: - { - QwtPainter::drawRect( painter, rect ); - break; - } - default: - break; - } - break; - } - case QwtPickerMachine::PolygonSelection: - { - if ( rubberBand() == PolygonRubberBand ) - painter->drawPolyline( pa ); - break; - } - default: - break; - } -} - -/*! - Draw the tracker - - \param painter Painter - \sa trackerRect(), trackerText() -*/ - -void QwtPicker::drawTracker( QPainter *painter ) const -{ - const QRect textRect = trackerRect( painter->font() ); - if ( !textRect.isEmpty() ) - { - const QwtText label = trackerText( d_data->trackerPosition ); - if ( !label.isEmpty() ) - 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 - - \param points Selected points - \return Selected points unmodified -*/ -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 -{ - return d_data->trackerPosition; -} - -/*! - Calculate the bounding rectangle for the tracker text - from the current position of the tracker - - \param font Font of the tracker text - \return Bounding rectangle of the tracker text - - \sa trackerPosition() -*/ -QRect QwtPicker::trackerRect( const QFont &font ) const -{ - if ( trackerMode() == AlwaysOff || - ( trackerMode() == ActiveOnly && !isActive() ) ) - { - return QRect(); - } - - if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) - return QRect(); - - QwtText text = trackerText( d_data->trackerPosition ); - if ( text.isEmpty() ) - return QRect(); - - 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->pickedPoints.count() > 1 - && rubberBand() != NoRubberBand ) - { - 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; - } - else - alignment = Qt::AlignTop | Qt::AlignRight; - - const int margin = 5; - - int x = pos.x(); - if ( alignment & Qt::AlignLeft ) - x -= textRect.width() + margin; - else if ( alignment & Qt::AlignRight ) - x += margin; - - int y = pos.y(); - if ( alignment & Qt::AlignBottom ) - y += margin; - else if ( alignment & Qt::AlignTop ) - y -= textRect.height() + margin; - - textRect.moveTopLeft( QPoint( x, y ) ); - - const QRect pickRect = pickArea().boundingRect().toRect(); - - 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; -} - -/*! - \brief Event filter - - When isEnabled() is 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 - rubber band and tracker up to date. - - \param object Object to be filtered - \param event Event - - \return Always false. - - \sa widgetEnterEvent(), widgetLeaveEvent(), - widgetMousePressEvent(), widgetMouseReleaseEvent(), - widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), - widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent(), - QObject::installEventFilter(), QObject::event() -*/ -bool QwtPicker::eventFilter( QObject *object, QEvent *event ) -{ - if ( object && object == parentWidget() ) - { - switch ( event->type() ) - { - case QEvent::Resize: - { - const QResizeEvent *re = static_cast<QResizeEvent *>( event ); - - /* - Adding/deleting additional event filters inside of an event filter - is not safe dues to the implementation in Qt ( changing alist while iterating ). - So we create the overlays in a way, that they don't install en event filter - ( parent set to NULL ) and do the resizing here. - */ - if ( d_data->trackerOverlay ) - d_data->trackerOverlay->resize( re->size() ); - - if ( d_data->rubberBandOverlay ) - d_data->rubberBandOverlay->resize( re->size() ); - - if ( d_data->resizeMode == Stretch ) - stretchSelection( re->oldSize(), re->size() ); - - updateDisplay(); - break; - } - case QEvent::Enter: - { - widgetEnterEvent( event ); - break; - } - case QEvent::Leave: - { - widgetLeaveEvent( event ); - break; - } - case QEvent::MouseButtonPress: - { - widgetMousePressEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseButtonRelease: - { - widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseButtonDblClick: - { - widgetMouseDoubleClickEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::MouseMove: - { - widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) ); - break; - } - case QEvent::KeyPress: - { - widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) ); - break; - } - case QEvent::KeyRelease: - { - widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) ); - break; - } - case QEvent::Wheel: - { - widgetWheelEvent( static_cast<QWheelEvent *>( event ) ); - break; - } - default: - break; - } - } - return false; -} - -/*! - Handle a mouse press event for the observed widget. - - \param mouseEvent Mouse event - - \sa eventFilter(), widgetMouseReleaseEvent(), - widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), - widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() -*/ -void QwtPicker::widgetMousePressEvent( QMouseEvent *mouseEvent ) -{ - transition( mouseEvent ); -} - -/*! - Handle a mouse move event for the observed widget. - - \param mouseEvent Mouse event - - \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), - widgetMouseDoubleClickEvent(), - widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() -*/ -void QwtPicker::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) -{ - if ( pickArea().contains( mouseEvent->pos() ) ) - d_data->trackerPosition = mouseEvent->pos(); - else - d_data->trackerPosition = QPoint( -1, -1 ); - - if ( !isActive() ) - updateDisplay(); - - 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 *event ) -{ - transition( event ); - - d_data->trackerPosition = QPoint( -1, -1 ); - if ( !isActive() ) - updateDisplay(); -} - -/*! - Handle a mouse release event for the observed widget. - - \param mouseEvent Mouse event - - \sa eventFilter(), widgetMousePressEvent(), - widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), - widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() -*/ -void QwtPicker::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) -{ - transition( mouseEvent ); -} - -/*! - Handle mouse double click event for the observed widget. - - \param mouseEvent Mouse event - - \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), - widgetMouseMoveEvent(), - widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() -*/ -void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent *mouseEvent ) -{ - 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 *wheelEvent ) -{ - if ( pickArea().contains( wheelEvent->pos() ) ) - d_data->trackerPosition = wheelEvent->pos(); - else - d_data->trackerPosition = QPoint( -1, -1 ); - - updateDisplay(); - - transition( wheelEvent ); -} - -/*! - Handle a key press event for the observed widget. - - Selections can be completely done by the keyboard. The arrow keys - move the cursor, the abort key aborts a selection. All other keys - are handled by the current state machine. - - \param keyEvent Key event - - \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), - widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), - widgetWheelEvent(), widgetKeyReleaseEvent(), stateMachine(), - QwtEventPattern::KeyPatternCode -*/ -void QwtPicker::widgetKeyPressEvent( QKeyEvent *keyEvent ) -{ - int dx = 0; - int dy = 0; - - int offset = 1; - if ( keyEvent->isAutoRepeat() ) - offset = 5; - - if ( keyMatch( KeyLeft, keyEvent ) ) - dx = -offset; - else if ( keyMatch( KeyRight, keyEvent ) ) - dx = offset; - else if ( keyMatch( KeyUp, keyEvent ) ) - dy = -offset; - else if ( keyMatch( KeyDown, keyEvent ) ) - dy = offset; - else if ( keyMatch( KeyAbort, keyEvent ) ) - { - reset(); - } - else - transition( keyEvent ); - - if ( dx != 0 || dy != 0 ) - { - const QRect rect = pickArea().boundingRect().toRect(); - const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() ); - - int x = pos.x() + dx; - x = qMax( rect.left(), x ); - x = qMin( rect.right(), x ); - - int y = pos.y() + dy; - y = qMax( rect.top(), y ); - y = qMin( rect.bottom(), 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 *keyEvent ) -{ - transition( keyEvent ); -} - -/*! - 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 event Event -*/ -void QwtPicker::transition( const QEvent *event ) -{ - if ( !d_data->stateMachine ) - return; - - const QList<QwtPickerMachine::Command> commandList = - d_data->stateMachine->transition( *this, event ); - - QPoint pos; - switch ( event->type() ) - { - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - { - const QMouseEvent *me = - static_cast< const QMouseEvent * >( event ); - pos = me->pos(); - break; - } - default: - pos = parentWidget()->mapFromGlobal( QCursor::pos() ); - } - - for ( int i = 0; i < commandList.count(); i++ ) - { - switch ( commandList[i] ) - { - case QwtPickerMachine::Begin: - { - begin(); - break; - } - case QwtPickerMachine::Append: - { - append( pos ); - break; - } - case QwtPickerMachine::Move: - { - move( pos ); - break; - } - case QwtPickerMachine::Remove: - { - remove(); - break; - } - case QwtPickerMachine::End: - { - end(); - break; - } - } - } -} - -/*! - Open a selection setting the state to active - - \sa isActive(), end(), append(), move() -*/ -void QwtPicker::begin() -{ - if ( d_data->isActive ) - return; - - 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 ) - { - QWidget *w = parentWidget(); - if ( w ) - d_data->trackerPosition = w->mapFromGlobal( QCursor::pos() ); - } - } - - updateDisplay(); - setMouseTracking( true ); -} - -/*! - \brief Close a selection setting the state to inactive. - - 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 ) -{ - if ( d_data->isActive ) - { - setMouseTracking( false ); - - d_data->isActive = false; - Q_EMIT activated( false ); - - if ( trackerMode() == ActiveOnly ) - d_data->trackerPosition = QPoint( -1, -1 ); - - if ( ok ) - ok = accept( d_data->pickedPoints ); - - if ( ok ) - Q_EMIT selected( d_data->pickedPoints ); - else - d_data->pickedPoints.resize( 0 ); - - updateDisplay(); - } - else - ok = false; - - return ok; -} - -/*! - Reset the state machine and terminate ( end(false) ) the selection -*/ -void QwtPicker::reset() -{ - if ( d_data->stateMachine ) - d_data->stateMachine->reset(); - - if ( isActive() ) - end( false ); -} - -/*! - Append a point to the selection and update rubber band and tracker. - The appended() signal is emitted. - - \param pos Additional point - - \sa isActive(), begin(), end(), move(), appended() -*/ -void QwtPicker::append( const QPoint &pos ) -{ - if ( d_data->isActive ) - { - const int idx = d_data->pickedPoints.count(); - d_data->pickedPoints.resize( idx + 1 ); - d_data->pickedPoints[idx] = pos; - - updateDisplay(); - Q_EMIT appended( pos ); - } -} - -/*! - Move the last point of the selection - The moved() signal is emitted. - - \param pos New position - \sa isActive(), begin(), end(), append() -*/ -void QwtPicker::move( const QPoint &pos ) -{ - if ( d_data->isActive ) - { - const int idx = d_data->pickedPoints.count() - 1; - if ( idx >= 0 ) - { - if ( d_data->pickedPoints[idx] != pos ) - { - d_data->pickedPoints[idx] = pos; - - updateDisplay(); - Q_EMIT moved( pos ); - } - } - } -} - -/*! - 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 fix up the selection - - Accepts all selections unmodified - - \param selection Selection to validate and fix up - \return true, when accepted, false otherwise -*/ -bool QwtPicker::accept( QPolygon &selection ) const -{ - Q_UNUSED( selection ); - return true; -} - -/*! - A picker is active between begin() and end(). - \return true if the selection is active. -*/ -bool QwtPicker::isActive() const -{ - return d_data->isActive; -} - -/*! - 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->pickedPoints; -} - -/*! - Scale the selection by the ratios of oldSize and newSize - The changed() signal is emitted. - - \param oldSize Previous size - \param newSize Current size - - \sa ResizeMode, setResizeMode(), resizeMode() -*/ -void QwtPicker::stretchSelection( const QSize &oldSize, const QSize &newSize ) -{ - if ( oldSize.isEmpty() ) - { - // 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() ); - const double yRatio = - double( newSize.height() ) / double( oldSize.height() ); - - for ( int i = 0; i < int( d_data->pickedPoints.count() ); i++ ) - { - QPoint &p = d_data->pickedPoints[i]; - p.setX( qRound( p.x() * xRatio ) ); - p.setY( qRound( p.y() * yRatio ) ); - - Q_EMIT changed( d_data->pickedPoints ); - } -} - -/*! - Set mouse tracking for the observed widget. - - In case of enable is true, the previous value - is saved, that is restored when enable is false. - - \warning Even when enable is false, mouse tracking might be restored - to true. When mouseTracking for the observed widget - has been changed directly by QWidget::setMouseTracking - while mouse tracking has been set to true, this value can't - be restored. -*/ - -void QwtPicker::setMouseTracking( bool enable ) -{ - QWidget *widget = parentWidget(); - if ( !widget ) - return; - - if ( enable ) - { - d_data->mouseTracking = widget->hasMouseTracking(); - widget->setMouseTracking( true ); - } - else - { - widget->setMouseTracking( d_data->mouseTracking ); - } -} - -/*! - Find the area of the observed widget, where selection might happen. - - \return parentWidget()->contentsRect() -*/ -QPainterPath QwtPicker::pickArea() const -{ - QPainterPath path; - - const QWidget *widget = parentWidget(); - if ( widget ) - path.addRect( widget->contentsRect() ); - - return path; -} - -//! Update the state of rubber band and tracker label -void QwtPicker::updateDisplay() -{ - QWidget *w = parentWidget(); - - bool showRubberband = false; - bool showTracker = false; - - if ( w && w->isVisible() && d_data->enabled ) - { - if ( rubberBand() != NoRubberBand && isActive() && - rubberBandPen().style() != Qt::NoPen ) - { - showRubberband = true; - } - - if ( trackerMode() == AlwaysOn || - ( trackerMode() == ActiveOnly && isActive() ) ) - { - if ( trackerPen() != Qt::NoPen - && !trackerRect( QFont() ).isEmpty() ) - { - showTracker = true; - } - } - } - - QPointer< QwtPickerRubberband > &rw = d_data->rubberBandOverlay; - if ( showRubberband ) - { - if ( rw.isNull() ) - { - rw = new QwtPickerRubberband( this, NULL ); // NULL -> no extra event filter - rw->setObjectName( "PickerRubberBand" ); - rw->setParent( w ); - rw->resize( w->size() ); - } - - if ( d_data->rubberBand <= RectRubberBand ) - rw->setMaskMode( QwtWidgetOverlay::MaskHint ); - else - rw->setMaskMode( QwtWidgetOverlay::AlphaMask ); - - rw->updateOverlay(); - } - else - { - if ( d_data->openGL ) - { - // Qt 4.8 crashes for a delete - if ( !rw.isNull() ) - { - rw->hide(); - rw->deleteLater(); - rw = NULL; - } - } - else - { - delete rw; - } - } - - QPointer< QwtPickerTracker > &tw = d_data->trackerOverlay; - if ( showTracker ) - { - if ( tw.isNull() ) - { - tw = new QwtPickerTracker( this, NULL ); // NULL -> no extra event filter - tw->setObjectName( "PickerTracker" ); - tw->setParent( w ); - tw->resize( w->size() ); - } - tw->setFont( d_data->trackerFont ); - tw->updateOverlay(); - } - else - { - if ( d_data->openGL ) - { - // Qt 4.8 crashes for a delete - if ( !tw.isNull() ) - { - tw->hide(); - tw->deleteLater(); - tw = NULL; - } - } - else - { - delete tw; - } - } -} - -//! \return Overlay displaying the rubber band -const QwtWidgetOverlay *QwtPicker::rubberBandOverlay() const -{ - return d_data->rubberBandOverlay; -} - -//! \return Overlay displaying the tracker text -const QwtWidgetOverlay *QwtPicker::trackerOverlay() const -{ - return d_data->trackerOverlay; -} - diff --git a/source/third_party/qwt/qwt_picker_machine.cpp b/source/third_party/qwt/qwt_picker_machine.cpp deleted file mode 100644 index d023485fed7b88a7b570664a3cb7edce1c5f4df6..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_picker_machine.cpp +++ /dev/null @@ -1,541 +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/qwt_picker_machine.h" -#include "qwt/qwt_event_pattern.h" -#include <qevent.h> - -//! Constructor -QwtPickerMachine::QwtPickerMachine( SelectionType type ): - d_selectionType( type ), - d_state( 0 ) -{ -} - -//! Destructor -QwtPickerMachine::~QwtPickerMachine() -{ -} - -//! Return the selection type -QwtPickerMachine::SelectionType QwtPickerMachine::selectionType() const -{ - return d_selectionType; -} - -//! Return the current state -int QwtPickerMachine::state() const -{ - return d_state; -} - -//! Change the current state -void QwtPickerMachine::setState( int state ) -{ - d_state = state; -} - -//! Set the current state to 0. -void QwtPickerMachine::reset() -{ - setState( 0 ); -} - -//! Constructor -QwtPickerTrackerMachine::QwtPickerTrackerMachine(): - QwtPickerMachine( NoSelection ) -{ -} - -//! Transition -QList<QwtPickerMachine::Command> QwtPickerTrackerMachine::transition( - const QwtEventPattern &, const QEvent *e ) -{ - QList<QwtPickerMachine::Command> cmdList; - - 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<QwtPickerMachine::Command> QwtPickerClickPointMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *event ) -{ - QList<QwtPickerMachine::Command> cmdList; - - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - cmdList += Begin; - cmdList += Append; - cmdList += End; - } - break; - } - case QEvent::KeyPress: - { - const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event ); - if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) - { - if ( !keyEvent->isAutoRepeat() ) - { - cmdList += Begin; - cmdList += Append; - cmdList += End; - } - } - break; - } - default: - break; - } - - return cmdList; -} - -//! Constructor -QwtPickerDragPointMachine::QwtPickerDragPointMachine(): - QwtPickerMachine( PointSelection ) -{ -} - -//! Transition -QList<QwtPickerMachine::Command> QwtPickerDragPointMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *event ) -{ - QList<QwtPickerMachine::Command> cmdList; - - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - setState( 1 ); - } - } - break; - } - case QEvent::MouseMove: - case QEvent::Wheel: - { - if ( state() != 0 ) - cmdList += Move; - break; - } - case QEvent::MouseButtonRelease: - { - if ( state() != 0 ) - { - cmdList += End; - setState( 0 ); - } - break; - } - case QEvent::KeyPress: - { - const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event ); - if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) - { - if ( !keyEvent->isAutoRepeat() ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - setState( 1 ); - } - else - { - cmdList += End; - setState( 0 ); - } - } - } - break; - } - default: - break; - } - - return cmdList; -} - -//! Constructor -QwtPickerClickRectMachine::QwtPickerClickRectMachine(): - QwtPickerMachine( RectSelection ) -{ -} - -//! Transition -QList<QwtPickerMachine::Command> QwtPickerClickRectMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *event ) -{ - QList<QwtPickerMachine::Command> cmdList; - - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - switch ( state() ) - { - case 0: - { - cmdList += Begin; - cmdList += Append; - setState( 1 ); - break; - } - case 1: - { - // Uh, strange we missed the MouseButtonRelease - break; - } - default: - { - cmdList += End; - setState( 0 ); - } - } - } - break; - } - case QEvent::MouseMove: - case QEvent::Wheel: - { - if ( state() != 0 ) - cmdList += Move; - break; - } - case QEvent::MouseButtonRelease: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - if ( state() == 1 ) - { - cmdList += Append; - setState( 2 ); - } - } - break; - } - case QEvent::KeyPress: - { - const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event ); - if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) - { - if ( !keyEvent->isAutoRepeat() ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - setState( 1 ); - } - else - { - if ( state() == 1 ) - { - cmdList += Append; - setState( 2 ); - } - else if ( state() == 2 ) - { - cmdList += End; - setState( 0 ); - } - } - } - } - break; - } - default: - break; - } - - return cmdList; -} - -//! Constructor -QwtPickerDragRectMachine::QwtPickerDragRectMachine(): - QwtPickerMachine( RectSelection ) -{ -} - -//! Transition -QList<QwtPickerMachine::Command> QwtPickerDragRectMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *event ) -{ - QList<QwtPickerMachine::Command> cmdList; - - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - cmdList += Append; - setState( 2 ); - } - } - break; - } - case QEvent::MouseMove: - case QEvent::Wheel: - { - if ( state() != 0 ) - cmdList += Move; - break; - } - case QEvent::MouseButtonRelease: - { - if ( state() == 2 ) - { - cmdList += End; - setState( 0 ); - } - break; - } - case QEvent::KeyPress: - { - if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, - static_cast<const QKeyEvent *> ( event ) ) ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - cmdList += Append; - setState( 2 ); - } - else - { - cmdList += End; - setState( 0 ); - } - } - break; - } - default: - break; - } - - return cmdList; -} - -//! Constructor -QwtPickerPolygonMachine::QwtPickerPolygonMachine(): - QwtPickerMachine( PolygonSelection ) -{ -} - -//! Transition -QList<QwtPickerMachine::Command> QwtPickerPolygonMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *event ) -{ - QList<QwtPickerMachine::Command> cmdList; - - switch ( event->type() ) - { - case QEvent::MouseButtonPress: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - cmdList += Append; - setState( 1 ); - } - else - { - cmdList += Append; - } - } - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect2, - static_cast<const QMouseEvent *>( event ) ) ) - { - if ( state() == 1 ) - { - cmdList += End; - setState( 0 ); - } - } - break; - } - case QEvent::MouseMove: - case QEvent::Wheel: - { - if ( state() != 0 ) - cmdList += Move; - break; - } - case QEvent::KeyPress: - { - const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event ); - if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) - { - if ( !keyEvent->isAutoRepeat() ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - cmdList += Append; - setState( 1 ); - } - else - { - cmdList += Append; - } - } - } - else if ( eventPattern.keyMatch( QwtEventPattern::KeySelect2, keyEvent ) ) - { - if ( !keyEvent->isAutoRepeat() ) - { - if ( state() == 1 ) - { - cmdList += End; - setState( 0 ); - } - } - } - break; - } - default: - break; - } - - return cmdList; -} - -//! Constructor -QwtPickerDragLineMachine::QwtPickerDragLineMachine(): - QwtPickerMachine( PolygonSelection ) -{ -} - -//! Transition -QList<QwtPickerMachine::Command> QwtPickerDragLineMachine::transition( - const QwtEventPattern &eventPattern, const QEvent *event ) -{ - QList<QwtPickerMachine::Command> cmdList; - - switch( event->type() ) - { - case QEvent::MouseButtonPress: - { - if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, - static_cast<const QMouseEvent *>( event ) ) ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - cmdList += Append; - setState( 1 ); - } - } - break; - } - case QEvent::KeyPress: - { - if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, - static_cast<const QKeyEvent *> ( event ) ) ) - { - if ( state() == 0 ) - { - cmdList += Begin; - cmdList += Append; - cmdList += Append; - setState( 1 ); - } - else - { - cmdList += End; - setState( 0 ); - } - } - break; - } - case QEvent::MouseMove: - case QEvent::Wheel: - { - if ( state() != 0 ) - cmdList += Move; - - break; - } - case QEvent::MouseButtonRelease: - { - if ( state() != 0 ) - { - cmdList += End; - setState( 0 ); - } - } - default: - break; - } - - return cmdList; -} diff --git a/source/third_party/qwt/qwt_pixel_matrix.cpp b/source/third_party/qwt/qwt_pixel_matrix.cpp deleted file mode 100644 index a6191c5a44db23daf48cc16ba12cde64ca8909df..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_pixel_matrix.cpp +++ /dev/null @@ -1,51 +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/qwt_pixel_matrix.h" - -/*! - \brief Constructor - - \param rect Bounding rectangle for the matrix -*/ -QwtPixelMatrix::QwtPixelMatrix( const QRect& rect ): - QBitArray( qMax( rect.width() * rect.height(), 0 ) ), - d_rect( rect ) -{ -} - -//! Destructor -QwtPixelMatrix::~QwtPixelMatrix() -{ -} - -/*! - Set the bounding rectangle of the matrix - - \param rect Bounding rectangle - - \note All bits are cleared - */ -void QwtPixelMatrix::setRect( const QRect& rect ) -{ - if ( rect != d_rect ) - { - d_rect = rect; - const int sz = qMax( rect.width() * rect.height(), 0 ); - resize( sz ); - } - - fill( false ); -} - -//! \return Bounding rectangle -QRect QwtPixelMatrix::rect() const -{ - return d_rect; -} diff --git a/source/third_party/qwt/qwt_plot.cpp b/source/third_party/qwt/qwt_plot.cpp deleted file mode 100644 index 6349ee88a06424f2afd4de4a33174e30cb1b13d7..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot.cpp +++ /dev/null @@ -1,1176 +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/qwt_plot.h" -#include "qwt/qwt_plot_dict.h" -#include "qwt/qwt_plot_layout.h" -#include "qwt/qwt_scale_widget.h" -#include "qwt/qwt_scale_engine.h" -#include "qwt/qwt_text_label.h" -#include "qwt/qwt_legend.h" -#include "qwt/qwt_legend_data.h" -#include "qwt/qwt_plot_canvas.h" -#include <qmath.h> -#include <qpainter.h> -#include <qpointer.h> -#include <qpaintengine.h> -#include <qapplication.h> -#include <qevent.h> - -static inline void qwtEnableLegendItems( QwtPlot *plot, bool on ) -{ - if ( on ) - { - QObject::connect( - plot, SIGNAL( legendDataChanged( - const QVariant &, const QList<QwtLegendData> & ) ), - plot, SLOT( updateLegendItems( - const QVariant &, const QList<QwtLegendData> & ) ) ); - } - else - { - QObject::disconnect( - plot, SIGNAL( legendDataChanged( - const QVariant &, const QList<QwtLegendData> & ) ), - plot, SLOT( updateLegendItems( - const QVariant &, const QList<QwtLegendData> & ) ) ); - } -} - -static void qwtSetTabOrder( - QWidget *first, QWidget *second, bool withChildren ) -{ - QList<QWidget *> tabChain; - tabChain += first; - tabChain += second; - - if ( withChildren ) - { - QList<QWidget *> children = second->findChildren<QWidget *>(); - - QWidget *w = second->nextInFocusChain(); - while ( children.contains( w ) ) - { - children.removeAll( w ); - - tabChain += w; - w = w->nextInFocusChain(); - } - } - - for ( int i = 0; i < tabChain.size() - 1; i++ ) - { - QWidget *from = tabChain[i]; - QWidget *to = tabChain[i+1]; - - const Qt::FocusPolicy policy1 = from->focusPolicy(); - const Qt::FocusPolicy policy2 = to->focusPolicy(); - - QWidget *proxy1 = from->focusProxy(); - QWidget *proxy2 = to->focusProxy(); - - from->setFocusPolicy( Qt::TabFocus ); - from->setFocusProxy( NULL); - - to->setFocusPolicy( Qt::TabFocus ); - to->setFocusProxy( NULL); - - QWidget::setTabOrder( from, to ); - - from->setFocusPolicy( policy1 ); - from->setFocusProxy( proxy1); - - to->setFocusPolicy( policy2 ); - to->setFocusProxy( proxy2 ); - } -} - -class QwtPlot::PrivateData -{ -public: - QPointer<QwtTextLabel> titleLabel; - QPointer<QwtTextLabel> footerLabel; - QPointer<QWidget> canvas; - QPointer<QwtAbstractLegend> legend; - QwtPlotLayout *layout; - - bool autoReplot; -}; - -/*! - \brief Constructor - \param parent Parent widget - */ -QwtPlot::QwtPlot( QWidget *parent ): - QFrame( parent ) -{ - initPlot( QwtText() ); -} - -/*! - \brief Constructor - \param title Title text - \param parent Parent widget - */ -QwtPlot::QwtPlot( const QwtText &title, QWidget *parent ): - QFrame( parent ) -{ - initPlot( title ); -} - -//! Destructor -QwtPlot::~QwtPlot() -{ - setAutoReplot( false ); - detachItems( QwtPlotItem::Rtti_PlotItem, autoDelete() ); - - delete d_data->layout; - deleteAxesData(); - delete d_data; -} - -/*! - \brief Initializes a QwtPlot instance - \param title Title text - */ -void QwtPlot::initPlot( const QwtText &title ) -{ - d_data = new PrivateData; - - d_data->layout = new QwtPlotLayout; - d_data->autoReplot = false; - - // title - d_data->titleLabel = new QwtTextLabel( this ); - d_data->titleLabel->setObjectName( "QwtPlotTitle" ); - d_data->titleLabel->setFont( QFont( fontInfo().family(), 14, QFont::Bold ) ); - - QwtText text( title ); - text.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap ); - d_data->titleLabel->setText( text ); - - // footer - d_data->footerLabel = new QwtTextLabel( this ); - d_data->footerLabel->setObjectName( "QwtPlotFooter" ); - - QwtText footer; - footer.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap ); - d_data->footerLabel->setText( footer ); - - // legend - d_data->legend = NULL; - - // axis - initAxesData(); - - // canvas - d_data->canvas = new QwtPlotCanvas( this ); - d_data->canvas->setObjectName( "QwtPlotCanvas" ); - d_data->canvas->installEventFilter( this ); - - setSizePolicy( QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding ); - - resize( 200, 200 ); - - QList<QWidget *> focusChain; - focusChain << this << d_data->titleLabel << axisWidget( xTop ) - << axisWidget( yLeft ) << d_data->canvas << axisWidget( yRight ) - << axisWidget( xBottom ) << d_data->footerLabel; - - for ( int i = 0; i < focusChain.size() - 1; i++ ) - qwtSetTabOrder( focusChain[i], focusChain[i+1], false ); - - qwtEnableLegendItems( this, true ); -} - -/*! - \brief Set the drawing canvas of the plot widget - - QwtPlot invokes methods of the canvas as meta methods ( see QMetaObject ). - In opposite to using conventional C++ techniques like virtual methods - they allow to use canvas implementations that are derived from - QWidget or QGLWidget. - - The following meta methods could be implemented: - - - replot() - When the canvas doesn't offer a replot method, QwtPlot calls - update() instead. - - - borderPath() - The border path is necessary to clip the content of the canvas - When the canvas doesn't have any special border ( f.e rounded corners ) - it is o.k. not to implement this method. - - The default canvas is a QwtPlotCanvas - - \param canvas Canvas Widget - \sa canvas() - */ -void QwtPlot::setCanvas( QWidget *canvas ) -{ - if ( canvas == d_data->canvas ) - return; - - delete d_data->canvas; - d_data->canvas = canvas; - - if ( canvas ) - { - canvas->setParent( this ); - canvas->installEventFilter( this ); - - if ( isVisible() ) - canvas->show(); - } -} - -/*! - \brief Adds handling of layout requests - \param event Event - - \return See QFrame::event() -*/ -bool QwtPlot::event( QEvent *event ) -{ - bool ok = QFrame::event( event ); - switch ( event->type() ) - { - case QEvent::LayoutRequest: - updateLayout(); - break; - case QEvent::PolishRequest: - replot(); - break; - default:; - } - return ok; -} - -/*! - \brief Event filter - - The plot handles the following events for the canvas: - - - QEvent::Resize - The canvas margins might depend on its size - - - QEvent::ContentsRectChange - The layout needs to be recalculated - - \param object Object to be filtered - \param event Event - - \return See QFrame::eventFilter() - - \sa updateCanvasMargins(), updateLayout() -*/ -bool QwtPlot::eventFilter( QObject *object, QEvent *event ) -{ - if ( object == d_data->canvas ) - { - if ( event->type() == QEvent::Resize ) - { - updateCanvasMargins(); - } - else if ( event->type() == QEvent::ContentsRectChange ) - { - updateLayout(); - } - } - - return QFrame::eventFilter( object, event ); -} - -//! Replots the plot if autoReplot() is \c true. -void QwtPlot::autoRefresh() -{ - if ( d_data->autoReplot ) - replot(); -} - -/*! - \brief Set or reset the autoReplot option - - If the autoReplot option is set, the plot will be - updated implicitly by manipulating member functions. - Since this may be time-consuming, it is recommended - to leave this option switched off and call replot() - explicitly if necessary. - - The autoReplot option is set to false by default, which - means that the user has to call replot() in order to make - changes visible. - \param tf \c true or \c false. Defaults to \c true. - \sa replot() -*/ -void QwtPlot::setAutoReplot( bool tf ) -{ - d_data->autoReplot = tf; -} - -/*! - \return true if the autoReplot option is set. - \sa setAutoReplot() -*/ -bool QwtPlot::autoReplot() const -{ - return d_data->autoReplot; -} - -/*! - Change the plot's title - \param title New title -*/ -void QwtPlot::setTitle( const QString &title ) -{ - if ( title != d_data->titleLabel->text().text() ) - { - d_data->titleLabel->setText( title ); - updateLayout(); - } -} - -/*! - Change the plot's title - \param title New title -*/ -void QwtPlot::setTitle( const QwtText &title ) -{ - if ( title != d_data->titleLabel->text() ) - { - d_data->titleLabel->setText( title ); - updateLayout(); - } -} - -//! \return Title of the plot -QwtText QwtPlot::title() const -{ - return d_data->titleLabel->text(); -} - -//! \return Title label widget. -QwtTextLabel *QwtPlot::titleLabel() -{ - return d_data->titleLabel; -} - -//! \return Title label widget. -const QwtTextLabel *QwtPlot::titleLabel() const -{ - return d_data->titleLabel; -} - -/*! - Change the text the footer - \param text New text of the footer -*/ -void QwtPlot::setFooter( const QString &text ) -{ - if ( text != d_data->footerLabel->text().text() ) - { - d_data->footerLabel->setText( text ); - updateLayout(); - } -} - -/*! - Change the text the footer - \param text New text of the footer -*/ -void QwtPlot::setFooter( const QwtText &text ) -{ - if ( text != d_data->footerLabel->text() ) - { - d_data->footerLabel->setText( text ); - updateLayout(); - } -} - -//! \return Text of the footer -QwtText QwtPlot::footer() const -{ - return d_data->footerLabel->text(); -} - -//! \return Footer label widget. -QwtTextLabel *QwtPlot::footerLabel() -{ - return d_data->footerLabel; -} - -//! \return Footer label widget. -const QwtTextLabel *QwtPlot::footerLabel() const -{ - return d_data->footerLabel; -} - -/*! - \brief Assign a new plot layout - - \param layout Layout() - \sa plotLayout() - */ -void QwtPlot::setPlotLayout( QwtPlotLayout *layout ) -{ - if ( layout != d_data->layout ) - { - delete d_data->layout; - d_data->layout = layout; - - updateLayout(); - } -} - -//! \return the plot's layout -QwtPlotLayout *QwtPlot::plotLayout() -{ - return d_data->layout; -} - -//! \return the plot's layout -const QwtPlotLayout *QwtPlot::plotLayout() const -{ - return d_data->layout; -} - -/*! - \return the plot's legend - \sa insertLegend() -*/ -QwtAbstractLegend *QwtPlot::legend() -{ - return d_data->legend; -} - -/*! - \return the plot's legend - \sa insertLegend() -*/ -const QwtAbstractLegend *QwtPlot::legend() const -{ - return d_data->legend; -} - - -/*! - \return the plot's canvas -*/ -QWidget *QwtPlot::canvas() -{ - return d_data->canvas; -} - -/*! - \return the plot's canvas -*/ -const QWidget *QwtPlot::canvas() const -{ - return d_data->canvas; -} - -/*! - \return Size hint for the plot widget - \sa minimumSizeHint() -*/ -QSize QwtPlot::sizeHint() const -{ - int dw = 0; - int dh = 0; - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - { - if ( axisEnabled( axisId ) ) - { - const int niceDist = 40; - const QwtScaleWidget *scaleWidget = axisWidget( axisId ); - const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv(); - const int majCnt = scaleDiv.ticks( QwtScaleDiv::MajorTick ).count(); - - if ( axisId == yLeft || axisId == yRight ) - { - int hDiff = ( majCnt - 1 ) * niceDist - - scaleWidget->minimumSizeHint().height(); - if ( hDiff > dh ) - dh = hDiff; - } - else - { - int wDiff = ( majCnt - 1 ) * niceDist - - scaleWidget->minimumSizeHint().width(); - if ( wDiff > dw ) - dw = wDiff; - } - } - } - return minimumSizeHint() + QSize( dw, dh ); -} - -/*! - \brief Return a minimum size hint -*/ -QSize QwtPlot::minimumSizeHint() const -{ - 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 ) -{ - QFrame::resizeEvent( e ); - updateLayout(); -} - -/*! - \brief Redraw the plot - - If the autoReplot option is not set (which is the default) - or if any curves are attached to raw data, the plot has to - be refreshed explicitly in order to make changes visible. - - \sa updateAxes(), setAutoReplot() -*/ -void QwtPlot::replot() -{ - bool doAutoReplot = autoReplot(); - setAutoReplot( false ); - - updateAxes(); - - /* - Maybe the layout needs to be updated, because of changed - axes labels. We need to process them here before painting - to avoid that scales and canvas get out of sync. - */ - QApplication::sendPostedEvents( this, QEvent::LayoutRequest ); - - if ( d_data->canvas ) - { - const bool ok = QMetaObject::invokeMethod( - d_data->canvas, "replot", Qt::DirectConnection ); - if ( !ok ) - { - // fallback, when canvas has no a replot method - d_data->canvas->update( d_data->canvas->contentsRect() ); - } - } - - setAutoReplot( doAutoReplot ); -} - -/*! - \brief Adjust plot content to its current size. - \sa resizeEvent() -*/ -void QwtPlot::updateLayout() -{ - d_data->layout->activate( this, contentsRect() ); - - QRect titleRect = d_data->layout->titleRect().toRect(); - QRect footerRect = d_data->layout->footerRect().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->titleLabel->text().isEmpty() ) - { - d_data->titleLabel->setGeometry( titleRect ); - if ( !d_data->titleLabel->isVisibleTo( this ) ) - d_data->titleLabel->show(); - } - else - d_data->titleLabel->hide(); - - if ( !d_data->footerLabel->text().isEmpty() ) - { - d_data->footerLabel->setGeometry( footerRect ); - if ( !d_data->footerLabel->isVisibleTo( this ) ) - d_data->footerLabel->show(); - } - else - d_data->footerLabel->hide(); - - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - { - if ( axisEnabled( axisId ) ) - { - axisWidget( axisId )->setGeometry( scaleRect[axisId] ); - -#if 1 - if ( axisId == xBottom || axisId == xTop ) - { - // do we need this code any longer ??? - - QRegion r( scaleRect[axisId] ); - if ( axisEnabled( yLeft ) ) - r = r.subtracted( QRegion( scaleRect[yLeft] ) ); - if ( axisEnabled( yRight ) ) - r = r.subtracted( QRegion( scaleRect[yRight] ) ); - r.translate( -scaleRect[ axisId ].x(), - -scaleRect[axisId].y() ); - - axisWidget( axisId )->setMask( r ); - } -#endif - if ( !axisWidget( axisId )->isVisibleTo( this ) ) - axisWidget( axisId )->show(); - } - else - axisWidget( axisId )->hide(); - } - - if ( d_data->legend ) - { - if ( d_data->legend->isEmpty() ) - { - d_data->legend->hide(); - } - else - { - d_data->legend->setGeometry( legendRect ); - d_data->legend->show(); - } - } - - d_data->canvas->setGeometry( canvasRect ); -} - -/*! - \brief Calculate the canvas margins - - \param maps QwtPlot::axisCnt maps, mapping between plot and paint device coordinates - \param canvasRect Bounding rectangle where to paint - \param left Return parameter for the left margin - \param top Return parameter for the top margin - \param right Return parameter for the right margin - \param bottom Return parameter for the bottom margin - - Plot items might indicate, that they need some extra space - at the borders of the canvas by the QwtPlotItem::Margins flag. - - updateCanvasMargins(), QwtPlotItem::getCanvasMarginHint() - */ -void QwtPlot::getCanvasMarginsHint( - const QwtScaleMap maps[], const QRectF &canvasRect, - double &left, double &top, double &right, double &bottom) const -{ - left = top = right = bottom = -1.0; - - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); - it != itmList.end(); ++it ) - { - const QwtPlotItem *item = *it; - if ( item->testItemAttribute( QwtPlotItem::Margins ) ) - { - double m[ QwtPlot::axisCnt ]; - item->getCanvasMarginHint( - maps[ item->xAxis() ], maps[ item->yAxis() ], - canvasRect, m[yLeft], m[xTop], m[yRight], m[xBottom] ); - - left = qMax( left, m[yLeft] ); - top = qMax( top, m[xTop] ); - right = qMax( right, m[yRight] ); - bottom = qMax( bottom, m[xBottom] ); - } - } -} - -/*! - \brief Update the canvas margins - - Plot items might indicate, that they need some extra space - at the borders of the canvas by the QwtPlotItem::Margins flag. - - getCanvasMarginsHint(), QwtPlotItem::getCanvasMarginHint() - */ -void QwtPlot::updateCanvasMargins() -{ - QwtScaleMap maps[axisCnt]; - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - maps[axisId] = canvasMap( axisId ); - - double margins[axisCnt]; - getCanvasMarginsHint( maps, canvas()->contentsRect(), - margins[yLeft], margins[xTop], margins[yRight], margins[xBottom] ); - - bool doUpdate = false; - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - { - if ( margins[axisId] >= 0.0 ) - { - const int m = qCeil( margins[axisId] ); - plotLayout()->setCanvasMargin( m, axisId); - doUpdate = true; - } - } - - if ( doUpdate ) - updateLayout(); -} - -/*! - Redraw the canvas. - \param painter Painter used for drawing - - \warning drawCanvas calls drawItems what is also used - for printing. Applications that like to add individual - plot items better overload drawItems() - \sa drawItems() -*/ -void QwtPlot::drawCanvas( QPainter *painter ) -{ - QwtScaleMap maps[axisCnt]; - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - maps[axisId] = canvasMap( axisId ); - - drawItems( painter, d_data->canvas->contentsRect(), maps ); -} - -/*! - Redraw the canvas items. - - \param painter Painter used for drawing - \param canvasRect Bounding rectangle where to paint - \param maps QwtPlot::axisCnt maps, mapping between plot and paint device coordinates - - \note Usually canvasRect is contentsRect() of the plot canvas. - Due to a bug in Qt this rectangle might be wrong for certain - frame styles ( f.e QFrame::Box ) and it might be necessary to - fix the margins manually using QWidget::setContentsMargins() -*/ - -void QwtPlot::drawItems( QPainter *painter, const QRectF &canvasRect, - const QwtScaleMap maps[axisCnt] ) const -{ - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); - it != itmList.end(); ++it ) - { - QwtPlotItem *item = *it; - if ( item && item->isVisible() ) - { - painter->save(); - - painter->setRenderHint( QPainter::Antialiasing, - item->testRenderHint( QwtPlotItem::RenderAntialiased ) ); - painter->setRenderHint( QPainter::HighQualityAntialiasing, - item->testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - item->draw( painter, - maps[item->xAxis()], maps[item->yAxis()], - canvasRect ); - - painter->restore(); - } - } -} - -/*! - \param axisId Axis - \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 map; - if ( !d_data->canvas ) - return map; - - map.setTransformation( axisScaleEngine( axisId )->transformation() ); - - const QwtScaleDiv &sd = axisScaleDiv( axisId ); - map.setScaleInterval( sd.lowerBound(), sd.upperBound() ); - - if ( axisEnabled( axisId ) ) - { - const QwtScaleWidget *s = axisWidget( axisId ); - if ( axisId == yLeft || axisId == yRight ) - { - double y = s->y() + s->startBorderDist() - d_data->canvas->y(); - double h = s->height() - s->startBorderDist() - s->endBorderDist(); - map.setPaintInterval( y + h, y ); - } - else - { - 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 QRect &canvasRect = d_data->canvas->contentsRect(); - if ( axisId == yLeft || axisId == yRight ) - { - int top = 0; - if ( !plotLayout()->alignCanvasToScale( xTop ) ) - top = plotLayout()->canvasMargin( xTop ); - - int bottom = 0; - if ( !plotLayout()->alignCanvasToScale( xBottom ) ) - bottom = plotLayout()->canvasMargin( xBottom ); - - map.setPaintInterval( canvasRect.bottom() - bottom, - canvasRect.top() + top ); - } - else - { - int left = 0; - if ( !plotLayout()->alignCanvasToScale( yLeft ) ) - left = plotLayout()->canvasMargin( yLeft ); - - int right = 0; - if ( !plotLayout()->alignCanvasToScale( yRight ) ) - right = plotLayout()->canvasMargin( yRight ); - - map.setPaintInterval( canvasRect.left() + left, - canvasRect.right() - right ); - } - } - - return map; -} - -/*! - \brief Change the background of the plotting area - - Sets brush to QPalette::Window of all color groups of - the palette of the canvas. Using canvas()->setPalette() - is a more powerful way to set these colors. - - \param brush New background brush - \sa canvasBackground() -*/ -void QwtPlot::setCanvasBackground( const QBrush &brush ) -{ - QPalette pal = d_data->canvas->palette(); - pal.setBrush( QPalette::Window, brush ); - - canvas()->setPalette( pal ); -} - -/*! - Nothing else than: canvas()->palette().brush( - QPalette::Normal, QPalette::Window); - - \return Background brush of the plotting area. - \sa setCanvasBackground() -*/ -QBrush QwtPlot::canvasBackground() const -{ - return canvas()->palette().brush( - QPalette::Normal, QPalette::Window ); -} - -/*! - \return \c true if the specified axis exists, otherwise \c false - \param axisId axis index - */ -bool QwtPlot::axisValid( int axisId ) -{ - return ( ( axisId >= QwtPlot::yLeft ) && ( axisId < QwtPlot::axisCnt ) ); -} - -/*! - \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 - with a best fit number of columns from left to right. - - insertLegend() will set the plot widget as parent for the legend. - The legend will be deleted in the destructor of the plot or when - another legend is inserted. - - Legends, that are not inserted into the layout of the plot widget - need to connect to the legendDataChanged() signal. Calling updateLegend() - initiates this signal for an initial update. When the application code - wants to implement its own layout this also needs to be done for - rendering plots to a document ( see QwtPlotRenderer ). - - \param legend Legend - \param pos The legend's position. For top/left position the number - of columns will be limited to 1, otherwise it will be set to - unlimited. - - \param ratio Ratio between legend and the bounding rectangle - of title, canvas and axes. The legend will be shrunk - 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. - - \sa legend(), QwtPlotLayout::legendPosition(), - QwtPlotLayout::setLegendPosition() -*/ -void QwtPlot::insertLegend( QwtAbstractLegend *legend, - QwtPlot::LegendPosition pos, double ratio ) -{ - d_data->layout->setLegendPosition( pos, ratio ); - - if ( legend != d_data->legend ) - { - if ( d_data->legend && d_data->legend->parent() == this ) - delete d_data->legend; - - d_data->legend = legend; - - if ( d_data->legend ) - { - connect( this, - SIGNAL( legendDataChanged( - const QVariant &, const QList<QwtLegendData> & ) ), - d_data->legend, - SLOT( updateLegend( - const QVariant &, const QList<QwtLegendData> & ) ) - ); - - if ( d_data->legend->parent() != this ) - d_data->legend->setParent( this ); - - qwtEnableLegendItems( this, false ); - updateLegend(); - qwtEnableLegendItems( this, true ); - - QwtLegend *lgd = qobject_cast<QwtLegend *>( legend ); - if ( lgd ) - { - switch ( d_data->layout->legendPosition() ) - { - case LeftLegend: - case RightLegend: - { - if ( lgd->maxColumns() == 0 ) - lgd->setMaxColumns( 1 ); // 1 column: align vertical - break; - } - case TopLegend: - case BottomLegend: - { - lgd->setMaxColumns( 0 ); // unlimited - break; - } - default: - break; - } - } - - QWidget *previousInChain = NULL; - switch ( d_data->layout->legendPosition() ) - { - case LeftLegend: - { - previousInChain = axisWidget( QwtPlot::xTop ); - break; - } - case TopLegend: - { - previousInChain = this; - break; - } - case RightLegend: - { - previousInChain = axisWidget( QwtPlot::yRight ); - break; - } - case BottomLegend: - { - previousInChain = footerLabel(); - break; - } - } - - if ( previousInChain ) - qwtSetTabOrder( previousInChain, legend, true ); - } - } - - updateLayout(); -} - -/*! - Emit legendDataChanged() for all plot item - - \sa QwtPlotItem::legendData(), legendDataChanged() - */ -void QwtPlot::updateLegend() -{ - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); - it != itmList.end(); ++it ) - { - updateLegend( *it ); - } -} - -/*! - Emit legendDataChanged() for a plot item - - \param plotItem Plot item - \sa QwtPlotItem::legendData(), legendDataChanged() - */ -void QwtPlot::updateLegend( const QwtPlotItem *plotItem ) -{ - if ( plotItem == NULL ) - return; - - QList<QwtLegendData> legendData; - - if ( plotItem->testItemAttribute( QwtPlotItem::Legend ) ) - legendData = plotItem->legendData(); - - const QVariant itemInfo = itemToInfo( const_cast< QwtPlotItem *>( plotItem) ); - Q_EMIT legendDataChanged( itemInfo, legendData ); -} - -/*! - \brief Update all plot items interested in legend attributes - - Call QwtPlotItem::updateLegend(), when the QwtPlotItem::LegendInterest - flag is set. - - \param itemInfo Info about the plot item - \param legendData Entries to be displayed for the plot item ( usually 1 ) - - \sa QwtPlotItem::LegendInterest, - QwtPlotLegendItem, QwtPlotItem::updateLegend() - */ -void QwtPlot::updateLegendItems( const QVariant &itemInfo, - const QList<QwtLegendData> &legendData ) -{ - QwtPlotItem *plotItem = infoToItem( itemInfo ); - if ( plotItem ) - { - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); - it != itmList.end(); ++it ) - { - QwtPlotItem *item = *it; - if ( item->testItemInterest( QwtPlotItem::LegendInterest ) ) - item->updateLegend( plotItem, legendData ); - } - } -} - -/*! - \brief Attach/Detach a plot item - - \param plotItem Plot item - \param on When true attach the item, otherwise detach it - */ -void QwtPlot::attachItem( QwtPlotItem *plotItem, bool on ) -{ - if ( plotItem->testItemInterest( QwtPlotItem::LegendInterest ) ) - { - // plotItem is some sort of legend - - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); - it != itmList.end(); ++it ) - { - QwtPlotItem *item = *it; - - QList<QwtLegendData> legendData; - if ( on && item->testItemAttribute( QwtPlotItem::Legend ) ) - { - legendData = item->legendData(); - plotItem->updateLegend( item, legendData ); - } - } - } - - if ( on ) - insertItem( plotItem ); - else - removeItem( plotItem ); - - Q_EMIT itemAttached( plotItem, on ); - - if ( plotItem->testItemAttribute( QwtPlotItem::Legend ) ) - { - // the item wants to be represented on the legend - - if ( on ) - { - updateLegend( plotItem ); - } - else - { - const QVariant itemInfo = itemToInfo( plotItem ); - Q_EMIT legendDataChanged( itemInfo, QList<QwtLegendData>() ); - } - } - - autoRefresh(); -} - -/*! - \brief Build an information, that can be used to identify - a plot item on the legend. - - The default implementation simply wraps the plot item - into a QVariant object. When overloading itemToInfo() - usually infoToItem() needs to reimplemeted too. - -\code - QVariant itemInfo; - qVariantSetValue( itemInfo, plotItem ); -\endcode - - \param plotItem Plot item - \return Plot item embedded in a QVariant - \sa infoToItem() - */ -QVariant QwtPlot::itemToInfo( QwtPlotItem *plotItem ) const -{ - QVariant itemInfo; - qVariantSetValue( itemInfo, plotItem ); - - return itemInfo; -} - -/*! - \brief Identify the plot item according to an item info object, - that has bee generated from itemToInfo(). - - The default implementation simply tries to unwrap a QwtPlotItem - pointer: - -\code - if ( itemInfo.canConvert<QwtPlotItem *>() ) - return qvariant_cast<QwtPlotItem *>( itemInfo ); -\endcode - \param itemInfo Plot item - \return A plot item, when successful, otherwise a NULL pointer. - \sa itemToInfo() -*/ -QwtPlotItem *QwtPlot::infoToItem( const QVariant &itemInfo ) const -{ - if ( itemInfo.canConvert<QwtPlotItem *>() ) - return qvariant_cast<QwtPlotItem *>( itemInfo ); - - return NULL; -} - - diff --git a/source/third_party/qwt/qwt_plot_abstract_barchart.cpp b/source/third_party/qwt/qwt_plot_abstract_barchart.cpp deleted file mode 100644 index 4fe2634aed5db91711a5625e5af7258eb9e39a86..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_abstract_barchart.cpp +++ /dev/null @@ -1,368 +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/qwt_plot_abstract_barchart.h" -#include "qwt/qwt_scale_map.h" - -static inline double qwtTransformWidth( - const QwtScaleMap &map, double value, double width ) -{ - const double w2 = 0.5 * width; - - const double v1 = map.transform( value - w2 ); - const double v2 = map.transform( value + w2 ); - - return qAbs( v2 - v1 ); -} - -class QwtPlotAbstractBarChart::PrivateData -{ -public: - PrivateData(): - layoutPolicy( QwtPlotAbstractBarChart::AutoAdjustSamples ), - layoutHint( 0.5 ), - spacing( 10 ), - margin( 5 ), - baseline( 0.0 ) - { - } - - QwtPlotAbstractBarChart::LayoutPolicy layoutPolicy; - double layoutHint; - int spacing; - int margin; - double baseline; -}; - -/*! - Constructor - \param title Title of the chart -*/ -QwtPlotAbstractBarChart::QwtPlotAbstractBarChart( const QwtText &title ): - QwtPlotSeriesItem( title ) -{ - d_data = new PrivateData; - - setItemAttribute( QwtPlotItem::Legend, true ); - setItemAttribute( QwtPlotItem::AutoScale, true ); - setItemAttribute( QwtPlotItem::Margins, true ); - setZ( 19.0 ); -} - -//! Destructor -QwtPlotAbstractBarChart::~QwtPlotAbstractBarChart() -{ - delete d_data; -} - -/*! - The combination of layoutPolicy() and layoutHint() define how the width - of the bars is calculated - - \param policy Layout policy - - \sa layoutPolicy(), layoutHint() - */ -void QwtPlotAbstractBarChart::setLayoutPolicy( LayoutPolicy policy ) -{ - if ( policy != d_data->layoutPolicy ) - { - d_data->layoutPolicy = policy; - itemChanged(); - } -} - -/*! - The combination of layoutPolicy() and layoutHint() define how the width - of the bars is calculated - - \return Layout policy of the chart item - \sa setLayoutPolicy(), layoutHint() - */ -QwtPlotAbstractBarChart::LayoutPolicy QwtPlotAbstractBarChart::layoutPolicy() const -{ - return d_data->layoutPolicy; -} - -/*! - The combination of layoutPolicy() and layoutHint() define how the width - of the bars is calculated - - \param hint Layout hint - - \sa LayoutPolicy, layoutPolicy(), layoutHint() - */ -void QwtPlotAbstractBarChart::setLayoutHint( double hint ) -{ - hint = qMax( 0.0, hint ); - if ( hint != d_data->layoutHint ) - { - d_data->layoutHint = hint; - itemChanged(); - } -} - -/*! - The combination of layoutPolicy() and layoutHint() define how the width - of the bars is calculated - - \return Layout policy of the chart item - \sa LayoutPolicy, setLayoutHint(), layoutPolicy() -*/ -double QwtPlotAbstractBarChart::layoutHint() const -{ - return d_data->layoutHint; -} - -/*! - \brief Set the spacing - - The spacing is the distance between 2 samples ( bars for QwtPlotBarChart or - a group of bars for QwtPlotMultiBarChart ) in paint device coordinates. - - \sa spacing() - */ -void QwtPlotAbstractBarChart::setSpacing( int spacing ) -{ - spacing = qMax( spacing, 0 ); - if ( spacing != d_data->spacing ) - { - d_data->spacing = spacing; - itemChanged(); - } -} - -/*! - \return Spacing between 2 samples ( bars or groups of bars ) - \sa setSpacing(), margin() - */ -int QwtPlotAbstractBarChart::spacing() const -{ - return d_data->spacing; -} -/*! - \brief Set the margin - - The margin is the distance between the outmost bars and the contentsRect() - of the canvas. The default setting is 5 pixels. - - \param margin Margin - - \sa spacing(), margin() - */ -void QwtPlotAbstractBarChart::setMargin( int margin ) -{ - margin = qMax( margin, 0 ); - if ( margin != d_data->margin ) - { - d_data->margin = margin; - itemChanged(); - } -} - -/*! - \return Margin between the outmost bars and the contentsRect() - of the canvas. - - \sa setMargin(), spacing() - */ -int QwtPlotAbstractBarChart::margin() const -{ - return d_data->margin; -} - -/*! - \brief Set the baseline - - The baseline is the origin for the chart. Each bar is - painted from the baseline in the direction of the sample - value. In case of a horizontal orientation() the baseline - is interpreted as x - otherwise as y - value. - - The default value for the baseline is 0. - - \param value Value for the baseline - - \sa baseline(), QwtPlotSeriesItem::orientation() -*/ -void QwtPlotAbstractBarChart::setBaseline( double value ) -{ - if ( value != d_data->baseline ) - { - d_data->baseline = value; - itemChanged(); - } -} - -/*! - \return Value for the origin of the bar chart - \sa setBaseline(), QwtPlotSeriesItem::orientation() - */ -double QwtPlotAbstractBarChart::baseline() const -{ - return d_data->baseline; -} - -/*! - Calculate the width for a sample in paint device coordinates - - \param map Scale map for the corresponding scale - \param canvasSize Size of the canvas in paint device coordinates - \param boundingSize Bounding size of the chart in plot coordinates - ( used in AutoAdjustSamples mode ) - \param value Value of the sample - - \return Sample width - \sa layoutPolicy(), layoutHint() -*/ -double QwtPlotAbstractBarChart::sampleWidth( const QwtScaleMap &map, - double canvasSize, double boundingSize, double value ) const -{ - double width; - - switch( d_data->layoutPolicy ) - { - case ScaleSamplesToAxes: - { - width = qwtTransformWidth( map, value, d_data->layoutHint ); - break; - } - case ScaleSampleToCanvas: - { - width = canvasSize * d_data->layoutHint; - break; - } - case FixedSampleSize: - { - width = d_data->layoutHint; - break; - } - case AutoAdjustSamples: - default: - { - const size_t numSamples = dataSize(); - - double w = 1.0; - if ( numSamples > 1 ) - { - w = qAbs( boundingSize / ( numSamples - 1 ) ); - } - - width = qwtTransformWidth( map, value, w ); - width -= d_data->spacing; - width = qMax( width, d_data->layoutHint ); - } - } - - return width; -} - -/*! - \brief Calculate a hint for the canvas margin - - Bar charts need to reserve some space for displaying the bars - for the first and the last sample. The hint is calculated - from the layoutHint() depending on the layoutPolicy(). - - The margins are in target device coordinates ( pixels on screen ) - - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle of the canvas in painter coordinates - \param left Returns the left margin - \param top Returns the top margin - \param right Returns the right margin - \param bottom Returns the bottom margin - - \return Margin - - \sa layoutPolicy(), layoutHint(), QwtPlotItem::Margins - QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins() - */ -void QwtPlotAbstractBarChart::getCanvasMarginHint( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRectF &canvasRect, - double &left, double &top, double &right, double &bottom ) const -{ - double hint = -1.0; - - switch( layoutPolicy() ) - { - case ScaleSampleToCanvas: - { - if ( orientation() == Qt::Vertical ) - hint = 0.5 * canvasRect.width() * d_data->layoutHint; - else - hint = 0.5 * canvasRect.height() * d_data->layoutHint; - - break; - } - case FixedSampleSize: - { - hint = 0.5 * d_data->layoutHint; - break; - } - case AutoAdjustSamples: - case ScaleSamplesToAxes: - default: - { - const size_t numSamples = dataSize(); - if ( numSamples <= 0 ) - break; - - // doesn't work for nonlinear scales - - const QRectF br = dataRect(); - double spacing = 0.0; - double sampleWidthS = 1.0; - - if ( layoutPolicy() == ScaleSamplesToAxes ) - { - sampleWidthS = qMax( d_data->layoutHint, 0.0 ); - } - else - { - spacing = d_data->spacing; - - if ( numSamples > 1 ) - { - sampleWidthS = qAbs( br.width() / ( numSamples - 1 ) ); - } - } - - double ds, w; - if ( orientation() == Qt::Vertical ) - { - ds = qAbs( xMap.sDist() ); - w = canvasRect.width(); - } - else - { - ds = qAbs( yMap.sDist() ); - w = canvasRect.height(); - } - - const double sampleWidthP = ( w - spacing * ( numSamples - 1 ) ) - * sampleWidthS / ( ds + sampleWidthS ); - - hint = 0.5 * sampleWidthP; - hint += qMax( d_data->margin, 0 ); - } - } - - if ( orientation() == Qt::Vertical ) - { - left = right = hint; - top = bottom = -1.0; // no hint - } - else - { - left = right = -1.0; // no hint - top = bottom = hint; - } -} diff --git a/source/third_party/qwt/qwt_plot_axis.cpp b/source/third_party/qwt/qwt_plot_axis.cpp deleted file mode 100644 index 53d116c44d8c5f29b574878dde35af2b7bcda128..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_axis.cpp +++ /dev/null @@ -1,719 +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/qwt_plot.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_scale_widget.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_scale_engine.h" - -class QwtPlot::AxisData -{ -public: - bool isEnabled; - bool doAutoScale; - - double minValue; - double maxValue; - double stepSize; - - int maxMajor; - int maxMinor; - - bool isValid; - - QwtScaleDiv scaleDiv; - QwtScaleEngine *scaleEngine; - QwtScaleWidget *scaleWidget; -}; - -//! Initialize axes -void QwtPlot::initAxesData() -{ - int axisId; - - for ( axisId = 0; axisId < axisCnt; axisId++ ) - d_axisData[axisId] = new AxisData; - - d_axisData[yLeft]->scaleWidget = - new QwtScaleWidget( QwtScaleDraw::LeftScale, this ); - d_axisData[yRight]->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[yRight]->scaleWidget->setObjectName( "QwtPlotAxisYRight" ); - d_axisData[xTop]->scaleWidget->setObjectName( "QwtPlotAxisXTop" ); - d_axisData[xBottom]->scaleWidget->setObjectName( "QwtPlotAxisXBottom" ); - -#if 1 - // better find the font sizes from the application font - QFont fscl( fontInfo().family(), 10 ); - QFont fttl( fontInfo().family(), 12, QFont::Bold ); -#endif - - for ( axisId = 0; axisId < axisCnt; axisId++ ) - { - AxisData &d = *d_axisData[axisId]; - - d.scaleEngine = new QwtLinearScaleEngine; - - d.scaleWidget->setTransformation( - d.scaleEngine->transformation() ); - - d.scaleWidget->setFont( fscl ); - d.scaleWidget->setMargin( 2 ); - - QwtText text = d.scaleWidget->title(); - text.setFont( fttl ); - d.scaleWidget->setTitle( text ); - - d.doAutoScale = true; - - d.minValue = 0.0; - d.maxValue = 1000.0; - d.stepSize = 0.0; - - d.maxMinor = 5; - d.maxMajor = 8; - - - d.isValid = false; - } - - d_axisData[yLeft]->isEnabled = true; - d_axisData[yRight]->isEnabled = false; - d_axisData[xBottom]->isEnabled = true; - d_axisData[xTop]->isEnabled = false; -} - -void QwtPlot::deleteAxesData() -{ - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - { - delete d_axisData[axisId]->scaleEngine; - delete d_axisData[axisId]; - d_axisData[axisId] = NULL; - } -} - -/*! - \return Scale widget of the specified axis, or NULL if axisId is invalid. - \param axisId Axis index -*/ -const QwtScaleWidget *QwtPlot::axisWidget( int axisId ) const -{ - if ( axisValid( axisId ) ) - return d_axisData[axisId]->scaleWidget; - - return NULL; -} - -/*! - \return Scale widget of the specified axis, or NULL if axisId is invalid. - \param axisId Axis index -*/ -QwtScaleWidget *QwtPlot::axisWidget( int axisId ) -{ - if ( axisValid( axisId ) ) - return d_axisData[axisId]->scaleWidget; - - return NULL; -} - -/*! - Change the scale engine for an axis - - \param axisId Axis index - \param scaleEngine Scale engine - - \sa axisScaleEngine() -*/ -void QwtPlot::setAxisScaleEngine( int axisId, QwtScaleEngine *scaleEngine ) -{ - if ( axisValid( axisId ) && scaleEngine != NULL ) - { - AxisData &d = *d_axisData[axisId]; - - delete d.scaleEngine; - d.scaleEngine = scaleEngine; - - d_axisData[axisId]->scaleWidget->setTransformation( - scaleEngine->transformation() ); - - d.isValid = false; - - autoRefresh(); - } -} - -/*! - \param axisId Axis index - \return Scale engine for a specific axis -*/ -QwtScaleEngine *QwtPlot::axisScaleEngine( int 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 -{ - if ( axisValid( axisId ) ) - return d_axisData[axisId]->scaleEngine; - else - return NULL; -} -/*! - \return \c True, if autoscaling is enabled - \param axisId Axis index -*/ -bool QwtPlot::axisAutoScale( int axisId ) const -{ - 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 -{ - if ( axisValid( axisId ) ) - return d_axisData[axisId]->isEnabled; - else - return false; -} - -/*! - \return The font of the scale labels for a specified axis - \param axisId Axis index -*/ -QFont QwtPlot::axisFont( int axisId ) const -{ - 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(), QwtScaleEngine::divideScale() -*/ -int QwtPlot::axisMaxMajor( int axisId ) const -{ - if ( axisValid( axisId ) ) - return d_axisData[axisId]->maxMajor; - else - return 0; -} - -/*! - \return the maximum number of minor ticks for a specified axis - \param axisId Axis index - \sa setAxisMaxMinor(), QwtScaleEngine::divideScale() -*/ -int QwtPlot::axisMaxMinor( int axisId ) const -{ - if ( axisValid( axisId ) ) - return d_axisData[axisId]->maxMinor; - else - return 0; -} - -/*! - \brief Return the scale division of a specified axis - - axisScaleDiv(axisId).lowerBound(), axisScaleDiv(axisId).upperBound() - are the current limits of the axis scale. - - \param axisId Axis index - \return Scale division - - \sa QwtScaleDiv, setAxisScaleDiv(), QwtScaleEngine::divideScale() -*/ -const QwtScaleDiv &QwtPlot::axisScaleDiv( int axisId ) const -{ - return d_axisData[axisId]->scaleDiv; -} - -/*! - \brief Return the scale draw of a specified axis - - \param axisId Axis index - \return Specified scaleDraw for axis, or NULL if axis is invalid. -*/ -const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const -{ - if ( !axisValid( axisId ) ) - return NULL; - - return axisWidget( axisId )->scaleDraw(); -} - -/*! - \brief Return the scale draw of a specified axis - - \param axisId Axis index - \return Specified scaleDraw for axis, or NULL if axis is invalid. -*/ -QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) -{ - if ( !axisValid( axisId ) ) - return NULL; - - return axisWidget( axisId )->scaleDraw(); -} - -/*! - \brief Return the step size parameter that has been set 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(), QwtScaleEngine::divideScale() -*/ -double QwtPlot::axisStepSize( int axisId ) const -{ - 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 Title of a specified axis - \param axisId Axis index -*/ -QwtText QwtPlot::axisTitle( int axisId ) const -{ - if ( axisValid( axisId ) ) - return axisWidget( axisId )->title(); - else - return QwtText(); -} - -/*! - \brief Enable or disable a specified axis - - When an axis is disabled, this only means that it is not - visible on the screen. Curves, markers and can be attached - to disabled axes, and transformation of screen coordinates - into values works as normal. - - Only xBottom and yLeft are enabled by default. - - \param axisId Axis index - \param tf \c true (enabled) or \c false (disabled) -*/ -void QwtPlot::enableAxis( int axisId, bool tf ) -{ - if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled ) - { - d_axisData[axisId]->isEnabled = tf; - updateLayout(); - } -} - -/*! - Transform the x or y coordinate of a position in the - drawing region into a value. - - \param axisId Axis index - \param pos position - - \return Position as axis coordinate - - \warning The position can be an x or a y coordinate, - depending on the specified axis. -*/ -double QwtPlot::invTransform( int axisId, int pos ) const -{ - if ( axisValid( axisId ) ) - return( canvasMap( axisId ).invTransform( pos ) ); - else - return 0.0; -} - - -/*! - \brief Transform a value into a coordinate in the plotting region - - \param axisId Axis index - \param value value - \return X or Y coordinate in the plotting region corresponding - to the value. -*/ -double QwtPlot::transform( int axisId, double value ) const -{ - if ( axisValid( axisId ) ) - return( canvasMap( axisId ).transform( value ) ); - else - return 0.0; -} - -/*! - \brief Change the font of an axis - - \param axisId Axis index - \param font Font - \warning This function changes the font of the tick labels, - not of the axis title. -*/ -void QwtPlot::setAxisFont( int axisId, const QFont &font ) -{ - if ( axisValid( axisId ) ) - axisWidget( axisId )->setFont( font ); -} - -/*! - \brief Enable autoscaling for a specified axis - - This member function is used to switch back to autoscaling mode - after a fixed scale has been set. Autoscaling is enabled by default. - - \param axisId Axis index - \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, bool on ) -{ - if ( axisValid( axisId ) && ( d_axisData[axisId]->doAutoScale != on ) ) - { - d_axisData[axisId]->doAutoScale = on; - autoRefresh(); - } -} - -/*! - \brief Disable autoscaling and specify a fixed scale for a selected axis. - - In updateAxes() the scale engine calculates a scale division from the - specified parameters, that will be assigned to the scale widget. So - updates of the scale widget usually happen delayed with the next replot. - - \param axisId Axis index - \param min Minimum of the scale - \param max Maximum of the scale - \param stepSize Major step size. If <code>step == 0</code>, the step size is - calculated automatically using the maxMajor setting. - - \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize(), QwtScaleEngine::divideScale() -*/ -void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize ) -{ - if ( axisValid( axisId ) ) - { - AxisData &d = *d_axisData[axisId]; - - d.doAutoScale = false; - d.isValid = false; - - d.minValue = min; - d.maxValue = max; - d.stepSize = stepSize; - - autoRefresh(); - } -} - -/*! - \brief Disable autoscaling and specify a fixed scale for a selected axis. - - The scale division will be stored locally only until the next call - of updateAxes(). So updates of the scale widget usually happen delayed with - the next replot. - - \param axisId Axis index - \param scaleDiv Scale division - - \sa setAxisScale(), setAxisAutoScale() -*/ -void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv ) -{ - if ( axisValid( axisId ) ) - { - AxisData &d = *d_axisData[axisId]; - - d.doAutoScale = false; - d.scaleDiv = scaleDiv; - d.isValid = true; - - autoRefresh(); - } -} - -/*! - \brief Set a scale draw - - \param axisId Axis index - \param scaleDraw Object responsible for drawing scales. - - By passing scaleDraw it is possible to extend QwtScaleDraw - functionality and let it take place in QwtPlot. Please note - that scaleDraw has to be created with new and will be deleted - 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. -*/ - -void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw ) -{ - if ( axisValid( axisId ) ) - { - axisWidget( axisId )->setScaleDraw( scaleDraw ); - autoRefresh(); - } -} - -/*! - Change the alignment of the tick labels - - \param axisId Axis index - \param alignment Or'd Qt::AlignmentFlags see <qnamespace.h> - - \sa QwtScaleDraw::setLabelAlignment() -*/ -void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment ) -{ - if ( axisValid( axisId ) ) - axisWidget( axisId )->setLabelAlignment( alignment ); -} - -/*! - Rotate all tick labels - - \param axisId Axis index - \param rotation Angle in degrees. When changing the label rotation, - the label alignment might be adjusted too. - - \sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment() -*/ -void QwtPlot::setAxisLabelRotation( int axisId, double rotation ) -{ - if ( axisValid( axisId ) ) - axisWidget( axisId )->setLabelRotation( rotation ); -} - -/*! - Set the maximum number of minor scale intervals for a specified axis - - \param axisId Axis index - \param maxMinor Maximum number of minor steps - - \sa axisMaxMinor() -*/ -void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor ) -{ - if ( axisValid( axisId ) ) - { - maxMinor = qBound( 0, maxMinor, 100 ); - - AxisData &d = *d_axisData[axisId]; - if ( maxMinor != d.maxMinor ) - { - d.maxMinor = maxMinor; - d.isValid = false; - autoRefresh(); - } - } -} - -/*! - Set the maximum number of major scale intervals for a specified axis - - \param axisId Axis index - \param maxMajor Maximum number of major steps - - \sa axisMaxMajor() -*/ -void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor ) -{ - if ( axisValid( axisId ) ) - { - maxMajor = qBound( 1, maxMajor, 10000 ); - - AxisData &d = *d_axisData[axisId]; - if ( maxMajor != d.maxMajor ) - { - d.maxMajor = maxMajor; - d.isValid = false; - autoRefresh(); - } - } -} - -/*! - \brief Change the title of a specified axis - - \param axisId Axis index - \param title axis title -*/ -void QwtPlot::setAxisTitle( int axisId, const QString &title ) -{ - if ( axisValid( axisId ) ) - axisWidget( axisId )->setTitle( title ); -} - -/*! - \brief Change the title of a specified axis - - \param axisId Axis index - \param title Axis title -*/ -void QwtPlot::setAxisTitle( int axisId, const QwtText &title ) -{ - if ( axisValid( axisId ) ) - axisWidget( axisId )->setTitle( title ); -} - -/*! - \brief Rebuild the axes scales - - In case of autoscaling the boundaries of a scale are calculated - from the bounding rectangles of all plot items, having the - QwtPlotItem::AutoScale flag enabled ( QwtScaleEngine::autoScale() ). - Then a scale division is calculated ( QwtScaleEngine::didvideScale() ) - and assigned to scale widget. - - When the scale boundaries have been assigned with setAxisScale() a - scale division is calculated ( QwtScaleEngine::didvideScale() ) - for this interval and assigned to the scale widget. - - When the scale has been set explicitly by setAxisScaleDiv() the - locally stored scale division gets assigned to the scale widget. - - The scale widget indicates modifications by emitting a - QwtScaleWidget::scaleDivChanged() signal. - - updateAxes() is usually called by replot(). - - \sa setAxisAutoScale(), setAxisScale(), setAxisScaleDiv(), replot() - QwtPlotItem::boundingRect() - */ -void QwtPlot::updateAxes() -{ - // Find bounding interval of the item data - // for all axes, where autoscaling is enabled - - QwtInterval intv[axisCnt]; - - const QwtPlotItemList& itmList = itemList(); - - QwtPlotItemIterator it; - for ( it = itmList.begin(); it != itmList.end(); ++it ) - { - const QwtPlotItem *item = *it; - - if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) ) - continue; - - if ( !item->isVisible() ) - continue; - - if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) ) - { - const QRectF rect = item->boundingRect(); - - if ( rect.width() >= 0.0 ) - intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() ); - - if ( rect.height() >= 0.0 ) - intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() ); - } - } - - // Adjust scales - - for ( int axisId = 0; axisId < axisCnt; axisId++ ) - { - AxisData &d = *d_axisData[axisId]; - - double minValue = d.minValue; - double maxValue = d.maxValue; - double stepSize = d.stepSize; - - if ( d.doAutoScale && intv[axisId].isValid() ) - { - d.isValid = false; - - minValue = intv[axisId].minValue(); - maxValue = intv[axisId].maxValue(); - - d.scaleEngine->autoScale( d.maxMajor, - minValue, maxValue, stepSize ); - } - if ( !d.isValid ) - { - d.scaleDiv = d.scaleEngine->divideScale( - minValue, maxValue, - d.maxMajor, d.maxMinor, stepSize ); - d.isValid = true; - } - - QwtScaleWidget *scaleWidget = axisWidget( axisId ); - scaleWidget->setScaleDiv( d.scaleDiv ); - - int startDist, endDist; - scaleWidget->getBorderDistHint( startDist, endDist ); - scaleWidget->setBorderDist( startDist, endDist ); - } - - for ( it = itmList.begin(); it != itmList.end(); ++it ) - { - QwtPlotItem *item = *it; - if ( item->testItemInterest( QwtPlotItem::ScaleInterest ) ) - { - item->updateScaleDiv( axisScaleDiv( item->xAxis() ), - axisScaleDiv( item->yAxis() ) ); - } - } -} - diff --git a/source/third_party/qwt/qwt_plot_barchart.cpp b/source/third_party/qwt/qwt_plot_barchart.cpp deleted file mode 100644 index 729140f657d1d901d9e568f4018a6a0290d6cf99..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_barchart.cpp +++ /dev/null @@ -1,459 +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/qwt_plot_barchart.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_column_symbol.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> - -class QwtPlotBarChart::PrivateData -{ -public: - PrivateData(): - symbol( NULL ), - legendMode( QwtPlotBarChart::LegendChartTitle ) - { - } - - ~PrivateData() - { - delete symbol; - } - - QwtColumnSymbol *symbol; - QwtPlotBarChart::LegendMode legendMode; -}; - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotBarChart::QwtPlotBarChart( const QwtText &title ): - QwtPlotAbstractBarChart( title ) -{ - init(); -} - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotBarChart::QwtPlotBarChart( const QString &title ): - QwtPlotAbstractBarChart( QwtText( title ) ) -{ - init(); -} - -//! Destructor -QwtPlotBarChart::~QwtPlotBarChart() -{ - delete d_data; -} - -void QwtPlotBarChart::init() -{ - d_data = new PrivateData; - setData( new QwtPointSeriesData() ); -} - -//! \return QwtPlotItem::Rtti_PlotBarChart -int QwtPlotBarChart::rtti() const -{ - return QwtPlotItem::Rtti_PlotBarChart; -} - -/*! - Initialize data with an array of points - - \param samples Vector of points - \note QVector is implicitly shared - \note QPolygonF is derived from QVector<QPointF> -*/ -void QwtPlotBarChart::setSamples( - const QVector<QPointF> &samples ) -{ - setData( new QwtPointSeriesData( samples ) ); -} - -/*! - Initialize data with an array of doubles - - The indices in the array are taken as x coordinate, - while the doubles are interpreted as y values. - - \param samples Vector of y coordinates - \note QVector is implicitly shared -*/ -void QwtPlotBarChart::setSamples( - const QVector<double> &samples ) -{ - QVector<QPointF> points; - for ( int i = 0; i < samples.size(); i++ ) - points += QPointF( i, samples[ i ] ); - - setData( new QwtPointSeriesData( points ) ); -} - -/*! - Assign a series of samples - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotBarChart::setSamples( QwtSeriesData<QPointF> *data ) -{ - setData( data ); -} - -/*! - \brief Assign a symbol - - The bar chart will take the ownership of the symbol, hence the previously - set symbol will be delete by setting a new one. If \p symbol is - \c NULL no symbol will be drawn. - - \param symbol Symbol - \sa symbol() -*/ -void QwtPlotBarChart::setSymbol( QwtColumnSymbol *symbol ) -{ - if ( symbol != d_data->symbol ) - { - delete d_data->symbol; - d_data->symbol = symbol; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Current symbol or NULL, when no symbol has been assigned - \sa setSymbol() -*/ -const QwtColumnSymbol *QwtPlotBarChart::symbol() const -{ - return d_data->symbol; -} - -/*! - Set the mode that decides what to display on the legend - - In case of LegendBarTitles barTitle() needs to be overloaded - to return individual titles for each bar. - - \param mode New mode - \sa legendMode(), legendData(), barTitle(), QwtPlotItem::ItemAttribute - */ -void QwtPlotBarChart::setLegendMode( LegendMode mode ) -{ - if ( mode != d_data->legendMode ) - { - d_data->legendMode = mode; - legendChanged(); - } -} - -/*! - \return Legend mode - \sa setLegendMode() - */ -QwtPlotBarChart::LegendMode QwtPlotBarChart::legendMode() const -{ - return d_data->legendMode; -} - -/*! - \return Bounding rectangle of all samples. - For an empty series the rectangle is invalid. -*/ -QRectF QwtPlotBarChart::boundingRect() const -{ - const size_t numSamples = dataSize(); - if ( numSamples == 0 ) - return QwtPlotSeriesItem::boundingRect(); - - QRectF rect = QwtPlotSeriesItem::boundingRect(); - if ( rect.height() >= 0 ) - { - const double baseLine = baseline(); - - if ( rect.bottom() < baseLine ) - rect.setBottom( baseLine ); - - if ( rect.top() > baseLine ) - rect.setTop( baseLine ); - } - - if ( orientation() == Qt::Horizontal ) - rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() ); - - return rect; -} - -/*! - Draw an interval of the bar chart - - \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 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 drawSymbols() -*/ -void QwtPlotBarChart::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; - - - const QRectF br = data()->boundingRect(); - const QwtInterval interval( br.left(), br.right() ); - - painter->save(); - - for ( int i = from; i <= to; i++ ) - { - drawSample( painter, xMap, yMap, - canvasRect, interval, i, sample( i ) ); - } - - painter->restore(); -} - -/*! - Draw a sample - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rect of the canvas - \param boundingInterval Bounding interval of sample values - \param index Index of the sample - \param sample Value of the sample - - \sa drawSeries() -*/ -void QwtPlotBarChart::drawSample( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, const QwtInterval &boundingInterval, - int index, const QPointF &sample ) const -{ - QwtColumnRect barRect; - - if ( orientation() == Qt::Horizontal ) - { - const double barHeight = sampleWidth( yMap, canvasRect.height(), - boundingInterval.width(), sample.y() ); - - const double x1 = xMap.transform( baseline() ); - const double x2 = xMap.transform( sample.y() ); - - const double y = yMap.transform( sample.x() ); - const double y1 = y - 0.5 * barHeight; - const double y2 = y + 0.5 * barHeight; - - barRect.direction = ( x1 < x2 ) ? - QwtColumnRect::LeftToRight : QwtColumnRect::RightToLeft; - - barRect.hInterval = QwtInterval( x1, x2 ).normalized(); - barRect.vInterval = QwtInterval( y1, y2 ); - } - else - { - const double barWidth = sampleWidth( xMap, canvasRect.width(), - boundingInterval.width(), sample.y() ); - - const double x = xMap.transform( sample.x() ); - const double x1 = x - 0.5 * barWidth; - const double x2 = x + 0.5 * barWidth; - - const double y1 = yMap.transform( baseline() ); - const double y2 = yMap.transform( sample.y() ); - - barRect.direction = ( y1 < y2 ) ? - QwtColumnRect::TopToBottom : QwtColumnRect::BottomToTop; - - barRect.hInterval = QwtInterval( x1, x2 ); - barRect.vInterval = QwtInterval( y1, y2 ).normalized(); - } - - drawBar( painter, index, sample, barRect ); -} - -/*! - Draw a bar - - \param painter Painter - \param sampleIndex Index of the sample represented by the bar - \param sample Value of the sample - \param rect Bounding rectangle of the bar - */ -void QwtPlotBarChart::drawBar( QPainter *painter, - int sampleIndex, const QPointF &sample, - const QwtColumnRect &rect ) const -{ - const QwtColumnSymbol *specialSym = - specialSymbol( sampleIndex, sample ); - - const QwtColumnSymbol *sym = specialSym; - if ( sym == NULL ) - sym = d_data->symbol; - - if ( sym ) - { - sym->draw( painter, rect ); - } - else - { - // we build a temporary default symbol - QwtColumnSymbol sym( QwtColumnSymbol::Box ); - sym.setLineWidth( 1 ); - sym.setFrameStyle( QwtColumnSymbol::Plain ); - sym.draw( painter, rect ); - } - - delete specialSym; -} - -/*! - Needs to be overloaded to return a - non default symbol for a specific sample - - \param sampleIndex Index of the sample represented by the bar - \param sample Value of the sample - - \return NULL, indicating to use the default symbol - */ -QwtColumnSymbol *QwtPlotBarChart::specialSymbol( - int sampleIndex, const QPointF &sample ) const -{ - Q_UNUSED( sampleIndex ); - Q_UNUSED( sample ); - - return NULL; -} - -/*! - \brief Return the title of a bar - - In LegendBarTitles mode the title is displayed on - the legend entry corresponding to a bar. - - The default implementation is a dummy, that is intended - to be overloaded. - - \param sampleIndex Index of the bar - \return An empty text - \sa LegendBarTitles - */ -QwtText QwtPlotBarChart::barTitle( int sampleIndex ) const -{ - Q_UNUSED( sampleIndex ); - return QwtText(); -} - -/*! - \brief Return all information, that is needed to represent - the item on the legend - - In case of LegendBarTitles an entry for each bar is returned, - otherwise the chart is represented like any other plot item - from its title() and the legendIcon(). - - \return Information, that is needed to represent the item on the legend - \sa title(), setLegendMode(), barTitle(), QwtLegend, QwtPlotLegendItem - */ -QList<QwtLegendData> QwtPlotBarChart::legendData() const -{ - QList<QwtLegendData> list; - - if ( d_data->legendMode == LegendBarTitles ) - { - const size_t numSamples = dataSize(); - for ( size_t i = 0; i < numSamples; i++ ) - { - QwtLegendData data; - - QVariant titleValue; - qVariantSetValue( titleValue, barTitle( i ) ); - data.setValue( QwtLegendData::TitleRole, titleValue ); - - if ( !legendIconSize().isEmpty() ) - { - QVariant iconValue; - qVariantSetValue( iconValue, - legendIcon( i, legendIconSize() ) ); - - data.setValue( QwtLegendData::IconRole, iconValue ); - } - - list += data; - } - } - else - { - return QwtPlotAbstractBarChart::legendData(); - } - - return list; -} - -/*! - \return Icon representing a bar or the chart on the legend - - When the legendMode() is LegendBarTitles the icon shows - the bar corresponding to index - otherwise the bar - displays the default symbol. - - \param index Index of the legend entry - \param size Icon size - - \sa setLegendMode(), drawBar(), - QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() - */ -QwtGraphic QwtPlotBarChart::legendIcon( - int index, const QSizeF &size ) const -{ - QwtColumnRect column; - column.hInterval = QwtInterval( 0.0, size.width() - 1.0 ); - column.vInterval = QwtInterval( 0.0, size.height() - 1.0 ); - - QwtGraphic icon; - icon.setDefaultSize( size ); - icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); - - QPainter painter( &icon ); - painter.setRenderHint( QPainter::Antialiasing, - testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - int barIndex = -1; - if ( d_data->legendMode == QwtPlotBarChart::LegendBarTitles ) - barIndex = index; - - drawBar( &painter, barIndex, QPointF(), column ); - - return icon; -} diff --git a/source/third_party/qwt/qwt_plot_canvas.cpp b/source/third_party/qwt/qwt_plot_canvas.cpp deleted file mode 100644 index 31aa1c883c4f8b1dba96bca81f35aac0798768bb..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_canvas.cpp +++ /dev/null @@ -1,1101 +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/qwt_plot_canvas.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_null_paintdevice.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_plot.h" -#include <qpainter.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qpaintengine.h> -#include <qevent.h> - -class QwtStyleSheetRecorder: public QwtNullPaintDevice -{ -public: - QwtStyleSheetRecorder( const QSize &size ): - d_size( 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 ), d_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; - } - } - } - } - -protected: - virtual QSize sizeMetrics() const - { - return d_size; - } - -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<QRectF> clipRects; - - struct Border - { - QList<QPainterPath> pathList; - QList<QRectF> rectList; - QRegion clipRegion; - } border; - - struct Background - { - QPainterPath path; - QBrush brush; - QPointF origin; - } background; - -private: - const QSize d_size; - - QPen d_pen; - QBrush d_brush; - QPointF d_origin; -}; - -static void qwtDrawBackground( QPainter *painter, QwtPlotCanvas *canvas ) -{ - painter->save(); - - const QPainterPath borderClip = canvas->borderPath( canvas->rect() ); - if ( !borderClip.isEmpty() ) - painter->setClipPath( borderClip, Qt::IntersectClip ); - - const QBrush &brush = - canvas->palette().brush( canvas->backgroundRole() ); - - if ( brush.style() == Qt::TexturePattern ) - { - QPixmap pm( canvas->size() ); - QwtPainter::fillPixmap( canvas, pm ); - painter->drawPixmap( 0, 0, pm ); - } - else if ( brush.gradient() ) - { - QVector<QRect> rects; - - if ( brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode ) - { - rects += canvas->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 - 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( canvas->size(), format ); - - QPainter p( &image ); - p.setPen( Qt::NoPen ); - p.setBrush( brush ); - - p.drawRects( rects ); - - p.end(); - - painter->drawImage( 0, 0, image ); - } - else - { - painter->setPen( Qt::NoPen ); - painter->setBrush( brush ); - - painter->drawRects( rects ); - } - } - else - { - 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 = path.elementAt(0); - QPainterPath::Element el3 = path.elementAt(3); - - path.setElementPositionAt( 0, el3.x, el3.y ); - path.setElementPositionAt( 3, el0.x, el0.y ); - } -} - -static QPainterPath qwtCombinePathList( const QRectF &rect, - const QList<QPainterPath> &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<QRectF> &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() ); - QwtPainter::fillPixmap( bgWidget, pm, widget->mapTo( bgWidget, rect.topLeft() ) ); - painter->drawPixmap( rect, pm ); - } - } -} - -static void qwtFillBackground( QPainter *painter, QwtPlotCanvas *canvas ) -{ - QVector<QRectF> 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 ) - { - QSizeF 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 ), - borderRadius( 0 ), - paintAttributes( 0 ), - backingStore( NULL ) - { - styleSheet.hasBorder = false; - } - - ~PrivateData() - { - delete backingStore; - } - - FocusIndicator focusIndicator; - double borderRadius; - QwtPlotCanvas::PaintAttributes paintAttributes; - QPixmap *backingStore; - - struct StyleSheet - { - bool hasBorder; - QPainterPath borderPath; - QVector<QRectF> cornerRects; - - struct StyleSheetBackground - { - QBrush brush; - QPointF origin; - } background; - - } styleSheet; - -}; - -/*! - \brief Constructor - - \param plot Parent plot widget - \sa QwtPlot::setCanvas() -*/ -QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ): - QFrame( plot ) -{ - setFrameStyle( QFrame::Panel | QFrame::Sunken ); - setLineWidth( 2 ); - - d_data = new PrivateData; - -#ifndef QT_NO_CURSOR - setCursor( Qt::CrossCursor ); -#endif - - setAutoFillBackground( true ); - setPaintAttribute( QwtPlotCanvas::BackingStore, true ); - setPaintAttribute( QwtPlotCanvas::Opaque, true ); - setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true ); -} - -//! Destructor -QwtPlotCanvas::~QwtPlotCanvas() -{ - delete d_data; -} - -//! Return parent plot widget -QwtPlot *QwtPlotCanvas::plot() -{ - return qobject_cast<QwtPlot *>( parent() ); -} - -//! Return parent plot widget -const QwtPlot *QwtPlotCanvas::plot() const -{ - return qobject_cast<const QwtPlot *>( parent() ); -} - -/*! - \brief Changing the paint attributes - - \param attribute Paint attribute - \param on On/Off - - \sa testPaintAttribute(), backingStore() -*/ -void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on ) -{ - if ( bool( d_data->paintAttributes & attribute ) == on ) - return; - - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; - - switch ( attribute ) - { - case BackingStore: - { - if ( on ) - { - if ( d_data->backingStore == NULL ) - d_data->backingStore = new QPixmap(); - - if ( isVisible() ) - { -#if QT_VERSION >= 0x050000 - *d_data->backingStore = grab( rect() ); -#else - *d_data->backingStore = - QPixmap::grabWidget( this, rect() ); -#endif - } - } - else - { - delete d_data->backingStore; - d_data->backingStore = NULL; - } - break; - } - case Opaque: - { - if ( on ) - setAttribute( Qt::WA_OpaquePaintEvent, true ); - - break; - } - case HackStyledBackground: - case ImmediatePaint: - { - break; - } - } -} - -/*! - Test whether a paint attribute is enabled - - \param attribute Paint attribute - \return true, when attribute is enabled - \sa setPaintAttribute() -*/ -bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const -{ - return d_data->paintAttributes & attribute; -} - -//! \return Backing store, might be null -const QPixmap *QwtPlotCanvas::backingStore() const -{ - return d_data->backingStore; -} - -//! Invalidate the internal backing store -void QwtPlotCanvas::invalidateBackingStore() -{ - if ( d_data->backingStore ) - *d_data->backingStore = QPixmap(); -} - -/*! - Set the focus indicator - - \sa FocusIndicator, focusIndicator() -*/ -void QwtPlotCanvas::setFocusIndicator( FocusIndicator focusIndicator ) -{ - d_data->focusIndicator = focusIndicator; -} - -/*! - \return Focus indicator - - \sa FocusIndicator, setFocusIndicator() -*/ -QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const -{ - return d_data->focusIndicator; -} - -/*! - Set the radius for the corners of the border frame - - \param radius Radius of a rounded corner - \sa borderRadius() -*/ -void QwtPlotCanvas::setBorderRadius( double radius ) -{ - d_data->borderRadius = qMax( 0.0, radius ); -} - -/*! - \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 - \return See QFrame::event() -*/ -bool QwtPlotCanvas::event( QEvent *event ) -{ - if ( event->type() == QEvent::PolishRequest ) - { - if ( testPaintAttribute( QwtPlotCanvas::Opaque ) ) - { - // Setting a style sheet changes the - // Qt::WA_OpaquePaintEvent attribute, but we insist - // on painting the background. - - 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 ) -{ - QPainter painter( this ); - painter.setClipRegion( event->region() ); - - if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) && - d_data->backingStore != NULL ) - { - QPixmap &bs = *d_data->backingStore; - if ( bs.size() != size() ) - { - bs = QwtPainter::backingStore( this, size() ); - - if ( testAttribute(Qt::WA_StyledBackground) ) - { - QPainter p( &bs ); - qwtFillBackground( &p, this ); - drawCanvas( &p, true ); - } - else - { - QPainter p; - if ( d_data->borderRadius <= 0.0 ) - { - QwtPainter::fillPixmap( this, bs ); - p.begin( &bs ); - drawCanvas( &p, false ); - } - else - { - p.begin( &bs ); - qwtFillBackground( &p, this ); - drawCanvas( &p, true ); - } - - if ( frameWidth() > 0 ) - drawBorder( &p ); - } - } - - painter.drawPixmap( 0, 0, *d_data->backingStore ); - } - else - { - 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() ) - { - qwtFillBackground( &painter, this ); - qwtDrawBackground( &painter, this ); - } - } - else - { - if ( borderRadius() > 0.0 ) - { - QPainterPath clipPath; - clipPath.addRect( rect() ); - clipPath = clipPath.subtracted( borderPath( rect() ) ); - - painter.save(); - - painter.setClipPath( clipPath, Qt::IntersectClip ); - qwtFillBackground( &painter, this ); - qwtDrawBackground( &painter, this ); - - painter.restore(); - } - } - - drawCanvas( &painter, false ); - - if ( frameWidth() > 0 ) - drawBorder( &painter ); - } - } - - if ( hasFocus() && focusIndicator() == CanvasFocusIndicator ) - drawFocusIndicator( &painter ); -} - -void QwtPlotCanvas::drawCanvas( QPainter *painter, bool withBackground ) -{ - bool hackStyledBackground = false; - - if ( withBackground && testAttribute( Qt::WA_StyledBackground ) - && testPaintAttribute( HackStyledBackground ) ) - { - // 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. - - if ( d_data->styleSheet.hasBorder && - !d_data->styleSheet.borderPath.isEmpty() ) - { - // We have a border with at least one rounded corner - hackStyledBackground = true; - } - } - - if ( withBackground ) - { - painter->save(); - - if ( testAttribute( Qt::WA_StyledBackground ) ) - { - if ( hackStyledBackground ) - { - // paint background without border - - 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() ) ); - - if ( d_data->borderRadius > 0.0 && ( rect() == frameRect() ) ) - { - if ( frameWidth() > 0 ) - { - painter->setClipPath( borderPath( rect() ) ); - painter->drawRect( rect() ); - } - else - { - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->drawPath( borderPath( rect() ) ); - } - } - else - { - painter->drawRect( rect() ); - } - } - - painter->restore(); - } - - painter->save(); - - if ( !d_data->styleSheet.borderPath.isEmpty() ) - { - painter->setClipPath( - d_data->styleSheet.borderPath, Qt::IntersectClip ); - } - else - { - if ( d_data->borderRadius > 0.0 ) - painter->setClipPath( borderPath( frameRect() ), Qt::IntersectClip ); - else - painter->setClipRect( contentsRect(), Qt::IntersectClip ); - } - - plot()->drawCanvas( painter ); - - painter->restore(); - - 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() -*/ -void QwtPlotCanvas::drawBorder( QPainter *painter ) -{ - if ( d_data->borderRadius > 0 ) - { - if ( frameWidth() > 0 ) - { - QwtPainter::drawRoundedFrame( painter, QRectF( frameRect() ), - d_data->borderRadius, d_data->borderRadius, - palette(), frameWidth(), frameStyle() ); - } - } - else - { -#if QT_VERSION >= 0x040500 -#if QT_VERSION < 0x050000 - QStyleOptionFrameV3 opt; -#else - QStyleOptionFrame opt; -#endif - opt.init(this); - - int frameShape = frameStyle() & QFrame::Shape_Mask; - int frameShadow = frameStyle() & QFrame::Shadow_Mask; - - opt.frameShape = QFrame::Shape( int( opt.frameShape ) | frameShape ); -#if 0 - opt.rect = frameRect(); -#endif - - switch (frameShape) - { - case QFrame::Box: - case QFrame::HLine: - case QFrame::VLine: - case QFrame::StyledPanel: - case QFrame::Panel: - { - opt.lineWidth = lineWidth(); - opt.midLineWidth = midLineWidth(); - break; - } - default: - { - opt.lineWidth = frameWidth(); - break; - } - } - - if ( frameShadow == Sunken ) - opt.state |= QStyle::State_Sunken; - else if ( frameShadow == Raised ) - opt.state |= QStyle::State_Raised; - - style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, this); -#else - drawFrame( painter ); -#endif - } -} - -/*! - 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 ) -{ - const int margin = 1; - - QRect focusRect = contentsRect(); - focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin, - focusRect.width() - 2 * margin, focusRect.height() - 2 * margin ); - - QwtPainter::drawFocusRect( painter, this, focusRect ); -} - -/*! - Invalidate the paint cache and repaint the canvas - \sa invalidatePaintCache() -*/ -void QwtPlotCanvas::replot() -{ - invalidateBackingStore(); - - if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) ) - repaint( contentsRect() ); - else - update( contentsRect() ); -} - -//! Update the cached information 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(); -} diff --git a/source/third_party/qwt/qwt_plot_curve.cpp b/source/third_party/qwt/qwt_plot_curve.cpp deleted file mode 100644 index 1b5068ce7b1c4d7e230bd6bf3c6cce09c06940d8..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_curve.cpp +++ /dev/null @@ -1,1204 +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/qwt_plot_curve.h" -#include "qwt/qwt_point_data.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_clipper.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_curve_fitter.h" -#include "qwt/qwt_symbol.h" -#include "qwt/qwt_point_mapper.h" -#include <qpainter.h> -#include <qpixmap.h> -#include <qalgorithms.h> -#include <qmath.h> - -static void qwtUpdateLegendIconSize( QwtPlotCurve *curve ) -{ - if ( curve->symbol() && - curve->testLegendAttribute( QwtPlotCurve::LegendShowSymbol ) ) - { - QSize sz = curve->symbol()->boundingRect().size(); - sz += QSize( 2, 2 ); // margin - - if ( curve->testLegendAttribute( 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 ) ); - } - - curve->setLegendIconSize( sz ); - } -} - -static int qwtVerifyRange( int size, int &i1, int &i2 ) -{ - if ( size < 1 ) - return 0; - - i1 = qBound( 0, i1, size - 1 ); - i2 = qBound( 0, i2, size - 1 ); - - if ( i1 > i2 ) - qSwap( i1, i2 ); - - return ( i2 - i1 + 1 ); -} - -class QwtPlotCurve::PrivateData -{ -public: - PrivateData(): - style( QwtPlotCurve::Lines ), - baseline( 0.0 ), - symbol( NULL ), - attributes( 0 ), - paintAttributes( - QwtPlotCurve::ClipPolygons | QwtPlotCurve::FilterPoints ), - legendAttributes( 0 ) - { - pen = QPen( Qt::black ); - curveFitter = new QwtSplineCurveFitter; - } - - ~PrivateData() - { - delete symbol; - delete curveFitter; - } - - QwtPlotCurve::CurveStyle style; - double baseline; - - const QwtSymbol *symbol; - QwtCurveFitter *curveFitter; - - QPen pen; - QBrush brush; - - QwtPlotCurve::CurveAttributes attributes; - QwtPlotCurve::PaintAttributes paintAttributes; - - QwtPlotCurve::LegendAttributes legendAttributes; -}; - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotCurve::QwtPlotCurve( const QwtText &title ): - QwtPlotSeriesItem( title ) -{ - init(); -} - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotCurve::QwtPlotCurve( const QString &title ): - QwtPlotSeriesItem( QwtText( title ) ) -{ - init(); -} - -//! Destructor -QwtPlotCurve::~QwtPlotCurve() -{ - delete d_data; -} - -//! Initialize internal members -void QwtPlotCurve::init() -{ - setItemAttribute( QwtPlotItem::Legend ); - setItemAttribute( QwtPlotItem::AutoScale ); - - d_data = new PrivateData; - setData( new QwtPointSeriesData() ); - - setZ( 20.0 ); -} - -//! \return QwtPlotItem::Rtti_PlotCurve -int QwtPlotCurve::rtti() const -{ - return QwtPlotItem::Rtti_PlotCurve; -} - -/*! - Specify an attribute how to draw the curve - - \param attribute Paint attribute - \param on On/Off - \sa testPaintAttribute() -*/ -void QwtPlotCurve::setPaintAttribute( PaintAttribute attribute, bool on ) -{ - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; -} - -/*! - \return True, when attribute is enabled - \sa setPaintAttribute() -*/ -bool QwtPlotCurve::testPaintAttribute( PaintAttribute attribute ) const -{ - return ( d_data->paintAttributes & attribute ); -} - -/*! - Specify an attribute how to draw the legend icon - - \param attribute Attribute - \param on On/Off - /sa testLegendAttribute(). legendIcon() -*/ -void QwtPlotCurve::setLegendAttribute( LegendAttribute attribute, bool on ) -{ - if ( on != testLegendAttribute( attribute ) ) - { - if ( on ) - d_data->legendAttributes |= attribute; - else - d_data->legendAttributes &= ~attribute; - - qwtUpdateLegendIconSize( this ); - legendChanged(); - } -} - -/*! - \return True, when attribute is enabled - \sa setLegendAttribute() -*/ -bool QwtPlotCurve::testLegendAttribute( LegendAttribute attribute ) const -{ - return ( d_data->legendAttributes & attribute ); -} - -/*! - Set the curve's drawing style - - \param style Curve style - \sa style() -*/ -void QwtPlotCurve::setStyle( CurveStyle style ) -{ - if ( style != d_data->style ) - { - d_data->style = style; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Style of the curve - \sa setStyle() -*/ -QwtPlotCurve::CurveStyle QwtPlotCurve::style() const -{ - return d_data->style; -} - -/*! - \brief Assign a symbol - - The curve will take the ownership of the symbol, hence the previously - set symbol will be delete by setting a new one. If \p symbol is - \c NULL no symbol will be drawn. - - \param symbol Symbol - \sa symbol() -*/ -void QwtPlotCurve::setSymbol( QwtSymbol *symbol ) -{ - if ( symbol != d_data->symbol ) - { - delete d_data->symbol; - d_data->symbol = symbol; - - qwtUpdateLegendIconSize( this ); - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Current symbol or NULL, when no symbol has been assigned - \sa setSymbol() -*/ -const QwtSymbol *QwtPlotCurve::symbol() const -{ - return d_data->symbol; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - Assign a pen - - \param pen New pen - \sa pen(), brush() -*/ -void QwtPlotCurve::setPen( const QPen &pen ) -{ - if ( pen != d_data->pen ) - { - d_data->pen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Pen used to draw the lines - \sa setPen(), brush() -*/ -const QPen& QwtPlotCurve::pen() const -{ - return d_data->pen; -} - -/*! - \brief Assign a brush. - - 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). - - \param brush New brush - \sa brush(), setBaseline(), baseline() -*/ -void QwtPlotCurve::setBrush( const QBrush &brush ) -{ - if ( brush != d_data->brush ) - { - d_data->brush = brush; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Brush used to fill the area between lines and the baseline - \sa setBrush(), setBaseline(), baseline() -*/ -const QBrush& QwtPlotCurve::brush() const -{ - return d_data->brush; -} - -/*! - 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 canvasRect Contents rectangle 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::drawSeries( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const -{ - const size_t numSamples = dataSize(); - - if ( !painter || numSamples <= 0 ) - return; - - if ( to < 0 ) - to = numSamples - 1; - - if ( qwtVerifyRange( numSamples, from, to ) > 0 ) - { - painter->save(); - painter->setPen( d_data->pen ); - - /* - 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, canvasRect, from, to ); - painter->restore(); - - if ( d_data->symbol && - ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) - { - painter->save(); - drawSymbols( painter, *d_data->symbol, - xMap, yMap, canvasRect, from, to ); - painter->restore(); - } - } -} - -/*! - \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 rectangle 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, - const QRectF &canvasRect, int from, int to ) const -{ - switch ( style ) - { - case Lines: - if ( testCurveAttribute( Fitted ) ) - { - // we always need the complete - // curve for fitting - from = 0; - to = dataSize() - 1; - } - drawLines( painter, xMap, yMap, canvasRect, from, to ); - break; - case Sticks: - drawSticks( painter, xMap, yMap, canvasRect, from, to ); - break; - case Steps: - drawSteps( painter, xMap, yMap, canvasRect, from, to ); - break; - case Dots: - drawDots( painter, xMap, yMap, canvasRect, from, to ); - break; - case NoCurve: - default: - break; - } -} - -/*! - \brief Draw lines - - If the CurveAttribute Fitted is enabled a QwtCurveFitter tries - to interpolate/smooth the curve, before it is painted. - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle 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(), - drawLines(), drawDots(), drawSteps(), drawSticks() -*/ -void QwtPlotCurve::drawLines( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const -{ - if ( from > to ) - return; - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - const bool doFit = ( d_data->attributes & Fitted ) && d_data->curveFitter; - const bool doFill = ( d_data->brush.style() != Qt::NoBrush ) - && ( d_data->brush.color().alpha() > 0 ); - - QRectF clipRect; - if ( d_data->paintAttributes & ClipPolygons ) - { - qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF()); - clipRect = canvasRect.adjusted(-pw, -pw, pw, pw); - } - - bool doIntegers = false; - -#if QT_VERSION < 0x040800 - - // For Qt <= 4.7 the raster paint engine is significantly faster - // for rendering QPolygon than for QPolygonF. So let's - // see if we can use it. - - if ( painter->paintEngine()->type() == QPaintEngine::Raster ) - { - // In case of filling or fitting performance doesn't count - // because both operations are much more expensive - // then drawing the polyline itself - - if ( !doFit && !doFill ) - doIntegers = true; - } -#endif - - const bool noDuplicates = d_data->paintAttributes & FilterPoints; - - QwtPointMapper mapper; - mapper.setFlag( QwtPointMapper::RoundPoints, doAlign ); - mapper.setFlag( QwtPointMapper::WeedOutPoints, noDuplicates ); - mapper.setBoundingRect( canvasRect ); - - if ( doIntegers ) - { - QPolygon polyline = mapper.toPolygon( - xMap, yMap, data(), from, to ); - - if ( d_data->paintAttributes & ClipPolygons ) - { - polyline = QwtClipper::clipPolygon( - clipRect.toAlignedRect(), polyline, false ); - } - - QwtPainter::drawPolyline( painter, polyline ); - } - else - { - QPolygonF polyline = mapper.toPolygonF( xMap, yMap, data(), from, to ); - - if ( doFit ) - polyline = d_data->curveFitter->fitCurve( polyline ); - - if ( doFill ) - { - if ( painter->pen().style() != Qt::NoPen ) - { - // here we are wasting memory for the filled copy, - // do polygon clipping twice etc .. TODO - - QPolygonF filled = polyline; - fillCurve( painter, xMap, yMap, canvasRect, filled ); - filled.clear(); - - if ( d_data->paintAttributes & ClipPolygons ) - { - polyline = QwtClipper::clipPolygonF( - clipRect, polyline, false ); - } - - QwtPainter::drawPolyline( painter, polyline ); - } - else - { - fillCurve( painter, xMap, yMap, canvasRect, polyline ); - } - } - else - { - if ( d_data->paintAttributes & ClipPolygons ) - { - polyline = QwtClipper::clipPolygonF( - clipRect, polyline, false ); - } - - QwtPainter::drawPolyline( painter, polyline ); - } - } -} - -/*! - Draw sticks - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle 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, - const QRectF &, int from, int to ) const -{ - painter->save(); - painter->setRenderHint( QPainter::Antialiasing, false ); - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - double x0 = xMap.transform( d_data->baseline ); - double y0 = yMap.transform( d_data->baseline ); - if ( doAlign ) - { - x0 = qRound( x0 ); - y0 = qRound( y0 ); - } - - const Qt::Orientation o = orientation(); - - const QwtSeriesData<QPointF> *series = data(); - - for ( int i = from; i <= to; i++ ) - { - const QPointF sample = 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(); -} - -/*! - Draw dots - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle 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, - const QRectF &canvasRect, int from, int to ) const -{ - const QColor color = painter->pen().color(); - - if ( painter->pen().style() == Qt::NoPen || color.alpha() == 0 ) - { - return; - } - - const bool doFill = ( d_data->brush.style() != Qt::NoBrush ) - && ( d_data->brush.color().alpha() > 0 ); - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - QwtPointMapper mapper; - mapper.setBoundingRect( canvasRect ); - mapper.setFlag( QwtPointMapper::RoundPoints, doAlign ); - - if ( d_data->paintAttributes & FilterPoints ) - { - if ( ( color.alpha() == 255 ) - && !( painter->renderHints() & QPainter::Antialiasing ) ) - { - mapper.setFlag( QwtPointMapper::WeedOutPoints, true ); - } - } - - if ( doFill ) - { - mapper.setFlag( QwtPointMapper::WeedOutPoints, false ); - - QPolygonF points = mapper.toPointsF( - xMap, yMap, data(), from, to ); - - QwtPainter::drawPoints( painter, points ); - fillCurve( painter, xMap, yMap, canvasRect, points ); - } - else if ( d_data->paintAttributes & ImageBuffer ) - { - const QImage image = mapper.toImage( xMap, yMap, - data(), from, to, d_data->pen, - painter->testRenderHint( QPainter::Antialiasing ), - renderThreadCount() ); - - painter->drawImage( canvasRect.toAlignedRect(), image ); - } - else if ( d_data->paintAttributes & MinimizeMemory ) - { - const QwtSeriesData<QPointF> *series = data(); - - for ( int i = from; i <= to; i++ ) - { - const QPointF sample = series->sample( i ); - - double xi = xMap.transform( sample.x() ); - double yi = yMap.transform( sample.y() ); - - if ( doAlign ) - { - xi = qRound( xi ); - yi = qRound( yi ); - } - - QwtPainter::drawPoint( painter, QPointF( xi, yi ) ); - } - } - else - { - if ( doAlign ) - { - const QPolygon points = mapper.toPoints( - xMap, yMap, data(), from, to ); - - QwtPainter::drawPoints( painter, points ); - } - else - { - const QPolygonF points = mapper.toPointsF( - xMap, yMap, data(), from, to ); - - QwtPainter::drawPoints( painter, points ); - } - } -} - -/*! - Draw step function - - The direction of the steps depends on Inverted attribute. - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle 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, - const QRectF &canvasRect, int from, int to ) const -{ - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - QPolygonF polygon( 2 * ( to - from ) + 1 ); - QPointF *points = polygon.data(); - - bool inverted = orientation() == Qt::Vertical; - if ( d_data->attributes & Inverted ) - inverted = !inverted; - - const QwtSeriesData<QPointF> *series = data(); - - int i, ip; - for ( i = from, ip = 0; i <= to; i++, ip += 2 ) - { - const QPointF sample = 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 ) - { - const QPointF &p0 = points[ip - 2]; - QPointF &p = points[ip - 1]; - - if ( inverted ) - { - p.rx() = p0.x(); - p.ry() = yi; - } - else - { - p.rx() = xi; - p.ry() = p0.y(); - } - } - - points[ip].rx() = xi; - points[ip].ry() = yi; - } - - if ( d_data->paintAttributes & ClipPolygons ) - { - const QPolygonF clipped = QwtClipper::clipPolygonF( - canvasRect, polygon, false ); - - QwtPainter::drawPolyline( painter, clipped ); - } - else - { - QwtPainter::drawPolyline( painter, polygon ); - } - - if ( d_data->brush.style() != Qt::NoBrush ) - fillCurve( painter, xMap, yMap, canvasRect, polygon ); -} - - -/*! - Specify an attribute for drawing the curve - - \param attribute Curve attribute - \param on On/Off - - /sa testCurveAttribute(), setCurveFitter() -*/ -void QwtPlotCurve::setCurveAttribute( CurveAttribute attribute, bool on ) -{ - if ( bool( d_data->attributes & attribute ) == on ) - return; - - if ( on ) - d_data->attributes |= attribute; - else - d_data->attributes &= ~attribute; - - itemChanged(); -} - -/*! - \return true, if attribute is enabled - \sa setCurveAttribute() -*/ -bool QwtPlotCurve::testCurveAttribute( CurveAttribute attribute ) const -{ - return d_data->attributes & attribute; -} - -/*! - Assign a 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 ) -{ - delete d_data->curveFitter; - d_data->curveFitter = curveFitter; - - itemChanged(); -} - -/*! - 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 - the curve brush - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle of the canvas - \param polygon Polygon - will be modified ! - - \sa setBrush(), setBaseline(), setStyle() -*/ -void QwtPlotCurve::fillCurve( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, QPolygonF &polygon ) const -{ - if ( d_data->brush.style() == Qt::NoBrush ) - return; - - closePolyline( painter, xMap, yMap, polygon ); - if ( polygon.count() <= 2 ) // a line can't be filled - return; - - 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( Qt::NoPen ); - painter->setBrush( brush ); - - 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. - - \param painter Painter - \param xMap X map - \param yMap Y map - \param polygon Polygon to be completed -*/ -void QwtPlotCurve::closePolyline( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - QPolygonF &polygon ) const -{ - if ( polygon.size() < 2 ) - return; - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - double baseline = d_data->baseline; - - if ( orientation() == Qt::Vertical ) - { - if ( yMap.transformation() ) - baseline = yMap.transformation()->bounded( baseline ); - - double refY = yMap.transform( baseline ); - if ( doAlign ) - refY = qRound( refY ); - - polygon += QPointF( polygon.last().x(), refY ); - polygon += QPointF( polygon.first().x(), refY ); - } - else - { - if ( xMap.transformation() ) - baseline = xMap.transformation()->bounded( baseline ); - - double refX = xMap.transform( baseline ); - if ( doAlign ) - refX = qRound( refX ); - - polygon += QPointF( refX, polygon.last().y() ); - polygon += QPointF( refX, polygon.first().y() ); - } -} - -/*! - Draw symbols - - \param painter Painter - \param symbol Curve symbol - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle 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(), drawSeries(), drawCurve() -*/ -void QwtPlotCurve::drawSymbols( QPainter *painter, const QwtSymbol &symbol, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const -{ - QwtPointMapper mapper; - mapper.setFlag( QwtPointMapper::RoundPoints, - QwtPainter::roundingAlignment( painter ) ); - mapper.setFlag( QwtPointMapper::WeedOutPoints, - testPaintAttribute( QwtPlotCurve::FilterPoints ) ); - mapper.setBoundingRect( canvasRect ); - - const int chunkSize = 500; - - for ( int i = from; i <= to; i += chunkSize ) - { - const int n = qMin( chunkSize, to - i + 1 ); - - const QPolygonF points = mapper.toPointsF( xMap, yMap, - data(), i, i + n - 1 ); - - if ( points.size() > 0 ) - symbol.drawSymbols( painter, points ); - } -} - -/*! - \brief Set the value of the baseline - - The baseline is needed for filling the curve with a brush or - the Sticks drawing style. - - The interpretation of the baseline depends on the orientation(). - With Qt::Horizontal, the baseline is interpreted as a horizontal line - at y = baseline(), with Qt::Vertical, 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(), QwtPlotAbstractSeriesItem::orientation() -*/ -void QwtPlotCurve::setBaseline( double value ) -{ - if ( d_data->baseline != value ) - { - d_data->baseline = value; - itemChanged(); - } -} - -/*! - \return Value of the baseline - \sa setBaseline() -*/ -double QwtPlotCurve::baseline() const -{ - return d_data->baseline; -} - -/*! - Find the closest curve point for a specific position - - \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 closest curve point - \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 - over all points -*/ -int QwtPlotCurve::closestPoint( const QPoint &pos, double *dist ) const -{ - const size_t numSamples = dataSize(); - - if ( plot() == NULL || numSamples <= 0 ) - return -1; - - const QwtSeriesData<QPointF> *series = data(); - - const QwtScaleMap xMap = plot()->canvasMap( xAxis() ); - const QwtScaleMap yMap = plot()->canvasMap( yAxis() ); - - int index = -1; - double dmin = 1.0e10; - - for ( uint i = 0; i < numSamples; i++ ) - { - const QPointF sample = series->sample( i ); - - 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 = qSqrt( dmin ); - - return index; -} - -/*! - \return Icon representing the curve on the legend - - \param index Index of the legend entry - ( ignored as there is only one ) - \param size Icon size - - \sa QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() - */ -QwtGraphic QwtPlotCurve::legendIcon( int index, - const QSizeF &size ) const -{ - Q_UNUSED( index ); - - if ( size.isEmpty() ) - return QwtGraphic(); - - QwtGraphic graphic; - graphic.setDefaultSize( size ); - graphic.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); - - QPainter painter( &graphic ); - painter.setRenderHint( QPainter::Antialiasing, - testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - if ( d_data->legendAttributes == 0 || - d_data->legendAttributes & QwtPlotCurve::LegendShowBrush ) - { - QBrush brush = d_data->brush; - - if ( brush.style() == Qt::NoBrush && - d_data->legendAttributes == 0 ) - { - 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 ) - { - QRectF r( 0, 0, size.width(), size.height() ); - painter.fillRect( r, brush ); - } - } - - if ( d_data->legendAttributes & QwtPlotCurve::LegendShowLine ) - { - if ( pen() != Qt::NoPen ) - { - QPen pn = pen(); - pn.setCapStyle( Qt::FlatCap ); - - painter.setPen( pn ); - - const double y = 0.5 * size.height(); - QwtPainter::drawLine( &painter, 0.0, y, size.width(), y ); - } - } - - if ( d_data->legendAttributes & QwtPlotCurve::LegendShowSymbol ) - { - if ( d_data->symbol ) - { - QRectF r( 0, 0, size.width(), size.height() ); - d_data->symbol->drawSymbol( &painter, r ); - } - } - - return graphic; -} - -/*! - Initialize data with an array of points. - - \param samples Vector of points - \note QVector is implicitly shared - \note QPolygonF is derived from QVector<QPointF> -*/ -void QwtPlotCurve::setSamples( const QVector<QPointF> &samples ) -{ - setData( new QwtPointSeriesData( samples ) ); -} - -/*! - Assign a series of points - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotCurve::setSamples( QwtSeriesData<QPointF> *data ) -{ - setData( data ); -} - -#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 ) -{ - setData( new QwtCPointerData( xData, yData, size ) ); -} - -/*! - 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 ) -{ - setData( new QwtPointArrayData( xData, yData, size ) ); -} - -/*! - \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<double> &xData, - const QVector<double> &yData ) -{ - setData( new QwtPointArrayData( xData, yData ) ); -} - -#endif // !QWT_NO_COMPAT - diff --git a/source/third_party/qwt/qwt_plot_dict.cpp b/source/third_party/qwt/qwt_plot_dict.cpp deleted file mode 100644 index 1a2f5474aaf777226b7b5a53a1652db0512da6af..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_dict.cpp +++ /dev/null @@ -1,191 +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/qwt_plot_dict.h" - -class QwtPlotDict::PrivateData -{ -public: - - class ItemList: public QList<QwtPlotItem *> - { - public: - void insertItem( QwtPlotItem *item ) - { - if ( item == NULL ) - return; - - QList<QwtPlotItem *>::iterator it = - qUpperBound( begin(), end(), item, LessZThan() ); - insert( it, item ); - } - - void removeItem( QwtPlotItem *item ) - { - if ( item == NULL ) - return; - - QList<QwtPlotItem *>::iterator it = - qLowerBound( begin(), end(), item, LessZThan() ); - - for ( ; it != end(); ++it ) - { - if ( item == *it ) - { - erase( it ); - break; - } - } - } - private: - class LessZThan - { - public: - inline bool operator()( const QwtPlotItem *item1, - const QwtPlotItem *item2 ) const - { - return item1->z() < item2->z(); - } - }; - }; - - ItemList itemList; - bool autoDelete; -}; - -/*! - Constructor - - Auto deletion is enabled. - \sa setAutoDelete(), QwtPlotItem::attach() -*/ -QwtPlotDict::QwtPlotDict() -{ - d_data = new QwtPlotDict::PrivateData; - d_data->autoDelete = true; -} - -/*! - Destructor - - If autoDelete() is on, all attached items will be deleted - \sa setAutoDelete(), autoDelete(), QwtPlotItem::attach() -*/ -QwtPlotDict::~QwtPlotDict() -{ - detachItems( QwtPlotItem::Rtti_PlotItem, d_data->autoDelete ); - delete d_data; -} - -/*! - En/Disable Auto deletion - - If Auto deletion is on all attached plot items will be deleted - in the destructor of QwtPlotDict. The default value is on. - - \sa autoDelete(), insertItem() -*/ -void QwtPlotDict::setAutoDelete( bool autoDelete ) -{ - d_data->autoDelete = autoDelete; -} - -/*! - \return true if auto deletion is enabled - \sa setAutoDelete(), insertItem() -*/ -bool QwtPlotDict::autoDelete() const -{ - return d_data->autoDelete; -} - -/*! - Insert a plot item - - \param item PlotItem - \sa removeItem() - */ -void QwtPlotDict::insertItem( QwtPlotItem *item ) -{ - d_data->itemList.insertItem( item ); -} - -/*! - Remove a plot item - - \param item PlotItem - \sa insertItem() - */ -void QwtPlotDict::removeItem( QwtPlotItem *item ) -{ - d_data->itemList.removeItem( item ); -} - -/*! - Detach items from the dictionary - - \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 ) -{ - PrivateData::ItemList list = d_data->itemList; - QwtPlotItemIterator it = list.begin(); - while ( it != list.end() ) - { - QwtPlotItem *item = *it; - - ++it; // increment before removing item from the list - - if ( rtti == QwtPlotItem::Rtti_PlotItem || item->rtti() == rtti ) - { - 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. -*/ -const QwtPlotItemList &QwtPlotDict::itemList() const -{ - return d_data->itemList; -} - -/*! - \return List of all attached plot items of a specific type. - \param rtti See QwtPlotItem::RttiValues - \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/source/third_party/qwt/qwt_plot_directpainter.cpp b/source/third_party/qwt/qwt_plot_directpainter.cpp deleted file mode 100644 index 71c2d7057eaa4e379dda5886da3fe857256c40a2..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_directpainter.cpp +++ /dev/null @@ -1,321 +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/qwt_plot_directpainter.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_plot_canvas.h" -#include "qwt/qwt_plot_seriesitem.h" -#include <qpainter.h> -#include <qevent.h> -#include <qapplication.h> -#include <qpixmap.h> - -static inline void qwtRenderItem( - QPainter *painter, const QRect &canvasRect, - QwtPlotSeriesItem *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 ); -} - -static inline bool qwtHasBackingStore( const QwtPlotCanvas *canvas ) -{ - return canvas->testPaintAttribute( QwtPlotCanvas::BackingStore ) - && canvas->backingStore() && !canvas->backingStore()->isNull(); -} - -class QwtPlotDirectPainter::PrivateData -{ -public: - PrivateData(): - attributes( 0 ), - hasClipping(false), - seriesItem( NULL ), - from( 0 ), - to( 0 ) - { - } - - QwtPlotDirectPainter::Attributes attributes; - - bool hasClipping; - QRegion clipRegion; - - QPainter painter; - - QwtPlotSeriesItem *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(); - } -} - -/*! - \return True, when attribute is enabled - \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( - QwtPlotSeriesItem *seriesItem, int from, int to ) -{ - if ( seriesItem == NULL || seriesItem->plot() == NULL ) - return; - - QWidget *canvas = seriesItem->plot()->canvas(); - const QRect canvasRect = canvas->contentsRect(); - - QwtPlotCanvas *plotCanvas = qobject_cast<QwtPlotCanvas *>( canvas ); - - if ( plotCanvas && qwtHasBackingStore( plotCanvas ) ) - { - QPainter painter( const_cast<QPixmap *>( plotCanvas->backingStore() ) ); - - if ( d_data->hasClipping ) - painter.setClipRegion( d_data->clipRegion ); - - qwtRenderItem( &painter, canvasRect, seriesItem, from, to ); - - painter.end(); - - if ( testAttribute( QwtPlotDirectPainter::FullRepaint ) ) - { - plotCanvas->repaint(); - return; - } - } - - bool immediatePaint = true; - if ( !canvas->testAttribute( Qt::WA_WState_InPaintEvent ) ) - { -#if QT_VERSION < 0x050000 - if ( !canvas->testAttribute( Qt::WA_PaintOutsidePaintEvent ) ) -#endif - immediatePaint = false; - } - - if ( immediatePaint ) - { - 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 ); - } - - qwtRenderItem( &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 = static_cast<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 ); - - QWidget *canvas = d_data->seriesItem->plot()->canvas(); - - QPainter painter( canvas ); - painter.setClipRegion( pe->region() ); - - bool doCopyCache = testAttribute( CopyBackingStore ); - - if ( doCopyCache ) - { - QwtPlotCanvas *plotCanvas = - qobject_cast<QwtPlotCanvas *>( canvas ); - if ( plotCanvas ) - { - doCopyCache = qwtHasBackingStore( plotCanvas ); - if ( doCopyCache ) - { - painter.drawPixmap( plotCanvas->contentsRect().topLeft(), - *plotCanvas->backingStore() ); - } - } - } - - if ( !doCopyCache ) - { - qwtRenderItem( &painter, canvas->contentsRect(), - d_data->seriesItem, d_data->from, d_data->to ); - } - - return true; // don't call QwtPlotCanvas::paintEvent() - } - } - - return false; -} diff --git a/source/third_party/qwt/qwt_plot_glcanvas.cpp b/source/third_party/qwt/qwt_plot_glcanvas.cpp deleted file mode 100644 index 8e5d43d66a5ae060f8c2ec02e5fa8242bdd9d0a2..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_glcanvas.cpp +++ /dev/null @@ -1,378 +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/qwt_plot_glcanvas.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_painter.h" -#include <qevent.h> -#include <qpainter.h> -#include <qdrawutil.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <QtOpenGL/QGLFormat> - -#define FIX_GL_TRANSLATION 0 - -static QWidget *qwtBGWidget( QWidget *widget ) -{ - QWidget *w = widget; - - for ( ; w->parentWidget() != NULL; w = w->parentWidget() ) - { - if ( w->autoFillBackground() || - w->testAttribute( Qt::WA_StyledBackground ) ) - { - return w; - } - } - - return w; -} - -static void qwtUpdateContentsRect( QwtPlotGLCanvas *canvas ) -{ - const int fw = canvas->frameWidth(); - canvas->setContentsMargins( fw, fw, fw, fw ); -} - -class QwtPlotGLCanvas::PrivateData -{ -public: - PrivateData(): - frameStyle( QFrame::Panel | QFrame::Sunken), - lineWidth( 2 ), - midLineWidth( 0 ) - { - } - - int frameStyle; - int lineWidth; - int midLineWidth; -}; - -class QwtPlotGLCanvasFormat: public QGLFormat -{ -public: - QwtPlotGLCanvasFormat(): - QGLFormat( QGLFormat::defaultFormat() ) - { - setSampleBuffers( true ); - } -}; - -/*! - \brief Constructor - - \param plot Parent plot widget - \sa QwtPlot::setCanvas() -*/ -QwtPlotGLCanvas::QwtPlotGLCanvas( QwtPlot *plot ): - QOpenGLWidget( plot ) -{ - d_data = new PrivateData; - -#ifndef QT_NO_CURSOR - setCursor( Qt::CrossCursor ); -#endif - - setAutoFillBackground( true ); - qwtUpdateContentsRect( this ); -} - -//! Destructor -QwtPlotGLCanvas::~QwtPlotGLCanvas() -{ - delete d_data; -} - -/*! - Set the frame style - - \param style The bitwise OR between a shape and a shadow. - - \sa frameStyle(), QFrame::setFrameStyle(), - setFrameShadow(), setFrameShape() - */ -void QwtPlotGLCanvas::setFrameStyle( int style ) -{ - if ( style != d_data->frameStyle ) - { - d_data->frameStyle = style; - qwtUpdateContentsRect( this ); - - update(); - } -} - -/*! - \return The bitwise OR between a frameShape() and a frameShadow() - \sa setFrameStyle(), QFrame::frameStyle() - */ -int QwtPlotGLCanvas::frameStyle() const -{ - return d_data->frameStyle; -} - -/*! - Set the frame shadow - - \param shadow Frame shadow - \sa frameShadow(), setFrameShape(), QFrame::setFrameShadow() - */ -void QwtPlotGLCanvas::setFrameShadow( Shadow shadow ) -{ - setFrameStyle(( d_data->frameStyle & QFrame::Shape_Mask ) | shadow ); -} - -/*! - \return Frame shadow - \sa setFrameShadow(), QFrame::setFrameShadow() - */ -QwtPlotGLCanvas::Shadow QwtPlotGLCanvas::frameShadow() const -{ - return (Shadow) ( d_data->frameStyle & QFrame::Shadow_Mask ); -} - -/*! - Set the frame shape - - \param shape Frame shape - \sa frameShape(), setFrameShadow(), QFrame::frameShape() - */ -void QwtPlotGLCanvas::setFrameShape( Shape shape ) -{ - setFrameStyle( ( d_data->frameStyle & QFrame::Shadow_Mask ) | shape ); -} - -/*! - \return Frame shape - \sa setFrameShape(), QFrame::frameShape() - */ -QwtPlotGLCanvas::Shape QwtPlotGLCanvas::frameShape() const -{ - return (Shape) ( d_data->frameStyle & QFrame::Shape_Mask ); -} - -/*! - Set the frame line width - - The default line width is 2 pixels. - - \param width Line width of the frame - \sa lineWidth(), setMidLineWidth() -*/ -void QwtPlotGLCanvas::setLineWidth( int width ) -{ - width = qMax( width, 0 ); - if ( width != d_data->lineWidth ) - { - d_data->lineWidth = qMax( width, 0 ); - qwtUpdateContentsRect( this ); - update(); - } -} - -/*! - \return Line width of the frame - \sa setLineWidth(), midLineWidth() - */ -int QwtPlotGLCanvas::lineWidth() const -{ - return d_data->lineWidth; -} - -/*! - Set the frame mid line width - - The default midline width is 0 pixels. - - \param width Midline width of the frame - \sa midLineWidth(), setLineWidth() -*/ -void QwtPlotGLCanvas::setMidLineWidth( int width ) -{ - width = qMax( width, 0 ); - if ( width != d_data->midLineWidth ) - { - d_data->midLineWidth = width; - qwtUpdateContentsRect( this ); - update(); - } -} - -/*! - \return Midline width of the frame - \sa setMidLineWidth(), lineWidth() - */ -int QwtPlotGLCanvas::midLineWidth() const -{ - return d_data->midLineWidth; -} - -/*! - \return Frame width depending on the style, line width and midline width. - */ -int QwtPlotGLCanvas::frameWidth() const -{ - return ( frameStyle() != NoFrame ) ? d_data->lineWidth : 0; -} - -/*! - Paint event - - \param event Paint event - \sa QwtPlot::drawCanvas() -*/ -void QwtPlotGLCanvas::paintEvent( QPaintEvent *event ) -{ - Q_UNUSED( event ); - - QPainter painter( this ); - -#if FIX_GL_TRANSLATION - if ( painter.paintEngine()->type() == QPaintEngine::OpenGL2 ) - { - // work around a translation bug of QPaintEngine::OpenGL2 - painter.translate( 1, 1 ); - } -#endif - - drawBackground( &painter ); - drawItems( &painter ); - - if ( !testAttribute( Qt::WA_StyledBackground ) ) - { - if ( frameWidth() > 0 ) - drawBorder( &painter ); - } -} -/*! - Qt event handler for QEvent::PolishRequest and QEvent::StyleChange - \param event Qt Event - \return See QGLWidget::event() -*/ -bool QwtPlotGLCanvas::event( QEvent *event ) -{ - const bool ok = QOpenGLWidget::event( event ); - - if ( event->type() == QEvent::PolishRequest || - event->type() == QEvent::StyleChange ) - { - // assuming, that we always have a styled background - // when we have a style sheet - - setAttribute( Qt::WA_StyledBackground, - testAttribute( Qt::WA_StyleSheet ) ); - } - - return ok; -} - -/*! - Draw the plot items - \param painter Painter - - \sa QwtPlot::drawCanvas() -*/ -void QwtPlotGLCanvas::drawItems( QPainter *painter ) -{ - painter->save(); - - painter->setClipRect( contentsRect(), Qt::IntersectClip ); - - QwtPlot *plot = qobject_cast< QwtPlot *>( parent() ); - if ( plot ) - plot->drawCanvas( painter ); - - painter->restore(); -} - -/*! - Draw the background of the canvas - \param painter Painter -*/ -void QwtPlotGLCanvas::drawBackground( QPainter *painter ) -{ - painter->save(); - - QWidget *w = qwtBGWidget( this ); - - const QPoint off = mapTo( w, QPoint() ); - painter->translate( -off ); - - const QRect fillRect = rect().translated( off ); - - if ( w->testAttribute( Qt::WA_StyledBackground ) ) - { - painter->setClipRect( fillRect ); - - QStyleOption opt; - opt.initFrom( w ); - w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w); - } - else - { - painter->fillRect( fillRect, - w->palette().brush( w->backgroundRole() ) ); - } - - painter->restore(); -} - -/*! - Draw the border of the canvas - \param painter Painter -*/ -void QwtPlotGLCanvas::drawBorder( QPainter *painter ) -{ - const int fw = frameWidth(); - if ( fw <= 0 ) - return; - - if ( frameShadow() == QwtPlotGLCanvas::Plain ) - { - qDrawPlainRect( painter, frameRect(), - palette().shadow().color(), lineWidth() ); - } - else - { - if ( frameShape() == QwtPlotGLCanvas::Box ) - { - qDrawShadeRect( painter, frameRect(), palette(), - frameShadow() == Sunken, lineWidth(), midLineWidth() ); - } - else - { - qDrawShadePanel( painter, frameRect(), palette(), - frameShadow() == Sunken, lineWidth() ); - } - } -} - -//! Calls repaint() -void QwtPlotGLCanvas::replot() -{ - repaint(); -} - -/*! - \return Empty path -*/ -QPainterPath QwtPlotGLCanvas::borderPath( const QRect &rect ) const -{ - Q_UNUSED( rect ); - return QPainterPath(); -} - -//! \return The rectangle where the frame is drawn in. -QRect QwtPlotGLCanvas::frameRect() const -{ - const int fw = frameWidth(); - return contentsRect().adjusted( -fw, -fw, fw, fw ); -} diff --git a/source/third_party/qwt/qwt_plot_grid.cpp b/source/third_party/qwt/qwt_plot_grid.cpp deleted file mode 100644 index 4868089c100269d721f8e3e85efd5f3812a452ef..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_grid.cpp +++ /dev/null @@ -1,438 +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/qwt_plot_grid.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_math.h" -#include <qpainter.h> -#include <qpen.h> - -class QwtPlotGrid::PrivateData -{ -public: - PrivateData(): - xEnabled( true ), - yEnabled( true ), - xMinEnabled( false ), - yMinEnabled( false ) - { - } - - bool xEnabled; - bool yEnabled; - bool xMinEnabled; - bool yMinEnabled; - - QwtScaleDiv xScaleDiv; - QwtScaleDiv yScaleDiv; - - QPen majorPen; - QPen minorPen; -}; - -//! Enables major grid, disables minor grid -QwtPlotGrid::QwtPlotGrid(): - QwtPlotItem( QwtText( "Grid" ) ) -{ - d_data = new PrivateData; - - setItemInterest( QwtPlotItem::ScaleInterest, true ); - setZ( 10.0 ); -} - -//! Destructor -QwtPlotGrid::~QwtPlotGrid() -{ - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotGrid -int QwtPlotGrid::rtti() const -{ - return QwtPlotItem::Rtti_PlotGrid; -} - -/*! - \brief Enable or disable vertical grid lines - \param on Enable (true) or disable - - \sa Minor grid lines can be enabled or disabled with - enableXMin() -*/ -void QwtPlotGrid::enableX( bool on ) -{ - if ( d_data->xEnabled != on ) - { - d_data->xEnabled = on; - - legendChanged(); - itemChanged(); - } -} - -/*! - \brief Enable or disable horizontal grid lines - \param on Enable (true) or disable - \sa Minor grid lines can be enabled or disabled with enableYMin() -*/ -void QwtPlotGrid::enableY( bool on ) -{ - if ( d_data->yEnabled != on ) - { - d_data->yEnabled = on; - - legendChanged(); - itemChanged(); - } -} - -/*! - \brief Enable or disable minor vertical grid lines. - \param on Enable (true) or disable - \sa enableX() -*/ -void QwtPlotGrid::enableXMin( bool on ) -{ - if ( d_data->xMinEnabled != on ) - { - d_data->xMinEnabled = on; - - legendChanged(); - itemChanged(); - } -} - -/*! - \brief Enable or disable minor horizontal grid lines - \param on Enable (true) or disable - \sa enableY() -*/ -void QwtPlotGrid::enableYMin( bool on ) -{ - if ( d_data->yMinEnabled != on ) - { - d_data->yMinEnabled = on; - - legendChanged(); - itemChanged(); - } -} - -/*! - Assign an x axis scale division - - \param scaleDiv Scale division -*/ -void QwtPlotGrid::setXDiv( const QwtScaleDiv &scaleDiv ) -{ - if ( d_data->xScaleDiv != scaleDiv ) - { - d_data->xScaleDiv = scaleDiv; - itemChanged(); - } -} - -/*! - Assign a y axis division - - \param scaleDiv Scale division -*/ -void QwtPlotGrid::setYDiv( const QwtScaleDiv &scaleDiv ) -{ - if ( d_data->yScaleDiv != scaleDiv ) - { - d_data->yScaleDiv = scaleDiv; - itemChanged(); - } -} - -/*! - Build and assign a pen for both major and minor grid lines - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotGrid::setPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - Assign a pen for both major and minor grid lines - - \param pen Pen - \sa setMajorPen(), setMinorPen() -*/ -void QwtPlotGrid::setPen( const QPen &pen ) -{ - if ( d_data->majorPen != pen || d_data->minorPen != pen ) - { - d_data->majorPen = pen; - d_data->minorPen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - Build and assign a pen for both major grid lines - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotGrid::setMajorPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setMajorPen( QPen( color, width, style ) ); -} - -/*! - Assign a pen for the major grid lines - - \param pen Pen - \sa majorPen(), setMinorPen(), setPen() -*/ -void QwtPlotGrid::setMajorPen( const QPen &pen ) -{ - if ( d_data->majorPen != pen ) - { - d_data->majorPen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - Build and assign a pen for the minor grid lines - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotGrid::setMinorPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setMinorPen( QPen( color, width, style ) ); -} - -/*! - Assign a pen for the minor grid lines - - \param pen Pen - \sa minorPen(), setMajorPen(), setPen() -*/ -void QwtPlotGrid::setMinorPen( const QPen &pen ) -{ - if ( d_data->minorPen != pen ) - { - d_data->minorPen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - \brief Draw the grid - - The grid is drawn into the bounding rectangle such that - grid lines 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 canvasRect Contents rectangle of the plot canvas -*/ -void QwtPlotGrid::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - // draw minor grid lines - QPen minorPen = d_data->minorPen; - minorPen.setCapStyle( Qt::FlatCap ); - - painter->setPen( minorPen ); - - 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 ) ); - } - - 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 ) ); - } - - // draw major grid lines - QPen majorPen = d_data->majorPen; - majorPen.setCapStyle( Qt::FlatCap ); - - painter->setPen( majorPen ); - - if ( d_data->xEnabled ) - { - drawLines( painter, canvasRect, Qt::Vertical, xMap, - d_data->xScaleDiv.ticks( QwtScaleDiv::MajorTick ) ); - } - - if ( d_data->yEnabled ) - { - drawLines( painter, canvasRect, Qt::Horizontal, yMap, - d_data->yScaleDiv.ticks( QwtScaleDiv::MajorTick ) ); - } -} - -void QwtPlotGrid::drawLines( QPainter *painter, const QRectF &canvasRect, - Qt::Orientation orientation, const QwtScaleMap &scaleMap, - const QList<double> &values ) const -{ - const double x1 = canvasRect.left(); - const double x2 = canvasRect.right() - 1.0; - const double y1 = canvasRect.top(); - const double y2 = canvasRect.bottom() - 1.0; - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - for ( int i = 0; i < values.count(); i++ ) - { - double value = scaleMap.transform( values[i] ); - if ( doAlign ) - value = qRound( value ); - - if ( orientation == Qt::Horizontal ) - { - if ( qwtFuzzyGreaterOrEqual( value, y1 ) && - qwtFuzzyLessOrEqual( value, y2 ) ) - { - QwtPainter::drawLine( painter, x1, value, x2, value ); - } - } - else - { - if ( qwtFuzzyGreaterOrEqual( value, x1 ) && - qwtFuzzyLessOrEqual( value, x2 ) ) - { - QwtPainter::drawLine( painter, value, y1, value, y2 ); - } - } - } -} - -/*! - \return the pen for the major grid lines - \sa setMajorPen(), setMinorPen(), setPen() -*/ -const QPen &QwtPlotGrid::majorPen() const -{ - return d_data->majorPen; -} - -/*! - \return the pen for the minor grid lines - \sa setMinorPen(), setMajorPen(), setPen() -*/ -const QPen &QwtPlotGrid::minorPen() const -{ - return d_data->minorPen; -} - -/*! - \return true if vertical grid lines are enabled - \sa enableX() -*/ -bool QwtPlotGrid::xEnabled() const -{ - return d_data->xEnabled; -} - -/*! - \return true if minor vertical grid lines are enabled - \sa enableXMin() -*/ -bool QwtPlotGrid::xMinEnabled() const -{ - return d_data->xMinEnabled; -} - -/*! - \return true if horizontal grid lines are enabled - \sa enableY() -*/ -bool QwtPlotGrid::yEnabled() const -{ - return d_data->yEnabled; -} - -/*! - \return true if minor horizontal grid lines are enabled - \sa enableYMin() -*/ -bool QwtPlotGrid::yMinEnabled() const -{ - return d_data->yMinEnabled; -} - - -/*! \return the scale division of the x axis */ -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; -} - -/*! - Update the grid to changes of the axes scale division - - \param xScaleDiv Scale division of the x-axis - \param yScaleDiv Scale division of the y-axis - - \sa QwtPlot::updateAxes() -*/ -void QwtPlotGrid::updateScaleDiv( const QwtScaleDiv& xScaleDiv, - const QwtScaleDiv& yScaleDiv ) -{ - setXDiv( xScaleDiv ); - setYDiv( yScaleDiv ); -} diff --git a/source/third_party/qwt/qwt_plot_histogram.cpp b/source/third_party/qwt/qwt_plot_histogram.cpp deleted file mode 100644 index 2c0b6dbc76e6efc3133c663af0b0342fbf356c05..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_histogram.cpp +++ /dev/null @@ -1,690 +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/qwt_plot_histogram.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_column_symbol.h" -#include "qwt/qwt_scale_map.h" -#include <qstring.h> -#include <qpainter.h> - -static inline bool qwtIsCombinable( 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(); - setData( 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; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Style of the histogram - \sa HistogramStyle, setStyle() -*/ -QwtPlotHistogram::HistogramStyle QwtPlotHistogram::style() const -{ - return d_data->style; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotHistogram::setPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, 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; - - legendChanged(); - 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; - - legendChanged(); - 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 different 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; - - legendChanged(); - 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 = data()->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<QwtIntervalSample> &samples ) -{ - setData( new QwtIntervalSeriesData( samples ) ); -} - -/*! - Assign a series of samples - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotHistogram::setSamples( - QwtSeriesData<QwtIntervalSample> *data ) -{ - setData( data ); -} - -/*! - 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 rectangle 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 = this->sample( i ); - - if ( !sample.interval.isValid() ) - { - flushPolygon( painter, v0, polygon ); - previous = sample; - continue; - } - - if ( previous.interval.isValid() ) - { - if ( !qwtIsCombinable( 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 ); - - const QwtSeriesData<QwtIntervalSample> *series = data(); - - for ( int i = from; i <= to; i++ ) - { - const QwtIntervalSample sample = 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 ); - - const QwtSeriesData<QwtIntervalSample> *series = data(); - - for ( int i = from; i <= to; i++ ) - { - const QwtIntervalSample sample = 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.pop_back(); - polygon.pop_back(); - } - 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 different 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 ); - } -} - -/*! - A plain rectangle without pen using the brush() - - \param index Index of the legend entry - ( ignored as there is only one ) - \param size Icon size - \return A graphic displaying the icon - - \sa QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() -*/ -QwtGraphic QwtPlotHistogram::legendIcon( int index, - const QSizeF &size ) const -{ - Q_UNUSED( index ); - return defaultIcon( d_data->brush, size ); -} diff --git a/source/third_party/qwt/qwt_plot_intervalcurve.cpp b/source/third_party/qwt/qwt_plot_intervalcurve.cpp deleted file mode 100644 index fe3a623450c67154d0708b44a268209f786f1a8b..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_intervalcurve.cpp +++ /dev/null @@ -1,603 +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/qwt_plot_intervalcurve.h" -#include "qwt/qwt_interval_symbol.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_clipper.h" -#include "qwt/qwt_painter.h" -#include <string.h> - -#include <qpainter.h> - -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 > xMax && 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( QwtPlotIntervalCurve::Tube ), - symbol( NULL ), - pen( Qt::black ), - brush( Qt::white ) - { - paintAttributes = QwtPlotIntervalCurve::ClipPolygons; - paintAttributes |= QwtPlotIntervalCurve::ClipSymbol; - - pen.setCapStyle( Qt::FlatCap ); - } - - ~PrivateData() - { - delete symbol; - } - - QwtPlotIntervalCurve::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; - setData( 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; -} - -/*! - \return True, when attribute is enabled - \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<QwtIntervalSample> &samples ) -{ - setData( new QwtIntervalSeriesData( samples ) ); -} - -/*! - Assign a series of samples - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotIntervalCurve::setSamples( - QwtSeriesData<QwtIntervalSample> *data ) -{ - setData( data ); -} - -/*! - 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; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Style of the curve - \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; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Current symbol or NULL, when no symbol has been assigned - \sa setSymbol() -*/ -const QwtIntervalSymbol *QwtPlotIntervalCurve::symbol() const -{ - return d_data->symbol; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotIntervalCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - \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; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return 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; - - legendChanged(); - 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 rectangle 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 rectangle 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 ); - ::memcpy( p.data(), points, size * sizeof( QPointF ) ); - p = QwtClipper::clipPolygonF( clipRect, p ); - QwtPainter::drawPolyline( painter, p ); - - p.resize( size ); - ::memcpy( p.data(), points + size, size * sizeof( QPointF ) ); - p = QwtClipper::clipPolygonF( clipRect, 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 rectangle 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 & ClipSymbol; - - 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(); -} - -/*! - \return Icon for the legend - - In case of Tube style() the icon is a plain rectangle filled with the brush(). - If a symbol is assigned it is scaled to size. - - \param index Index of the legend entry - ( ignored as there is only one ) - \param size Icon size - - \sa QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() -*/ -QwtGraphic QwtPlotIntervalCurve::legendIcon( - int index, const QSizeF &size ) const -{ - Q_UNUSED( index ); - - if ( size.isEmpty() ) - return QwtGraphic(); - - QwtGraphic icon; - icon.setDefaultSize( size ); - icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); - - QPainter painter( &icon ); - painter.setRenderHint( QPainter::Antialiasing, - testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - if ( d_data->style == Tube ) - { - QRectF r( 0, 0, size.width(), size.height() ); - 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 ) - { - const double x = 0.5 * size.width(); - - d_data->symbol->draw( &painter, orientation(), - QPointF( x, 0 ), QPointF( x, size.height() - 1.0 ) ); - } - else - { - const double y = 0.5 * size.height(); - - d_data->symbol->draw( &painter, orientation(), - QPointF( 0.0, y ), QPointF( size.width() - 1.0, y ) ); - } - } - - return icon; -} diff --git a/source/third_party/qwt/qwt_plot_item.cpp b/source/third_party/qwt/qwt_plot_item.cpp deleted file mode 100644 index f76c00752625debc3e73889e86cab2f797856673..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_item.cpp +++ /dev/null @@ -1,698 +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/qwt_plot_item.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_legend_data.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_graphic.h" -#include <qpainter.h> - -class QwtPlotItem::PrivateData -{ -public: - PrivateData(): - plot( NULL ), - isVisible( true ), - attributes( 0 ), - interests( 0 ), - renderHints( 0 ), - renderThreadCount( 1 ), - z( 0.0 ), - xAxis( QwtPlot::xBottom ), - yAxis( QwtPlot::yLeft ), - legendIconSize( 8, 8 ) - { - } - - mutable QwtPlot *plot; - - bool isVisible; - - QwtPlotItem::ItemAttributes attributes; - QwtPlotItem::ItemInterests interests; - - QwtPlotItem::RenderHints renderHints; - uint renderThreadCount; - - double z; - - int xAxis; - int yAxis; - - QwtText title; - QSize legendIconSize; -}; - -/*! - Constructor - \param title Title of the item -*/ -QwtPlotItem::QwtPlotItem( const QwtText &title ) -{ - d_data = new PrivateData; - d_data->title = title; -} - -//! Destroy the QwtPlotItem -QwtPlotItem::~QwtPlotItem() -{ - 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 - detach the QwtPlotItem from any plot from a previous call to attach (if - necessary). If a NULL argument is passed, it will detach from any QwtPlot it - was attached to. - - \param plot Plot widget - \sa detach() -*/ -void QwtPlotItem::attach( QwtPlot *plot ) -{ - if ( plot == d_data->plot ) - return; - - if ( d_data->plot ) - d_data->plot->attachItem( this, false ); - - d_data->plot = plot; - - if ( d_data->plot ) - d_data->plot->attachItem( this, true ); -} - -/*! - \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 - runtime type information is disabled and it is not possible - to do a dynamic_cast<...>. - - \return rtti value - \sa RttiValues -*/ -int QwtPlotItem::rtti() const -{ - return Rtti_PlotItem; -} - -//! Return attached plot -QwtPlot *QwtPlotItem::plot() const -{ - return d_data->plot; -} - -/*! - Plot items are painted in increasing z-order. - - \return setZ(), QwtPlotDict::itemList() -*/ -double QwtPlotItem::z() const -{ - return d_data->z; -} - -/*! - \brief Set the z value - - Plot items are painted in increasing z-order. - - \param z Z-value - \sa z(), QwtPlotDict::itemList() -*/ -void QwtPlotItem::setZ( double z ) -{ - if ( 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 ) - d_data->plot->attachItem( this, true ); - - itemChanged(); - } -} - -/*! - Set a new title - - \param title Title - \sa title() -*/ -void QwtPlotItem::setTitle( const QString &title ) -{ - setTitle( QwtText( title ) ); -} - -/*! - Set a new title - - \param title Title - \sa title() -*/ -void QwtPlotItem::setTitle( const QwtText &title ) -{ - if ( d_data->title != title ) - { - d_data->title = title; - - legendChanged(); -#if 0 - itemChanged(); -#endif - } -} - -/*! - \return Title of the item - \sa setTitle() -*/ -const QwtText &QwtPlotItem::title() const -{ - return d_data->title; -} - -/*! - Toggle an item attribute - - \param attribute Attribute type - \param on true/false - - \sa testItemAttribute(), ItemInterest -*/ -void QwtPlotItem::setItemAttribute( ItemAttribute attribute, bool on ) -{ - if ( d_data->attributes.testFlag( attribute ) != on ) - { - if ( on ) - d_data->attributes |= attribute; - else - d_data->attributes &= ~attribute; - - if ( attribute == QwtPlotItem::Legend ) - legendChanged(); - - itemChanged(); - } -} - -/*! - Test an item attribute - - \param attribute Attribute type - \return true/false - \sa setItemAttribute(), ItemInterest -*/ -bool QwtPlotItem::testItemAttribute( ItemAttribute attribute ) const -{ - return d_data->attributes.testFlag( attribute ); -} - -/*! - Toggle an item interest - - \param interest Interest type - \param on true/false - - \sa testItemInterest(), ItemAttribute -*/ -void QwtPlotItem::setItemInterest( ItemInterest interest, bool on ) -{ - if ( d_data->interests.testFlag( interest ) != on ) - { - if ( on ) - d_data->interests |= interest; - else - d_data->interests &= ~interest; - - itemChanged(); - } -} - -/*! - Test an item interest - - \param interest Interest type - \return true/false - \sa setItemInterest(), ItemAttribute -*/ -bool QwtPlotItem::testItemInterest( ItemInterest interest ) const -{ - return d_data->interests.testFlag( interest ); -} - -/*! - Toggle an render hint - - \param hint Render hint - \param on true/false - - \sa testRenderHint(), RenderHint -*/ -void QwtPlotItem::setRenderHint( RenderHint hint, bool on ) -{ - if ( d_data->renderHints.testFlag( hint ) != on ) - { - if ( on ) - d_data->renderHints |= hint; - else - d_data->renderHints &= ~hint; - - itemChanged(); - } -} - -/*! - Test a render hint - - \param hint Render hint - \return true/false - \sa setRenderHint(), RenderHint -*/ -bool QwtPlotItem::testRenderHint( RenderHint hint ) const -{ - return d_data->renderHints.testFlag( hint ); -} - -/*! - On multi core systems rendering of certain plot item - ( f.e QwtPlotRasterItem ) can be done in parallel in - several threads. - - The default setting is set to 1. - - \param numThreads Number of threads to be used for rendering. - If numThreads is set to 0, the system specific - ideal thread count is used. - - The default thread count is 1 ( = no additional threads ) -*/ -void QwtPlotItem::setRenderThreadCount( uint numThreads ) -{ - d_data->renderThreadCount = numThreads; -} - -/*! - \return Number of threads to be used for rendering. - If numThreads() is set to 0, the system specific - ideal thread count is used. -*/ -uint QwtPlotItem::renderThreadCount() const -{ - return d_data->renderThreadCount; -} - -/*! - Set the size of the legend icon - - The default setting is 8x8 pixels - - \param size Size - \sa legendIconSize(), legendIcon() -*/ -void QwtPlotItem::setLegendIconSize( const QSize &size ) -{ - if ( d_data->legendIconSize != size ) - { - d_data->legendIconSize = size; - legendChanged(); - } -} - -/*! - \return Legend icon size - \sa setLegendIconSize(), legendIcon() -*/ -QSize QwtPlotItem::legendIconSize() const -{ - return d_data->legendIconSize; -} - -/*! - \return Icon representing the item on the legend - - The default implementation returns an invalid icon - - \param index Index of the legend entry - ( usually there is only one ) - \param size Icon size - - \sa setLegendIconSize(), legendData() - */ -QwtGraphic QwtPlotItem::legendIcon( - int index, const QSizeF &size ) const -{ - Q_UNUSED( index ) - Q_UNUSED( size ) - - return QwtGraphic(); -} - -/*! - \brief Return a default icon from a brush - - The default icon is a filled rectangle used - in several derived classes as legendIcon(). - - \param brush Fill brush - \param size Icon size - - \return A filled rectangle - */ -QwtGraphic QwtPlotItem::defaultIcon( - const QBrush &brush, const QSizeF &size ) const -{ - QwtGraphic icon; - if ( !size.isEmpty() ) - { - icon.setDefaultSize( size ); - - QRectF r( 0, 0, size.width(), size.height() ); - - QPainter painter( &icon ); - painter.fillRect( r, brush ); - } - - return icon; -} - -//! Show the item -void QwtPlotItem::show() -{ - setVisible( true ); -} - -//! Hide the item -void QwtPlotItem::hide() -{ - setVisible( false ); -} - -/*! - Show/Hide the item - - \param on Show if true, otherwise hide - \sa isVisible(), show(), hide() -*/ -void QwtPlotItem::setVisible( bool on ) -{ - if ( on != d_data->isVisible ) - { - d_data->isVisible = on; - itemChanged(); - } -} - -/*! - \return true if visible - \sa setVisible(), show(), hide() -*/ -bool QwtPlotItem::isVisible() const -{ - return d_data->isVisible; -} - -/*! - Update the legend and call QwtPlot::autoRefresh() for the - parent plot. - - \sa QwtPlot::legendChanged(), QwtPlot::autoRefresh() -*/ -void QwtPlotItem::itemChanged() -{ - if ( d_data->plot ) - d_data->plot->autoRefresh(); -} - -/*! - Update the legend of the parent plot. - \sa QwtPlot::updateLegend(), itemChanged() -*/ -void QwtPlotItem::legendChanged() -{ - if ( testItemAttribute( QwtPlotItem::Legend ) && d_data->plot ) - d_data->plot->updateLegend( this ); -} - -/*! - Set X and Y axis - - The item will painted according to the coordinates of its Axes. - - \param xAxis X Axis ( QwtPlot::xBottom or QwtPlot::xTop ) - \param yAxis Y Axis ( QwtPlot::yLeft or QwtPlot::yRight ) - - \sa setXAxis(), setYAxis(), xAxis(), yAxis(), QwtPlot::Axis -*/ -void QwtPlotItem::setAxes( int xAxis, int yAxis ) -{ - if ( xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop ) - d_data->xAxis = xAxis; - - if ( yAxis == QwtPlot::yLeft || yAxis == QwtPlot::yRight ) - d_data->yAxis = yAxis; - - itemChanged(); -} - -/*! - Set the X axis - - The item will painted according to the coordinates its Axes. - - \param axis X Axis ( QwtPlot::xBottom or QwtPlot::xTop ) - \sa setAxes(), setYAxis(), xAxis(), QwtPlot::Axis -*/ -void QwtPlotItem::setXAxis( int axis ) -{ - if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) - { - d_data->xAxis = axis; - itemChanged(); - } -} - -/*! - Set the Y axis - - The item will painted according to the coordinates its Axes. - - \param axis Y Axis ( QwtPlot::yLeft or QwtPlot::yRight ) - \sa setAxes(), setXAxis(), yAxis(), QwtPlot::Axis -*/ -void QwtPlotItem::setYAxis( int axis ) -{ - if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight ) - { - d_data->yAxis = axis; - itemChanged(); - } -} - -//! Return xAxis -int QwtPlotItem::xAxis() const -{ - return d_data->xAxis; -} - -//! Return yAxis -int QwtPlotItem::yAxis() const -{ - return d_data->yAxis; -} - -/*! - \return An invalid bounding rect: QRectF(1.0, 1.0, -2.0, -2.0) - \note A width or height < 0.0 is ignored by the autoscaler -*/ -QRectF QwtPlotItem::boundingRect() const -{ - return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid -} - -/*! - \brief Calculate a hint for the canvas margin - - When the QwtPlotItem::Margins flag is enabled the plot item - indicates, that it needs some margins at the borders of the canvas. - This is f.e. used by bar charts to reserve space for displaying - the bars. - - The margins are in target device coordinates ( pixels on screen ) - - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle of the canvas in painter coordinates - \param left Returns the left margin - \param top Returns the top margin - \param right Returns the right margin - \param bottom Returns the bottom margin - - \return The default implementation returns 0 for all margins - - \sa QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins() - */ -void QwtPlotItem::getCanvasMarginHint( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRectF &canvasRect, - double &left, double &top, double &right, double &bottom ) const -{ - Q_UNUSED( xMap ); - Q_UNUSED( yMap ); - Q_UNUSED( canvasRect ); - - // use QMargins, when we don't need to support Qt < 4.6 anymore - left = top = right = bottom = 0.0; -} - -/*! - \brief Return all information, that is needed to represent - the item on the legend - - Most items are represented by one entry on the legend - showing an icon and a text, but f.e. QwtPlotMultiBarChart - displays one entry for each bar. - - QwtLegendData is basically a list of QVariants that makes it - possible to overload and reimplement legendData() to - return almost any type of information, that is understood - by the receiver that acts as the legend. - - The default implementation returns one entry with - the title() of the item and the legendIcon(). - - \return Data, that is needed to represent the item on the legend - \sa title(), legendIcon(), QwtLegend, QwtPlotLegendItem - */ -QList<QwtLegendData> QwtPlotItem::legendData() const -{ - QwtLegendData data; - - QwtText label = title(); - label.setRenderFlags( label.renderFlags() & Qt::AlignLeft ); - - QVariant titleValue; - qVariantSetValue( titleValue, label ); - data.setValue( QwtLegendData::TitleRole, titleValue ); - - const QwtGraphic graphic = legendIcon( 0, legendIconSize() ); - if ( !graphic.isNull() ) - { - QVariant iconValue; - qVariantSetValue( iconValue, graphic ); - data.setValue( QwtLegendData::IconRole, iconValue ); - } - - QList<QwtLegendData> list; - list += data; - - return list; -} - -/*! - \brief Update the item to changes of the axes scale division - - Update the item, when the axes of plot have changed. - The default implementation does nothing, but items that depend - on the scale division (like QwtPlotGrid()) have to reimplement - updateScaleDiv() - - updateScaleDiv() is only called when the ScaleInterest interest - is enabled. The default implementation does nothing. - - \param xScaleDiv Scale division of the x-axis - \param yScaleDiv Scale division of the y-axis - - \sa QwtPlot::updateAxes(), ScaleInterest -*/ -void QwtPlotItem::updateScaleDiv( const QwtScaleDiv &xScaleDiv, - const QwtScaleDiv &yScaleDiv ) -{ - Q_UNUSED( xScaleDiv ); - Q_UNUSED( yScaleDiv ); -} - -/*! - \brief Update the item to changes of the legend info - - Plot items that want to display a legend ( not those, that want to - be displayed on a legend ! ) will have to implement updateLegend(). - - updateLegend() is only called when the LegendInterest interest - is enabled. The default implementation does nothing. - - \param item Plot item to be displayed on a legend - \param data Attributes how to display item on the legend - - \sa QwtPlotLegendItem - - \note Plot items, that want to be displayed on a legend - need to enable the QwtPlotItem::Legend flag and to implement - legendData() and legendIcon() - */ -void QwtPlotItem::updateLegend( const QwtPlotItem *item, - const QList<QwtLegendData> &data ) -{ - Q_UNUSED( item ); - Q_UNUSED( data ); -} - -/*! - \brief Calculate the bounding scale rectangle of 2 maps - - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - - \return Bounding scale rect of the scale maps, not normalized -*/ -QRectF QwtPlotItem::scaleRect( const QwtScaleMap &xMap, - const QwtScaleMap &yMap ) const -{ - return QRectF( xMap.s1(), yMap.s1(), - xMap.sDist(), yMap.sDist() ); -} - -/*! - \brief Calculate the bounding paint rectangle of 2 maps - - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - - \return Bounding paint rectangle of the scale maps, not normalized -*/ -QRectF QwtPlotItem::paintRect( const QwtScaleMap &xMap, - const QwtScaleMap &yMap ) const -{ - const QRectF rect( xMap.p1(), yMap.p1(), - xMap.pDist(), yMap.pDist() ); - - return rect; -} diff --git a/source/third_party/qwt/qwt_plot_layout.cpp b/source/third_party/qwt/qwt_plot_layout.cpp deleted file mode 100644 index 8d7c4bd982c8977fbcc21c8fcc40c8334296193b..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_layout.cpp +++ /dev/null @@ -1,1442 +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/qwt_plot_layout.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_text_label.h" -#include "qwt/qwt_scale_widget.h" -#include "qwt/qwt_abstract_legend.h" -#include <qscrollbar.h> -#include <qmath.h> - -class QwtPlotLayout::LayoutData -{ -public: - void init( const QwtPlot *, const QRectF &rect ); - - struct t_legendData - { - int frameWidth; - int hScrollExtent; - int vScrollExtent; - QSize hint; - } legend; - - struct t_titleData - { - QwtText text; - int frameWidth; - } title; - - struct t_footerData - { - QwtText text; - int frameWidth; - } footer; - - struct t_scaleData - { - bool isEnabled; - const QwtScaleWidget *scaleWidget; - QFont scaleFont; - int start; - int end; - int baseLineOffset; - double tickOffset; - int dimWithoutTitle; - } scale[QwtPlot::axisCnt]; - - struct t_canvasData - { - int contentsMargins[ QwtPlot::axisCnt ]; - - } canvas; -}; - -/* - Extract all layout relevant data from the plot components -*/ -void QwtPlotLayout::LayoutData::init( const QwtPlot *plot, const QRectF &rect ) -{ - // legend - - if ( plot->legend() ) - { - legend.frameWidth = plot->legend()->frameWidth(); - legend.hScrollExtent = - plot->legend()->scrollExtent( Qt::Horizontal ); - legend.vScrollExtent = - plot->legend()->scrollExtent( Qt::Vertical ); - - const QSize hint = plot->legend()->sizeHint(); - - const int w = qMin( hint.width(), qFloor( rect.width() ) ); - - int h = plot->legend()->heightForWidth( w ); - if ( h <= 0 ) - h = hint.height(); - - legend.hint = QSize( w, h ); - } - - // title - - title.frameWidth = 0; - title.text = QwtText(); - - if ( plot->titleLabel() ) - { - const QwtTextLabel *label = plot->titleLabel(); - title.text = label->text(); - if ( !( title.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) ) - title.text.setFont( label->font() ); - - title.frameWidth = plot->titleLabel()->frameWidth(); - } - - // footer - - footer.frameWidth = 0; - footer.text = QwtText(); - - if ( plot->footerLabel() ) - { - const QwtTextLabel *label = plot->footerLabel(); - footer.text = label->text(); - if ( !( footer.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) ) - footer.text.setFont( label->font() ); - - footer.frameWidth = plot->footerLabel()->frameWidth(); - } - - // scales - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - if ( plot->axisEnabled( axis ) ) - { - const QwtScaleWidget *scaleWidget = plot->axisWidget( axis ); - - scale[axis].isEnabled = true; - - scale[axis].scaleWidget = scaleWidget; - - scale[axis].scaleFont = scaleWidget->font(); - - scale[axis].start = scaleWidget->startBorderDist(); - scale[axis].end = scaleWidget->endBorderDist(); - - scale[axis].baseLineOffset = scaleWidget->margin(); - scale[axis].tickOffset = scaleWidget->margin(); - if ( scaleWidget->scaleDraw()->hasComponent( - QwtAbstractScaleDraw::Ticks ) ) - { - scale[axis].tickOffset += - scaleWidget->scaleDraw()->maxTickLength(); - } - - scale[axis].dimWithoutTitle = scaleWidget->dimForLength( - QWIDGETSIZE_MAX, scale[axis].scaleFont ); - - if ( !scaleWidget->title().isEmpty() ) - { - scale[axis].dimWithoutTitle -= - scaleWidget->titleHeightForWidth( QWIDGETSIZE_MAX ); - } - } - else - { - scale[axis].isEnabled = false; - scale[axis].start = 0; - scale[axis].end = 0; - scale[axis].baseLineOffset = 0; - scale[axis].tickOffset = 0.0; - scale[axis].dimWithoutTitle = 0; - } - } - - // canvas - - plot->canvas()->getContentsMargins( - &canvas.contentsMargins[ QwtPlot::yLeft ], - &canvas.contentsMargins[ QwtPlot::xTop ], - &canvas.contentsMargins[ QwtPlot::yRight ], - &canvas.contentsMargins[ QwtPlot::xBottom ] ); -} - -class QwtPlotLayout::PrivateData -{ -public: - PrivateData(): - spacing( 5 ) - { - } - - QRectF titleRect; - QRectF footerRect; - QRectF legendRect; - QRectF scaleRect[QwtPlot::axisCnt]; - QRectF canvasRect; - - QwtPlotLayout::LayoutData layoutData; - - QwtPlot::LegendPosition legendPos; - double legendRatio; - unsigned int spacing; - unsigned int canvasMargin[QwtPlot::axisCnt]; - bool alignCanvasToScales[QwtPlot::axisCnt]; -}; - -/*! - \brief Constructor - */ - -QwtPlotLayout::QwtPlotLayout() -{ - d_data = new PrivateData; - - setLegendPosition( QwtPlot::BottomLegend ); - setCanvasMargin( 4 ); - setAlignCanvasToScales( false ); - - invalidate(); -} - -//! Destructor -QwtPlotLayout::~QwtPlotLayout() -{ - delete d_data; -} - -/*! - 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. - -1 means margin at all borders. - \sa canvasMargin() - - \warning The margin will have no effect when alignCanvasToScale() is true -*/ - -void QwtPlotLayout::setCanvasMargin( int margin, int axis ) -{ - if ( margin < -1 ) - margin = -1; - - if ( axis == -1 ) - { - for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) - d_data->canvasMargin[axis] = margin; - } - else if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->canvasMargin[axis] = margin; -} - -/*! - \param axisId Axis index - \return Margin around the scale tick borders - \sa setCanvasMargin() -*/ -int QwtPlotLayout::canvasMargin( int axisId ) const -{ - if ( axisId < 0 || axisId >= QwtPlot::axisCnt ) - return 0; - - return d_data->canvasMargin[axisId]; -} - -/*! - \brief Set the align-canvas-to-axis-scales flag for all axes - - \param on True/False - \sa setAlignCanvasToScale(), alignCanvasToScale() -*/ -void QwtPlotLayout::setAlignCanvasToScales( bool on ) -{ - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - d_data->alignCanvasToScales[axis] = on; -} - -/*! - Change the align-canvas-to-axis-scales setting. The canvas may: - - - extend beyond the axis scale ends to maximize its size, - - align with the axis scale ends to control its size. - - The axisId parameter is somehow confusing as it identifies a border - of the plot and not the axes, that are aligned. F.e when QwtPlot::yLeft - is set, the left end of the the x-axes ( QwtPlot::xTop, QwtPlot::xBottom ) - is aligned. - - \param axisId Axis index - \param on New align-canvas-to-axis-scales setting - - \sa setCanvasMargin(), alignCanvasToScale(), setAlignCanvasToScales() - \warning In case of on == true canvasMargin() will have no effect -*/ -void QwtPlotLayout::setAlignCanvasToScale( int axisId, bool on ) -{ - if ( axisId >= 0 && axisId < QwtPlot::axisCnt ) - d_data->alignCanvasToScales[axisId] = on; -} - -/*! - Return the align-canvas-to-axis-scales setting. The canvas may: - - extend beyond the axis scale ends to maximize its size - - align with the axis scale ends to control its size. - - \param axisId Axis index - \return align-canvas-to-axis-scales setting - \sa setAlignCanvasToScale(), setAlignCanvasToScale(), setCanvasMargin() -*/ -bool QwtPlotLayout::alignCanvasToScale( int axisId ) const -{ - if ( axisId < 0 || axisId >= QwtPlot::axisCnt ) - return false; - - return d_data->alignCanvasToScales[ axisId ]; -} - -/*! - Change the spacing of the plot. The spacing is the distance - between the plot components. - - \param spacing New spacing - \sa setCanvasMargin(), spacing() -*/ -void QwtPlotLayout::setSpacing( int spacing ) -{ - d_data->spacing = qMax( 0, spacing ); -} - -/*! - \return Spacing - \sa margin(), setSpacing() -*/ -int QwtPlotLayout::spacing() const -{ - return d_data->spacing; -} - -/*! - \brief Specify the position of the legend - \param pos The legend's position. - \param ratio Ratio between legend and the bounding rectangle - of title, footer, canvas and axes. The legend will be shrunk - 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. - - \sa QwtPlot::setLegendPosition() -*/ - -void QwtPlotLayout::setLegendPosition( QwtPlot::LegendPosition pos, double ratio ) -{ - if ( ratio > 1.0 ) - ratio = 1.0; - - switch ( pos ) - { - case QwtPlot::TopLegend: - case QwtPlot::BottomLegend: - if ( ratio <= 0.0 ) - ratio = 0.33; - d_data->legendRatio = ratio; - d_data->legendPos = pos; - break; - case QwtPlot::LeftLegend: - case QwtPlot::RightLegend: - if ( ratio <= 0.0 ) - ratio = 0.5; - d_data->legendRatio = ratio; - d_data->legendPos = pos; - break; - default: - break; - } -} - -/*! - \brief Specify the position of the legend - \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 ) -{ - setLegendPosition( pos, 0.0 ); -} - -/*! - \return Position of the legend - \sa setLegendPosition(), QwtPlot::setLegendPosition(), - QwtPlot::legendPosition() -*/ -QwtPlot::LegendPosition QwtPlotLayout::legendPosition() const -{ - return d_data->legendPos; -} - -/*! - Specify the relative size of the legend in the plot - \param ratio Ratio between legend and the bounding rectangle - of title, footer, canvas and axes. The legend will be shrunk - 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. -*/ -void QwtPlotLayout::setLegendRatio( double ratio ) -{ - setLegendPosition( legendPosition(), ratio ); -} - -/*! - \return The relative size of the legend in the plot. - \sa setLegendPosition() -*/ -double QwtPlotLayout::legendRatio() const -{ - return d_data->legendRatio; -} - -/*! - \brief Set the geometry for the title - - This method is intended to be used from derived layouts - overloading activate() - - \sa titleRect(), activate() - */ -void QwtPlotLayout::setTitleRect( const QRectF &rect ) -{ - d_data->titleRect = rect; -} - -/*! - \return Geometry for the title - \sa activate(), invalidate() -*/ -QRectF QwtPlotLayout::titleRect() const -{ - return d_data->titleRect; -} - -/*! - \brief Set the geometry for the footer - - This method is intended to be used from derived layouts - overloading activate() - - \sa footerRect(), activate() - */ -void QwtPlotLayout::setFooterRect( const QRectF &rect ) -{ - d_data->footerRect = rect; -} - -/*! - \return Geometry for the footer - \sa activate(), invalidate() -*/ -QRectF QwtPlotLayout::footerRect() const -{ - return d_data->footerRect; -} - -/*! - \brief Set the geometry for the legend - - This method is intended to be used from derived layouts - overloading activate() - - \param rect Rectangle for the legend - - \sa legendRect(), activate() - */ -void QwtPlotLayout::setLegendRect( const QRectF &rect ) -{ - d_data->legendRect = rect; -} - -/*! - \return Geometry for the legend - \sa activate(), invalidate() -*/ -QRectF QwtPlotLayout::legendRect() const -{ - return d_data->legendRect; -} - -/*! - \brief Set the geometry for an axis - - This method is intended to be used from derived layouts - overloading activate() - - \param axis Axis index - \param rect Rectangle for the scale - - \sa scaleRect(), activate() - */ -void QwtPlotLayout::setScaleRect( int axis, const QRectF &rect ) -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->scaleRect[axis] = rect; -} - -/*! - \param axis Axis index - \return Geometry for the scale - \sa activate(), invalidate() -*/ -QRectF QwtPlotLayout::scaleRect( int axis ) const -{ - if ( axis < 0 || axis >= QwtPlot::axisCnt ) - { - static QRectF dummyRect; - return dummyRect; - } - return d_data->scaleRect[axis]; -} - -/*! - \brief Set the geometry for the canvas - - This method is intended to be used from derived layouts - overloading activate() - - \sa canvasRect(), activate() - */ -void QwtPlotLayout::setCanvasRect( const QRectF &rect ) -{ - d_data->canvasRect = rect; -} - -/*! - \return Geometry for the canvas - \sa activate(), invalidate() -*/ -QRectF QwtPlotLayout::canvasRect() const -{ - return d_data->canvasRect; -} - -/*! - Invalidate the geometry of all components. - \sa activate() -*/ -void QwtPlotLayout::invalidate() -{ - d_data->titleRect = d_data->footerRect - = d_data->legendRect = d_data->canvasRect = QRect(); - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - d_data->scaleRect[axis] = QRect(); -} - -/*! - \return Minimum size hint - \param plot Plot widget - - \sa QwtPlot::minimumSizeHint() -*/ - -QSize QwtPlotLayout::minimumSizeHint( const QwtPlot *plot ) const -{ - class ScaleData - { - public: - ScaleData() - { - w = h = minLeft = minRight = tickOffset = 0; - } - - int w; - int h; - int minLeft; - int minRight; - int tickOffset; - } scaleData[QwtPlot::axisCnt]; - - int canvasBorder[QwtPlot::axisCnt]; - - int fw; - plot->canvas()->getContentsMargins( &fw, NULL, NULL, NULL ); - - int axis; - for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - if ( plot->axisEnabled( 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.tickOffset = scl->margin(); - if ( scl->scaleDraw()->hasComponent( QwtAbstractScaleDraw::Ticks ) ) - sd.tickOffset += qCeil( scl->scaleDraw()->maxTickLength() ); - } - - canvasBorder[axis] = fw + 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.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 ) ) - { - if ( ( sd.minLeft > canvasBorder[QwtPlot::xBottom] ) && - scaleData[QwtPlot::xBottom].h ) - { - int shiftBottom = sd.minLeft - canvasBorder[QwtPlot::xBottom]; - if ( shiftBottom > scaleData[QwtPlot::xBottom].tickOffset ) - shiftBottom = scaleData[QwtPlot::xBottom].tickOffset; - - sd.h -= shiftBottom; - } - if ( ( sd.minLeft > canvasBorder[QwtPlot::xTop] ) && - scaleData[QwtPlot::xTop].h ) - { - int shiftTop = sd.minRight - canvasBorder[QwtPlot::xTop]; - if ( shiftTop > scaleData[QwtPlot::xTop].tickOffset ) - shiftTop = scaleData[QwtPlot::xTop].tickOffset; - - sd.h -= shiftTop; - } - } - } - - const QWidget *canvas = plot->canvas(); - - int left, top, right, bottom; - canvas->getContentsMargins( &left, &top, &right, &bottom ); - - const QSize minCanvasSize = canvas->minimumSize(); - - int w = scaleData[QwtPlot::yLeft].w + scaleData[QwtPlot::yRight].w; - int cw = qMax( scaleData[QwtPlot::xBottom].w, scaleData[QwtPlot::xTop].w ) - + left + 1 + right + 1; - w += qMax( cw, minCanvasSize.width() ); - - int h = scaleData[QwtPlot::xBottom].h + scaleData[QwtPlot::xTop].h; - int ch = qMax( scaleData[QwtPlot::yLeft].h, scaleData[QwtPlot::yRight].h ) - + top + 1 + bottom + 1; - h += qMax( ch, minCanvasSize.height() ); - - const QwtTextLabel *labels[2]; - labels[0] = plot->titleLabel(); - labels[1] = plot->footerLabel(); - - for ( int i = 0; i < 2; i++ ) - { - const QwtTextLabel *label = labels[i]; - if ( label && !label->text().isEmpty() ) - { - // 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 ) ); - - int labelW = w; - if ( centerOnCanvas ) - { - labelW -= scaleData[QwtPlot::yLeft].w - + scaleData[QwtPlot::yRight].w; - } - - int labelH = label->heightForWidth( labelW ); - if ( labelH > labelW ) // Compensate for a long title - { - w = labelW = labelH; - if ( centerOnCanvas ) - { - w += scaleData[QwtPlot::yLeft].w - + scaleData[QwtPlot::yRight].w; - } - - labelH = label->heightForWidth( labelW ); - } - h += labelH + d_data->spacing; - } - } - - // Compute the legend contribution - - const QwtAbstractLegend *legend = plot->legend(); - if ( legend && !legend->isEmpty() ) - { - if ( d_data->legendPos == QwtPlot::LeftLegend - || d_data->legendPos == QwtPlot::RightLegend ) - { - int legendW = legend->sizeHint().width(); - int legendH = legend->heightForWidth( legendW ); - - if ( legend->frameWidth() > 0 ) - w += d_data->spacing; - - if ( legendH > h ) - legendW += legend->scrollExtent( Qt::Horizontal ); - - if ( d_data->legendRatio < 1.0 ) - legendW = qMin( legendW, int( w / ( 1.0 - d_data->legendRatio ) ) ); - - w += legendW + d_data->spacing; - } - else // QwtPlot::Top, QwtPlot::Bottom - { - 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 = qMin( legendH, int( h / ( 1.0 - d_data->legendRatio ) ) ); - - h += legendH + d_data->spacing; - } - } - - return QSize( w, h ); -} - -/*! - Find the geometry for the legend - - \param options Options how to layout the legend - \param rect Rectangle where to place the legend - - \return Geometry for the legend - \sa Options -*/ - -QRectF QwtPlotLayout::layoutLegend( Options options, - const QRectF &rect ) const -{ - const QSize hint( d_data->layoutData.legend.hint ); - - int dim; - 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 = qMin( hint.width(), int( rect.width() * d_data->legendRatio ) ); - - if ( !( options & IgnoreScrollbars ) ) - { - if ( hint.height() > rect.height() ) - { - // The legend will need additional - // space for the vertical scrollbar. - - dim += d_data->layoutData.legend.hScrollExtent; - } - } - } - else - { - dim = qMin( hint.height(), int( rect.height() * d_data->legendRatio ) ); - dim = qMax( dim, d_data->layoutData.legend.vScrollExtent ); - } - - QRectF legendRect = rect; - switch ( d_data->legendPos ) - { - case QwtPlot::LeftLegend: - legendRect.setWidth( dim ); - break; - case QwtPlot::RightLegend: - legendRect.setX( rect.right() - dim ); - legendRect.setWidth( dim ); - break; - case QwtPlot::TopLegend: - legendRect.setHeight( dim ); - break; - case QwtPlot::BottomLegend: - legendRect.setY( rect.bottom() - dim ); - legendRect.setHeight( dim ); - break; - } - - return legendRect; -} - -/*! - Align the legend to the canvas - - \param canvasRect Geometry of the canvas - \param legendRect Maximum geometry for the legend - - \return Geometry for the aligned legend -*/ -QRectF QwtPlotLayout::alignLegend( const QRectF &canvasRect, - const QRectF &legendRect ) const -{ - QRectF alignedRect = legendRect; - - 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() ); - } - } - else - { - if ( d_data->layoutData.legend.hint.height() < canvasRect.height() ) - { - alignedRect.setY( canvasRect.y() ); - alignedRect.setHeight( canvasRect.height() ); - } - } - - return alignedRect; -} - -/*! - Expand all line breaks in text labels, and calculate the height - of their widgets in orientation of the text. - - \param options Options how to layout the legend - \param rect Bounding rectangle for title, footer, axes and canvas. - \param dimTitle Expanded height of the title widget - \param dimFooter Expanded height of the footer widget - \param dimAxis Expanded heights of the axis in axis orientation. - - \sa Options -*/ -void QwtPlotLayout::expandLineBreaks( Options options, const QRectF &rect, - int &dimTitle, int &dimFooter, int dimAxis[QwtPlot::axisCnt] ) const -{ - dimTitle = dimFooter = 0; - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - dimAxis[axis] = 0; - - int backboneOffset[QwtPlot::axisCnt]; - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - backboneOffset[axis] = 0; - if ( !( options & IgnoreFrames ) ) - backboneOffset[axis] += d_data->layoutData.canvas.contentsMargins[ axis ]; - - if ( !d_data->alignCanvasToScales[axis] ) - backboneOffset[axis] += d_data->canvasMargin[axis]; - } - - bool done = false; - while ( !done ) - { - done = true; - - // the size for the 4 axis depend on each other. Expanding - // the height of a horizontal axis will shrink the height - // for the vertical axis, shrinking the height of a vertical - // axis will result in a line break what will expand the - // width and results in shrinking the width of a horizontal - // axis what might result in a line break of a horizontal - // axis ... . So we loop as long until no size changes. - - if ( !( ( options & IgnoreTitle ) || - d_data->layoutData.title.text.isEmpty() ) ) - { - double w = rect.width(); - - if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled - != d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) - { - // center to the canvas - w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; - } - - int d = qCeil( d_data->layoutData.title.text.heightForWidth( w ) ); - if ( !( options & IgnoreFrames ) ) - d += 2 * d_data->layoutData.title.frameWidth; - - if ( d > dimTitle ) - { - dimTitle = d; - done = false; - } - } - - if ( !( ( options & IgnoreFooter ) || - d_data->layoutData.footer.text.isEmpty() ) ) - { - double w = rect.width(); - - if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled - != d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) - { - // center to the canvas - w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; - } - - int d = qCeil( d_data->layoutData.footer.text.heightForWidth( w ) ); - if ( !( options & IgnoreFrames ) ) - d += 2 * d_data->layoutData.footer.frameWidth; - - if ( d > dimFooter ) - { - dimFooter = d; - done = false; - } - } - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - const struct LayoutData::t_scaleData &scaleData = - d_data->layoutData.scale[axis]; - - if ( scaleData.isEnabled ) - { - double length; - if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom ) - { - length = rect.width() - dimAxis[QwtPlot::yLeft] - - dimAxis[QwtPlot::yRight]; - length -= scaleData.start + scaleData.end; - - if ( dimAxis[QwtPlot::yRight] > 0 ) - length -= 1; - - 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] - - dimAxis[QwtPlot::xBottom]; - length -= scaleData.start + scaleData.end; - length -= 1; - - if ( dimAxis[QwtPlot::xBottom] <= 0 ) - length -= 1; - if ( dimAxis[QwtPlot::xTop] <= 0 ) - length -= 1; - - if ( dimAxis[QwtPlot::xBottom] > 0 ) - { - length += qMin( - d_data->layoutData.scale[QwtPlot::xBottom].tickOffset, - double( scaleData.start - backboneOffset[QwtPlot::xBottom] ) ); - } - if ( dimAxis[QwtPlot::xTop] > 0 ) - { - length += qMin( - d_data->layoutData.scale[QwtPlot::xTop].tickOffset, - double( scaleData.end - backboneOffset[QwtPlot::xTop] ) ); - } - - if ( dimTitle > 0 ) - length -= dimTitle + d_data->spacing; - } - - int d = scaleData.dimWithoutTitle; - if ( !scaleData.scaleWidget->title().isEmpty() ) - { - d += scaleData.scaleWidget->titleHeightForWidth( qFloor( length ) ); - } - - - if ( d > dimAxis[axis] ) - { - dimAxis[axis] = d; - done = false; - } - } - } - } -} - -/*! - Align the ticks of the axis to the canvas borders using - the empty corners. - - \param options Layout options - \param canvasRect Geometry of the canvas ( IN/OUT ) - \param scaleRect Geometries of the scales ( IN/OUT ) - - \sa Options -*/ - -void QwtPlotLayout::alignScales( Options options, - QRectF &canvasRect, QRectF scaleRect[QwtPlot::axisCnt] ) const -{ - int backboneOffset[QwtPlot::axisCnt]; - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - backboneOffset[axis] = 0; - - if ( !d_data->alignCanvasToScales[axis] ) - { - backboneOffset[axis] += d_data->canvasMargin[axis]; - } - - if ( !( options & IgnoreFrames ) ) - { - backboneOffset[axis] += - d_data->layoutData.canvas.contentsMargins[axis]; - } - } - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - if ( !scaleRect[axis].isValid() ) - continue; - - const int startDist = d_data->layoutData.scale[axis].start; - const int endDist = d_data->layoutData.scale[axis].end; - - QRectF &axisRect = scaleRect[axis]; - - if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom ) - { - const QRectF &leftScaleRect = scaleRect[QwtPlot::yLeft]; - const int leftOffset = - backboneOffset[QwtPlot::yLeft] - startDist; - - if ( leftScaleRect.isValid() ) - { - const double dx = leftOffset + leftScaleRect.width(); - if ( d_data->alignCanvasToScales[QwtPlot::yLeft] && dx < 0.0 ) - { - /* - The axis needs more space than the width - of the left scale. - */ - const double cLeft = canvasRect.left(); // qreal -> double - canvasRect.setLeft( qMax( cLeft, 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[QwtPlot::yLeft] && leftOffset < 0 ) - { - canvasRect.setLeft( qMax( canvasRect.left(), - axisRect.left() - leftOffset ) ); - } - else - { - if ( leftOffset > 0 ) - axisRect.setLeft( axisRect.left() + leftOffset ); - } - } - - const QRectF &rightScaleRect = scaleRect[QwtPlot::yRight]; - const int rightOffset = - backboneOffset[QwtPlot::yRight] - endDist + 1; - - if ( rightScaleRect.isValid() ) - { - const double dx = rightOffset + rightScaleRect.width(); - if ( d_data->alignCanvasToScales[QwtPlot::yRight] && dx < 0 ) - { - /* - The axis needs more space than the width - of the right scale. - */ - const double cRight = canvasRect.right(); // qreal -> double - canvasRect.setRight( qMin( cRight, axisRect.right() + dx ) ); - } - - const double maxRight = rightScaleRect.right(); - const double right = axisRect.right() - rightOffset; - axisRect.setRight( qMin( right, maxRight ) ); - } - else - { - if ( d_data->alignCanvasToScales[QwtPlot::yRight] && rightOffset < 0 ) - { - canvasRect.setRight( qMin( canvasRect.right(), - axisRect.right() + rightOffset ) ); - } - else - { - if ( rightOffset > 0 ) - axisRect.setRight( axisRect.right() - rightOffset ); - } - } - } - else // QwtPlot::yLeft, QwtPlot::yRight - { - const QRectF &bottomScaleRect = scaleRect[QwtPlot::xBottom]; - const int bottomOffset = - backboneOffset[QwtPlot::xBottom] - endDist + 1; - - if ( bottomScaleRect.isValid() ) - { - const double dy = bottomOffset + bottomScaleRect.height(); - if ( d_data->alignCanvasToScales[QwtPlot::xBottom] && dy < 0 ) - { - /* - The axis needs more space than the height - of the bottom scale. - */ - const double cBottom = canvasRect.bottom(); // qreal -> double - canvasRect.setBottom( qMin( cBottom, 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[QwtPlot::xBottom] && bottomOffset < 0 ) - { - canvasRect.setBottom( qMin( canvasRect.bottom(), - axisRect.bottom() + bottomOffset ) ); - } - else - { - if ( bottomOffset > 0 ) - axisRect.setBottom( axisRect.bottom() - bottomOffset ); - } - } - - const QRectF &topScaleRect = scaleRect[QwtPlot::xTop]; - const int topOffset = backboneOffset[QwtPlot::xTop] - startDist; - - if ( topScaleRect.isValid() ) - { - const double dy = topOffset + topScaleRect.height(); - if ( d_data->alignCanvasToScales[QwtPlot::xTop] && dy < 0 ) - { - /* - The axis needs more space than the height - of the top scale. - */ - const double cTop = canvasRect.top(); // qreal -> double - canvasRect.setTop( qMax( cTop, 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[QwtPlot::xTop] && topOffset < 0 ) - { - canvasRect.setTop( qMax( canvasRect.top(), - axisRect.top() - topOffset ) ); - } - else - { - if ( topOffset > 0 ) - axisRect.setTop( axisRect.top() + topOffset ); - } - } - } - } - - /* - The canvas has been aligned to the scale with largest - border distances. Now we have to realign the other scale. - */ - - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - QRectF &sRect = scaleRect[axis]; - - if ( !sRect.isValid() ) - continue; - - if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) - { - if ( d_data->alignCanvasToScales[QwtPlot::yLeft] ) - { - double y = canvasRect.left() - d_data->layoutData.scale[axis].start; - if ( !( options & IgnoreFrames ) ) - y += d_data->layoutData.canvas.contentsMargins[ QwtPlot::yLeft ]; - - sRect.setLeft( y ); - } - if ( d_data->alignCanvasToScales[QwtPlot::yRight] ) - { - double y = canvasRect.right() - 1 + d_data->layoutData.scale[axis].end; - if ( !( options & IgnoreFrames ) ) - y -= d_data->layoutData.canvas.contentsMargins[ QwtPlot::yRight ]; - - sRect.setRight( y ); - } - - if ( d_data->alignCanvasToScales[ axis ] ) - { - if ( axis == QwtPlot::xTop ) - sRect.setBottom( canvasRect.top() ); - else - sRect.setTop( canvasRect.bottom() ); - } - } - else - { - if ( d_data->alignCanvasToScales[QwtPlot::xTop] ) - { - double x = canvasRect.top() - d_data->layoutData.scale[axis].start; - if ( !( options & IgnoreFrames ) ) - x += d_data->layoutData.canvas.contentsMargins[ QwtPlot::xTop ]; - - sRect.setTop( x ); - } - if ( d_data->alignCanvasToScales[QwtPlot::xBottom] ) - { - double x = canvasRect.bottom() - 1 + d_data->layoutData.scale[axis].end; - if ( !( options & IgnoreFrames ) ) - x -= d_data->layoutData.canvas.contentsMargins[ QwtPlot::xBottom ]; - - sRect.setBottom( x ); - } - - if ( d_data->alignCanvasToScales[ axis ] ) - { - if ( axis == QwtPlot::yLeft ) - sRect.setRight( canvasRect.left() ); - else - sRect.setLeft( canvasRect.right() ); - } - } - } -} - -/*! - \brief Recalculate the geometry of all components. - - \param plot Plot to be layout - \param plotRect Rectangle where to place the components - \param options Layout options - - \sa invalidate(), titleRect(), footerRect() - legendRect(), scaleRect(), canvasRect() -*/ -void QwtPlotLayout::activate( const QwtPlot *plot, - const QRectF &plotRect, Options options ) -{ - invalidate(); - - QRectF rect( plotRect ); // undistributed rest of the plot rect - - // We extract all layout relevant parameters from the widgets, - // and save them to d_data->layoutData. - - d_data->layoutData.init( plot, rect ); - - if ( !( options & IgnoreLegend ) - && plot->legend() && !plot->legend()->isEmpty() ) - { - d_data->legendRect = layoutLegend( options, rect ); - - // subtract d_data->legendRect from rect - - const QRegion region( rect.toRect() ); - rect = region.subtracted( d_data->legendRect.toRect() ).boundingRect(); - - 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; - } - } - - /* - +---+-----------+---+ - | Title | - +---+-----------+---+ - | | Axis | | - +---+-----------+---+ - | A | | A | - | x | Canvas | x | - | i | | i | - | s | | s | - +---+-----------+---+ - | | Axis | | - +---+-----------+---+ - | Footer | - +---+-----------+---+ - */ - - // title, footer and axes 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. - // expandLineBreaks finds the height/width for title, footer and axes - // including all line breaks. - - int dimTitle, dimFooter, dimAxes[QwtPlot::axisCnt]; - expandLineBreaks( options, rect, dimTitle, dimFooter, dimAxes ); - - if ( dimTitle > 0 ) - { - d_data->titleRect.setRect( - rect.left(), rect.top(), rect.width(), dimTitle ); - - rect.setTop( d_data->titleRect.bottom() + d_data->spacing ); - - if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled != - d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) - { - // if only one of the y axes is missing we align - // the title centered to the canvas - - d_data->titleRect.setX( rect.left() + dimAxes[QwtPlot::yLeft] ); - d_data->titleRect.setWidth( rect.width() - - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] ); - } - } - - if ( dimFooter > 0 ) - { - d_data->footerRect.setRect( - rect.left(), rect.bottom() - dimFooter, rect.width(), dimFooter ); - - rect.setBottom( d_data->footerRect.top() - d_data->spacing ); - - if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled != - d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) - { - // if only one of the y axes is missing we align - // the footer centered to the canvas - - d_data->footerRect.setX( rect.left() + dimAxes[QwtPlot::yLeft] ); - d_data->footerRect.setWidth( rect.width() - - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] ); - } - } - - d_data->canvasRect.setRect( - rect.x() + dimAxes[QwtPlot::yLeft], - rect.y() + dimAxes[QwtPlot::xTop], - rect.width() - dimAxes[QwtPlot::yRight] - dimAxes[QwtPlot::yLeft], - rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop] ); - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - // set the rects for the axes - - if ( dimAxes[axis] ) - { - int dim = dimAxes[axis]; - QRectF &scaleRect = d_data->scaleRect[axis]; - - scaleRect = d_data->canvasRect; - switch ( axis ) - { - case QwtPlot::yLeft: - scaleRect.setX( d_data->canvasRect.left() - dim ); - scaleRect.setWidth( dim ); - break; - case QwtPlot::yRight: - scaleRect.setX( d_data->canvasRect.right() ); - scaleRect.setWidth( dim ); - break; - case QwtPlot::xBottom: - scaleRect.setY( d_data->canvasRect.bottom() ); - scaleRect.setHeight( dim ); - break; - case QwtPlot::xTop: - scaleRect.setY( d_data->canvasRect.top() - dim ); - scaleRect.setHeight( dim ); - break; - } - scaleRect = scaleRect.normalized(); - } - } - - // +---+-----------+---+ - // | <- Axis -> | - // +-^-+-----------+-^-+ - // | | | | | | - // | | | | - // | A | | A | - // | x | Canvas | x | - // | i | | i | - // | s | | s | - // | | | | - // | | | | | | - // +-V-+-----------+-V-+ - // | <- Axis -> | - // +---+-----------+---+ - - // The ticks of the axes - not the labels above - should - // 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() ) - { - // 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 ); - } -} diff --git a/source/third_party/qwt/qwt_plot_legenditem.cpp b/source/third_party/qwt/qwt_plot_legenditem.cpp deleted file mode 100644 index 633c0661d6e30f2bace54fc51398ab5e00c0ddbd..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_legenditem.cpp +++ /dev/null @@ -1,872 +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/qwt_plot_legenditem.h" -#include "qwt/qwt_dyngrid_layout.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_painter.h" -#include <qlayoutitem.h> -#include <qpen.h> -#include <qbrush.h> -#include <qpainter.h> -#include <qmath.h> - -class QwtLegendLayoutItem: public QLayoutItem -{ -public: - QwtLegendLayoutItem( const QwtPlotLegendItem *, const QwtPlotItem * ); - virtual ~QwtLegendLayoutItem(); - - const QwtPlotItem *plotItem() const; - - void setData( const QwtLegendData & ); - const QwtLegendData &data() const; - - virtual Qt::Orientations expandingDirections() const; - virtual QRect geometry() const; - virtual bool hasHeightForWidth() const; - virtual int heightForWidth( int w ) const; - virtual bool isEmpty() const; - virtual QSize maximumSize() const; - virtual int minimumHeightForWidth( int w ) const; - virtual QSize minimumSize() const; - virtual void setGeometry( const QRect & r ); - virtual QSize sizeHint() const; - -private: - - const QwtPlotLegendItem *d_legendItem; - const QwtPlotItem *d_plotItem; - QwtLegendData d_data; - - QRect d_rect; -}; - -QwtLegendLayoutItem::QwtLegendLayoutItem( - const QwtPlotLegendItem *legendItem, const QwtPlotItem *plotItem ): - d_legendItem( legendItem ), - d_plotItem( plotItem) -{ -} - -QwtLegendLayoutItem::~QwtLegendLayoutItem() -{ -} - -const QwtPlotItem *QwtLegendLayoutItem::plotItem() const -{ - return d_plotItem; -} - -void QwtLegendLayoutItem::setData( const QwtLegendData &data ) -{ - d_data = data; -} - -const QwtLegendData &QwtLegendLayoutItem::data() const -{ - return d_data; -} - -Qt::Orientations QwtLegendLayoutItem::expandingDirections() const -{ - return Qt::Horizontal; -} - -bool QwtLegendLayoutItem::hasHeightForWidth() const -{ - return !d_data.title().isEmpty(); -} - -int QwtLegendLayoutItem::minimumHeightForWidth( int w ) const -{ - return d_legendItem->heightForWidth( d_data, w ); -} - -int QwtLegendLayoutItem::heightForWidth( int w ) const -{ - return d_legendItem->heightForWidth( d_data, w ); -} - -bool QwtLegendLayoutItem::isEmpty() const -{ - return false; -} - -QSize QwtLegendLayoutItem::maximumSize() const -{ - return QSize( QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX ); -} - -QSize QwtLegendLayoutItem::minimumSize() const -{ - return d_legendItem->minimumSize( d_data ); -} - -QSize QwtLegendLayoutItem::sizeHint() const -{ - return minimumSize(); -} - -void QwtLegendLayoutItem::setGeometry( const QRect &rect ) -{ - d_rect = rect; -} - -QRect QwtLegendLayoutItem::geometry() const -{ - return d_rect; -} - -class QwtPlotLegendItem::PrivateData -{ -public: - PrivateData(): - itemMargin( 4 ), - itemSpacing( 4 ), - borderRadius( 0.0 ), - borderPen( Qt::NoPen ), - backgroundBrush( Qt::NoBrush ), - backgroundMode( QwtPlotLegendItem::LegendBackground ), - borderDistance( 10 ), - alignment( Qt::AlignRight | Qt::AlignBottom ) - { - layout = new QwtDynGridLayout(); - layout->setMaxColumns( 2 ); - - layout->setSpacing( 0 ); - layout->setContentsMargins( 0, 0, 0, 0 ); - } - - ~PrivateData() - { - delete layout; - } - - QFont font; - QPen textPen; - int itemMargin; - int itemSpacing; - - double borderRadius; - QPen borderPen; - QBrush backgroundBrush; - QwtPlotLegendItem::BackgroundMode backgroundMode; - - int borderDistance; - Qt::Alignment alignment; - - QMap< const QwtPlotItem *, QList<QwtLegendLayoutItem *> > map; - QwtDynGridLayout *layout; -}; - -//! Constructor -QwtPlotLegendItem::QwtPlotLegendItem(): - QwtPlotItem( QwtText( "Legend" ) ) -{ - d_data = new PrivateData; - - setItemInterest( QwtPlotItem::LegendInterest, true ); - setZ( 100.0 ); -} - -//! Destructor -QwtPlotLegendItem::~QwtPlotLegendItem() -{ - clearLegend(); - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotLegend -int QwtPlotLegendItem::rtti() const -{ - return QwtPlotItem::Rtti_PlotLegend; -} - -/*! - \brief Set the alignmnet - - Alignment means the position of the legend relative - to the geometry of the plot canvas. - - \param alignment Alignment flags - - \sa alignment(), setMaxColumns() - - \note To align a legend with many items horizontally - the number of columns need to be limited - */ -void QwtPlotLegendItem::setAlignment( Qt::Alignment alignment ) -{ - if ( d_data->alignment != alignment ) - { - d_data->alignment = alignment; - itemChanged(); - } -} - -/*! - \return Alignment flags - \sa setAlignment() - */ -Qt::Alignment QwtPlotLegendItem::alignment() const -{ - return d_data->alignment; -} - -/*! - \brief Limit the number of columns - - When aligning the legend horizontally ( Qt::AlignLeft, Qt::AlignRight ) - the number of columns needs to be limited to avoid, that - the width of the legend grows with an increasing number of entries. - - \param maxColumns Maximum number of columns. 0 means unlimited. - \sa maxColumns(), QwtDynGridLayout::setMaxColumns() - */ -void QwtPlotLegendItem::setMaxColumns( uint maxColumns ) -{ - if ( maxColumns != d_data->layout->maxColumns() ) - { - d_data->layout->setMaxColumns( maxColumns ); - itemChanged(); - } -} - -/*! - \return Maximum number of columns - \sa maxColumns(), QwtDynGridLayout::maxColumns() - */ -uint QwtPlotLegendItem::maxColumns() const -{ - return d_data->layout->maxColumns(); -} - -/*! - \brief Set the margin around legend items - - The default setting for the margin is 0. - - \param margin Margin in pixels - \sa margin(), setSpacing(), setItemMargin(), setItemSpacing - */ -void QwtPlotLegendItem::setMargin( int margin ) -{ - margin = qMax( margin, 0 ); - if ( margin != this->margin() ) - { - d_data->layout->setContentsMargins( - margin, margin, margin, margin ); - - itemChanged(); - } -} - -/*! - \return Margin around the legend items - \sa setMargin(), spacing(), itemMargin(), itemSpacing() - */ -int QwtPlotLegendItem::margin() const -{ - int left; - d_data->layout->getContentsMargins( &left, NULL, NULL, NULL ); - - return left; -} - -/*! - \brief Set the spacing between the legend items - - \param spacing Spacing in pixels - \sa spacing(), setMargin() -*/ -void QwtPlotLegendItem::setSpacing( int spacing ) -{ - spacing = qMax( spacing, 0 ); - if ( spacing != d_data->layout->spacing() ) - { - d_data->layout->setSpacing( spacing ); - itemChanged(); - } -} - -/*! - \return Spacing between the legend items - \sa setSpacing(), margin(), itemSpacing(), itemMargin() - */ -int QwtPlotLegendItem::spacing() const -{ - return d_data->layout->spacing(); -} - -/*! - Set the margin around each item - - \param margin Margin - \sa itemMargin(), setItemSpacing(), setMargin(), setSpacing() - */ -void QwtPlotLegendItem::setItemMargin( int margin ) -{ - margin = qMax( margin, 0 ); - if ( margin != d_data->itemMargin ) - { - d_data->itemMargin = margin; - - d_data->layout->invalidate(); - itemChanged(); - } -} - -/*! - \return Margin around each item - \sa setItemMargin(), itemSpacing(), margin(), spacing() -*/ -int QwtPlotLegendItem::itemMargin() const -{ - return d_data->itemMargin; -} - -/*! - Set the spacing inside of each item - - \param spacing Spacing - \sa itemSpacing(), setItemMargin(), setMargin(), setSpacing() - */ -void QwtPlotLegendItem::setItemSpacing( int spacing ) -{ - spacing = qMax( spacing, 0 ); - if ( spacing != d_data->itemSpacing ) - { - d_data->itemSpacing = spacing; - - d_data->layout->invalidate(); - itemChanged(); - } - -} - -/*! - \return Spacing inside of each item - \sa setItemSpacing(), itemMargin(), margin(), spacing() -*/ -int QwtPlotLegendItem::itemSpacing() const -{ - return d_data->itemSpacing; -} - -/*! - Change the font used for drawing the text label - - \param font Legend font - \sa font() -*/ -void QwtPlotLegendItem::setFont( const QFont &font ) -{ - if ( font != d_data->font ) - { - d_data->font = font; - - d_data->layout->invalidate(); - itemChanged(); - } -} - -/*! - \return Font used for drawing the text label - \sa setFont() -*/ -QFont QwtPlotLegendItem::font() const -{ - return d_data->font; -} - -/*! - \brief Set the margin between the legend and the canvas border - - The default setting for the margin is 10 pixels. - - \param distance Margin in pixels - \sa setMargin() - */ -void QwtPlotLegendItem::setBorderDistance( int distance ) -{ - if ( distance < 0 ) - distance = -1; - - if ( distance != d_data->borderDistance ) - { - d_data->borderDistance = distance; - itemChanged(); - } -} - -/*! - \return Margin between the legend and the canvas border - \sa margin() - */ -int QwtPlotLegendItem::borderDistance() const -{ - return d_data->borderDistance; -} - -/*! - Set the radius for the border - - \param radius A value <= 0 defines a rectangular border - \sa borderRadius(), setBorderPen() - */ -void QwtPlotLegendItem::setBorderRadius( double radius ) -{ - radius = qMax( 0.0, radius ); - - if ( radius != d_data->borderRadius ) - { - d_data->borderRadius = radius; - itemChanged(); - } -} - -/*! - \return Radius of the border - \sa setBorderRadius(), setBorderPen() - */ -double QwtPlotLegendItem::borderRadius() const -{ - return d_data->borderRadius; -} - -/*! - Set the pen for drawing the border - - \param pen Border pen - \sa borderPen(), setBackgroundBrush() - */ -void QwtPlotLegendItem::setBorderPen( const QPen &pen ) -{ - if ( d_data->borderPen != pen ) - { - d_data->borderPen = pen; - itemChanged(); - } -} - -/*! - \return Pen for drawing the border - \sa setBorderPen(), backgroundBrush() - */ -QPen QwtPlotLegendItem::borderPen() const -{ - return d_data->borderPen; -} - -/*! - \brief Set the background brush - - The brush is used to fill the background - - \param brush Brush - \sa backgroundBrush(), setBackgroundMode(), drawBackground() - */ -void QwtPlotLegendItem::setBackgroundBrush( const QBrush &brush ) -{ - if ( d_data->backgroundBrush != brush ) - { - d_data->backgroundBrush = brush; - itemChanged(); - } -} - -/*! - \return Brush is used to fill the background - \sa setBackgroundBrush(), backgroundMode(), drawBackground() - */ -QBrush QwtPlotLegendItem::backgroundBrush() const -{ - return d_data->backgroundBrush; -} - -/*! - \brief Set the background mode - - Depending on the mode the complete legend or each item - might have an background. - - The default setting is LegendBackground. - - \sa backgroundMode(), setBackgroundBrush(), drawBackground() - */ -void QwtPlotLegendItem::setBackgroundMode( BackgroundMode mode ) -{ - if ( mode != d_data->backgroundMode ) - { - d_data->backgroundMode = mode; - itemChanged(); - } -} - -/*! - \return backgroundMode - \sa setBackgroundMode(), backgroundBrush(), drawBackground() - */ -QwtPlotLegendItem::BackgroundMode QwtPlotLegendItem::backgroundMode() const -{ - return d_data->backgroundMode; -} - -/*! - \brief Set the pen for drawing text labels - - \param pen Text pen - \sa textPen(), setFont() - */ -void QwtPlotLegendItem::setTextPen( const QPen &pen ) -{ - if ( d_data->textPen != pen ) - { - d_data->textPen = pen; - itemChanged(); - } -} - -/*! - \return Pen for drawing text labels - \sa setTextPen(), font() - */ -QPen QwtPlotLegendItem::textPen() const -{ - return d_data->textPen; -} - -/*! - Draw the legend - - \param painter Painter - \param xMap x Scale Map - \param yMap y Scale Map - \param canvasRect Contents rectangle of the canvas in painter coordinates -*/ -void QwtPlotLegendItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - Q_UNUSED( xMap ); - Q_UNUSED( yMap ); - - d_data->layout->setGeometry( geometry( canvasRect ) ); - if ( d_data->layout->geometry().isEmpty() ) - { - // don't draw a legend when having no content - return; - } - - if ( d_data->backgroundMode == QwtPlotLegendItem::LegendBackground ) - drawBackground( painter, d_data->layout->geometry() ); - - for ( int i = 0; i < d_data->layout->count(); i++ ) - { - const QwtLegendLayoutItem *layoutItem = - static_cast<QwtLegendLayoutItem *>( d_data->layout->itemAt( i ) ); - - if ( d_data->backgroundMode == QwtPlotLegendItem::ItemBackground ) - drawBackground( painter, layoutItem->geometry() ); - - painter->save(); - - drawLegendData( painter, layoutItem->plotItem(), - layoutItem->data(), layoutItem->geometry() ); - - painter->restore(); - } -} - -/*! - Draw a rounded rect - - \param painter Painter - \param rect Bounding rectangle - - \sa setBorderRadius(), setBorderPen(), - setBackgroundBrush(), setBackgroundMode() - */ -void QwtPlotLegendItem::drawBackground( - QPainter *painter, const QRectF &rect ) const -{ - painter->save(); - - painter->setPen( d_data->borderPen ); - painter->setBrush( d_data->backgroundBrush ); - - const double radius = d_data->borderRadius; - painter->drawRoundedRect( rect, radius, radius ); - - painter->restore(); -} - -/*! - Calculate the geometry of the legend on the canvas - - \param canvasRect Geometry of the canvas - \return Geometry of the legend -*/ -QRect QwtPlotLegendItem::geometry( const QRectF &canvasRect ) const -{ - QRect rect; - rect.setSize( d_data->layout->sizeHint() ); - - int margin = d_data->borderDistance; - if ( d_data->alignment & Qt::AlignHCenter ) - { - int x = qRound( canvasRect.center().x() ); - rect.moveCenter( QPoint( x, rect.center().y() ) ); - } - else if ( d_data->alignment & Qt::AlignRight ) - { - rect.moveRight( qFloor( canvasRect.right() - margin ) ); - } - else - { - rect.moveLeft( qCeil( canvasRect.left() + margin ) ); - } - - if ( d_data->alignment & Qt::AlignVCenter ) - { - int y = qRound( canvasRect.center().y() ); - rect.moveCenter( QPoint( rect.center().x(), y ) ); - } - else if ( d_data->alignment & Qt::AlignBottom ) - { - rect.moveBottom( qFloor( canvasRect.bottom() - margin ) ); - } - else - { - rect.moveTop( qCeil( canvasRect.top() + margin ) ); - } - - return rect; -} - -/*! - Update the legend items according to modifications of a - plot item - - \param plotItem Plot item - \param data Attributes of the legend entries - */ -void QwtPlotLegendItem::updateLegend( const QwtPlotItem *plotItem, - const QList<QwtLegendData> &data ) -{ - if ( plotItem == NULL ) - return; - - QList<QwtLegendLayoutItem *> layoutItems; - - QMap<const QwtPlotItem *, QList<QwtLegendLayoutItem *> >::iterator it = - d_data->map.find( plotItem ); - if ( it != d_data->map.end() ) - layoutItems = it.value(); - - bool changed = false; - - if ( data.size() != layoutItems.size() ) - { - changed = true; - - for ( int i = 0; i < layoutItems.size(); i++ ) - { - d_data->layout->removeItem( layoutItems[i] ); - delete layoutItems[i]; - } - layoutItems.clear(); - - if ( it != d_data->map.end() ) - d_data->map.remove( plotItem ); - - if ( !data.isEmpty() ) - { - for ( int i = 0; i < data.size(); i++ ) - { - QwtLegendLayoutItem *layoutItem = - new QwtLegendLayoutItem( this, plotItem ); - d_data->layout->addItem( layoutItem ); - layoutItems += layoutItem; - } - - d_data->map.insert( plotItem, layoutItems ); - } - } - - for ( int i = 0; i < data.size(); i++ ) - { - if ( layoutItems[i]->data().values() != data[i].values() ) - { - layoutItems[i]->setData( data[i] ); - changed = true; - } - } - - if ( changed ) - { - d_data->layout->invalidate(); - itemChanged(); - } -} - -//! Remove all items from the legend -void QwtPlotLegendItem::clearLegend() -{ - if ( !d_data->map.isEmpty() ) - { - d_data->map.clear(); - - for ( int i = d_data->layout->count() - 1; i >= 0; i-- ) - delete d_data->layout->takeAt( i ); - - itemChanged(); - } -} - -/*! - Draw an entry on the legend - - \param painter Qt Painter - \param plotItem Plot item, represented by the entry - \param data Attributes of the legend entry - \param rect Bounding rectangle for the entry - */ -void QwtPlotLegendItem::drawLegendData( QPainter *painter, - const QwtPlotItem *plotItem, const QwtLegendData &data, - const QRectF &rect ) const -{ - Q_UNUSED( plotItem ); - - const int m = d_data->itemMargin; - const QRectF r = rect.toRect().adjusted( m, m, -m, -m ); - - painter->setClipRect( r, Qt::IntersectClip ); - - int titleOff = 0; - - const QwtGraphic graphic = data.icon(); - if ( !graphic.isEmpty() ) - { - QRectF iconRect( r.topLeft(), graphic.defaultSize() ); - - iconRect.moveCenter( - QPoint( iconRect.center().x(), rect.center().y() ) ); - - graphic.render( painter, iconRect, Qt::KeepAspectRatio ); - - titleOff += iconRect.width() + d_data->itemSpacing; - } - - const QwtText text = data.title(); - if ( !text.isEmpty() ) - { - painter->setPen( textPen() ); - painter->setFont( font() ); - - const QRectF textRect = r.adjusted( titleOff, 0, 0, 0 ); - text.draw( painter, textRect ); - } -} - -/*! - Minimum size hint needed to display an entry - - \param data Attributes of the legend entry - \return Minimum size - */ -QSize QwtPlotLegendItem::minimumSize( const QwtLegendData &data ) const -{ - QSize size( 2 * d_data->itemMargin, 2 * d_data->itemMargin ); - - if ( !data.isValid() ) - return size; - - const QwtGraphic graphic = data.icon(); - const QwtText text = data.title(); - - int w = 0; - int h = 0; - - if ( !graphic.isNull() ) - { - w = graphic.width(); - h = graphic.height(); - } - - if ( !text.isEmpty() ) - { - const QSizeF sz = text.textSize( font() ); - - w += qCeil( sz.width() ); - h = qMax( h, qCeil( sz.height() ) ); - } - - if ( graphic.width() > 0 && !text.isEmpty() ) - w += d_data->itemSpacing; - - size += QSize( w, h ); - return size; -} - -/*! - \return The preferred height, for a width. - \param data Attributes of the legend entry - \param width Width -*/ -int QwtPlotLegendItem::heightForWidth( - const QwtLegendData &data, int width ) const -{ - width -= 2 * d_data->itemMargin; - - const QwtGraphic graphic = data.icon(); - const QwtText text = data.title(); - - if ( text.isEmpty() ) - return graphic.height(); - - if ( graphic.width() > 0 ) - width -= graphic.width() + d_data->itemSpacing; - - int h = text.heightForWidth( width, font() ); - h += 2 * d_data->itemMargin; - - return qMax( graphic.height(), h ); -} - -/*! - \return All plot items with an entry on the legend - \note A plot item might have more than one entry on the legend - */ -QList< const QwtPlotItem * > QwtPlotLegendItem::plotItems() const -{ - return d_data->map.keys(); -} - -/*! - \return Geometries of the items of a plot item - \note Usually a plot item has only one entry on the legend -*/ -QList< QRect > QwtPlotLegendItem::legendGeometries( - const QwtPlotItem *plotItem ) const -{ - QList<QwtLegendLayoutItem *> layoutItems; - - QMap<const QwtPlotItem *, QList<QwtLegendLayoutItem *> >::iterator it = - d_data->map.find( plotItem ); - if ( it != d_data->map.end() ) - layoutItems = it.value(); - - QList<QRect> geometries; - for ( int i = 0; i < layoutItems.size(); i++ ) - geometries += layoutItems[i]->geometry(); - - return geometries; -} diff --git a/source/third_party/qwt/qwt_plot_magnifier.cpp b/source/third_party/qwt/qwt_plot_magnifier.cpp deleted file mode 100644 index de6984627783d0139a0d144c2fd7fa3e85a4fd6c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_magnifier.cpp +++ /dev/null @@ -1,165 +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/qwt_plot.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_plot_magnifier.h" -#include <qevent.h> - -class QwtPlotMagnifier::PrivateData -{ -public: - PrivateData() - { - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - isAxisEnabled[axis] = true; - } - - bool isAxisEnabled[QwtPlot::axisCnt]; -}; - -/*! - Constructor - \param canvas Plot canvas to be magnified -*/ -QwtPlotMagnifier::QwtPlotMagnifier( QWidget *canvas ): - QwtMagnifier( canvas ) -{ - d_data = new PrivateData(); -} - -//! Destructor -QwtPlotMagnifier::~QwtPlotMagnifier() -{ - delete d_data; -} - -/*! - \brief En/Disable an axis - - Only Axes that are enabled will be zoomed. - All other axes will remain unchanged. - - \param axis Axis, see QwtPlot::Axis - \param on On/Off - - \sa isAxisEnabled() -*/ -void QwtPlotMagnifier::setAxisEnabled( int axis, bool on ) -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->isAxisEnabled[axis] = on; -} - -/*! - Test if an axis is enabled - - \param axis Axis, see QwtPlot::Axis - \return True, if the axis is enabled - - \sa setAxisEnabled() -*/ -bool QwtPlotMagnifier::isAxisEnabled( int axis ) const -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - return d_data->isAxisEnabled[axis]; - - return true; -} - -//! Return observed plot canvas -QWidget *QwtPlotMagnifier::canvas() -{ - return parentWidget(); -} - -//! Return Observed plot canvas -const QWidget *QwtPlotMagnifier::canvas() const -{ - return parentWidget(); -} - -//! Return plot widget, containing the observed plot canvas -QwtPlot *QwtPlotMagnifier::plot() -{ - QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<QwtPlot *>( w ); -} - -//! Return plot widget, containing the observed plot canvas -const QwtPlot *QwtPlotMagnifier::plot() const -{ - const QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<const QwtPlot *>( w ); -} - -/*! - Zoom in/out the axes scales - \param factor A value < 1.0 zooms in, a value > 1.0 zooms out. -*/ -void QwtPlotMagnifier::rescale( double factor ) -{ - QwtPlot* plt = plot(); - if ( plt == NULL ) - return; - - factor = qAbs( factor ); - if ( factor == 1.0 || factor == 0.0 ) - return; - - bool doReplot = false; - - const bool autoReplot = plt->autoReplot(); - plt->setAutoReplot( false ); - - for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) - { - if ( isAxisEnabled( axisId ) ) - { - const QwtScaleMap scaleMap = plt->canvasMap( axisId ); - - double v1 = scaleMap.s1(); - double v2 = scaleMap.s2(); - - if ( scaleMap.transformation() ) - { - // the coordinate system of the paint device is always linear - - v1 = scaleMap.transform( v1 ); // scaleMap.p1() - v2 = scaleMap.transform( v2 ); // scaleMap.p2() - } - - const double center = 0.5 * ( v1 + v2 ); - const double width_2 = 0.5 * ( v2 - v1 ) * factor; - - v1 = center - width_2; - v2 = center + width_2; - - if ( scaleMap.transformation() ) - { - v1 = scaleMap.invTransform( v1 ); - v2 = scaleMap.invTransform( v2 ); - } - - plt->setAxisScale( axisId, v1, v2 ); - doReplot = true; - } - } - - plt->setAutoReplot( autoReplot ); - - if ( doReplot ) - plt->replot(); -} diff --git a/source/third_party/qwt/qwt_plot_marker.cpp b/source/third_party/qwt/qwt_plot_marker.cpp deleted file mode 100644 index 6a8ff342019cdac98a2530341ff16275b5dc68bd..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_marker.cpp +++ /dev/null @@ -1,610 +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/qwt_plot_marker.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_symbol.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_math.h" -#include <qpainter.h> - -class QwtPlotMarker::PrivateData -{ -public: - PrivateData(): - labelAlignment( Qt::AlignCenter ), - labelOrientation( Qt::Horizontal ), - spacing( 2 ), - symbol( NULL ), - style( QwtPlotMarker::NoLine ), - xValue( 0.0 ), - yValue( 0.0 ) - { - } - - ~PrivateData() - { - delete symbol; - } - - QwtText label; - Qt::Alignment labelAlignment; - Qt::Orientation labelOrientation; - int spacing; - - QPen pen; - const QwtSymbol *symbol; - LineStyle style; - - double xValue; - double yValue; -}; - -//! Sets alignment to Qt::AlignCenter, and style to QwtPlotMarker::NoLine -QwtPlotMarker::QwtPlotMarker( const QString &title ): - QwtPlotItem( QwtText( title ) ) -{ - d_data = new PrivateData; - setZ( 30.0 ); -} - -//! Sets alignment to Qt::AlignCenter, and style to QwtPlotMarker::NoLine -QwtPlotMarker::QwtPlotMarker( const QwtText &title ): - QwtPlotItem( title ) -{ - d_data = new PrivateData; - setZ( 30.0 ); -} - -//! Destructor -QwtPlotMarker::~QwtPlotMarker() -{ - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotMarker -int QwtPlotMarker::rtti() const -{ - return QwtPlotItem::Rtti_PlotMarker; -} - -//! Return Value -QPointF QwtPlotMarker::value() const -{ - return QPointF( d_data->xValue, d_data->yValue ); -} - -//! Return x Value -double QwtPlotMarker::xValue() const -{ - return d_data->xValue; -} - -//! Return y Value -double QwtPlotMarker::yValue() const -{ - return d_data->yValue; -} - -//! Set Value -void QwtPlotMarker::setValue( const QPointF& pos ) -{ - setValue( pos.x(), pos.y() ); -} - -//! Set Value -void QwtPlotMarker::setValue( double x, double y ) -{ - if ( x != d_data->xValue || y != d_data->yValue ) - { - d_data->xValue = x; - d_data->yValue = y; - itemChanged(); - } -} - -//! Set X Value -void QwtPlotMarker::setXValue( double x ) -{ - setValue( x, d_data->yValue ); -} - -//! Set Y Value -void QwtPlotMarker::setYValue( double y ) -{ - setValue( d_data->xValue, y ); -} - -/*! - Draw the marker - - \param painter Painter - \param xMap x Scale Map - \param yMap y Scale Map - \param canvasRect Contents rectangle of the canvas in painter coordinates -*/ -void QwtPlotMarker::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - const QPointF pos( xMap.transform( d_data->xValue ), - yMap.transform( d_data->yValue ) ); - - // draw lines - - drawLines( painter, canvasRect, pos ); - - // draw symbol - if ( d_data->symbol && - ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) - { - const QSizeF sz = d_data->symbol->size(); - - const QRectF clipRect = canvasRect.adjusted( - -sz.width(), -sz.height(), sz.width(), sz.height() ); - - if ( clipRect.contains( pos ) ) - d_data->symbol->drawSymbol( painter, pos ); - } - - drawLabel( painter, canvasRect, pos ); -} - -/*! - Draw the lines marker - - \param painter Painter - \param canvasRect Contents rectangle of the canvas in painter coordinates - \param pos Position of the marker, translated into widget coordinates - - \sa drawLabel(), QwtSymbol::drawSymbol() -*/ -void QwtPlotMarker::drawLines( QPainter *painter, - const QRectF &canvasRect, const QPointF &pos ) const -{ - if ( d_data->style == NoLine ) - return; - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - painter->setPen( d_data->pen ); - if ( d_data->style == QwtPlotMarker::HLine || - d_data->style == QwtPlotMarker::Cross ) - { - double y = pos.y(); - if ( doAlign ) - y = qRound( y ); - - QwtPainter::drawLine( painter, canvasRect.left(), - y, canvasRect.right() - 1.0, y ); - } - if ( d_data->style == QwtPlotMarker::VLine || - d_data->style == QwtPlotMarker::Cross ) - { - double x = pos.x(); - if ( doAlign ) - x = qRound( x ); - - QwtPainter::drawLine( painter, x, - canvasRect.top(), x, canvasRect.bottom() - 1.0 ); - } -} - -/*! - Align and draw the text label of the marker - - \param painter Painter - \param canvasRect Contents rectangle of the canvas in painter coordinates - \param pos Position of the marker, translated into widget coordinates - - \sa drawLabel(), QwtSymbol::drawSymbol() -*/ -void QwtPlotMarker::drawLabel( QPainter *painter, - const QRectF &canvasRect, const QPointF &pos ) const -{ - if ( d_data->label.isEmpty() ) - return; - - Qt::Alignment align = d_data->labelAlignment; - QPointF alignPos = pos; - - QSizeF symbolOff( 0, 0 ); - - switch ( d_data->style ) - { - case QwtPlotMarker::VLine: - { - // In VLine-style the y-position is pointless and - // the alignment flags are relative to the canvas - - if ( d_data->labelAlignment & Qt::AlignTop ) - { - alignPos.setY( canvasRect.top() ); - align &= ~Qt::AlignTop; - align |= Qt::AlignBottom; - } - else if ( d_data->labelAlignment & Qt::AlignBottom ) - { - // In HLine-style the x-position is pointless and - // the alignment flags are relative to the canvas - - alignPos.setY( canvasRect.bottom() - 1 ); - align &= ~Qt::AlignBottom; - align |= Qt::AlignTop; - } - else - { - alignPos.setY( canvasRect.center().y() ); - } - break; - } - case QwtPlotMarker::HLine: - { - if ( d_data->labelAlignment & Qt::AlignLeft ) - { - alignPos.setX( canvasRect.left() ); - align &= ~Qt::AlignLeft; - align |= Qt::AlignRight; - } - else if ( d_data->labelAlignment & Qt::AlignRight ) - { - alignPos.setX( canvasRect.right() - 1 ); - align &= ~Qt::AlignRight; - align |= Qt::AlignLeft; - } - else - { - alignPos.setX( canvasRect.center().x() ); - } - break; - } - default: - { - if ( d_data->symbol && - ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) - { - symbolOff = d_data->symbol->size() + QSizeF( 1, 1 ); - symbolOff /= 2; - } - } - } - - qreal pw2 = d_data->pen.widthF() / 2.0; - if ( pw2 == 0.0 ) - pw2 = 0.5; - - const int spacing = d_data->spacing; - - const qreal xOff = qMax( pw2, symbolOff.width() ); - const qreal yOff = qMax( pw2, symbolOff.height() ); - - const QSizeF textSize = d_data->label.textSize( painter->font() ); - - if ( align & Qt::AlignLeft ) - { - alignPos.rx() -= xOff + spacing; - if ( d_data->labelOrientation == Qt::Vertical ) - alignPos.rx() -= textSize.height(); - else - alignPos.rx() -= textSize.width(); - } - else if ( align & Qt::AlignRight ) - { - alignPos.rx() += xOff + spacing; - } - else - { - if ( d_data->labelOrientation == Qt::Vertical ) - alignPos.rx() -= textSize.height() / 2; - else - alignPos.rx() -= textSize.width() / 2; - } - - if ( align & Qt::AlignTop ) - { - alignPos.ry() -= yOff + spacing; - if ( d_data->labelOrientation != Qt::Vertical ) - alignPos.ry() -= textSize.height(); - } - else if ( align & Qt::AlignBottom ) - { - alignPos.ry() += yOff + spacing; - if ( d_data->labelOrientation == Qt::Vertical ) - alignPos.ry() += textSize.width(); - } - else - { - if ( d_data->labelOrientation == Qt::Vertical ) - alignPos.ry() += textSize.width() / 2; - else - alignPos.ry() -= textSize.height() / 2; - } - - painter->translate( alignPos.x(), alignPos.y() ); - if ( d_data->labelOrientation == Qt::Vertical ) - painter->rotate( -90.0 ); - - const QRectF textRect( 0, 0, textSize.width(), textSize.height() ); - d_data->label.draw( painter, textRect ); -} - -/*! - \brief Set the line style - \param style Line style. - \sa lineStyle() -*/ -void QwtPlotMarker::setLineStyle( LineStyle style ) -{ - if ( style != d_data->style ) - { - d_data->style = style; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return the line style - \sa setLineStyle() -*/ -QwtPlotMarker::LineStyle QwtPlotMarker::lineStyle() const -{ - return d_data->style; -} - -/*! - \brief Assign a symbol - \param symbol New symbol - \sa symbol() -*/ -void QwtPlotMarker::setSymbol( const QwtSymbol *symbol ) -{ - if ( symbol != d_data->symbol ) - { - delete d_data->symbol; - d_data->symbol = symbol; - - if ( symbol ) - setLegendIconSize( symbol->boundingRect().size() ); - - legendChanged(); - itemChanged(); - } -} - -/*! - \return the symbol - \sa setSymbol(), QwtSymbol -*/ -const QwtSymbol *QwtPlotMarker::symbol() const -{ - return d_data->symbol; -} - -/*! - \brief Set the label - \param label Label text - \sa label() -*/ -void QwtPlotMarker::setLabel( const QwtText& label ) -{ - if ( label != d_data->label ) - { - d_data->label = label; - itemChanged(); - } -} - -/*! - \return the label - \sa setLabel() -*/ -QwtText QwtPlotMarker::label() const -{ - return d_data->label; -} - -/*! - \brief Set the alignment of the label - - In case of QwtPlotMarker::HLine the alignment is relative to the - y position of the marker, but the horizontal flags correspond to the - canvas rectangle. In case of QwtPlotMarker::VLine the alignment is - relative to the x position of the marker, but the vertical flags - correspond to the canvas rectangle. - - In all other styles the alignment is relative to the marker's position. - - \param align Alignment. - \sa labelAlignment(), labelOrientation() -*/ -void QwtPlotMarker::setLabelAlignment( Qt::Alignment align ) -{ - if ( align != d_data->labelAlignment ) - { - d_data->labelAlignment = align; - itemChanged(); - } -} - -/*! - \return the label alignment - \sa setLabelAlignment(), setLabelOrientation() -*/ -Qt::Alignment QwtPlotMarker::labelAlignment() const -{ - return d_data->labelAlignment; -} - -/*! - \brief Set the orientation of the label - - When orientation is Qt::Vertical the label is rotated by 90.0 degrees - ( from bottom to top ). - - \param orientation Orientation of the label - - \sa labelOrientation(), setLabelAlignment() -*/ -void QwtPlotMarker::setLabelOrientation( Qt::Orientation orientation ) -{ - if ( orientation != d_data->labelOrientation ) - { - d_data->labelOrientation = orientation; - itemChanged(); - } -} - -/*! - \return the label orientation - \sa setLabelOrientation(), labelAlignment() -*/ -Qt::Orientation QwtPlotMarker::labelOrientation() const -{ - return d_data->labelOrientation; -} - -/*! - \brief Set the spacing - - When the label is not centered on the marker position, the spacing - is the distance between the position and the label. - - \param spacing Spacing - \sa spacing(), setLabelAlignment() -*/ -void QwtPlotMarker::setSpacing( int spacing ) -{ - if ( spacing < 0 ) - spacing = 0; - - if ( spacing == d_data->spacing ) - return; - - d_data->spacing = spacing; - itemChanged(); -} - -/*! - \return the spacing - \sa setSpacing() -*/ -int QwtPlotMarker::spacing() const -{ - return d_data->spacing; -} - -/*! - Build and assign a line pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotMarker::setLinePen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setLinePen( QPen( color, width, style ) ); -} - -/*! - Specify a pen for the line. - - \param pen New pen - \sa linePen() -*/ -void QwtPlotMarker::setLinePen( const QPen &pen ) -{ - if ( pen != d_data->pen ) - { - d_data->pen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return the line pen - \sa setLinePen() -*/ -const QPen &QwtPlotMarker::linePen() const -{ - return d_data->pen; -} - -QRectF QwtPlotMarker::boundingRect() const -{ - return QRectF( d_data->xValue, d_data->yValue, 0.0, 0.0 ); -} - -/*! - \return Icon representing the marker on the legend - - \param index Index of the legend entry - ( usually there is only one ) - \param size Icon size - - \sa setLegendIconSize(), legendData() -*/ -QwtGraphic QwtPlotMarker::legendIcon( int index, - const QSizeF &size ) const -{ - Q_UNUSED( index ); - - if ( size.isEmpty() ) - return QwtGraphic(); - - QwtGraphic icon; - icon.setDefaultSize( size ); - icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); - - QPainter painter( &icon ); - painter.setRenderHint( QPainter::Antialiasing, - testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - if ( d_data->style != QwtPlotMarker::NoLine ) - { - painter.setPen( d_data->pen ); - - if ( d_data->style == QwtPlotMarker::HLine || - d_data->style == QwtPlotMarker::Cross ) - { - const double y = 0.5 * size.height(); - - QwtPainter::drawLine( &painter, - 0.0, y, size.width(), y ); - } - - if ( d_data->style == QwtPlotMarker::VLine || - d_data->style == QwtPlotMarker::Cross ) - { - const double x = 0.5 * size.width(); - - QwtPainter::drawLine( &painter, - x, 0.0, x, size.height() ); - } - } - - if ( d_data->symbol ) - { - const QRect r( 0.0, 0.0, size.width(), size.height() ); - d_data->symbol->drawSymbol( &painter, r ); - } - - return icon; -} - diff --git a/source/third_party/qwt/qwt_plot_multi_barchart.cpp b/source/third_party/qwt/qwt_plot_multi_barchart.cpp deleted file mode 100644 index 3ee76f61824666637b0f8f564238844621b74c78..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_multi_barchart.cpp +++ /dev/null @@ -1,744 +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/qwt_plot_multi_barchart.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_column_symbol.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qpalette.h> -#include <qmap.h> - -inline static bool qwtIsIncreasing( - const QwtScaleMap &map, const QVector<double> &values ) -{ - bool isInverting = map.isInverting(); - - for ( int i = 0; i < values.size(); i++ ) - { - const double y = values[ i ]; - if ( y != 0.0 ) - return ( map.isInverting() != ( y > 0.0 ) ); - } - - return !isInverting; -} - -class QwtPlotMultiBarChart::PrivateData -{ -public: - PrivateData(): - style( QwtPlotMultiBarChart::Grouped ) - { - } - - QwtPlotMultiBarChart::ChartStyle style; - QList<QwtText> barTitles; - QMap<int, QwtColumnSymbol *> symbolMap; -}; - -/*! - Constructor - \param title Title of the chart -*/ -QwtPlotMultiBarChart::QwtPlotMultiBarChart( const QwtText &title ): - QwtPlotAbstractBarChart( title ) -{ - init(); -} - -/*! - Constructor - \param title Title of the chart -*/ -QwtPlotMultiBarChart::QwtPlotMultiBarChart( const QString &title ): - QwtPlotAbstractBarChart( QwtText( title ) ) -{ - init(); -} - -//! Destructor -QwtPlotMultiBarChart::~QwtPlotMultiBarChart() -{ - resetSymbolMap(); - delete d_data; -} - -void QwtPlotMultiBarChart::init() -{ - d_data = new PrivateData; - setData( new QwtSetSeriesData() ); -} - -//! \return QwtPlotItem::Rtti_PlotBarChart -int QwtPlotMultiBarChart::rtti() const -{ - return QwtPlotItem::Rtti_PlotMultiBarChart; -} - -/*! - Initialize data with an array of samples. - \param samples Vector of points -*/ -void QwtPlotMultiBarChart::setSamples( - const QVector<QwtSetSample> &samples ) -{ - setData( new QwtSetSeriesData( samples ) ); -} - -/*! - Initialize data with an array of samples. - \param samples Vector of points -*/ -void QwtPlotMultiBarChart::setSamples( - const QVector< QVector<double> > &samples ) -{ - QVector<QwtSetSample> s; - for ( int i = 0; i < samples.size(); i++ ) - s += QwtSetSample( i, samples[ i ] ); - - setData( new QwtSetSeriesData( s ) ); -} - -/*! - Assign a series of samples - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotMultiBarChart::setSamples( - QwtSeriesData<QwtSetSample> *data ) -{ - setData( data ); -} - -/*! - \brief Set the titles for the bars - - The titles are used for the legend. - - \param titles Bar titles - - \sa barTitles(), legendData() - */ -void QwtPlotMultiBarChart::setBarTitles( const QList<QwtText> &titles ) -{ - d_data->barTitles = titles; - itemChanged(); -} - -/*! - \return Bar titles - \sa setBarTitles(), legendData() - */ -QList<QwtText> QwtPlotMultiBarChart::barTitles() const -{ - return d_data->barTitles; -} - -/*! - \brief Add a symbol to the symbol map - - Assign a default symbol for drawing the bar representing all values - with the same index in a set. - - \param valueIndex Index of a value in a set - \param symbol Symbol used for drawing a bar - - \sa symbol(), resetSymbolMap(), specialSymbol() -*/ -void QwtPlotMultiBarChart::setSymbol( int valueIndex, QwtColumnSymbol *symbol ) -{ - if ( valueIndex < 0 ) - return; - - QMap<int, QwtColumnSymbol *>::iterator it = - d_data->symbolMap.find(valueIndex); - if ( it == d_data->symbolMap.end() ) - { - if ( symbol != NULL ) - { - d_data->symbolMap.insert( valueIndex, symbol ); - - legendChanged(); - itemChanged(); - } - } - else - { - if ( symbol != it.value() ) - { - delete it.value(); - - if ( symbol == NULL ) - { - d_data->symbolMap.remove( valueIndex ); - } - else - { - it.value() = symbol; - } - - legendChanged(); - itemChanged(); - } - } -} - -/*! - Find a symbol in the symbol map - - \param valueIndex Index of a value in a set - \return The symbol, that had been set by setSymbol() or NULL. - - \sa setSymbol(), specialSymbol(), drawBar() -*/ -const QwtColumnSymbol *QwtPlotMultiBarChart::symbol( int valueIndex ) const -{ - QMap<int, QwtColumnSymbol *>::const_iterator it = - d_data->symbolMap.find( valueIndex ); - - return ( it == d_data->symbolMap.end() ) ? NULL : it.value(); -} - -/*! - Find a symbol in the symbol map - - \param valueIndex Index of a value in a set - \return The symbol, that had been set by setSymbol() or NULL. - - \sa setSymbol(), specialSymbol(), drawBar() -*/ -QwtColumnSymbol *QwtPlotMultiBarChart::symbol( int valueIndex ) -{ - QMap<int, QwtColumnSymbol *>::iterator it = - d_data->symbolMap.find( valueIndex ); - - return ( it == d_data->symbolMap.end() ) ? NULL : it.value(); -} - -/*! - Remove all symbols from the symbol map - */ -void QwtPlotMultiBarChart::resetSymbolMap() -{ - for ( QMap<int, QwtColumnSymbol *>::iterator it - = d_data->symbolMap.begin(); it != d_data->symbolMap.end(); ++it ) - { - delete it.value(); - } - - d_data->symbolMap.clear(); -} - -/*! - \brief Create a symbol for special values - - Usually the symbols for displaying a bar are set by setSymbols() and - common for all sets. By overloading specialSymbol() it is possible to - create a temporary symbol() for displaying a special value. - - The symbol has to be created by new each time specialSymbol() is - called. As soon as the symbol is painted this symbol gets deleted. - - When no symbol ( NULL ) is returned, the value will be displayed - with the standard symbol that is used for all symbols with the same - valueIndex. - - \param sampleIndex Index of the sample - \param valueIndex Index of the value in the set - - \return NULL, meaning that the value is not special - - */ -QwtColumnSymbol *QwtPlotMultiBarChart::specialSymbol( - int sampleIndex, int valueIndex ) const -{ - Q_UNUSED( sampleIndex ); - Q_UNUSED( valueIndex ); - - return NULL; -} - -/*! - Set the style of the chart - - \param style Chart style - \sa style() - */ -void QwtPlotMultiBarChart::setStyle( ChartStyle style ) -{ - if ( style != d_data->style ) - { - d_data->style = style; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Style of the chart - \sa setStyle() - */ -QwtPlotMultiBarChart::ChartStyle QwtPlotMultiBarChart::style() const -{ - return d_data->style; -} - -/*! - \return Bounding rectangle of all samples. - For an empty series the rectangle is invalid. -*/ -QRectF QwtPlotMultiBarChart::boundingRect() const -{ - const size_t numSamples = dataSize(); - - if ( numSamples == 0 ) - return QwtPlotSeriesItem::boundingRect(); - - const double baseLine = baseline(); - - QRectF rect; - - if ( d_data->style != QwtPlotMultiBarChart::Stacked ) - { - rect = QwtPlotSeriesItem::boundingRect(); - - if ( rect.height() >= 0 ) - { - if ( rect.bottom() < baseLine ) - rect.setBottom( baseLine ); - if ( rect.top() > baseLine ) - rect.setTop( baseLine ); - } - } - else - { - double xMin, xMax, yMin, yMax; - - xMin = xMax = 0.0; - yMin = yMax = baseLine; - - const QwtSeriesData<QwtSetSample> *series = data(); - - for ( size_t i = 0; i < numSamples; i++ ) - { - const QwtSetSample sample = series->sample( i ); - if ( i == 0 ) - { - xMin = xMax = sample.value; - } - else - { - xMin = qMin( xMin, sample.value ); - xMax = qMax( xMax, sample.value ); - } - - const double y = baseLine + sample.added(); - - yMin = qMin( yMin, y ); - yMax = qMax( yMax, y ); - } - rect.setRect( xMin, yMin, xMax - xMin, yMax - yMin ); - } - - if ( orientation() == Qt::Horizontal ) - rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() ); - - return rect; -} - -/*! - Draw an interval of the bar chart - - \param painter Painter - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle 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 drawSymbols() -*/ -void QwtPlotMultiBarChart::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; - - - const QRectF br = data()->boundingRect(); - const QwtInterval interval( br.left(), br.right() ); - - painter->save(); - - for ( int i = from; i <= to; i++ ) - { - drawSample( painter, xMap, yMap, - canvasRect, interval, i, sample( i ) ); - } - - painter->restore(); -} - -/*! - Draw a sample - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle of the canvas - \param boundingInterval Bounding interval of sample values - \param index Index of the sample to be painted - \param sample Sample value - - \sa drawSeries() -*/ -void QwtPlotMultiBarChart::drawSample( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, const QwtInterval &boundingInterval, - int index, const QwtSetSample& sample ) const -{ - if ( sample.set.size() <= 0 ) - return; - - double sampleW; - - if ( orientation() == Qt::Horizontal ) - { - sampleW = sampleWidth( yMap, canvasRect.height(), - boundingInterval.width(), sample.value ); - } - else - { - sampleW = sampleWidth( xMap, canvasRect.width(), - boundingInterval.width(), sample.value ); - } - - if ( d_data->style == Stacked ) - { - drawStackedBars( painter, xMap, yMap, - canvasRect, index, sampleW, sample ); - } - else - { - drawGroupedBars( painter, xMap, yMap, - canvasRect, index, sampleW, sample ); - } -} - -/*! - Draw a grouped sample - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle of the canvas - \param index Index of the sample to be painted - \param sampleWidth Boundng width for all bars of the smaple - \param sample Sample - - \sa drawSeries(), sampleWidth() -*/ -void QwtPlotMultiBarChart::drawGroupedBars( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int index, double sampleWidth, - const QwtSetSample& sample ) const -{ - Q_UNUSED( canvasRect ); - - const int numBars = sample.set.size(); - if ( numBars == 0 ) - return; - - if ( orientation() == Qt::Vertical ) - { - const double barWidth = sampleWidth / numBars; - - const double y1 = yMap.transform( baseline() ); - const double x0 = xMap.transform( sample.value ) - 0.5 * sampleWidth; - - for ( int i = 0; i < numBars; i++ ) - { - const double x1 = x0 + i * barWidth; - const double x2 = x1 + barWidth; - - const double y2 = yMap.transform( sample.set[i] ); - - QwtColumnRect barRect; - barRect.direction = ( y1 < y2 ) ? - QwtColumnRect::TopToBottom : QwtColumnRect::BottomToTop; - - barRect.hInterval = QwtInterval( x1, x2 ).normalized(); - if ( i != 0 ) - barRect.hInterval.setBorderFlags( QwtInterval::ExcludeMinimum ); - - barRect.vInterval = QwtInterval( y1, y2 ).normalized(); - - drawBar( painter, index, i, barRect ); - } - } - else - { - const double barHeight = sampleWidth / numBars; - - const double x1 = xMap.transform( baseline() ); - const double y0 = yMap.transform( sample.value ) - 0.5 * sampleWidth; - - for ( int i = 0; i < numBars; i++ ) - { - double y1 = y0 + i * barHeight; - double y2 = y1 + barHeight; - - double x2 = xMap.transform( sample.set[i] ); - - QwtColumnRect barRect; - barRect.direction = x1 < x2 ? - QwtColumnRect::LeftToRight : QwtColumnRect::RightToLeft; - - barRect.hInterval = QwtInterval( x1, x2 ).normalized(); - - barRect.vInterval = QwtInterval( y1, y2 ); - if ( i != 0 ) - barRect.vInterval.setBorderFlags( QwtInterval::ExcludeMinimum ); - - drawBar( painter, index, i, barRect ); - } - } -} - -/*! - Draw a stacked sample - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle of the canvas - \param index Index of the sample to be painted - \param sampleWidth Width of the bars - \param sample Sample - - \sa drawSeries(), sampleWidth() -*/ -void QwtPlotMultiBarChart::drawStackedBars( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int index, - double sampleWidth, const QwtSetSample& sample ) const -{ - Q_UNUSED( canvasRect ); // clipping the bars ? - - const int numBars = sample.set.size(); - if ( numBars == 0 ) - return; - - QwtInterval::BorderFlag borderFlags = QwtInterval::IncludeBorders; - - if ( orientation() == Qt::Vertical ) - { - const double x1 = xMap.transform( sample.value ) - 0.5 * sampleWidth; - const double x2 = x1 + sampleWidth; - - const bool increasing = qwtIsIncreasing( yMap, sample.set ); - - QwtColumnRect bar; - bar.direction = increasing ? - QwtColumnRect::TopToBottom : QwtColumnRect::BottomToTop; - - bar.hInterval = QwtInterval( x1, x2 ).normalized(); - - double sum = baseline(); - - const int numBars = sample.set.size(); - for ( int i = 0; i < numBars; i++ ) - { - const double si = sample.set[ i ]; - if ( si == 0.0 ) - continue; - - const double y1 = yMap.transform( sum ); - const double y2 = yMap.transform( sum + si ); - - if ( ( y2 > y1 ) != increasing ) - { - // stacked bars need to be in the same direction - continue; - } - - bar.vInterval = QwtInterval( y1, y2 ).normalized(); - bar.vInterval.setBorderFlags( borderFlags ); - - drawBar( painter, index, i, bar ); - - sum += si; - - if ( increasing ) - borderFlags = QwtInterval::ExcludeMinimum; - else - borderFlags = QwtInterval::ExcludeMaximum; - } - } - else - { - const double y1 = yMap.transform( sample.value ) - 0.5 * sampleWidth; - const double y2 = y1 + sampleWidth; - - const bool increasing = qwtIsIncreasing( xMap, sample.set ); - - QwtColumnRect bar; - bar.direction = increasing ? - QwtColumnRect::LeftToRight : QwtColumnRect::RightToLeft; - bar.vInterval = QwtInterval( y1, y2 ).normalized(); - - double sum = baseline(); - - for ( int i = 0; i < sample.set.size(); i++ ) - { - const double si = sample.set[ i ]; - if ( si == 0.0 ) - continue; - - const double x1 = xMap.transform( sum ); - const double x2 = xMap.transform( sum + si ); - - if ( ( x2 > x1 ) != increasing ) - { - // stacked bars need to be in the same direction - continue; - } - - bar.hInterval = QwtInterval( x1, x2 ).normalized(); - bar.hInterval.setBorderFlags( borderFlags ); - - drawBar( painter, index, i, bar ); - - sum += si; - - if ( increasing ) - borderFlags = QwtInterval::ExcludeMinimum; - else - borderFlags = QwtInterval::ExcludeMaximum; - } - } -} - -/*! - Draw a bar - - \param painter Painter - \param sampleIndex Index of the sample - might be -1 when the - bar is painted for the legend - \param valueIndex Index of a value in a set - \param rect Directed target rectangle for the bar - - \sa drawSeries() -*/ -void QwtPlotMultiBarChart::drawBar( QPainter *painter, - int sampleIndex, int valueIndex, const QwtColumnRect &rect ) const -{ - const QwtColumnSymbol *specialSym = NULL; - if ( sampleIndex >= 0 ) - specialSym = specialSymbol( sampleIndex, valueIndex ); - - const QwtColumnSymbol *sym = specialSym; - if ( sym == NULL ) - sym = symbol( valueIndex ); - - if ( sym ) - { - sym->draw( painter, rect ); - } - else - { - // we build a temporary default symbol - QwtColumnSymbol sym( QwtColumnSymbol::Box ); - sym.setLineWidth( 1 ); - sym.setFrameStyle( QwtColumnSymbol::Plain ); - sym.draw( painter, rect ); - } - - delete specialSym; -} - -/*! - \return Information to be displayed on the legend - - The chart is represented by a list of entries - one for each bar title. - Each element contains a bar title and an icon showing its corresponding bar. - - \sa barTitles(), legendIcon(), legendIconSize() -*/ -QList<QwtLegendData> QwtPlotMultiBarChart::legendData() const -{ - QList<QwtLegendData> list; - - for ( int i = 0; i < d_data->barTitles.size(); i++ ) - { - QwtLegendData data; - - QVariant titleValue; - qVariantSetValue( titleValue, d_data->barTitles[i] ); - data.setValue( QwtLegendData::TitleRole, titleValue ); - - if ( !legendIconSize().isEmpty() ) - { - QVariant iconValue; - qVariantSetValue( iconValue, - legendIcon( i, legendIconSize() ) ); - - data.setValue( QwtLegendData::IconRole, iconValue ); - } - - list += data; - } - - return list; -} - -/*! - \return Icon for representing a bar on the legend - - \param index Index of the bar - \param size Icon size - - \return An icon showing a bar - \sa drawBar(), legendData() - */ -QwtGraphic QwtPlotMultiBarChart::legendIcon( int index, - const QSizeF &size ) const -{ - QwtColumnRect column; - column.hInterval = QwtInterval( 0.0, size.width() - 1.0 ); - column.vInterval = QwtInterval( 0.0, size.height() - 1.0 ); - - QwtGraphic icon; - icon.setDefaultSize( size ); - icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); - - QPainter painter( &icon ); - painter.setRenderHint( QPainter::Antialiasing, - testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - drawBar( &painter, -1, index, column ); - - return icon; -} - diff --git a/source/third_party/qwt/qwt_plot_panner.cpp b/source/third_party/qwt/qwt_plot_panner.cpp deleted file mode 100644 index 6b8cbe7719724f7014992e71c10607e4834862db..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_panner.cpp +++ /dev/null @@ -1,275 +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/qwt_plot_panner.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_painter.h" -#include <qbitmap.h> -#include <qstyle.h> -#include <qstyleoption.h> - -static QBitmap qwtBorderMask( const QWidget *canvas, const QSize &size ) -{ - const QRect r( 0, 0, size.width(), size.height() ); - - QPainterPath borderPath; - - ( void )QMetaObject::invokeMethod( - const_cast< QWidget *>( canvas ), "borderPath", Qt::DirectConnection, - Q_RETURN_ARG( QPainterPath, borderPath ), Q_ARG( QRect, r ) ); - - if ( borderPath.isEmpty() ) - { - if ( canvas->contentsRect() == canvas->rect() ) - return QBitmap(); - - QBitmap mask( size ); - mask.fill( Qt::color0 ); - - QPainter painter( &mask ); - painter.fillRect( canvas->contentsRect(), Qt::color1 ); - - return mask; - } - - QImage image( size, QImage::Format_ARGB32_Premultiplied ); - image.fill( Qt::color0 ); - - QPainter painter( &image ); - painter.setClipPath( borderPath ); - painter.fillRect( r, Qt::color1 ); - - // now erase the frame - - painter.setCompositionMode( QPainter::CompositionMode_DestinationOut ); - - if ( canvas->testAttribute(Qt::WA_StyledBackground ) ) - { - QStyleOptionFrame opt; - opt.initFrom(canvas); - opt.rect = r; - canvas->style()->drawPrimitive( QStyle::PE_Frame, &opt, &painter, canvas ); - } - else - { - const QVariant borderRadius = canvas->property( "borderRadius" ); - const QVariant frameWidth = canvas->property( "frameWidth" ); - - if ( borderRadius.type() == QVariant::Double - && frameWidth.type() == QVariant::Int ) - { - const double br = borderRadius.toDouble(); - const int fw = frameWidth.toInt(); - - if ( br > 0.0 && fw > 0 ) - { - painter.setPen( QPen( Qt::color1, fw ) ); - painter.setBrush( Qt::NoBrush ); - painter.setRenderHint( QPainter::Antialiasing, true ); - - painter.drawPath( borderPath ); - } - } - } - - painter.end(); - - const QImage mask = image.createMaskFromColor( - QColor( Qt::color1 ).rgb(), Qt::MaskOutColor ); - - return QBitmap::fromImage( mask ); -} - -class QwtPlotPanner::PrivateData -{ -public: - PrivateData() - { - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - isAxisEnabled[axis] = true; - } - - bool isAxisEnabled[QwtPlot::axisCnt]; -}; - -/*! - \brief A panner for the canvas of a QwtPlot - - The panner is enabled for all axes - - \param canvas Plot canvas to pan, also the parent object - - \sa setAxisEnabled() -*/ -QwtPlotPanner::QwtPlotPanner( QWidget *canvas ): - QwtPanner( canvas ) -{ - d_data = new PrivateData(); - - connect( this, SIGNAL( panned( int, int ) ), - SLOT( moveCanvas( int, int ) ) ); -} - -//! Destructor -QwtPlotPanner::~QwtPlotPanner() -{ - delete d_data; -} - -/*! - \brief En/Disable an axis - - Axes that are enabled will be synchronized to the - result of panning. All other axes will remain unchanged. - - \param axis Axis, see QwtPlot::Axis - \param on On/Off - - \sa isAxisEnabled(), moveCanvas() -*/ -void QwtPlotPanner::setAxisEnabled( int axis, bool on ) -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->isAxisEnabled[axis] = on; -} - -/*! - Test if an axis is enabled - - \param axis Axis, see QwtPlot::Axis - \return True, if the axis is enabled - - \sa setAxisEnabled(), moveCanvas() -*/ -bool QwtPlotPanner::isAxisEnabled( int axis ) const -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - return d_data->isAxisEnabled[axis]; - - return true; -} - -//! Return observed plot canvas -QWidget *QwtPlotPanner::canvas() -{ - return parentWidget(); -} - -//! Return Observed plot canvas -const QWidget *QwtPlotPanner::canvas() const -{ - return parentWidget(); -} - -//! Return plot widget, containing the observed plot canvas -QwtPlot *QwtPlotPanner::plot() -{ - QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<QwtPlot *>( w ); -} - -//! Return plot widget, containing the observed plot canvas -const QwtPlot *QwtPlotPanner::plot() const -{ - const QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<const QwtPlot *>( w ); -} - -/*! - Adjust the enabled axes according to dx/dy - - \param dx Pixel offset in x direction - \param dy Pixel offset in y direction - - \sa QwtPanner::panned() -*/ -void QwtPlotPanner::moveCanvas( int dx, int dy ) -{ - if ( dx == 0 && dy == 0 ) - return; - - QwtPlot *plot = this->plot(); - if ( plot == NULL ) - return; - - const bool doAutoReplot = plot->autoReplot(); - plot->setAutoReplot( false ); - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - if ( !d_data->isAxisEnabled[axis] ) - continue; - - const QwtScaleMap map = plot->canvasMap( axis ); - - const double p1 = map.transform( plot->axisScaleDiv( axis ).lowerBound() ); - const double p2 = map.transform( plot->axisScaleDiv( axis ).upperBound() ); - - double d1, d2; - if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) - { - d1 = map.invTransform( p1 - dx ); - d2 = map.invTransform( p2 - dx ); - } - else - { - d1 = map.invTransform( p1 - dy ); - d2 = map.invTransform( p2 - dy ); - } - - plot->setAxisScale( axis, d1, d2 ); - } - - plot->setAutoReplot( doAutoReplot ); - plot->replot(); -} - -/*! - Calculate a mask from the border path of the canvas - - \return Mask as bitmap - \sa QwtPlotCanvas::borderPath() -*/ -QBitmap QwtPlotPanner::contentsMask() const -{ - if ( canvas() ) - return qwtBorderMask( canvas(), size() ); - - return QwtPanner::contentsMask(); -} - -/*! - \return Pixmap with the content of the canvas - */ -QPixmap QwtPlotPanner::grab() const -{ - const QWidget *cv = canvas(); - if ( cv && cv->inherits( "QGLWidget" ) ) - { - // we can't grab from a QGLWidget - - QPixmap pm( cv->size() ); - QwtPainter::fillPixmap( cv, pm ); - - QPainter painter( &pm ); - const_cast<QwtPlot *>( plot() )->drawCanvas( &painter ); - - return pm; - } - - return QwtPanner::grab(); -} - diff --git a/source/third_party/qwt/qwt_plot_picker.cpp b/source/third_party/qwt/qwt_plot_picker.cpp deleted file mode 100644 index 14bccb53305667a7113cd85a0d701c6cb2c54b5e..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_picker.cpp +++ /dev/null @@ -1,378 +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/qwt_plot_picker.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_picker_machine.h" - -/*! - \brief Create a plot picker - - The picker is set to those x- and y-axis of the plot - that are enabled. If both or no x-axis are enabled, the picker - is set to QwtPlot::xBottom. If both or no y-axis are - enabled, it is set to QwtPlot::yLeft. - - \param canvas Plot canvas to observe, also the parent object - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect() -*/ - -QwtPlotPicker::QwtPlotPicker( QWidget *canvas ): - QwtPicker( canvas ), - d_xAxis( -1 ), - d_yAxis( -1 ) -{ - if ( !canvas ) - return; - - // attach axes - - int xAxis = QwtPlot::xBottom; - - const QwtPlot *plot = QwtPlotPicker::plot(); - if ( !plot->axisEnabled( QwtPlot::xBottom ) && - plot->axisEnabled( QwtPlot::xTop ) ) - { - xAxis = QwtPlot::xTop; - } - - int yAxis = QwtPlot::yLeft; - if ( !plot->axisEnabled( QwtPlot::yLeft ) && - plot->axisEnabled( QwtPlot::yRight ) ) - { - yAxis = QwtPlot::yRight; - } - - setAxis( xAxis, yAxis ); -} - -/*! - Create a plot picker - - \param xAxis Set the x axis of the picker - \param yAxis Set the y axis of the picker - \param canvas Plot canvas to observe, also the parent object - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect() -*/ -QwtPlotPicker::QwtPlotPicker( int xAxis, int yAxis, QWidget *canvas ): - QwtPicker( canvas ), - d_xAxis( xAxis ), - d_yAxis( yAxis ) -{ -} - -/*! - Create a plot picker - - \param xAxis X axis of the picker - \param yAxis Y axis of the picker - \param rubberBand Rubber band style - \param trackerMode Tracker mode - \param canvas Plot canvas to observe, also the parent object - - \sa QwtPicker, QwtPicker::setSelectionFlags(), QwtPicker::setRubberBand(), - QwtPicker::setTrackerMode - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect() -*/ -QwtPlotPicker::QwtPlotPicker( int xAxis, int yAxis, - RubberBand rubberBand, DisplayMode trackerMode, - QWidget *canvas ): - QwtPicker( rubberBand, trackerMode, canvas ), - d_xAxis( xAxis ), - d_yAxis( yAxis ) -{ -} - -//! Destructor -QwtPlotPicker::~QwtPlotPicker() -{ -} - -//! \return Observed plot canvas -QWidget *QwtPlotPicker::canvas() -{ - return parentWidget(); -} - -//! \return Observed plot canvas -const QWidget *QwtPlotPicker::canvas() const -{ - return parentWidget(); -} - -//! \return Plot widget, containing the observed plot canvas -QwtPlot *QwtPlotPicker::plot() -{ - QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<QwtPlot *>( w ); -} - -//! \return Plot widget, containing the observed plot canvas -const QwtPlot *QwtPlotPicker::plot() const -{ - const QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<const QwtPlot *>( w ); -} - -/*! - \return Normalized bounding rectangle of the axes - \sa QwtPlot::autoReplot(), QwtPlot::replot(). -*/ -QRectF QwtPlotPicker::scaleRect() const -{ - QRectF rect; - - if ( plot() ) - { - const QwtScaleDiv &xs = plot()->axisScaleDiv( xAxis() ); - const QwtScaleDiv &ys = plot()->axisScaleDiv( yAxis() ); - - rect = QRectF( xs.lowerBound(), ys.lowerBound(), - xs.range(), ys.range() ); - rect = rect.normalized(); - } - - return rect; -} - -/*! - Set the x and y axes of the picker - - \param xAxis X axis - \param yAxis Y axis -*/ -void QwtPlotPicker::setAxis( int xAxis, int yAxis ) -{ - const QwtPlot *plt = plot(); - if ( !plt ) - return; - - if ( xAxis != d_xAxis || yAxis != d_yAxis ) - { - d_xAxis = xAxis; - d_yAxis = yAxis; - } -} - -//! Return x axis -int QwtPlotPicker::xAxis() const -{ - return d_xAxis; -} - -//! Return y axis -int QwtPlotPicker::yAxis() const -{ - return d_yAxis; -} - -/*! - Translate a pixel position into a position string - - \param pos Position in pixel coordinates - \return Position string -*/ -QwtText QwtPlotPicker::trackerText( const QPoint &pos ) const -{ - return trackerTextF( invTransform( pos ) ); -} - -/*! - \brief Translate a position into a position string - - In case of HLineRubberBand the label is the value of the - y position, in case of VLineRubberBand the value of the x position. - Otherwise the label contains x and y position separated by a ',' . - - The format for the double to string conversion is "%.4f". - - \param pos Position - \return Position string -*/ -QwtText QwtPlotPicker::trackerTextF( const QPointF &pos ) const -{ - QString text; - - switch ( rubberBand() ) - { - case HLineRubberBand: - text.sprintf( "%.4f", pos.y() ); - break; - case VLineRubberBand: - text.sprintf( "%.4f", pos.x() ); - break; - default: - text.sprintf( "%.4f, %.4f", pos.x(), pos.y() ); - } - return QwtText( text ); -} - -/*! - Append a point to the selection and update rubber band and tracker. - - \param pos Additional point - \sa isActive, begin(), end(), move(), appended() - - \note The appended(const QPoint &), appended(const QDoublePoint &) - signals are emitted. -*/ -void QwtPlotPicker::append( const QPoint &pos ) -{ - QwtPicker::append( pos ); - Q_EMIT appended( invTransform( pos ) ); -} - -/*! - Move the last point of the selection - - \param pos New position - \sa isActive, begin(), end(), append() - - \note The moved(const QPoint &), moved(const QDoublePoint &) - signals are emitted. -*/ -void QwtPlotPicker::move( const QPoint &pos ) -{ - QwtPicker::move( pos ); - Q_EMIT moved( invTransform( pos ) ); -} - -/*! - Close a selection setting the state to inactive. - - \param ok If true, complete the selection and emit selected signals - otherwise discard the selection. - \return True if the selection has been accepted, false otherwise -*/ - -bool QwtPlotPicker::end( bool ok ) -{ - ok = QwtPicker::end( ok ); - if ( !ok ) - return false; - - QwtPlot *plot = QwtPlotPicker::plot(); - if ( !plot ) - return false; - - const QPolygon points = selection(); - if ( points.count() == 0 ) - return false; - - QwtPickerMachine::SelectionType selectionType = - QwtPickerMachine::NoSelection; - - if ( stateMachine() ) - selectionType = stateMachine()->selectionType(); - - switch ( selectionType ) - { - case QwtPickerMachine::PointSelection: - { - const QPointF pos = invTransform( points.first() ); - Q_EMIT selected( pos ); - break; - } - case QwtPickerMachine::RectSelection: - { - if ( points.count() >= 2 ) - { - const QPoint p1 = points.first(); - const QPoint p2 = points.last(); - - const QRect rect = QRect( p1, p2 ).normalized(); - Q_EMIT selected( invTransform( rect ) ); - } - break; - } - case QwtPickerMachine::PolygonSelection: - { - QVector<QPointF> dpa( points.count() ); - for ( int i = 0; i < points.count(); i++ ) - dpa[i] = invTransform( points[i] ); - - Q_EMIT selected( dpa ); - } - default: - break; - } - - return true; -} - -/*! - Translate a rectangle from pixel into plot coordinates - - \return Rectangle in plot coordinates - \sa transform() -*/ -QRectF QwtPlotPicker::invTransform( const QRect &rect ) const -{ - const QwtScaleMap xMap = plot()->canvasMap( d_xAxis ); - const QwtScaleMap yMap = plot()->canvasMap( d_yAxis ); - - return QwtScaleMap::invTransform( xMap, yMap, rect ); -} - -/*! - Translate a rectangle from plot into pixel coordinates - \return Rectangle in pixel coordinates - \sa invTransform() -*/ -QRect QwtPlotPicker::transform( const QRectF &rect ) const -{ - const QwtScaleMap xMap = plot()->canvasMap( d_xAxis ); - const QwtScaleMap yMap = plot()->canvasMap( d_yAxis ); - - return QwtScaleMap::transform( xMap, yMap, rect ).toRect(); -} - -/*! - Translate a point from pixel into plot coordinates - \return Point in plot coordinates - \sa transform() -*/ -QPointF QwtPlotPicker::invTransform( const QPoint &pos ) const -{ - QwtScaleMap xMap = plot()->canvasMap( d_xAxis ); - QwtScaleMap yMap = plot()->canvasMap( d_yAxis ); - - return QPointF( - xMap.invTransform( pos.x() ), - yMap.invTransform( pos.y() ) - ); -} - -/*! - Translate a point from plot into pixel coordinates - \return Point in pixel coordinates - \sa invTransform() -*/ -QPoint QwtPlotPicker::transform( const QPointF &pos ) const -{ - QwtScaleMap xMap = plot()->canvasMap( d_xAxis ); - QwtScaleMap yMap = plot()->canvasMap( d_yAxis ); - - const QPointF p( xMap.transform( pos.x() ), - yMap.transform( pos.y() ) ); - - return p.toPoint(); -} diff --git a/source/third_party/qwt/qwt_plot_rasteritem.cpp b/source/third_party/qwt/qwt_plot_rasteritem.cpp deleted file mode 100644 index eeebc85310f450ca7b4633e5b5acca95092ad34b..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_rasteritem.cpp +++ /dev/null @@ -1,961 +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/qwt_plot_rasteritem.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_painter.h" -#include <qapplication.h> -#include <qdesktopwidget.h> -#include <qpainter.h> -#include <qpaintengine.h> -#include <qmath.h> -#if QT_VERSION >= 0x040400 -#include <qthread.h> -#include <qfuture.h> -#include <QtConcurrent/qtconcurrentrun.h> -#endif -#include <float.h> - -class QwtPlotRasterItem::PrivateData -{ -public: - PrivateData(): - alpha( -1 ), - paintAttributes( QwtPlotRasterItem::PaintInDeviceResolution ) - { - cache.policy = QwtPlotRasterItem::NoCache; - } - - int alpha; - - QwtPlotRasterItem::PaintAttributes paintAttributes; - - struct ImageCache - { - QwtPlotRasterItem::CachePolicy policy; - QRectF area; - QSizeF size; - QImage image; - } cache; -}; - - -static QRectF qwtAlignRect(const QRectF &rect) -{ - QRectF r; - r.setLeft( qRound( rect.left() ) ); - r.setRight( qRound( rect.right() ) ); - r.setTop( qRound( rect.top() ) ); - r.setBottom( qRound( rect.bottom() ) ); - - return r; -} - -static QRectF qwtStripRect(const QRectF &rect, const QRectF &area, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtInterval &xInterval, const QwtInterval &yInterval) -{ - QRectF r = rect; - if ( xInterval.borderFlags() & QwtInterval::ExcludeMinimum ) - { - if ( area.left() <= xInterval.minValue() ) - { - if ( xMap.isInverting() ) - r.adjust(0, 0, -1, 0); - else - r.adjust(1, 0, 0, 0); - } - } - - if ( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) - { - if ( area.right() >= xInterval.maxValue() ) - { - if ( xMap.isInverting() ) - r.adjust(1, 0, 0, 0); - else - r.adjust(0, 0, -1, 0); - } - } - - if ( yInterval.borderFlags() & QwtInterval::ExcludeMinimum ) - { - if ( area.top() <= yInterval.minValue() ) - { - if ( yMap.isInverting() ) - r.adjust(0, 0, 0, -1); - else - r.adjust(0, 1, 0, 0); - } - } - - if ( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) - { - if ( area.bottom() >= yInterval.maxValue() ) - { - if ( yMap.isInverting() ) - r.adjust(0, 1, 0, 0); - else - r.adjust(0, 0, 0, -1); - } - } - - return r; -} - -static QImage qwtExpandImage(const QImage &image, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &area, const QRectF &area2, const QRectF &paintRect, - const QwtInterval &xInterval, const QwtInterval &yInterval ) -{ - const QRectF strippedRect = qwtStripRect(paintRect, area2, - xMap, yMap, xInterval, yInterval); - const QSize sz = strippedRect.toRect().size(); - - const int w = image.width(); - const int h = image.height(); - - const QRectF r = QwtScaleMap::transform(xMap, yMap, area).normalized(); - const double pw = ( r.width() - 1) / w; - const double ph = ( r.height() - 1) / h; - - double px0, py0; - if ( !xMap.isInverting() ) - { - px0 = xMap.transform( area2.left() ); - px0 = qRound( px0 ); - px0 = px0 - xMap.transform( area.left() ); - } - else - { - px0 = xMap.transform( area2.right() ); - px0 = qRound( px0 ); - px0 -= xMap.transform( area.right() ); - - px0 -= 1.0; - } - px0 += strippedRect.left() - paintRect.left(); - - if ( !yMap.isInverting() ) - { - py0 = yMap.transform( area2.top() ); - py0 = qRound( py0 ); - py0 -= yMap.transform( area.top() ); - } - else - { - py0 = yMap.transform( area2.bottom() ); - py0 = qRound( py0 ); - py0 -= yMap.transform( area.bottom() ); - - py0 -= 1.0; - } - py0 += strippedRect.top() - paintRect.top(); - - QImage expanded(sz, image.format()); - - switch( image.depth() ) - { - case 32: - { - for ( int y1 = 0; y1 < h; y1++ ) - { - int yy1; - if ( y1 == 0 ) - { - yy1 = 0; - } - else - { - yy1 = qRound( y1 * ph - py0 ); - if ( yy1 < 0 ) - yy1 = 0; - } - - int yy2; - if ( y1 == h - 1 ) - { - yy2 = sz.height(); - } - else - { - yy2 = qRound( ( y1 + 1 ) * ph - py0 ); - if ( yy2 > sz.height() ) - yy2 = sz.height(); - } - - const quint32 *line1 = - reinterpret_cast<const quint32 *>( image.scanLine( y1 ) ); - - for ( int x1 = 0; x1 < w; x1++ ) - { - int xx1; - if ( x1 == 0 ) - { - xx1 = 0; - } - else - { - xx1 = qRound( x1 * pw - px0 ); - if ( xx1 < 0 ) - xx1 = 0; - } - - int xx2; - if ( x1 == w - 1 ) - { - xx2 = sz.width(); - } - else - { - xx2 = qRound( ( x1 + 1 ) * pw - px0 ); - if ( xx2 > sz.width() ) - xx2 = sz.width(); - } - - const quint32 rgb( line1[x1] ); - for ( int y2 = yy1; y2 < yy2; y2++ ) - { - quint32 *line2 = reinterpret_cast<quint32 *>( - expanded.scanLine( y2 ) ); - - for ( int x2 = xx1; x2 < xx2; x2++ ) - line2[x2] = rgb; - } - } - } - break; - } - case 8: - { - for ( int y1 = 0; y1 < h; y1++ ) - { - int yy1; - if ( y1 == 0 ) - { - yy1 = 0; - } - else - { - yy1 = qRound( y1 * ph - py0 ); - if ( yy1 < 0 ) - yy1 = 0; - } - - int yy2; - if ( y1 == h - 1 ) - { - yy2 = sz.height(); - } - else - { - yy2 = qRound( ( y1 + 1 ) * ph - py0 ); - if ( yy2 > sz.height() ) - yy2 = sz.height(); - } - - const uchar *line1 = image.scanLine( y1 ); - - for ( int x1 = 0; x1 < w; x1++ ) - { - int xx1; - if ( x1 == 0 ) - { - xx1 = 0; - } - else - { - xx1 = qRound( x1 * pw - px0 ); - if ( xx1 < 0 ) - xx1 = 0; - } - - int xx2; - if ( x1 == w - 1 ) - { - xx2 = sz.width(); - } - else - { - xx2 = qRound( ( x1 + 1 ) * pw - px0 ); - if ( xx2 > sz.width() ) - xx2 = sz.width(); - } - - for ( int y2 = yy1; y2 < yy2; y2++ ) - { - uchar *line2 = expanded.scanLine( y2 ); - memset( line2 + xx1, line1[x1], xx2 - xx1 ); - } - } - } - break; - } - default: - expanded = image; - } - - return expanded; -} - -static QRectF qwtExpandToPixels(const QRectF &rect, const QRectF &pixelRect) -{ - const double pw = pixelRect.width(); - const double ph = pixelRect.height(); - - const double dx1 = pixelRect.left() - rect.left(); - const double dx2 = pixelRect.right() - rect.right(); - const double dy1 = pixelRect.top() - rect.top(); - const double dy2 = pixelRect.bottom() - rect.bottom(); - - QRectF r; - r.setLeft( pixelRect.left() - qCeil( dx1 / pw ) * pw ); - r.setTop( pixelRect.top() - qCeil( dy1 / ph ) * ph ); - r.setRight( pixelRect.right() - qFloor( dx2 / pw ) * pw ); - r.setBottom( pixelRect.bottom() - qFloor( dy2 / ph ) * ph ); - - return r; -} - -static void qwtTransformMaps( const QTransform &tr, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - QwtScaleMap &xxMap, QwtScaleMap &yyMap ) -{ - const QPointF p1 = tr.map( QPointF( xMap.p1(), yMap.p1() ) ); - const QPointF p2 = tr.map( QPointF( xMap.p2(), yMap.p2() ) ); - - xxMap = xMap; - xxMap.setPaintInterval( p1.x(), p2.x() ); - - yyMap = yMap; - yyMap.setPaintInterval( p1.y(), p2.y() ); -} - -static void qwtAdjustMaps( QwtScaleMap &xMap, QwtScaleMap &yMap, - const QRectF &area, const QRectF &paintRect) -{ - double sx1 = area.left(); - double sx2 = area.right(); - if ( xMap.isInverting() ) - qSwap(sx1, sx2); - - double sy1 = area.top(); - double sy2 = area.bottom(); - - if ( yMap.isInverting() ) - qSwap(sy1, sy2); - - xMap.setPaintInterval(paintRect.left(), paintRect.right()); - xMap.setScaleInterval(sx1, sx2); - - yMap.setPaintInterval(paintRect.top(), paintRect.bottom()); - yMap.setScaleInterval(sy1, sy2); -} - -static bool qwtUseCache( QwtPlotRasterItem::CachePolicy policy, - const QPainter *painter ) -{ - bool doCache = false; - - if ( policy == QwtPlotRasterItem::PaintCache ) - { - // Caching doesn't make sense, when the item is - // not painted to screen - - switch ( painter->paintEngine()->type() ) - { - case QPaintEngine::SVG: - case QPaintEngine::Pdf: - case QPaintEngine::PostScript: - case QPaintEngine::MacPrinter: - case QPaintEngine::Picture: - break; - default:; - doCache = true; - } - } - - return doCache; -} - -static void qwtToRgba( const QImage* from, QImage* to, - const QRect& tile, int alpha ) -{ - const QRgb mask1 = qRgba( 0, 0, 0, alpha ); - const QRgb mask2 = qRgba( 255, 255, 255, 0 ); - const QRgb mask3 = qRgba( 0, 0, 0, 255 ); - - const int y0 = tile.top(); - const int y1 = tile.bottom(); - const int x0 = tile.left(); - const int x1 = tile.right(); - - if ( from->depth() == 8 ) - { - for ( int y = y0; y <= y1; y++ ) - { - QRgb *alphaLine = reinterpret_cast<QRgb *>( to->scanLine( y ) ); - const unsigned char *line = from->scanLine( y ); - - for ( int x = x0; x <= x1; x++ ) - *alphaLine++ = ( from->color( *line++ ) & mask2 ) | mask1; - } - } - else if ( from->depth() == 32 ) - { - for ( int y = y0; y <= y1; y++ ) - { - QRgb *alphaLine = reinterpret_cast<QRgb *>( to->scanLine( y ) ); - const QRgb *line = reinterpret_cast<const QRgb *>( from->scanLine( y ) ); - - for ( int x = x0; x <= x1; x++ ) - { - const QRgb rgb = *line++; - if ( rgb & mask3 ) // alpha != 0 - *alphaLine++ = ( rgb & mask2 ) | mask1; - else - *alphaLine++ = rgb; - } - } - } -} - -//! Constructor -QwtPlotRasterItem::QwtPlotRasterItem( const QString& title ): - QwtPlotItem( QwtText( title ) ) -{ - init(); -} - -//! Constructor -QwtPlotRasterItem::QwtPlotRasterItem( const QwtText& title ): - QwtPlotItem( title ) -{ - init(); -} - -//! Destructor -QwtPlotRasterItem::~QwtPlotRasterItem() -{ - delete d_data; -} - -void QwtPlotRasterItem::init() -{ - d_data = new PrivateData(); - - setItemAttribute( QwtPlotItem::AutoScale, true ); - setItemAttribute( QwtPlotItem::Legend, false ); - - setZ( 8.0 ); -} - -/*! - Specify an attribute how to draw the raster item - - \param attribute Paint attribute - \param on On/Off - /sa PaintAttribute, testPaintAttribute() -*/ -void QwtPlotRasterItem::setPaintAttribute( PaintAttribute attribute, bool on ) -{ - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; -} - -/*! - \return True, when attribute is enabled - \sa PaintAttribute, setPaintAttribute() -*/ -bool QwtPlotRasterItem::testPaintAttribute( PaintAttribute attribute ) const -{ - return ( d_data->paintAttributes & attribute ); -} - -/*! - \brief Set an alpha value for the raster data - - Often a plot has several types of raster data organized in layers. - ( f.e a geographical map, with weather statistics ). - Using setAlpha() raster items can be stacked easily. - - The alpha value is a value [0, 255] to - control the transparency of the image. 0 represents a fully - transparent color, while 255 represents a fully opaque color. - - \param alpha Alpha value - - - alpha >= 0\n - All alpha values of the pixels returned by renderImage() will be set to - alpha, beside those with an alpha value of 0 (invalid pixels). - - alpha < 0 - The alpha values returned by renderImage() are not changed. - - The default alpha value is -1. - - \sa alpha() -*/ -void QwtPlotRasterItem::setAlpha( int alpha ) -{ - if ( alpha < 0 ) - alpha = -1; - - if ( alpha > 255 ) - alpha = 255; - - if ( alpha != d_data->alpha ) - { - d_data->alpha = alpha; - - itemChanged(); - } -} - -/*! - \return Alpha value of the raster item - \sa setAlpha() -*/ -int QwtPlotRasterItem::alpha() const -{ - return d_data->alpha; -} - -/*! - Change the cache policy - - The default policy is NoCache - - \param policy Cache policy - \sa CachePolicy, cachePolicy() -*/ -void QwtPlotRasterItem::setCachePolicy( - QwtPlotRasterItem::CachePolicy policy ) -{ - if ( d_data->cache.policy != policy ) - { - d_data->cache.policy = policy; - - invalidateCache(); - itemChanged(); - } -} - -/*! - \return Cache policy - \sa CachePolicy, setCachePolicy() -*/ -QwtPlotRasterItem::CachePolicy QwtPlotRasterItem::cachePolicy() const -{ - return d_data->cache.policy; -} - -/*! - Invalidate the paint cache - \sa setCachePolicy() -*/ -void QwtPlotRasterItem::invalidateCache() -{ - d_data->cache.image = QImage(); - d_data->cache.area = QRect(); - d_data->cache.size = QSize(); -} - -/*! - \brief Pixel hint - - The geometry of a pixel is used to calculated the resolution and - alignment of the rendered image. - - Width and height of the hint need to be the horizontal - and vertical distances between 2 neighbored points. - The center of the hint has to be the position of any point - ( it doesn't matter which one ). - - Limiting the resolution of the image might significantly improve - the performance and heavily reduce the amount of memory when rendering - a QImage from the raster data. - - The default implementation returns an empty rectangle (QRectF()), - meaning, that the image will be rendered in target device ( f.e screen ) - resolution. - - \param area In most implementations the resolution of the data doesn't - depend on the requested area. - - \return Bounding rectangle of a pixel - - \sa render(), renderImage() -*/ -QRectF QwtPlotRasterItem::pixelHint( const QRectF &area ) const -{ - Q_UNUSED( area ); - return QRectF(); -} - -/*! - \brief Draw the raster data - \param painter Painter - \param xMap X-Scale Map - \param yMap Y-Scale Map - \param canvasRect Contents rectangle of the plot canvas -*/ -void QwtPlotRasterItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - if ( canvasRect.isEmpty() || d_data->alpha == 0 ) - return; - - const bool doCache = qwtUseCache( d_data->cache.policy, painter ); - - const QwtInterval xInterval = interval( Qt::XAxis ); - const QwtInterval yInterval = interval( Qt::YAxis ); - - /* - Scaling an image always results in a loss of - precision/quality. So we always render the image in - paint device resolution. - */ - - QwtScaleMap xxMap, yyMap; - qwtTransformMaps( painter->transform(), xMap, yMap, xxMap, yyMap ); - - QRectF paintRect = painter->transform().mapRect( canvasRect ); - QRectF area = QwtScaleMap::invTransform( xxMap, yyMap, paintRect ); - - const QRectF br = boundingRect(); - if ( br.isValid() && !br.contains( area ) ) - { - area &= br; - if ( !area.isValid() ) - return; - - paintRect = QwtScaleMap::transform( xxMap, yyMap, area ); - } - - QRectF imageRect; - QImage image; - - QRectF pixelRect = pixelHint(area); - if ( !pixelRect.isEmpty() ) - { - // one pixel of the target device in plot coordinates - const double dx = qAbs( xxMap.invTransform( 1 ) - xxMap.invTransform( 0 ) ); - const double dy = qAbs( yyMap.invTransform( 1 ) - yyMap.invTransform( 0 ) ); - - if ( dx > pixelRect.width() && dy > pixelRect.height() ) - { - /* - When the resolution of the data pixels is higher than - the resolution of the target device we render in - target device resolution. - */ - pixelRect = QRectF(); - } - else - { - /* - If only one dimension is of the data pixel is higher - we expand the pixel rect to the resolution of the target device. - */ - - if ( dx > pixelRect.width() ) - pixelRect.setWidth( dx ); - - if ( dy > pixelRect.height() ) - pixelRect.setHeight( dy ); - } - } - - if ( pixelRect.isEmpty() ) - { - if ( QwtPainter::roundingAlignment( painter ) ) - { - // we want to have maps, where the boundaries of - // the aligned paint rectangle exactly match the area - - paintRect = qwtAlignRect(paintRect); - qwtAdjustMaps(xxMap, yyMap, area, paintRect); - } - - // When we have no information about position and size of - // data pixels we render in resolution of the paint device. - - image = compose(xxMap, yyMap, - area, paintRect, paintRect.size().toSize(), doCache); - if ( image.isNull() ) - return; - - // Remove pixels at the boundaries, when explicitly - // excluded in the intervals - - imageRect = qwtStripRect(paintRect, area, - xxMap, yyMap, xInterval, yInterval); - - if ( imageRect != paintRect ) - { - const QRect r( - qRound( imageRect.x() - paintRect.x()), - qRound( imageRect.y() - paintRect.y() ), - qRound( imageRect.width() ), - qRound( imageRect.height() ) ); - - image = image.copy(r); - } - } - else - { - if ( QwtPainter::roundingAlignment( painter ) ) - paintRect = qwtAlignRect(paintRect); - - // align the area to the data pixels - QRectF imageArea = qwtExpandToPixels(area, pixelRect); - - if ( imageArea.right() == xInterval.maxValue() && - !( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) ) - { - imageArea.adjust(0, 0, pixelRect.width(), 0); - } - if ( imageArea.bottom() == yInterval.maxValue() && - !( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) ) - { - imageArea.adjust(0, 0, 0, pixelRect.height() ); - } - - QSize imageSize; - imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) ); - imageSize.setHeight( qRound( imageArea.height() / pixelRect.height() ) ); - - image = compose(xxMap, yyMap, - imageArea, paintRect, imageSize, doCache ); - - if ( image.isNull() ) - return; - - imageRect = qwtStripRect(paintRect, area, - xxMap, yyMap, xInterval, yInterval); - - if ( ( image.width() > 1 || image.height() > 1 ) && - testPaintAttribute( PaintInDeviceResolution ) ) - { - // Because of rounding errors the pixels - // need to be expanded manually to rectangles of - // different sizes - - image = qwtExpandImage(image, xxMap, yyMap, - imageArea, area, paintRect, xInterval, yInterval ); - } - } - - painter->save(); - painter->setWorldTransform( QTransform() ); - - QwtPainter::drawImage( painter, imageRect, image ); - - painter->restore(); -} - -/*! - \return Bounding interval for an axis - - This method is intended to be reimplemented by derived classes. - The default implementation returns an invalid interval. - - \param axis X, Y, or Z axis -*/ -QwtInterval QwtPlotRasterItem::interval(Qt::Axis axis) const -{ - Q_UNUSED( axis ); - return QwtInterval(); -} - -/*! - \return Bounding rectangle of the data - \sa QwtPlotRasterItem::interval() -*/ -QRectF QwtPlotRasterItem::boundingRect() const -{ - const QwtInterval intervalX = interval( Qt::XAxis ); - const QwtInterval intervalY = interval( Qt::YAxis ); - - if ( !intervalX.isValid() && !intervalY.isValid() ) - return QRectF(); // no bounding rect - - QRectF r; - - if ( intervalX.isValid() ) - { - r.setLeft( intervalX.minValue() ); - r.setRight( intervalX.maxValue() ); - } - else - { - r.setLeft(-0.5 * FLT_MAX); - r.setWidth(FLT_MAX); - } - - if ( intervalY.isValid() ) - { - r.setTop( intervalY.minValue() ); - r.setBottom( intervalY.maxValue() ); - } - else - { - r.setTop(-0.5 * FLT_MAX); - r.setHeight(FLT_MAX); - } - - return r.normalized(); -} - -QImage QwtPlotRasterItem::compose( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &imageArea, const QRectF &paintRect, - const QSize &imageSize, bool doCache) const -{ - QImage image; - if ( imageArea.isEmpty() || paintRect.isEmpty() || imageSize.isEmpty() ) - return image; - - if ( doCache ) - { - if ( !d_data->cache.image.isNull() - && d_data->cache.area == imageArea - && d_data->cache.size == paintRect.size() ) - { - image = d_data->cache.image; - } - } - - if ( image.isNull() ) - { - double dx = 0.0; - if ( paintRect.toRect().width() > imageSize.width() ) - dx = imageArea.width() / imageSize.width(); - - const QwtScaleMap xxMap = - imageMap(Qt::Horizontal, xMap, imageArea, imageSize, dx); - - double dy = 0.0; - if ( paintRect.toRect().height() > imageSize.height() ) - dy = imageArea.height() / imageSize.height(); - - const QwtScaleMap yyMap = - imageMap(Qt::Vertical, yMap, imageArea, imageSize, dy); - - image = renderImage( xxMap, yyMap, imageArea, imageSize ); - - if ( doCache ) - { - d_data->cache.area = imageArea; - d_data->cache.size = paintRect.size(); - d_data->cache.image = image; - } - } - - if ( d_data->alpha >= 0 && d_data->alpha < 255 ) - { - QImage alphaImage( image.size(), QImage::Format_ARGB32 ); - -#if QT_VERSION >= 0x040400 && !defined(QT_NO_QFUTURE) - uint numThreads = renderThreadCount(); - - if ( numThreads <= 0 ) - numThreads = QThread::idealThreadCount(); - - if ( numThreads <= 0 ) - numThreads = 1; - - const int numRows = image.height() / numThreads; - - QList< QFuture<void> > futures; - for ( uint i = 0; i < numThreads; i++ ) - { - QRect tile( 0, i * numRows, image.width(), numRows ); - if ( i == numThreads - 1 ) - { - tile.setHeight( image.height() - i * numRows ); - qwtToRgba( &image, &alphaImage, tile, d_data->alpha ); - } - else - { - futures += QtConcurrent::run( - &qwtToRgba, &image, &alphaImage, tile, d_data->alpha ); - } - } - for ( int i = 0; i < futures.size(); i++ ) - futures[i].waitForFinished(); -#else - const QRect tile( 0, 0, image.width(), image.height() ); - qwtToRgba( &image, &alphaImage, tile, d_data->alpha ); -#endif - image = alphaImage; - } - - return image; -} - -/*! - \brief Calculate a scale map for painting to an image - - \param orientation Orientation, Qt::Horizontal means a X axis - \param map Scale map for rendering the plot item - \param area Area to be painted on the image - \param imageSize Image size - \param pixelSize Width/Height of a data pixel - - \return Calculated scale map -*/ -QwtScaleMap QwtPlotRasterItem::imageMap( - Qt::Orientation orientation, - const QwtScaleMap &map, const QRectF &area, - const QSize &imageSize, double pixelSize) const -{ - double p1, p2, s1, s2; - - if ( orientation == Qt::Horizontal ) - { - p1 = 0.0; - p2 = imageSize.width(); - s1 = area.left(); - s2 = area.right(); - } - else - { - p1 = 0.0; - p2 = imageSize.height(); - s1 = area.top(); - s2 = area.bottom(); - } - - if ( pixelSize > 0.0 ) - { - double off = 0.5 * pixelSize; - if ( map.isInverting() ) - off = -off; - - s1 += off; - s2 += off; - } - else - { - p2--; - } - - if ( map.isInverting() && ( s1 < s2 ) ) - qSwap( s1, s2 ); - - QwtScaleMap newMap = map; - newMap.setPaintInterval( p1, p2 ); - newMap.setScaleInterval( s1, s2 ); - - return newMap; -} diff --git a/source/third_party/qwt/qwt_plot_renderer.cpp b/source/third_party/qwt/qwt_plot_renderer.cpp deleted file mode 100644 index ae59625df0150ec0b215a18d7e14deb87889527f..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_renderer.cpp +++ /dev/null @@ -1,1014 +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/qwt_plot_renderer.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_plot_layout.h" -#include "qwt/qwt_abstract_legend.h" -#include "qwt/qwt_scale_widget.h" -#include "qwt/qwt_scale_engine.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_text_label.h" -#include "qwt/qwt_math.h" -#include <qpainter.h> -#include <qpaintengine.h> -#include <qtransform.h> -#include <qfiledialog.h> -#include <qfileinfo.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qimagewriter.h> -#include <QtPrintSupport/qprinter.h> -#include <QtPrintSupport/qprintdialog.h> -#ifndef QWT_NO_SVG -#ifdef QT_SVG_LIB -#include <qsvggenerator.h> -#endif -#endif - -static QPainterPath qwtCanvasClip( - const QWidget* canvas, const QRectF &canvasRect ) -{ - // The clip region is calculated in integers - // To avoid too much rounding errors better - // calculate it in target device resolution - - int x1 = qCeil( canvasRect.left() ); - int x2 = qFloor( canvasRect.right() ); - int y1 = qCeil( canvasRect.top() ); - int y2 = qFloor( canvasRect.bottom() ); - - const QRect r( x1, y1, x2 - x1 - 1, y2 - y1 - 1 ); - - QPainterPath clipPath; - - ( void ) QMetaObject::invokeMethod( - const_cast< QWidget *>( canvas ), "borderPath", - Qt::DirectConnection, - Q_RETURN_ARG( QPainterPath, clipPath ), Q_ARG( QRect, r ) ); - - return clipPath; -} - -class QwtPlotRenderer::PrivateData -{ -public: - PrivateData(): - discardFlags( QwtPlotRenderer::DiscardNone ), - layoutFlags( QwtPlotRenderer::DefaultLayout ) - { - } - - QwtPlotRenderer::DiscardFlags discardFlags; - QwtPlotRenderer::LayoutFlags layoutFlags; -}; - -/*! - Constructor - \param parent Parent object -*/ -QwtPlotRenderer::QwtPlotRenderer( QObject *parent ): - QObject( parent ) -{ - d_data = new PrivateData; -} - -//! Destructor -QwtPlotRenderer::~QwtPlotRenderer() -{ - delete d_data; -} - -/*! - Change a flag, indicating what to discard from rendering - - \param flag Flag to change - \param on On/Off - - \sa DiscardFlag, testDiscardFlag(), setDiscardFlags(), discardFlags() -*/ -void QwtPlotRenderer::setDiscardFlag( DiscardFlag flag, bool on ) -{ - if ( on ) - d_data->discardFlags |= flag; - else - d_data->discardFlags &= ~flag; -} - -/*! - \return True, if flag is enabled. - \param flag Flag to be tested - \sa DiscardFlag, setDiscardFlag(), setDiscardFlags(), discardFlags() -*/ -bool QwtPlotRenderer::testDiscardFlag( DiscardFlag flag ) const -{ - return d_data->discardFlags & flag; -} - -/*! - Set the flags, indicating what to discard from rendering - - \param flags Flags - \sa DiscardFlag, setDiscardFlag(), testDiscardFlag(), discardFlags() -*/ -void QwtPlotRenderer::setDiscardFlags( DiscardFlags flags ) -{ - d_data->discardFlags = flags; -} - -/*! - \return Flags, indicating what to discard from rendering - \sa DiscardFlag, setDiscardFlags(), setDiscardFlag(), testDiscardFlag() -*/ -QwtPlotRenderer::DiscardFlags QwtPlotRenderer::discardFlags() const -{ - return d_data->discardFlags; -} - -/*! - Change a layout flag - - \param flag Flag to change - \param on On/Off - - \sa LayoutFlag, testLayoutFlag(), setLayoutFlags(), layoutFlags() -*/ -void QwtPlotRenderer::setLayoutFlag( LayoutFlag flag, bool on ) -{ - if ( on ) - d_data->layoutFlags |= flag; - else - d_data->layoutFlags &= ~flag; -} - -/*! - \return True, if flag is enabled. - \param flag Flag to be tested - \sa LayoutFlag, setLayoutFlag(), setLayoutFlags(), layoutFlags() -*/ -bool QwtPlotRenderer::testLayoutFlag( LayoutFlag flag ) const -{ - return d_data->layoutFlags & flag; -} - -/*! - Set the layout flags - - \param flags Flags - \sa LayoutFlag, setLayoutFlag(), testLayoutFlag(), layoutFlags() -*/ -void QwtPlotRenderer::setLayoutFlags( LayoutFlags flags ) -{ - d_data->layoutFlags = flags; -} - -/*! - \return Layout flags - \sa LayoutFlag, setLayoutFlags(), setLayoutFlag(), testLayoutFlag() -*/ -QwtPlotRenderer::LayoutFlags QwtPlotRenderer::layoutFlags() const -{ - return d_data->layoutFlags; -} - -/*! - Render a plot to a file - - The format of the document will be auto-detected from the - suffix of the file name. - - \param plot Plot widget - \param fileName Path of the file, where the document will be stored - \param sizeMM Size for the document in millimeters. - \param resolution Resolution in dots per Inch (dpi) -*/ -void QwtPlotRenderer::renderDocument( QwtPlot *plot, - const QString &fileName, const QSizeF &sizeMM, int resolution ) -{ - renderDocument( plot, fileName, - QFileInfo( fileName ).suffix(), sizeMM, resolution ); -} - -/*! - Render a plot to a file - - Supported formats are: - - - pdf\n - Portable Document Format PDF - - ps\n - Postcript - - svg\n - Scalable Vector Graphics SVG - - all image formats supported by Qt\n - see QImageWriter::supportedImageFormats() - - Scalable vector graphic formats like PDF or SVG are superior to - raster graphics formats. - - \param plot Plot widget - \param fileName Path of the file, where the document will be stored - \param format Format for the document - \param sizeMM Size for the document in millimeters. - \param resolution Resolution in dots per Inch (dpi) - - \sa renderTo(), render(), QwtPainter::setRoundingAlignment() -*/ -void QwtPlotRenderer::renderDocument( QwtPlot *plot, - const QString &fileName, const QString &format, - const QSizeF &sizeMM, int resolution ) -{ - if ( plot == NULL || sizeMM.isEmpty() || resolution <= 0 ) - return; - - QString title = plot->title().text(); - if ( title.isEmpty() ) - title = "Plot Document"; - - const double mmToInch = 1.0 / 25.4; - const QSizeF size = sizeMM * mmToInch * resolution; - - const QRectF documentRect( 0.0, 0.0, size.width(), size.height() ); - - const QString fmt = format.toLower(); - if ( fmt == "pdf" ) - { -#ifndef QT_NO_PRINTER - QPrinter printer; - printer.setOutputFormat( QPrinter::PdfFormat ); - printer.setColorMode( QPrinter::Color ); - printer.setFullPage( true ); - printer.setPaperSize( sizeMM, QPrinter::Millimeter ); - printer.setDocName( title ); - printer.setOutputFileName( fileName ); - printer.setResolution( resolution ); - - QPainter painter( &printer ); - render( plot, &painter, documentRect ); -#endif - } - else if ( fmt == "ps" ) - { -#if QT_VERSION < 0x050000 -#ifndef QT_NO_PRINTER - QPrinter printer; - printer.setOutputFormat( QPrinter::PostScriptFormat ); - printer.setColorMode( QPrinter::Color ); - printer.setFullPage( true ); - printer.setPaperSize( sizeMM, QPrinter::Millimeter ); - printer.setDocName( title ); - printer.setOutputFileName( fileName ); - printer.setResolution( resolution ); - - QPainter painter( &printer ); - render( plot, &painter, documentRect ); -#endif -#endif - } - else if ( fmt == "svg" ) - { -#ifndef QWT_NO_SVG -#ifdef QT_SVG_LIB -#if QT_VERSION >= 0x040500 - QSvgGenerator generator; - generator.setTitle( title ); - generator.setFileName( fileName ); - generator.setResolution( resolution ); - generator.setViewBox( documentRect ); - - QPainter painter( &generator ); - render( plot, &painter, documentRect ); -#endif -#endif -#endif - } - else - { - if ( QImageWriter::supportedImageFormats().indexOf( - format.toLatin1() ) >= 0 ) - { - const QRect imageRect = documentRect.toRect(); - const int dotsPerMeter = qRound( resolution * mmToInch * 1000.0 ); - - QImage image( imageRect.size(), QImage::Format_ARGB32 ); - image.setDotsPerMeterX( dotsPerMeter ); - image.setDotsPerMeterY( dotsPerMeter ); - image.fill( QColor( Qt::white ).rgb() ); - - QPainter painter( &image ); - render( plot, &painter, imageRect ); - painter.end(); - - image.save( fileName, format.toLatin1() ); - } - } -} - -/*! - \brief Render the plot to a \c QPaintDevice - - This function renders the contents of a QwtPlot instance to - \c QPaintDevice object. The target rectangle is derived from - its device metrics. - - \param plot Plot to be rendered - \param paintDevice device to paint on, f.e a QImage - - \sa renderDocument(), render(), QwtPainter::setRoundingAlignment() -*/ - -void QwtPlotRenderer::renderTo( - QwtPlot *plot, QPaintDevice &paintDevice ) const -{ - int w = paintDevice.width(); - int h = paintDevice.height(); - - QPainter p( &paintDevice ); - render( plot, &p, QRectF( 0, 0, w, h ) ); -} - -/*! - \brief Render the plot to a QPrinter - - This function renders the contents of a QwtPlot instance to - \c QPaintDevice object. The size is derived from the printer - metrics. - - \param plot Plot to be rendered - \param printer Printer to paint on - - \sa renderDocument(), render(), QwtPainter::setRoundingAlignment() -*/ - -#ifndef QT_NO_PRINTER - -void QwtPlotRenderer::renderTo( - QwtPlot *plot, QPrinter &printer ) const -{ - int w = printer.width(); - int h = printer.height(); - - QRectF rect( 0, 0, w, h ); - double aspect = rect.width() / rect.height(); - if ( ( aspect < 1.0 ) ) - rect.setHeight( aspect * rect.width() ); - - QPainter p( &printer ); - render( plot, &p, rect ); -} - -#endif - -#ifndef QWT_NO_SVG -#ifdef QT_SVG_LIB -#if QT_VERSION >= 0x040500 - -/*! - \brief Render the plot to a QSvgGenerator - - If the generator has a view box, the plot will be rendered into it. - If it has no viewBox but a valid size the target coordinates - will be (0, 0, generator.width(), generator.height()). Otherwise - the target rectangle will be QRectF(0, 0, 800, 600); - - \param plot Plot to be rendered - \param generator SVG generator -*/ -void QwtPlotRenderer::renderTo( - QwtPlot *plot, QSvgGenerator &generator ) const -{ - QRectF rect = generator.viewBoxF(); - if ( rect.isEmpty() ) - rect.setRect( 0, 0, generator.width(), generator.height() ); - - if ( rect.isEmpty() ) - rect.setRect( 0, 0, 800, 600 ); // something - - QPainter p( &generator ); - render( plot, &p, rect ); -} -#endif -#endif -#endif - -/*! - Paint the contents of a QwtPlot instance into a given rectangle. - - \param plot Plot to be rendered - \param painter Painter - \param plotRect Bounding rectangle - - \sa renderDocument(), renderTo(), QwtPainter::setRoundingAlignment() -*/ -void QwtPlotRenderer::render( QwtPlot *plot, - QPainter *painter, const QRectF &plotRect ) const -{ - if ( painter == 0 || !painter->isActive() || - !plotRect.isValid() || plot->size().isNull() ) - { - return; - } - - if ( !( d_data->discardFlags & DiscardBackground ) ) - QwtPainter::drawBackgound( painter, plotRect, plot ); - - /* - The layout engine uses the same methods as they are used - by the Qt layout system. Therefore we need to calculate the - layout in screen coordinates and paint with a scaled painter. - */ - QTransform transform; - transform.scale( - double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(), - double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() ); - - QRectF layoutRect = transform.inverted().mapRect( plotRect ); - - if ( !( d_data->discardFlags & DiscardBackground ) ) - { - // subtract the contents margins - - int left, top, right, bottom; - plot->getContentsMargins( &left, &top, &right, &bottom ); - layoutRect.adjust( left, top, -right, -bottom ); - } - - QwtPlotLayout *layout = plot->plotLayout(); - - int baseLineDists[QwtPlot::axisCnt]; - int canvasMargins[QwtPlot::axisCnt]; - - for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) - { - canvasMargins[ axisId ] = layout->canvasMargin( axisId ); - - if ( d_data->layoutFlags & FrameWithScales ) - { - QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); - if ( scaleWidget ) - { - baseLineDists[axisId] = scaleWidget->margin(); - scaleWidget->setMargin( 0 ); - } - - if ( !plot->axisEnabled( axisId ) ) - { - int left = 0; - int right = 0; - int top = 0; - int bottom = 0; - - // When we have a scale the frame is painted on - // the position of the backbone - otherwise we - // need to introduce a margin around the canvas - - switch( axisId ) - { - case QwtPlot::yLeft: - layoutRect.adjust( 1, 0, 0, 0 ); - break; - case QwtPlot::yRight: - layoutRect.adjust( 0, 0, -1, 0 ); - break; - case QwtPlot::xTop: - layoutRect.adjust( 0, 1, 0, 0 ); - break; - case QwtPlot::xBottom: - layoutRect.adjust( 0, 0, 0, -1 ); - break; - default: - break; - } - layoutRect.adjust( left, top, right, bottom ); - } - } - } - - // Calculate the layout for the document. - - QwtPlotLayout::Options layoutOptions = QwtPlotLayout::IgnoreScrollbars; - - if ( ( d_data->layoutFlags & FrameWithScales ) || - ( d_data->discardFlags & DiscardCanvasFrame ) ) - { - layoutOptions |= QwtPlotLayout::IgnoreFrames; - } - - - if ( d_data->discardFlags & DiscardLegend ) - layoutOptions |= QwtPlotLayout::IgnoreLegend; - - if ( d_data->discardFlags & DiscardTitle ) - layoutOptions |= QwtPlotLayout::IgnoreTitle; - - if ( d_data->discardFlags & DiscardFooter ) - layoutOptions |= QwtPlotLayout::IgnoreFooter; - - layout->activate( plot, layoutRect, layoutOptions ); - - // canvas - - QwtScaleMap maps[QwtPlot::axisCnt]; - buildCanvasMaps( plot, layout->canvasRect(), maps ); - if ( updateCanvasMargins( plot, layout->canvasRect(), maps ) ) - { - // recalculate maps and layout, when the margins - // have been changed - - layout->activate( plot, layoutRect, layoutOptions ); - buildCanvasMaps( plot, layout->canvasRect(), maps ); - } - - // now start painting - - painter->save(); - painter->setWorldTransform( transform, true ); - - renderCanvas( plot, painter, layout->canvasRect(), maps ); - - if ( !( d_data->discardFlags & DiscardTitle ) - && ( !plot->titleLabel()->text().isEmpty() ) ) - { - renderTitle( plot, painter, layout->titleRect() ); - } - - if ( !( d_data->discardFlags & DiscardFooter ) - && ( !plot->footerLabel()->text().isEmpty() ) ) - { - renderFooter( plot, painter, layout->footerRect() ); - } - - if ( !( d_data->discardFlags & DiscardLegend ) - && plot->legend() && !plot->legend()->isEmpty() ) - { - renderLegend( plot, painter, layout->legendRect() ); - } - - for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) - { - QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); - if ( scaleWidget ) - { - int baseDist = scaleWidget->margin(); - - int startDist, endDist; - scaleWidget->getBorderDistHint( startDist, endDist ); - - renderScale( plot, painter, axisId, startDist, endDist, - baseDist, layout->scaleRect( axisId ) ); - } - } - - painter->restore(); - - // restore all setting to their original attributes. - for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) - { - if ( d_data->layoutFlags & FrameWithScales ) - { - QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); - if ( scaleWidget ) - scaleWidget->setMargin( baseLineDists[axisId] ); - } - - layout->setCanvasMargin( canvasMargins[axisId] ); - } - - layout->invalidate(); - -} - -/*! - Render the title into a given rectangle. - - \param plot Plot widget - \param painter Painter - \param rect Bounding rectangle -*/ -void QwtPlotRenderer::renderTitle( const QwtPlot *plot, - QPainter *painter, const QRectF &rect ) const -{ - painter->setFont( plot->titleLabel()->font() ); - - const QColor color = plot->titleLabel()->palette().color( - QPalette::Active, QPalette::Text ); - - painter->setPen( color ); - plot->titleLabel()->text().draw( painter, rect ); -} - -/*! - Render the footer into a given rectangle. - - \param plot Plot widget - \param painter Painter - \param rect Bounding rectangle -*/ -void QwtPlotRenderer::renderFooter( const QwtPlot *plot, - QPainter *painter, const QRectF &rect ) const -{ - painter->setFont( plot->footerLabel()->font() ); - - const QColor color = plot->footerLabel()->palette().color( - QPalette::Active, QPalette::Text ); - - painter->setPen( color ); - plot->footerLabel()->text().draw( painter, rect ); -} - - -/*! - Render the legend into a given rectangle. - - \param plot Plot widget - \param painter Painter - \param rect Bounding rectangle -*/ -void QwtPlotRenderer::renderLegend( const QwtPlot *plot, - QPainter *painter, const QRectF &rect ) const -{ - if ( plot->legend() ) - { - bool fillBackground = !( d_data->discardFlags & DiscardBackground ); - plot->legend()->renderLegend( painter, rect, fillBackground ); - } -} - -/*! - \brief Paint a scale into a given rectangle. - Paint the scale into a given rectangle. - - \param plot Plot widget - \param painter Painter - \param axisId Axis - \param startDist Start border distance - \param endDist End border distance - \param baseDist Base distance - \param rect Bounding rectangle -*/ -void QwtPlotRenderer::renderScale( const QwtPlot *plot, - QPainter *painter, - int axisId, int startDist, int endDist, int baseDist, - const QRectF &rect ) const -{ - if ( !plot->axisEnabled( axisId ) ) - return; - - const QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); - if ( scaleWidget->isColorBarEnabled() - && scaleWidget->colorBarWidth() > 0 ) - { - scaleWidget->drawColorBar( painter, scaleWidget->colorBarRect( rect ) ); - baseDist += scaleWidget->colorBarWidth() + scaleWidget->spacing(); - } - - painter->save(); - - QwtScaleDraw::Alignment align; - double x, y, w; - - switch ( axisId ) - { - case QwtPlot::yLeft: - { - x = rect.right() - 1.0 - baseDist; - y = rect.y() + startDist; - w = rect.height() - startDist - endDist; - align = QwtScaleDraw::LeftScale; - break; - } - case QwtPlot::yRight: - { - x = rect.left() + baseDist; - y = rect.y() + startDist; - w = rect.height() - startDist - endDist; - align = QwtScaleDraw::RightScale; - break; - } - case QwtPlot::xTop: - { - x = rect.left() + startDist; - y = rect.bottom() - 1.0 - baseDist; - w = rect.width() - startDist - endDist; - align = QwtScaleDraw::TopScale; - break; - } - case QwtPlot::xBottom: - { - x = rect.left() + startDist; - y = rect.top() + baseDist; - w = rect.width() - startDist - endDist; - align = QwtScaleDraw::BottomScale; - break; - } - default: - return; - } - - scaleWidget->drawTitle( painter, align, rect ); - - painter->setFont( scaleWidget->font() ); - - QwtScaleDraw *sd = const_cast<QwtScaleDraw *>( scaleWidget->scaleDraw() ); - const QPointF sdPos = sd->pos(); - const double sdLength = sd->length(); - - sd->move( x, y ); - sd->setLength( w ); - - QPalette palette = scaleWidget->palette(); - palette.setCurrentColorGroup( QPalette::Active ); - sd->draw( painter, palette ); - - // reset previous values - sd->move( sdPos ); - sd->setLength( sdLength ); - - painter->restore(); -} - -/*! - Render the canvas into a given rectangle. - - \param plot Plot widget - \param painter Painter - \param map Maps mapping between plot and paint device coordinates - \param canvasRect Canvas rectangle -*/ -void QwtPlotRenderer::renderCanvas( const QwtPlot *plot, - QPainter *painter, const QRectF &canvasRect, - const QwtScaleMap *map ) const -{ - const QWidget *canvas = plot->canvas(); - - QRectF r = canvasRect.adjusted( 0.0, 0.0, -1.0, -1.0 ); - - if ( d_data->layoutFlags & FrameWithScales ) - { - painter->save(); - - r.adjust( -1.0, -1.0, 1.0, 1.0 ); - painter->setPen( QPen( Qt::black ) ); - - if ( !( d_data->discardFlags & DiscardCanvasBackground ) ) - { - const QBrush bgBrush = - canvas->palette().brush( plot->backgroundRole() ); - painter->setBrush( bgBrush ); - } - - QwtPainter::drawRect( painter, r ); - - painter->restore(); - painter->save(); - - painter->setClipRect( canvasRect ); - plot->drawItems( painter, canvasRect, map ); - - painter->restore(); - } - else if ( canvas->testAttribute( Qt::WA_StyledBackground ) ) - { - QPainterPath clipPath; - - painter->save(); - - if ( !( d_data->discardFlags & DiscardCanvasBackground ) ) - { - QwtPainter::drawBackgound( painter, r, canvas ); - clipPath = qwtCanvasClip( canvas, canvasRect ); - } - - painter->restore(); - painter->save(); - - if ( clipPath.isEmpty() ) - painter->setClipRect( canvasRect ); - else - painter->setClipPath( clipPath ); - - plot->drawItems( painter, canvasRect, map ); - - painter->restore(); - } - else - { - QPainterPath clipPath; - - int frameWidth = 0; - - if ( !( d_data->discardFlags & DiscardCanvasFrame ) ) - { - const QVariant fw = canvas->property( "frameWidth" ); - if ( fw.type() == QVariant::Int ) - frameWidth = fw.toInt(); - - clipPath = qwtCanvasClip( canvas, canvasRect ); - } - - QRectF innerRect = canvasRect.adjusted( - frameWidth, frameWidth, -frameWidth, -frameWidth ); - - painter->save(); - - if ( clipPath.isEmpty() ) - { - painter->setClipRect( innerRect ); - } - else - { - painter->setClipPath( clipPath ); - } - - if ( !( d_data->discardFlags & DiscardCanvasBackground ) ) - { - QwtPainter::drawBackgound( painter, innerRect, canvas ); - } - - plot->drawItems( painter, innerRect, map ); - - painter->restore(); - - if ( frameWidth > 0 ) - { - painter->save(); - - const int frameStyle = - canvas->property( "frameShadow" ).toInt() | - canvas->property( "frameShape" ).toInt(); - - const int frameWidth = canvas->property( "frameWidth" ).toInt(); - - - const QVariant borderRadius = canvas->property( "borderRadius" ); - if ( borderRadius.type() == QVariant::Double - && borderRadius.toDouble() > 0.0 ) - { - const double r = borderRadius.toDouble(); - - QwtPainter::drawRoundedFrame( painter, canvasRect, - r, r, canvas->palette(), frameWidth, frameStyle ); - } - else - { - const int midLineWidth = canvas->property( "midLineWidth" ).toInt(); - - QwtPainter::drawFrame( painter, canvasRect, - canvas->palette(), canvas->foregroundRole(), - frameWidth, midLineWidth, frameStyle ); - } - painter->restore(); - } - } -} - -/*! - Calculated the scale maps for rendering the canvas - - \param plot Plot widget - \param canvasRect Target rectangle - \param maps Scale maps to be calculated -*/ -void QwtPlotRenderer::buildCanvasMaps( const QwtPlot *plot, - const QRectF &canvasRect, QwtScaleMap maps[] ) const -{ - for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) - { - maps[axisId].setTransformation( - plot->axisScaleEngine( axisId )->transformation() ); - - const QwtScaleDiv &scaleDiv = plot->axisScaleDiv( axisId ); - maps[axisId].setScaleInterval( - scaleDiv.lowerBound(), scaleDiv.upperBound() ); - - double from, to; - if ( plot->axisEnabled( axisId ) ) - { - const int sDist = plot->axisWidget( axisId )->startBorderDist(); - const int eDist = plot->axisWidget( axisId )->endBorderDist(); - const QRectF scaleRect = plot->plotLayout()->scaleRect( axisId ); - - if ( axisId == QwtPlot::xTop || axisId == QwtPlot::xBottom ) - { - from = scaleRect.left() + sDist; - to = scaleRect.right() - eDist; - } - else - { - from = scaleRect.bottom() - eDist; - to = scaleRect.top() + sDist; - } - } - else - { - int margin = 0; - if ( !plot->plotLayout()->alignCanvasToScale( axisId ) ) - margin = plot->plotLayout()->canvasMargin( axisId ); - - if ( axisId == QwtPlot::yLeft || axisId == QwtPlot::yRight ) - { - from = canvasRect.bottom() - margin; - to = canvasRect.top() + margin; - } - else - { - from = canvasRect.left() + margin; - to = canvasRect.right() - margin; - } - } - maps[axisId].setPaintInterval( from, to ); - } -} - -bool QwtPlotRenderer::updateCanvasMargins( QwtPlot *plot, - const QRectF &canvasRect, const QwtScaleMap maps[] ) const -{ - double margins[QwtPlot::axisCnt]; - plot->getCanvasMarginsHint( maps, canvasRect, - margins[QwtPlot::yLeft], margins[QwtPlot::xTop], - margins[QwtPlot::yRight], margins[QwtPlot::xBottom] ); - - bool marginsChanged = false; - for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) - { - if ( margins[axisId] >= 0.0 ) - { - const int m = qCeil( margins[axisId] ); - plot->plotLayout()->setCanvasMargin( m, axisId); - marginsChanged = true; - } - } - - return marginsChanged; -} - -/*! - \brief Execute a file dialog and render the plot to the selected file - - \param plot Plot widget - \param documentName Default document name - \param sizeMM Size for the document in millimeters. - \param resolution Resolution in dots per Inch (dpi) - - \return True, when exporting was successful - \sa renderDocument() -*/ -bool QwtPlotRenderer::exportTo( QwtPlot *plot, const QString &documentName, - const QSizeF &sizeMM, int resolution ) -{ - if ( plot == NULL ) - return false; - - QString fileName = documentName; - - // What about translation - -#ifndef QT_NO_FILEDIALOG - const QList<QByteArray> imageFormats = - QImageWriter::supportedImageFormats(); - - QStringList filter; -#ifndef QT_NO_PRINTER - filter += QString( "PDF " ) + tr( "Documents" ) + " (*.pdf)"; -#endif -#ifndef QWT_NO_SVG - filter += QString( "SVG " ) + tr( "Documents" ) + " (*.svg)"; -#endif -#ifndef QT_NO_PRINTER - filter += QString( "Postscript " ) + tr( "Documents" ) + " (*.ps)"; -#endif - - if ( imageFormats.size() > 0 ) - { - QString imageFilter( tr( "Images" ) ); - imageFilter += " ("; - for ( int i = 0; i < imageFormats.size(); i++ ) - { - if ( i > 0 ) - imageFilter += " "; - imageFilter += "*."; - imageFilter += imageFormats[i]; - } - imageFilter += ")"; - - filter += imageFilter; - } - - fileName = QFileDialog::getSaveFileName( - NULL, tr( "Export File Name" ), fileName, - filter.join( ";;" ), NULL, QFileDialog::DontConfirmOverwrite ); -#endif - if ( fileName.isEmpty() ) - return false; - - renderDocument( plot, fileName, sizeMM, resolution ); - - return true; -} diff --git a/source/third_party/qwt/qwt_plot_rescaler.cpp b/source/third_party/qwt/qwt_plot_rescaler.cpp deleted file mode 100644 index d0d7ff15ab56cac690a8b8c4e8ab4e9934d4ccf6..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_rescaler.cpp +++ /dev/null @@ -1,631 +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/qwt_plot_rescaler.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_interval.h" -#include "qwt/qwt_plot_canvas.h" -#include <qevent.h> -#include <qalgorithms.h> - -class QwtPlotRescaler::AxisData -{ -public: - AxisData(): - aspectRatio( 1.0 ), - expandingDirection( QwtPlotRescaler::ExpandUp ) - { - } - - double aspectRatio; - QwtInterval intervalHint; - QwtPlotRescaler::ExpandingDirection expandingDirection; - mutable QwtScaleDiv scaleDiv; -}; - -class QwtPlotRescaler::PrivateData -{ -public: - PrivateData(): - referenceAxis( QwtPlot::xBottom ), - rescalePolicy( QwtPlotRescaler::Expanding ), - isEnabled( false ), - inReplot( 0 ) - { - } - - int referenceAxis; - RescalePolicy rescalePolicy; - QwtPlotRescaler::AxisData axisData[QwtPlot::axisCnt]; - bool isEnabled; - - mutable int inReplot; -}; - -/*! - Constructor - - \param canvas Canvas - \param referenceAxis Reference axis, see RescalePolicy - \param policy Rescale policy - - \sa setRescalePolicy(), setReferenceAxis() -*/ -QwtPlotRescaler::QwtPlotRescaler( QWidget *canvas, - int referenceAxis, RescalePolicy policy ): - QObject( canvas ) -{ - d_data = new PrivateData; - d_data->referenceAxis = referenceAxis; - d_data->rescalePolicy = policy; - - setEnabled( true ); -} - -//! Destructor -QwtPlotRescaler::~QwtPlotRescaler() -{ - delete d_data; -} - -/*! - \brief En/disable the rescaler - - When enabled is true an event filter is installed for - the canvas, otherwise the event filter is removed. - - \param on true or false - \sa isEnabled(), eventFilter() -*/ -void QwtPlotRescaler::setEnabled( bool on ) -{ - if ( d_data->isEnabled != on ) - { - d_data->isEnabled = on; - - QWidget *w = canvas(); - if ( w ) - { - if ( d_data->isEnabled ) - w->installEventFilter( this ); - else - w->removeEventFilter( this ); - } - } -} - -/*! - \return true when enabled, false otherwise - \sa setEnabled, eventFilter() -*/ -bool QwtPlotRescaler::isEnabled() const -{ - return d_data->isEnabled; -} - -/*! - Change the rescale policy - - \param policy Rescale policy - \sa rescalePolicy() -*/ -void QwtPlotRescaler::setRescalePolicy( RescalePolicy policy ) -{ - d_data->rescalePolicy = policy; -} - -/*! - \return Rescale policy - \sa setRescalePolicy() -*/ -QwtPlotRescaler::RescalePolicy QwtPlotRescaler::rescalePolicy() const -{ - return d_data->rescalePolicy; -} - -/*! - Set the reference axis ( see RescalePolicy ) - - \param axis Axis index ( QwtPlot::Axis ) - \sa referenceAxis() -*/ -void QwtPlotRescaler::setReferenceAxis( int axis ) -{ - d_data->referenceAxis = axis; -} - -/*! - \return Reference axis ( see RescalePolicy ) - \sa setReferenceAxis() -*/ -int QwtPlotRescaler::referenceAxis() const -{ - return d_data->referenceAxis; -} - -/*! - Set the direction in which all axis should be expanded - - \param direction Direction - \sa expandingDirection() -*/ -void QwtPlotRescaler::setExpandingDirection( - ExpandingDirection direction ) -{ - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - setExpandingDirection( axis, direction ); -} - -/*! - Set the direction in which an axis should be expanded - - \param axis Axis index ( see QwtPlot::AxisId ) - \param direction Direction - \sa expandingDirection() -*/ -void QwtPlotRescaler::setExpandingDirection( - int axis, ExpandingDirection direction ) -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->axisData[axis].expandingDirection = direction; -} - -/*! - \return Direction in which an axis should be expanded - - \param axis Axis index ( see QwtPlot::AxisId ) - \sa setExpandingDirection() -*/ -QwtPlotRescaler::ExpandingDirection -QwtPlotRescaler::expandingDirection( int axis ) const -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - return d_data->axisData[axis].expandingDirection; - - return ExpandBoth; -} - -/*! - Set the aspect ratio between the scale of the reference axis - and the other scales. The default ratio is 1.0 - - \param ratio Aspect ratio - \sa aspectRatio() -*/ -void QwtPlotRescaler::setAspectRatio( double ratio ) -{ - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - setAspectRatio( axis, ratio ); -} - -/*! - Set the aspect ratio between the scale of the reference axis - and another scale. The default ratio is 1.0 - - \param axis Axis index ( see QwtPlot::AxisId ) - \param ratio Aspect ratio - \sa aspectRatio() -*/ -void QwtPlotRescaler::setAspectRatio( int axis, double ratio ) -{ - if ( ratio < 0.0 ) - ratio = 0.0; - - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->axisData[axis].aspectRatio = ratio; -} - -/*! - \return Aspect ratio between an axis and the reference axis. - - \param axis Axis index ( see QwtPlot::AxisId ) - \sa setAspectRatio() -*/ -double QwtPlotRescaler::aspectRatio( int axis ) const -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - return d_data->axisData[axis].aspectRatio; - - return 0.0; -} - -/*! - Set an interval hint for an axis - - In Fitting mode, the hint is used as minimal interval - that always needs to be displayed. - - \param axis Axis, see QwtPlot::Axis - \param interval Axis - \sa intervalHint(), RescalePolicy -*/ -void QwtPlotRescaler::setIntervalHint( int axis, - const QwtInterval &interval ) -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - d_data->axisData[axis].intervalHint = interval; -} - -/*! - \param axis Axis, see QwtPlot::Axis - \return Interval hint - \sa setIntervalHint(), RescalePolicy -*/ -QwtInterval QwtPlotRescaler::intervalHint( int axis ) const -{ - if ( axis >= 0 && axis < QwtPlot::axisCnt ) - return d_data->axisData[axis].intervalHint; - - return QwtInterval(); -} - -//! \return plot canvas -QWidget *QwtPlotRescaler::canvas() -{ - return qobject_cast<QWidget *>( parent() ); -} - -//! \return plot canvas -const QWidget *QwtPlotRescaler::canvas() const -{ - return qobject_cast<const QWidget *>( parent() ); -} - -//! \return plot widget -QwtPlot *QwtPlotRescaler::plot() -{ - QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<QwtPlot *>( w ); -} - -//! \return plot widget -const QwtPlot *QwtPlotRescaler::plot() const -{ - const QWidget *w = canvas(); - if ( w ) - w = w->parentWidget(); - - return qobject_cast<const QwtPlot *>( w ); -} - -//! Event filter for the plot canvas -bool QwtPlotRescaler::eventFilter( QObject *object, QEvent *event ) -{ - if ( object && object == canvas() ) - { - switch ( event->type() ) - { - case QEvent::Resize: - { - canvasResizeEvent( static_cast<QResizeEvent *>( event ) ); - break; - } - case QEvent::PolishRequest: - { - rescale(); - break; - } - default:; - } - } - - return false; -} - -/*! - Event handler for resize events of the plot canvas - - \param event Resize event - \sa rescale() -*/ -void QwtPlotRescaler::canvasResizeEvent( QResizeEvent* event ) -{ - int left, top, right, bottom; - canvas()->getContentsMargins( &left, &top, &right, &bottom ); - - const QSize marginSize( left + right, top + bottom ); - - const QSize newSize = event->size() - marginSize; - const QSize oldSize = event->oldSize() - marginSize; - - rescale( oldSize, newSize ); -} - -//! Adjust the plot axes scales -void QwtPlotRescaler::rescale() const -{ - const QSize size = canvas()->contentsRect().size(); - rescale( size, size ); -} - -/*! - Adjust the plot axes scales - - \param oldSize Previous size of the canvas - \param newSize New size of the canvas -*/ -void QwtPlotRescaler::rescale( - const QSize &oldSize, const QSize &newSize ) const -{ - if ( newSize.isEmpty() ) - return; - - QwtInterval intervals[QwtPlot::axisCnt]; - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - intervals[axis] = interval( axis ); - - const int refAxis = referenceAxis(); - intervals[refAxis] = expandScale( refAxis, oldSize, newSize ); - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - if ( aspectRatio( axis ) > 0.0 && axis != refAxis ) - intervals[axis] = syncScale( axis, intervals[refAxis], newSize ); - } - - updateScales( intervals ); -} - -/*! - Calculate the new scale interval of a plot axis - - \param axis Axis index ( see QwtPlot::AxisId ) - \param oldSize Previous size of the canvas - \param newSize New size of the canvas - - \return Calculated new interval for the axis -*/ -QwtInterval QwtPlotRescaler::expandScale( int axis, - const QSize &oldSize, const QSize &newSize ) const -{ - const QwtInterval oldInterval = interval( axis ); - - QwtInterval expanded = oldInterval; - switch ( rescalePolicy() ) - { - case Fixed: - { - break; // do nothing - } - case Expanding: - { - if ( !oldSize.isEmpty() ) - { - double width = oldInterval.width(); - if ( orientation( axis ) == Qt::Horizontal ) - width *= double( newSize.width() ) / oldSize.width(); - else - width *= double( newSize.height() ) / oldSize.height(); - - expanded = expandInterval( oldInterval, - width, expandingDirection( axis ) ); - } - break; - } - case Fitting: - { - double dist = 0.0; - for ( int ax = 0; ax < QwtPlot::axisCnt; ax++ ) - { - const double d = pixelDist( ax, newSize ); - if ( d > dist ) - dist = d; - } - if ( dist > 0.0 ) - { - double width; - if ( orientation( axis ) == Qt::Horizontal ) - width = newSize.width() * dist; - else - width = newSize.height() * dist; - - expanded = expandInterval( intervalHint( axis ), - width, expandingDirection( axis ) ); - } - break; - } - } - - return expanded; -} - -/*! - Synchronize an axis scale according to the scale of the reference axis - - \param axis Axis index ( see QwtPlot::AxisId ) - \param reference Interval of the reference axis - \param size Size of the canvas - - \return New interval for axis -*/ -QwtInterval QwtPlotRescaler::syncScale( int axis, - const QwtInterval& reference, const QSize &size ) const -{ - double dist; - if ( orientation( referenceAxis() ) == Qt::Horizontal ) - dist = reference.width() / size.width(); - else - dist = reference.width() / size.height(); - - if ( orientation( axis ) == Qt::Horizontal ) - dist *= size.width(); - else - dist *= size.height(); - - dist /= aspectRatio( axis ); - - QwtInterval intv; - if ( rescalePolicy() == Fitting ) - intv = intervalHint( axis ); - else - intv = interval( axis ); - - intv = expandInterval( intv, dist, expandingDirection( axis ) ); - - return intv; -} - -/*! - \return Orientation of an axis - \param axis Axis index ( see QwtPlot::AxisId ) -*/ -Qt::Orientation QwtPlotRescaler::orientation( int axis ) const -{ - if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight ) - return Qt::Vertical; - - return Qt::Horizontal; -} - -/*! - \param axis Axis index ( see QwtPlot::AxisId ) - \return Normalized interval of an axis -*/ -QwtInterval QwtPlotRescaler::interval( int axis ) const -{ - if ( axis < 0 || axis >= QwtPlot::axisCnt ) - return QwtInterval(); - - return plot()->axisScaleDiv( axis ).interval().normalized(); -} - -/*! - Expand the interval - - \param interval Interval to be expanded - \param width Distance to be added to the interval - \param direction Direction of the expand operation - - \return Expanded interval -*/ -QwtInterval QwtPlotRescaler::expandInterval( - const QwtInterval &interval, double width, - ExpandingDirection direction ) const -{ - QwtInterval expanded = interval; - - switch ( direction ) - { - case ExpandUp: - expanded.setMinValue( interval.minValue() ); - expanded.setMaxValue( interval.minValue() + width ); - break; - - case ExpandDown: - expanded.setMaxValue( interval.maxValue() ); - expanded.setMinValue( interval.maxValue() - width ); - break; - - case ExpandBoth: - default: - expanded.setMinValue( interval.minValue() + - interval.width() / 2.0 - width / 2.0 ); - expanded.setMaxValue( expanded.minValue() + width ); - } - return expanded; -} - -double QwtPlotRescaler::pixelDist( int axis, const QSize &size ) const -{ - const QwtInterval intv = intervalHint( axis ); - - double dist = 0.0; - if ( !intv.isNull() ) - { - if ( axis == referenceAxis() ) - dist = intv.width(); - else - { - const double r = aspectRatio( axis ); - if ( r > 0.0 ) - dist = intv.width() * r; - } - } - - if ( dist > 0.0 ) - { - if ( orientation( axis ) == Qt::Horizontal ) - dist /= size.width(); - else - dist /= size.height(); - } - - return dist; -} - -/*! - Update the axes scales - - \param intervals Scale intervals -*/ -void QwtPlotRescaler::updateScales( - QwtInterval intervals[QwtPlot::axisCnt] ) const -{ - if ( d_data->inReplot >= 5 ) - { - return; - } - - QwtPlot *plt = const_cast<QwtPlot *>( plot() ); - - const bool doReplot = plt->autoReplot(); - plt->setAutoReplot( false ); - - for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) - { - if ( axis == referenceAxis() || aspectRatio( axis ) > 0.0 ) - { - double v1 = intervals[axis].minValue(); - double v2 = intervals[axis].maxValue(); - - if ( !plt->axisScaleDiv( axis ).isIncreasing() ) - qSwap( v1, v2 ); - - if ( d_data->inReplot >= 1 ) - d_data->axisData[axis].scaleDiv = plt->axisScaleDiv( axis ); - - if ( d_data->inReplot >= 2 ) - { - QList<double> ticks[QwtScaleDiv::NTickTypes]; - for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) - ticks[i] = d_data->axisData[axis].scaleDiv.ticks( i ); - - plt->setAxisScaleDiv( axis, QwtScaleDiv( v1, v2, ticks ) ); - } - else - { - plt->setAxisScale( axis, v1, v2 ); - } - } - } - - QwtPlotCanvas *canvas = qobject_cast<QwtPlotCanvas *>( plt->canvas() ); - - bool immediatePaint = false; - if ( canvas ) - { - immediatePaint = canvas->testPaintAttribute( QwtPlotCanvas::ImmediatePaint ); - canvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false ); - } - - plt->setAutoReplot( doReplot ); - - d_data->inReplot++; - plt->replot(); - d_data->inReplot--; - - if ( canvas && immediatePaint ) - { - canvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, true ); - } -} diff --git a/source/third_party/qwt/qwt_plot_scaleitem.cpp b/source/third_party/qwt/qwt_plot_scaleitem.cpp deleted file mode 100644 index 3c691887121c6732b25e2ea0ed847e690bd921c7..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_scaleitem.cpp +++ /dev/null @@ -1,478 +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/qwt_plot_scaleitem.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_interval.h" -#include <qpalette.h> -#include <qpainter.h> - -class QwtPlotScaleItem::PrivateData -{ -public: - PrivateData(): - position( 0.0 ), - borderDistance( -1 ), - scaleDivFromAxis( true ), - scaleDraw( new QwtScaleDraw() ) - { - } - - ~PrivateData() - { - delete scaleDraw; - } - - QwtInterval scaleInterval( const QRectF &, - const QwtScaleMap &, const QwtScaleMap & ) const; - - QPalette palette; - QFont font; - double position; - int borderDistance; - bool scaleDivFromAxis; - QwtScaleDraw *scaleDraw; -}; - -QwtInterval QwtPlotScaleItem::PrivateData::scaleInterval( const QRectF &canvasRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap ) const -{ - QwtInterval interval; - if ( scaleDraw->orientation() == Qt::Horizontal ) - { - interval.setMinValue( xMap.invTransform( canvasRect.left() ) ); - interval.setMaxValue( xMap.invTransform( canvasRect.right() - 1 ) ); - } - else - { - interval.setMinValue( yMap.invTransform( canvasRect.bottom() - 1 ) ); - interval.setMaxValue( yMap.invTransform( canvasRect.top() ) ); - } - - return interval; -} - -/*! - \brief Constructor for scale item at the position pos. - - \param alignment In case of QwtScaleDraw::BottomScale or QwtScaleDraw::TopScale - the scale item is corresponding to the xAxis(), - otherwise it corresponds to the yAxis(). - - \param pos x or y position, depending on the corresponding axis. - - \sa setPosition(), setAlignment() -*/ -QwtPlotScaleItem::QwtPlotScaleItem( - QwtScaleDraw::Alignment alignment, const double pos ): - QwtPlotItem( QwtText( "Scale" ) ) -{ - d_data = new PrivateData; - d_data->position = pos; - d_data->scaleDraw->setAlignment( alignment ); - - setItemInterest( QwtPlotItem::ScaleInterest, true ); - setZ( 11.0 ); -} - -//! Destructor -QwtPlotScaleItem::~QwtPlotScaleItem() -{ - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotScale -int QwtPlotScaleItem::rtti() const -{ - return QwtPlotItem::Rtti_PlotScale; -} - -/*! - \brief Assign a scale division - - When assigning a scaleDiv the scale division won't be synchronized - with the corresponding axis anymore. - - \param scaleDiv Scale division - \sa scaleDiv(), setScaleDivFromAxis(), isScaleDivFromAxis() -*/ -void QwtPlotScaleItem::setScaleDiv( const QwtScaleDiv& scaleDiv ) -{ - d_data->scaleDivFromAxis = false; - d_data->scaleDraw->setScaleDiv( scaleDiv ); -} - -//! \return Scale division -const QwtScaleDiv& QwtPlotScaleItem::scaleDiv() const -{ - return d_data->scaleDraw->scaleDiv(); -} - -/*! - Enable/Disable the synchronization of the scale division with - the corresponding axis. - - \param on true/false - \sa isScaleDivFromAxis() -*/ -void QwtPlotScaleItem::setScaleDivFromAxis( bool on ) -{ - if ( on != d_data->scaleDivFromAxis ) - { - d_data->scaleDivFromAxis = on; - if ( on ) - { - const QwtPlot *plt = plot(); - if ( plt ) - { - updateScaleDiv( plt->axisScaleDiv( xAxis() ), - plt->axisScaleDiv( yAxis() ) ); - itemChanged(); - } - } - } -} - -/*! - \return True, if the synchronization of the scale division with - the corresponding axis is enabled. - \sa setScaleDiv(), setScaleDivFromAxis() -*/ -bool QwtPlotScaleItem::isScaleDivFromAxis() const -{ - return d_data->scaleDivFromAxis; -} - -/*! - Set the palette - \sa QwtAbstractScaleDraw::draw(), palette() -*/ -void QwtPlotScaleItem::setPalette( const QPalette &palette ) -{ - if ( palette != d_data->palette ) - { - d_data->palette = palette; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return palette - \sa setPalette() -*/ -QPalette QwtPlotScaleItem::palette() const -{ - return d_data->palette; -} - -/*! - Change the tick label font - \sa font() -*/ -void QwtPlotScaleItem::setFont( const QFont &font ) -{ - if ( font != d_data->font ) - { - d_data->font = font; - itemChanged(); - } -} - -/*! - \return tick label font - \sa setFont() -*/ -QFont QwtPlotScaleItem::font() const -{ - return d_data->font; -} - -/*! - \brief Set a scale draw - - \param scaleDraw object responsible for drawing scales. - - The main use case for replacing the default QwtScaleDraw is - to overload QwtAbstractScaleDraw::label, to replace or swallow - tick labels. - - \sa scaleDraw() -*/ -void QwtPlotScaleItem::setScaleDraw( QwtScaleDraw *scaleDraw ) -{ - if ( scaleDraw == NULL ) - return; - - if ( scaleDraw != d_data->scaleDraw ) - delete d_data->scaleDraw; - - d_data->scaleDraw = scaleDraw; - - const QwtPlot *plt = plot(); - if ( plt ) - { - updateScaleDiv( plt->axisScaleDiv( xAxis() ), - plt->axisScaleDiv( yAxis() ) ); - } - - itemChanged(); -} - -/*! - \return Scale draw - \sa setScaleDraw() -*/ -const QwtScaleDraw *QwtPlotScaleItem::scaleDraw() const -{ - return d_data->scaleDraw; -} - -/*! - \return Scale draw - \sa setScaleDraw() -*/ -QwtScaleDraw *QwtPlotScaleItem::scaleDraw() -{ - return d_data->scaleDraw; -} - -/*! - Change the position of the scale - - The position is interpreted as y value for horizontal axes - and as x value for vertical axes. - - The border distance is set to -1. - - \param pos New position - \sa position(), setAlignment() -*/ -void QwtPlotScaleItem::setPosition( double pos ) -{ - if ( d_data->position != pos ) - { - d_data->position = pos; - d_data->borderDistance = -1; - itemChanged(); - } -} - -/*! - \return Position of the scale - \sa setPosition(), setAlignment() -*/ -double QwtPlotScaleItem::position() const -{ - return d_data->position; -} - -/*! - \brief Align the scale to the canvas - - If distance is >= 0 the scale will be aligned to a - border of the contents rectangle of the canvas. If - alignment() is QwtScaleDraw::LeftScale, the scale will - be aligned to the right border, if it is QwtScaleDraw::TopScale - it will be aligned to the bottom (and vice versa), - - If distance is < 0 the scale will be at the position(). - - \param distance Number of pixels between the canvas border and the - backbone of the scale. - - \sa setPosition(), borderDistance() -*/ -void QwtPlotScaleItem::setBorderDistance( int distance ) -{ - if ( distance < 0 ) - distance = -1; - - if ( distance != d_data->borderDistance ) - { - d_data->borderDistance = distance; - itemChanged(); - } -} - -/*! - \return Distance from a canvas border - \sa setBorderDistance(), setPosition() -*/ -int QwtPlotScaleItem::borderDistance() const -{ - return d_data->borderDistance; -} - -/*! - Change the alignment of the scale - - The alignment sets the orientation of the scale and the position of - the ticks: - - - QwtScaleDraw::BottomScale: horizontal, ticks below - - QwtScaleDraw::TopScale: horizontal, ticks above - - QwtScaleDraw::LeftScale: vertical, ticks left - - QwtScaleDraw::RightScale: vertical, ticks right - - For horizontal scales the position corresponds to QwtPlotItem::yAxis(), - otherwise to QwtPlotItem::xAxis(). - - \sa scaleDraw(), QwtScaleDraw::alignment(), setPosition() -*/ -void QwtPlotScaleItem::setAlignment( QwtScaleDraw::Alignment alignment ) -{ - QwtScaleDraw *sd = d_data->scaleDraw; - if ( sd->alignment() != alignment ) - { - sd->setAlignment( alignment ); - itemChanged(); - } -} - -/*! - \brief Draw the scale -*/ -void QwtPlotScaleItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - QwtScaleDraw *sd = d_data->scaleDraw; - - if ( d_data->scaleDivFromAxis ) - { - const QwtInterval interval = - d_data->scaleInterval( canvasRect, xMap, yMap ); - - if ( interval != sd->scaleDiv().interval() ) - { - QwtScaleDiv scaleDiv = sd->scaleDiv(); - scaleDiv.setInterval( interval ); - sd->setScaleDiv( scaleDiv ); - } - } - - QPen pen = painter->pen(); - pen.setStyle( Qt::SolidLine ); - painter->setPen( pen ); - - if ( sd->orientation() == Qt::Horizontal ) - { - double y; - if ( d_data->borderDistance >= 0 ) - { - if ( sd->alignment() == QwtScaleDraw::BottomScale ) - y = canvasRect.top() + d_data->borderDistance; - else - { - y = canvasRect.bottom() - d_data->borderDistance; - } - - } - else - { - y = yMap.transform( d_data->position ); - } - - if ( y < canvasRect.top() || y > canvasRect.bottom() ) - return; - - sd->move( canvasRect.left(), y ); - sd->setLength( canvasRect.width() - 1 ); - - QwtTransform *transform = NULL; - if ( xMap.transformation() ) - transform = xMap.transformation()->copy(); - - sd->setTransformation( transform ); - } - else // == Qt::Vertical - { - double x; - if ( d_data->borderDistance >= 0 ) - { - if ( sd->alignment() == QwtScaleDraw::RightScale ) - x = canvasRect.left() + d_data->borderDistance; - else - { - x = canvasRect.right() - d_data->borderDistance; - } - } - else - { - x = xMap.transform( d_data->position ); - } - if ( x < canvasRect.left() || x > canvasRect.right() ) - return; - - sd->move( x, canvasRect.top() ); - sd->setLength( canvasRect.height() - 1 ); - - QwtTransform *transform = NULL; - if ( yMap.transformation() ) - transform = yMap.transformation()->copy(); - - sd->setTransformation( transform ); - } - - painter->setFont( d_data->font ); - - sd->draw( painter, d_data->palette ); -} - -/*! - \brief Update the item to changes of the axes scale division - - In case of isScaleDivFromAxis(), the scale draw is synchronized - to the correspond axis. - - \param xScaleDiv Scale division of the x-axis - \param yScaleDiv Scale division of the y-axis - - \sa QwtPlot::updateAxes() -*/ - -void QwtPlotScaleItem::updateScaleDiv( const QwtScaleDiv& xScaleDiv, - const QwtScaleDiv& yScaleDiv ) -{ - QwtScaleDraw *scaleDraw = d_data->scaleDraw; - - if ( d_data->scaleDivFromAxis && scaleDraw ) - { - const QwtScaleDiv &scaleDiv = - scaleDraw->orientation() == Qt::Horizontal ? xScaleDiv : yScaleDiv; - - const QwtPlot *plt = plot(); - if ( plt != NULL ) - { - const QRectF canvasRect = plt->canvas()->contentsRect(); - - const QwtInterval interval = d_data->scaleInterval( - canvasRect, plt->canvasMap( xAxis() ), plt->canvasMap( yAxis() ) ); - - QwtScaleDiv sd = scaleDiv; - sd.setInterval( interval ); - - if ( sd != scaleDraw->scaleDiv() ) - { - // the internal label cache of QwtScaleDraw - // is cleared here, so better avoid pointless - // assignments. - - scaleDraw->setScaleDiv( sd ); - } - } - else - { - scaleDraw->setScaleDiv( scaleDiv ); - } - } -} diff --git a/source/third_party/qwt/qwt_plot_seriesitem.cpp b/source/third_party/qwt/qwt_plot_seriesitem.cpp deleted file mode 100644 index 4376b067457e826d9bba966ee1c85c328bc63923..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_seriesitem.cpp +++ /dev/null @@ -1,112 +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/qwt_plot_seriesitem.h" - -class QwtPlotSeriesItem::PrivateData -{ -public: - PrivateData(): - orientation( Qt::Vertical ) - { - } - - Qt::Orientation orientation; -}; - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotSeriesItem::QwtPlotSeriesItem( const QwtText &title ): - QwtPlotItem( title ) -{ - d_data = new PrivateData(); - setItemInterest( QwtPlotItem::ScaleInterest, true ); -} - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotSeriesItem::QwtPlotSeriesItem( const QString &title ): - QwtPlotItem( QwtText( title ) ) -{ - d_data = new PrivateData(); -} - -//! Destructor -QwtPlotSeriesItem::~QwtPlotSeriesItem() -{ - delete d_data; -} - -/*! - Set the orientation of the item. - - The orientation() might be used in specific way by a plot item. - F.e. a QwtPlotCurve uses it to identify how to display the curve - int QwtPlotCurve::Steps or QwtPlotCurve::Sticks style. - - \sa orientation() -*/ -void QwtPlotSeriesItem::setOrientation( Qt::Orientation orientation ) -{ - if ( d_data->orientation != orientation ) - { - d_data->orientation = orientation; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Orientation of the plot item - \sa setOrientation() -*/ -Qt::Orientation QwtPlotSeriesItem::orientation() const -{ - return d_data->orientation; -} - -/*! - \brief Draw the complete series - - \param painter Painter - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle of the canvas -*/ -void QwtPlotSeriesItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - drawSeries( painter, xMap, yMap, canvasRect, 0, -1 ); -} - -QRectF QwtPlotSeriesItem::boundingRect() const -{ - return dataRect(); -} - -void QwtPlotSeriesItem::updateScaleDiv( - const QwtScaleDiv &xScaleDiv, const QwtScaleDiv &yScaleDiv ) -{ - const QRectF rect = QRectF( - xScaleDiv.lowerBound(), yScaleDiv.lowerBound(), - xScaleDiv.range(), yScaleDiv.range() ); - - setRectOfInterest( rect ); -} - -void QwtPlotSeriesItem::dataChanged() -{ - itemChanged(); -} diff --git a/source/third_party/qwt/qwt_plot_shapeitem.cpp b/source/third_party/qwt/qwt_plot_shapeitem.cpp deleted file mode 100644 index ba422bf2d4c37420dade1d7a19e1c0b0bd81eece..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_shapeitem.cpp +++ /dev/null @@ -1,497 +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/qwt_plot_shapeitem.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_curve_fitter.h" -#include "qwt/qwt_clipper.h" - -static QPainterPath qwtTransformPath( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QPainterPath &path, bool doAlign ) -{ - QPainterPath shape; - shape.setFillRule( path.fillRule() ); - - for ( int i = 0; i < path.elementCount(); i++ ) - { - const QPainterPath::Element &element = path.elementAt( i ); - - double x = xMap.transform( element.x ); - double y = yMap.transform( element.y ); - - switch( element.type ) - { - case QPainterPath::MoveToElement: - { - if ( doAlign ) - { - x = qRound( x ); - y = qRound( y ); - } - - shape.moveTo( x, y ); - break; - } - case QPainterPath::LineToElement: - { - if ( doAlign ) - { - x = qRound( x ); - y = qRound( y ); - } - - shape.lineTo( x, y ); - break; - } - case QPainterPath::CurveToElement: - { - const QPainterPath::Element& element1 = path.elementAt( ++i ); - const double x1 = xMap.transform( element1.x ); - const double y1 = yMap.transform( element1.y ); - - const QPainterPath::Element& element2 = path.elementAt( ++i ); - const double x2 = xMap.transform( element2.x ); - const double y2 = yMap.transform( element2.y ); - - shape.cubicTo( x, y, x1, y1, x2, y2 ); - break; - } - case QPainterPath::CurveToDataElement: - { - break; - } - } - } - - return shape; -} - - -class QwtPlotShapeItem::PrivateData -{ -public: - PrivateData(): - legendMode( QwtPlotShapeItem::LegendColor ), - renderTolerance( 0.0 ) - { - } - - QwtPlotShapeItem::PaintAttributes paintAttributes; - QwtPlotShapeItem::LegendMode legendMode; - - double renderTolerance; - QRectF boundingRect; - - QPen pen; - QBrush brush; - QPainterPath shape; -}; - -/*! - \brief Constructor - - Sets the following item attributes: - - QwtPlotItem::AutoScale: true - - QwtPlotItem::Legend: false - - \param title Title -*/ -QwtPlotShapeItem::QwtPlotShapeItem( const QString& title ): - QwtPlotItem( QwtText( title ) ) -{ - init(); -} - -/*! - \brief Constructor - - Sets the following item attributes: - - QwtPlotItem::AutoScale: true - - QwtPlotItem::Legend: false - - \param title Title -*/ -QwtPlotShapeItem::QwtPlotShapeItem( const QwtText& title ): - QwtPlotItem( title ) -{ - init(); -} - -//! Destructor -QwtPlotShapeItem::~QwtPlotShapeItem() -{ - delete d_data; -} - -void QwtPlotShapeItem::init() -{ - d_data = new PrivateData(); - d_data->boundingRect = QwtPlotItem::boundingRect(); - - setItemAttribute( QwtPlotItem::AutoScale, true ); - setItemAttribute( QwtPlotItem::Legend, false ); - - setZ( 8.0 ); -} - -//! \return QwtPlotItem::Rtti_PlotShape -int QwtPlotShapeItem::rtti() const -{ - return QwtPlotItem::Rtti_PlotShape; -} - -/*! - Specify an attribute how to draw the shape - - \param attribute Paint attribute - \param on On/Off - \sa testPaintAttribute() -*/ -void QwtPlotShapeItem::setPaintAttribute( PaintAttribute attribute, bool on ) -{ - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; -} - -/*! - \return True, when attribute is enabled - \sa setPaintAttribute() -*/ -bool QwtPlotShapeItem::testPaintAttribute( PaintAttribute attribute ) const -{ - return ( d_data->paintAttributes & attribute ); -} - -/*! - Set the mode how to represent the item on the legend - - \param mode Mode - \sa legendMode() - */ -void QwtPlotShapeItem::setLegendMode( LegendMode mode ) -{ - if ( mode != d_data->legendMode ) - { - d_data->legendMode = mode; - legendChanged(); - } -} - -/*! - \return Mode how to represent the item on the legend - \sa legendMode() - */ -QwtPlotShapeItem::LegendMode QwtPlotShapeItem::legendMode() const -{ - return d_data->legendMode; -} - -//! Bounding rectangle of the shape -QRectF QwtPlotShapeItem::boundingRect() const -{ - return d_data->boundingRect; -} - -/*! - \brief Set a path built from a rectangle - - \param rect Rectangle - \sa setShape(), setPolygon(), shape() - */ -void QwtPlotShapeItem::setRect( const QRectF &rect ) -{ - QPainterPath path; - path.addRect( rect ); - - setShape( path ); -} - -/*! - \brief Set a path built from a polygon - - \param polygon Polygon - \sa setShape(), setRect(), shape() - */ -void QwtPlotShapeItem::setPolygon( const QPolygonF &polygon ) -{ - QPainterPath shape; - shape.addPolygon( polygon ); - - setShape( shape ); -} - -/*! - \brief Set the shape to be displayed - - \param shape Shape - \sa setShape(), shape() - */ -void QwtPlotShapeItem::setShape( const QPainterPath &shape ) -{ - if ( shape != d_data->shape ) - { - d_data->shape = shape; - if ( shape.isEmpty() ) - { - d_data->boundingRect = QwtPlotItem::boundingRect(); - } - else - { - d_data->boundingRect = shape.boundingRect(); - } - - itemChanged(); - } -} - -/*! - \return Shape to be displayed - \sa setShape() - */ -QPainterPath QwtPlotShapeItem::shape() const -{ - return d_data->shape; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotShapeItem::setPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - \brief Assign a pen - - The pen is used to draw the outline of the shape - - \param pen Pen - \sa pen(), brush() -*/ -void QwtPlotShapeItem::setPen( const QPen &pen ) -{ - if ( pen != d_data->pen ) - { - d_data->pen = pen; - itemChanged(); - } -} - -/*! - \return Pen used to draw the outline of the shape - \sa setPen(), brush() -*/ -QPen QwtPlotShapeItem::pen() const -{ - return d_data->pen; -} - -/*! - Assign a brush. - - The brush is used to fill the path - - \param brush Brush - \sa brush(), pen() -*/ -void QwtPlotShapeItem::setBrush( const QBrush &brush ) -{ - if ( brush != d_data->brush ) - { - d_data->brush = brush; - itemChanged(); - } -} - -/*! - \return Brush used to fill the shape - \sa setBrush(), pen() -*/ -QBrush QwtPlotShapeItem::brush() const -{ - return d_data->brush; -} - -/*! - \brief Set the tolerance for the weeding optimization - - After translating the shape into target device coordinate - ( usually widget geometries ) the painter path can be simplified - by a point weeding algorithm ( Douglas-Peucker ). - - For shapes built from curves and ellipses weeding might - have the opposite effect because they have to be expanded - to polygons. - - \param tolerance Accepted error when reducing the number of points - A value <= 0.0 disables weeding. - - \sa renderTolerance(), QwtWeedingCurveFitter - */ -void QwtPlotShapeItem::setRenderTolerance( double tolerance ) -{ - tolerance = qMax( tolerance, 0.0 ); - - if ( tolerance != d_data->renderTolerance ) - { - d_data->renderTolerance = tolerance; - itemChanged(); - } -} - -/*! - \return Tolerance for the weeding optimization - \sa setRenderTolerance() - */ -double QwtPlotShapeItem::renderTolerance() const -{ - return d_data->renderTolerance; -} - -/*! - Draw the shape item - - \param painter Painter - \param xMap X-Scale Map - \param yMap Y-Scale Map - \param canvasRect Contents rect of the plot canvas -*/ -void QwtPlotShapeItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - if ( d_data->shape.isEmpty() ) - return; - - if ( d_data->pen.style() == Qt::NoPen - && d_data->brush.style() == Qt::NoBrush ) - { - return; - } - - const QRectF cr = QwtScaleMap::invTransform( - xMap, yMap, canvasRect.toRect() ); - - const QRectF &br = d_data->boundingRect; - - if ( ( br.left() > cr.right() ) || ( br.right() < cr.left() ) - || ( br.top() > cr.bottom() ) || ( br.bottom() < cr.top() ) ) - { - // outside the visisble area - return; - } - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - QPainterPath path = qwtTransformPath( xMap, yMap, - d_data->shape, doAlign ); - - if ( testPaintAttribute( QwtPlotShapeItem::ClipPolygons ) ) - { - qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF()); - QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw ); - - QPainterPath clippedPath; - clippedPath.setFillRule( path.fillRule() ); - - const QList<QPolygonF> polygons = path.toSubpathPolygons(); - for ( int i = 0; i < polygons.size(); i++ ) - { - const QPolygonF p = QwtClipper::clipPolygonF( - clipRect, polygons[i], true ); - - clippedPath.addPolygon( p ); - - } - - path = clippedPath; - } - - if ( d_data->renderTolerance > 0.0 ) - { - QwtWeedingCurveFitter fitter( d_data->renderTolerance ); - - QPainterPath fittedPath; - fittedPath.setFillRule( path.fillRule() ); - - const QList<QPolygonF> polygons = path.toSubpathPolygons(); - for ( int i = 0; i < polygons.size(); i++ ) - fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) ); - - path = fittedPath; - } - - painter->setPen( d_data->pen ); - painter->setBrush( d_data->brush ); - - painter->drawPath( path ); -} - -/*! - \return A rectangle filled with the color of the brush ( or the pen ) - - \param index Index of the legend entry - ( usually there is only one ) - \param size Icon size - - \sa setLegendIconSize(), legendData() -*/ -QwtGraphic QwtPlotShapeItem::legendIcon( int index, - const QSizeF &size ) const -{ - Q_UNUSED( index ); - - QwtGraphic icon; - icon.setDefaultSize( size ); - - if ( size.isEmpty() ) - return icon; - - if ( d_data->legendMode == QwtPlotShapeItem::LegendShape ) - { - const QRectF &br = d_data->boundingRect; - - QPainter painter( &icon ); - painter.setRenderHint( QPainter::Antialiasing, - testRenderHint( QwtPlotItem::RenderAntialiased ) ); - - painter.translate( -br.topLeft() ); - - painter.setPen( d_data->pen ); - painter.setBrush( d_data->brush ); - painter.drawPath( d_data->shape ); - } - else - { - QColor iconColor; - if ( d_data->brush.style() != Qt::NoBrush ) - iconColor = d_data->brush.color(); - else - iconColor = d_data->pen.color(); - - icon = defaultIcon( iconColor, size ); - } - - return icon; -} - diff --git a/source/third_party/qwt/qwt_plot_spectrocurve.cpp b/source/third_party/qwt/qwt_plot_spectrocurve.cpp deleted file mode 100644 index bb54a80a5cf14f68744e0bc6e9ed4c423de1bdef..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_spectrocurve.cpp +++ /dev/null @@ -1,321 +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/qwt_plot_spectrocurve.h" -#include "qwt/qwt_color_map.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> - -class QwtPlotSpectroCurve::PrivateData -{ -public: - PrivateData(): - colorRange( 0.0, 1000.0 ), - penWidth(0.0), - paintAttributes( QwtPlotSpectroCurve::ClipPoints ) - { - colorMap = new QwtLinearColorMap(); - } - - ~PrivateData() - { - delete colorMap; - } - - QwtColorMap *colorMap; - QwtInterval colorRange; - QVector<QRgb> colorTable; - double penWidth; - QwtPlotSpectroCurve::PaintAttributes paintAttributes; -}; - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotSpectroCurve::QwtPlotSpectroCurve( const QwtText &title ): - QwtPlotSeriesItem( title ) -{ - init(); -} - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotSpectroCurve::QwtPlotSpectroCurve( const QString &title ): - QwtPlotSeriesItem( QwtText( title ) ) -{ - init(); -} - -//! Destructor -QwtPlotSpectroCurve::~QwtPlotSpectroCurve() -{ - delete d_data; -} - -/*! - \brief Initialize data members -*/ -void QwtPlotSpectroCurve::init() -{ - setItemAttribute( QwtPlotItem::Legend ); - setItemAttribute( QwtPlotItem::AutoScale ); - - d_data = new PrivateData; - setData( new QwtPoint3DSeriesData() ); - - setZ( 20.0 ); -} - -//! \return QwtPlotItem::Rtti_PlotSpectroCurve -int QwtPlotSpectroCurve::rtti() const -{ - return QwtPlotItem::Rtti_PlotSpectroCurve; -} - -/*! - Specify an attribute how to draw the curve - - \param attribute Paint attribute - \param on On/Off - /sa PaintAttribute, testPaintAttribute() -*/ -void QwtPlotSpectroCurve::setPaintAttribute( PaintAttribute attribute, bool on ) -{ - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; -} - -/*! - \return True, when attribute is enabled - \sa PaintAttribute, setPaintAttribute() -*/ -bool QwtPlotSpectroCurve::testPaintAttribute( PaintAttribute attribute ) const -{ - return ( d_data->paintAttributes & attribute ); -} - -/*! - Initialize data with an array of samples. - \param samples Vector of points -*/ -void QwtPlotSpectroCurve::setSamples( const QVector<QwtPoint3D> &samples ) -{ - setData( new QwtPoint3DSeriesData( samples ) ); -} - -/*! - Assign a series of samples - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotSpectroCurve::setSamples( - QwtSeriesData<QwtPoint3D> *data ) -{ - setData( data ); -} - -/*! - Change the color map - - Often it is useful to display the mapping between intensities and - colors as an additional plot axis, showing a color bar. - - \param colorMap Color Map - - \sa colorMap(), setColorRange(), QwtColorMap::color(), - QwtScaleWidget::setColorBarEnabled(), QwtScaleWidget::setColorMap() -*/ -void QwtPlotSpectroCurve::setColorMap( QwtColorMap *colorMap ) -{ - if ( colorMap != d_data->colorMap ) - { - delete d_data->colorMap; - d_data->colorMap = colorMap; - } - - legendChanged(); - itemChanged(); -} - -/*! - \return Color Map used for mapping the intensity values to colors - \sa setColorMap(), setColorRange(), QwtColorMap::color() -*/ -const QwtColorMap *QwtPlotSpectroCurve::colorMap() const -{ - return d_data->colorMap; -} - -/*! - Set the value interval, that corresponds to the color map - - \param interval interval.minValue() corresponds to 0.0, - interval.maxValue() to 1.0 on the color map. - - \sa colorRange(), setColorMap(), QwtColorMap::color() -*/ -void QwtPlotSpectroCurve::setColorRange( const QwtInterval &interval ) -{ - if ( interval != d_data->colorRange ) - { - d_data->colorRange = interval; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Value interval, that corresponds to the color map - \sa setColorRange(), setColorMap(), QwtColorMap::color() -*/ -QwtInterval &QwtPlotSpectroCurve::colorRange() const -{ - return d_data->colorRange; -} - -/*! - Assign a pen width - - \param penWidth New pen width - \sa penWidth() -*/ -void QwtPlotSpectroCurve::setPenWidth(double penWidth) -{ - if ( penWidth < 0.0 ) - penWidth = 0.0; - - if ( d_data->penWidth != penWidth ) - { - d_data->penWidth = penWidth; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Pen width used to draw a dot - \sa setPenWidth() -*/ -double QwtPlotSpectroCurve::penWidth() const -{ - return d_data->penWidth; -} - -/*! - Draw a subset of the points - - \param painter Painter - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle 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 drawDots() -*/ -void QwtPlotSpectroCurve::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 ) - to = dataSize() - 1; - - if ( from < 0 ) - from = 0; - - if ( from > to ) - return; - - drawDots( painter, xMap, yMap, canvasRect, from, to ); -} - -/*! - Draw a subset of the points - - \param painter Painter - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle 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() -*/ -void QwtPlotSpectroCurve::drawDots( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const -{ - if ( !d_data->colorRange.isValid() ) - return; - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - const QwtColorMap::Format format = d_data->colorMap->format(); - if ( format == QwtColorMap::Indexed ) - d_data->colorTable = d_data->colorMap->colorTable( d_data->colorRange ); - - const QwtSeriesData<QwtPoint3D> *series = data(); - - for ( int i = from; i <= to; i++ ) - { - const QwtPoint3D sample = series->sample( i ); - - double xi = xMap.transform( sample.x() ); - double yi = yMap.transform( sample.y() ); - if ( doAlign ) - { - xi = qRound( xi ); - yi = qRound( yi ); - } - - if ( d_data->paintAttributes & QwtPlotSpectroCurve::ClipPoints ) - { - if ( !canvasRect.contains( xi, yi ) ) - continue; - } - - if ( format == QwtColorMap::RGB ) - { - const QRgb rgb = d_data->colorMap->rgb( - d_data->colorRange, sample.z() ); - - painter->setPen( QPen( QColor::fromRgba( rgb ), d_data->penWidth ) ); - } - else - { - const unsigned char index = d_data->colorMap->colorIndex( - d_data->colorRange, sample.z() ); - - painter->setPen( QPen( QColor::fromRgba( d_data->colorTable[index] ), - d_data->penWidth ) ); - } - - QwtPainter::drawPoint( painter, QPointF( xi, yi ) ); - } - - d_data->colorTable.clear(); -} diff --git a/source/third_party/qwt/qwt_plot_spectrogram.cpp b/source/third_party/qwt/qwt_plot_spectrogram.cpp deleted file mode 100644 index deed41d609fc6b26e5b43f2bbcc2360bed4457af..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_spectrogram.cpp +++ /dev/null @@ -1,676 +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/qwt_plot_spectrogram.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_interval.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_color_map.h" -#include <qimage.h> -#include <qpen.h> -#include <qpainter.h> -#include <qmath.h> -#include <qalgorithms.h> -#if QT_VERSION >= 0x040400 -#include <qthread.h> -#include <qfuture.h> -#include <QtConcurrent/qtconcurrentrun.h> -#endif - -#define DEBUG_RENDER 0 - -#if DEBUG_RENDER -#include <QElapsedTimer> -#endif - -class QwtPlotSpectrogram::PrivateData -{ -public: - PrivateData(): - data( NULL ) - { - colorMap = new QwtLinearColorMap(); - displayMode = ImageMode; - - conrecFlags = QwtRasterData::IgnoreAllVerticesOnLevel; -#if 0 - conrecFlags |= QwtRasterData::IgnoreOutOfRange; -#endif - } - ~PrivateData() - { - delete data; - delete colorMap; - } - - QwtRasterData *data; - QwtColorMap *colorMap; - DisplayModes displayMode; - - QList<double> contourLevels; - QPen defaultContourPen; - QwtRasterData::ConrecFlags conrecFlags; -}; - -/*! - Sets the following item attributes: - - QwtPlotItem::AutoScale: true - - QwtPlotItem::Legend: false - - The z value is initialized by 8.0. - - \param title Title - - \sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ() -*/ -QwtPlotSpectrogram::QwtPlotSpectrogram( const QString &title ): - QwtPlotRasterItem( title ) -{ - d_data = new PrivateData(); - - setItemAttribute( QwtPlotItem::AutoScale, true ); - setItemAttribute( QwtPlotItem::Legend, false ); - - setZ( 8.0 ); -} - -//! Destructor -QwtPlotSpectrogram::~QwtPlotSpectrogram() -{ - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotSpectrogram -int QwtPlotSpectrogram::rtti() const -{ - return QwtPlotItem::Rtti_PlotSpectrogram; -} - -/*! - The display mode controls how the raster data will be represented. - - \param mode Display mode - \param on On/Off - - The default setting enables ImageMode. - - \sa DisplayMode, displayMode() -*/ -void QwtPlotSpectrogram::setDisplayMode( DisplayMode mode, bool on ) -{ - if ( on != bool( mode & d_data->displayMode ) ) - { - if ( on ) - d_data->displayMode |= mode; - else - d_data->displayMode &= ~mode; - } - - legendChanged(); - itemChanged(); -} - -/*! - The display mode controls how the raster data will be represented. - - \param mode Display mode - \return true if mode is enabled -*/ -bool QwtPlotSpectrogram::testDisplayMode( DisplayMode mode ) const -{ - return ( d_data->displayMode & mode ); -} - -/*! - Change the color map - - Often it is useful to display the mapping between intensities and - colors as an additional plot axis, showing a color bar. - - \param colorMap Color Map - - \sa colorMap(), QwtScaleWidget::setColorBarEnabled(), - QwtScaleWidget::setColorMap() -*/ -void QwtPlotSpectrogram::setColorMap( QwtColorMap *colorMap ) -{ - if ( d_data->colorMap != colorMap ) - { - delete d_data->colorMap; - d_data->colorMap = colorMap; - } - - invalidateCache(); - - legendChanged(); - itemChanged(); -} - -/*! - \return Color Map used for mapping the intensity values to colors - \sa setColorMap() -*/ -const QwtColorMap *QwtPlotSpectrogram::colorMap() const -{ - return d_data->colorMap; -} - -/*! - Build and assign the default pen for the contour lines - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotSpectrogram::setDefaultContourPen( - const QColor &color, qreal width, Qt::PenStyle style ) -{ - setDefaultContourPen( QPen( color, width, style ) ); -} - -/*! - \brief Set the default pen for the contour lines - - If the spectrogram has a valid default contour pen - a contour line is painted using the default contour pen. - Otherwise (pen.style() == Qt::NoPen) the pen is calculated - for each contour level using contourPen(). - - \sa defaultContourPen(), contourPen() -*/ -void QwtPlotSpectrogram::setDefaultContourPen( const QPen &pen ) -{ - if ( pen != d_data->defaultContourPen ) - { - d_data->defaultContourPen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Default contour pen - \sa setDefaultContourPen() -*/ -QPen QwtPlotSpectrogram::defaultContourPen() const -{ - return d_data->defaultContourPen; -} - -/*! - \brief Calculate the pen for a contour line - - The color of the pen is the color for level calculated by the color map - - \param level Contour level - \return Pen for the contour line - \note contourPen is only used if defaultContourPen().style() == Qt::NoPen - - \sa setDefaultContourPen(), setColorMap(), setContourLevels() -*/ -QPen QwtPlotSpectrogram::contourPen( double level ) const -{ - if ( d_data->data == NULL || d_data->colorMap == NULL ) - return QPen(); - - const QwtInterval intensityRange = d_data->data->interval(Qt::ZAxis); - const QColor c( d_data->colorMap->rgb( intensityRange, level ) ); - - return QPen( c ); -} - -/*! - Modify an attribute of the CONREC algorithm, used to calculate - the contour lines. - - \param flag CONREC flag - \param on On/Off - - \sa testConrecFlag(), renderContourLines(), - QwtRasterData::contourLines() -*/ -void QwtPlotSpectrogram::setConrecFlag( - QwtRasterData::ConrecFlag flag, bool on ) -{ - if ( bool( d_data->conrecFlags & flag ) == on ) - return; - - if ( on ) - d_data->conrecFlags |= flag; - else - d_data->conrecFlags &= ~flag; - - itemChanged(); -} - -/*! - Test an attribute of the CONREC algorithm, used to calculate - the contour lines. - - \param flag CONREC flag - \return true, is enabled - - The default setting enables QwtRasterData::IgnoreAllVerticesOnLevel - - \sa setConrecClag(), renderContourLines(), - QwtRasterData::contourLines() -*/ -bool QwtPlotSpectrogram::testConrecFlag( - QwtRasterData::ConrecFlag flag ) const -{ - return d_data->conrecFlags & flag; -} - -/*! - Set the levels of the contour lines - - \param levels Values of the contour levels - \sa contourLevels(), renderContourLines(), - QwtRasterData::contourLines() - - \note contourLevels returns the same levels but sorted. -*/ -void QwtPlotSpectrogram::setContourLevels( const QList<double> &levels ) -{ - d_data->contourLevels = levels; - qSort( d_data->contourLevels ); - - legendChanged(); - itemChanged(); -} - -/*! - \return Levels of the contour lines. - - The levels are sorted in increasing order. - - \sa contourLevels(), renderContourLines(), - QwtRasterData::contourLines() -*/ -QList<double> QwtPlotSpectrogram::contourLevels() const -{ - return d_data->contourLevels; -} - -/*! - Set the data to be displayed - - \param data Spectrogram Data - \sa data() -*/ -void QwtPlotSpectrogram::setData( QwtRasterData *data ) -{ - if ( data != d_data->data ) - { - delete d_data->data; - d_data->data = data; - - invalidateCache(); - itemChanged(); - } -} - -/*! - \return Spectrogram data - \sa setData() -*/ -const QwtRasterData *QwtPlotSpectrogram::data() const -{ - return d_data->data; -} - -/*! - \return Spectrogram data - \sa setData() -*/ -QwtRasterData *QwtPlotSpectrogram::data() -{ - return d_data->data; -} - -/*! - \return Bounding interval for an axis - - The default implementation returns the interval of the - associated raster data object. - - \param axis X, Y, or Z axis - \sa QwtRasterData::interval() -*/ -QwtInterval QwtPlotSpectrogram::interval(Qt::Axis axis) const -{ - if ( d_data->data == NULL ) - return QwtInterval(); - - return d_data->data->interval( axis ); -} - -/*! - \brief Pixel hint - - The geometry of a pixel is used to calculated the resolution and - alignment of the rendered image. - - The default implementation returns data()->pixelHint( rect ); - - \param area In most implementations the resolution of the data doesn't - depend on the requested area. - - \return Bounding rectangle of a pixel - - \sa QwtPlotRasterItem::pixelHint(), QwtRasterData::pixelHint(), - render(), renderImage() -*/ -QRectF QwtPlotSpectrogram::pixelHint( const QRectF &area ) const -{ - if ( d_data->data == NULL ) - return QRectF(); - - return d_data->data->pixelHint( area ); -} - -/*! - \brief Render an image from data and color map. - - For each pixel of area the value is mapped into a color. - - \param xMap X-Scale Map - \param yMap Y-Scale Map - \param area Requested area for the image in scale coordinates - \param imageSize Size of the requested image - - \return A QImage::Format_Indexed8 or QImage::Format_ARGB32 depending - on the color map. - - \sa QwtRasterData::value(), QwtColorMap::rgb(), - QwtColorMap::colorIndex() -*/ -QImage QwtPlotSpectrogram::renderImage( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &area, const QSize &imageSize ) const -{ - if ( imageSize.isEmpty() || d_data->data == NULL - || d_data->colorMap == NULL ) - { - return QImage(); - } - - const QwtInterval intensityRange = d_data->data->interval( Qt::ZAxis ); - if ( !intensityRange.isValid() ) - return QImage(); - - QImage::Format format = ( d_data->colorMap->format() == QwtColorMap::RGB ) - ? QImage::Format_ARGB32 : QImage::Format_Indexed8; - - QImage image( imageSize, format ); - - if ( d_data->colorMap->format() == QwtColorMap::Indexed ) - image.setColorTable( d_data->colorMap->colorTable( intensityRange ) ); - - d_data->data->initRaster( area, image.size() ); - -#if DEBUG_RENDER - QElapsedTimer time; - time.start(); -#endif - -#if QT_VERSION >= 0x040400 && !defined(QT_NO_QFUTURE) - uint numThreads = renderThreadCount(); - - if ( numThreads <= 0 ) - numThreads = QThread::idealThreadCount(); - - if ( numThreads <= 0 ) - numThreads = 1; - - const int numRows = imageSize.height() / numThreads; - - QList< QFuture<void> > futures; - for ( uint i = 0; i < numThreads; i++ ) - { - QRect tile( 0, i * numRows, image.width(), numRows ); - if ( i == numThreads - 1 ) - { - tile.setHeight( image.height() - i * numRows ); - renderTile( xMap, yMap, tile, &image ); - } - else - { - futures += QtConcurrent::run( - this, &QwtPlotSpectrogram::renderTile, - xMap, yMap, tile, &image ); - } - } - for ( int i = 0; i < futures.size(); i++ ) - futures[i].waitForFinished(); - -#else // QT_VERSION < 0x040400 - const QRect tile( 0, 0, image.width(), image.height() ); - renderTile( xMap, yMap, tile, &image ); -#endif - -#if DEBUG_RENDER - const qint64 elapsed = time.elapsed(); - qDebug() << "renderImage" << imageSize << elapsed; -#endif - - d_data->data->discardRaster(); - - return image; -} - -/*! - \brief Render a tile of an image. - - Rendering in tiles can be used to composite an image in parallel - threads. - - \param xMap X-Scale Map - \param yMap Y-Scale Map - \param tile Geometry of the tile in image coordinates - \param image Image to be rendered -*/ -void QwtPlotSpectrogram::renderTile( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &tile, QImage *image ) const -{ - const QwtInterval range = d_data->data->interval( Qt::ZAxis ); - if ( !range.isValid() ) - return; - - if ( d_data->colorMap->format() == QwtColorMap::RGB ) - { - for ( int y = tile.top(); y <= tile.bottom(); y++ ) - { - const double ty = yMap.invTransform( y ); - - QRgb *line = reinterpret_cast<QRgb *>( image->scanLine( y ) ); - line += tile.left(); - - for ( int x = tile.left(); x <= tile.right(); x++ ) - { - const double tx = xMap.invTransform( x ); - - *line++ = d_data->colorMap->rgb( range, - d_data->data->value( tx, ty ) ); - } - } - } - else if ( d_data->colorMap->format() == QwtColorMap::Indexed ) - { - for ( int y = tile.top(); y <= tile.bottom(); y++ ) - { - const double ty = yMap.invTransform( y ); - - unsigned char *line = image->scanLine( y ); - line += tile.left(); - - for ( int x = tile.left(); x <= tile.right(); x++ ) - { - const double tx = xMap.invTransform( x ); - - *line++ = d_data->colorMap->colorIndex( range, - d_data->data->value( tx, ty ) ); - } - } - } -} - -/*! - \brief Return the raster to be used by the CONREC contour algorithm. - - A larger size will improve the precision of the CONREC algorithm, - but will slow down the time that is needed to calculate the lines. - - The default implementation returns rect.size() / 2 bounded to - the resolution depending on pixelSize(). - - \param area Rectangle, where to calculate the contour lines - \param rect Rectangle in pixel coordinates, where to paint the contour lines - \return Raster to be used by the CONREC contour algorithm. - - \note The size will be bounded to rect.size(). - - \sa drawContourLines(), QwtRasterData::contourLines() -*/ -QSize QwtPlotSpectrogram::contourRasterSize( - const QRectF &area, const QRect &rect ) const -{ - QSize raster = rect.size() / 2; - - const QRectF pixelRect = pixelHint( area ); - if ( !pixelRect.isEmpty() ) - { - const QSize res( qCeil( rect.width() / pixelRect.width() ), - qCeil( rect.height() / pixelRect.height() ) ); - raster = raster.boundedTo( res ); - } - - return raster; -} - -/*! - Calculate contour lines - - \param rect Rectangle, where to calculate the contour lines - \param raster Raster, used by the CONREC algorithm - \return Calculated contour lines - - \sa contourLevels(), setConrecFlag(), - QwtRasterData::contourLines() -*/ -QwtRasterData::ContourLines QwtPlotSpectrogram::renderContourLines( - const QRectF &rect, const QSize &raster ) const -{ - if ( d_data->data == NULL ) - return QwtRasterData::ContourLines(); - - return d_data->data->contourLines( rect, raster, - d_data->contourLevels, d_data->conrecFlags ); -} - -/*! - Paint the contour lines - - \param painter Painter - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param contourLines Contour lines - - \sa renderContourLines(), defaultContourPen(), contourPen() -*/ -void QwtPlotSpectrogram::drawContourLines( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtRasterData::ContourLines &contourLines ) const -{ - if ( d_data->data == NULL ) - return; - - const int numLevels = d_data->contourLevels.size(); - for ( int l = 0; l < numLevels; l++ ) - { - const double level = d_data->contourLevels[l]; - - QPen pen = defaultContourPen(); - if ( pen.style() == Qt::NoPen ) - pen = contourPen( level ); - - if ( pen.style() == Qt::NoPen ) - continue; - - painter->setPen( pen ); - - const QPolygonF &lines = contourLines[level]; - for ( int i = 0; i < lines.size(); i += 2 ) - { - const QPointF p1( xMap.transform( lines[i].x() ), - yMap.transform( lines[i].y() ) ); - const QPointF p2( xMap.transform( lines[i+1].x() ), - yMap.transform( lines[i+1].y() ) ); - - QwtPainter::drawLine( painter, p1, p2 ); - } - } -} - -/*! - \brief Draw the spectrogram - - \param painter Painter - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle of the canvas in painter coordinates - - \sa setDisplayMode(), renderImage(), - QwtPlotRasterItem::draw(), drawContourLines() -*/ -void QwtPlotSpectrogram::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - if ( d_data->displayMode & ImageMode ) - QwtPlotRasterItem::draw( painter, xMap, yMap, canvasRect ); - - if ( d_data->displayMode & ContourMode ) - { - // Add some pixels at the borders - const int margin = 2; - QRectF rasterRect( canvasRect.x() - margin, canvasRect.y() - margin, - canvasRect.width() + 2 * margin, canvasRect.height() + 2 * margin ); - - QRectF area = QwtScaleMap::invTransform( xMap, yMap, rasterRect ); - - const QRectF br = boundingRect(); - if ( br.isValid() ) - { - area &= br; - if ( area.isEmpty() ) - return; - - rasterRect = QwtScaleMap::transform( xMap, yMap, area ); - } - - QSize raster = contourRasterSize( area, rasterRect.toRect() ); - raster = raster.boundedTo( rasterRect.toRect().size() ); - if ( raster.isValid() ) - { - const QwtRasterData::ContourLines lines = - renderContourLines( area, raster ); - - drawContourLines( painter, xMap, yMap, lines ); - } - } -} diff --git a/source/third_party/qwt/qwt_plot_svgitem.cpp b/source/third_party/qwt/qwt_plot_svgitem.cpp deleted file mode 100644 index c1d9934a9f185d77ebe39d21b673cbdf108a1eb1..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_svgitem.cpp +++ /dev/null @@ -1,224 +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/qwt_plot_svgitem.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> - -#ifndef QT_NO_SVG - -#include <QtSvg/qsvgrenderer.h> - -class QwtPlotSvgItem::PrivateData -{ -public: - PrivateData() - { - } - - QRectF boundingRect; - QSvgRenderer renderer; -}; - -/*! - \brief Constructor - - Sets the following item attributes: - - QwtPlotItem::AutoScale: true - - QwtPlotItem::Legend: false - - \param title Title -*/ -QwtPlotSvgItem::QwtPlotSvgItem( const QString& title ): - QwtPlotItem( QwtText( title ) ) -{ - init(); -} - -/*! - \brief Constructor - - Sets the following item attributes: - - QwtPlotItem::AutoScale: true - - QwtPlotItem::Legend: false - - \param title Title -*/ -QwtPlotSvgItem::QwtPlotSvgItem( const QwtText& title ): - QwtPlotItem( title ) -{ - init(); -} - -//! Destructor -QwtPlotSvgItem::~QwtPlotSvgItem() -{ - delete d_data; -} - -void QwtPlotSvgItem::init() -{ - d_data = new PrivateData(); - d_data->boundingRect = QwtPlotItem::boundingRect(); - - setItemAttribute( QwtPlotItem::AutoScale, true ); - setItemAttribute( QwtPlotItem::Legend, false ); - - setZ( 8.0 ); -} - -//! \return QwtPlotItem::Rtti_PlotSVG -int QwtPlotSvgItem::rtti() const -{ - return QwtPlotItem::Rtti_PlotSVG; -} - -/*! - Load a SVG file - - \param rect Bounding rectangle - \param fileName SVG file name - - \return true, if the SVG file could be loaded -*/ -bool QwtPlotSvgItem::loadFile( const QRectF &rect, - const QString &fileName ) -{ - d_data->boundingRect = rect; - const bool ok = d_data->renderer.load( fileName ); - - legendChanged(); - itemChanged(); - - return ok; -} - -/*! - Load SVG data - - \param rect Bounding rectangle - \param data in SVG format - - \return true, if the SVG data could be loaded -*/ -bool QwtPlotSvgItem::loadData( const QRectF &rect, - const QByteArray &data ) -{ - d_data->boundingRect = rect; - const bool ok = d_data->renderer.load( data ); - - legendChanged(); - itemChanged(); - - return ok; -} - -//! Bounding rectangle of the item -QRectF QwtPlotSvgItem::boundingRect() const -{ - return d_data->boundingRect; -} - -//! \return Renderer used to render the SVG data -const QSvgRenderer &QwtPlotSvgItem::renderer() const -{ - return d_data->renderer; -} - -//! \return Renderer used to render the SVG data -QSvgRenderer &QwtPlotSvgItem::renderer() -{ - return d_data->renderer; -} - -/*! - Draw the SVG item - - \param painter Painter - \param xMap X-Scale Map - \param yMap Y-Scale Map - \param canvasRect Contents rect of the plot canvas -*/ -void QwtPlotSvgItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - const QRectF cRect = QwtScaleMap::invTransform( - xMap, yMap, canvasRect.toRect() ); - const QRectF bRect = boundingRect(); - if ( bRect.isValid() && cRect.isValid() ) - { - QRectF rect = bRect; - if ( bRect.contains( cRect ) ) - rect = cRect; - - const QRectF r = QwtScaleMap::transform( xMap, yMap, rect ); - render( painter, viewBox( rect ), r ); - } -} - -/*! - Render the SVG data - - \param painter Painter - \param viewBox View Box, see QSvgRenderer::viewBox() - \param rect Target rectangle on the paint device -*/ -void QwtPlotSvgItem::render( QPainter *painter, - const QRectF &viewBox, const QRectF &rect ) const -{ - if ( !viewBox.isValid() ) - return; - - QRectF r = rect; - - if ( QwtPainter::roundingAlignment( painter ) ) - { - r.setLeft ( qRound( r.left() ) ); - r.setRight ( qRound( r.right() ) ); - r.setTop ( qRound( r.top() ) ); - r.setBottom ( qRound( r.bottom() ) ); - } - - d_data->renderer.setViewBox( viewBox ); - d_data->renderer.render( painter, r ); -} - -/*! - Calculate the view box from rect and boundingRect(). - - \param rect Rectangle in scale coordinates - \return View box, see QSvgRenderer::viewBox() -*/ -QRectF QwtPlotSvgItem::viewBox( const QRectF &rect ) const -{ - const QSize sz = d_data->renderer.defaultSize(); - const QRectF br = boundingRect(); - - if ( !rect.isValid() || !br.isValid() || sz.isNull() ) - return QRectF(); - - QwtScaleMap xMap; - xMap.setScaleInterval( br.left(), br.right() ); - xMap.setPaintInterval( 0, sz.width() ); - - QwtScaleMap yMap; - yMap.setScaleInterval( br.top(), br.bottom() ); - yMap.setPaintInterval( sz.height(), 0 ); - - const double x1 = xMap.transform( rect.left() ); - const double x2 = xMap.transform( rect.right() ); - const double y1 = yMap.transform( rect.bottom() ); - const double y2 = yMap.transform( rect.top() ); - - return QRectF( x1, y1, x2 - x1, y2 - y1 ); -} - -#endif \ No newline at end of file diff --git a/source/third_party/qwt/qwt_plot_textlabel.cpp b/source/third_party/qwt/qwt_plot_textlabel.cpp deleted file mode 100644 index 141364c57e79445a0bb98db649fcaa0e6c949499..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_textlabel.cpp +++ /dev/null @@ -1,272 +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/qwt_plot_textlabel.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include <qpainter.h> -#include <qpixmap.h> -#include <qmath.h> - -static QRect qwtItemRect( int renderFlags, - const QRectF &rect, const QSizeF &itemSize ) -{ - int x; - if ( renderFlags & Qt::AlignLeft ) - { - x = rect.left(); - } - else if ( renderFlags & Qt::AlignRight ) - { - x = rect.right() - itemSize.width(); - } - else - { - x = rect.center().x() - 0.5 * itemSize.width(); - } - - int y; - if ( renderFlags & Qt::AlignTop ) - { - y = rect.top(); - } - else if ( renderFlags & Qt::AlignBottom ) - { - y = rect.bottom() - itemSize.height(); - } - else - { - y = rect.center().y() - 0.5 * itemSize.height(); - } - - return QRect( x, y, itemSize.width(), itemSize.height() ); -} - -class QwtPlotTextLabel::PrivateData -{ -public: - PrivateData(): - margin( 5 ) - { - } - - QwtText text; - int margin; - - QPixmap pixmap; -}; - -/*! - \brief Constructor - - Initializes an text label with an empty text - - Sets the following item attributes: - - - QwtPlotItem::AutoScale: true - - QwtPlotItem::Legend: false - - The z value is initialized by 150 - - \sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ() -*/ - -QwtPlotTextLabel::QwtPlotTextLabel(): - QwtPlotItem( QwtText( "Label" ) ) -{ - d_data = new PrivateData; - - setItemAttribute( QwtPlotItem::AutoScale, false ); - setItemAttribute( QwtPlotItem::Legend, false ); - - setZ( 150 ); -} - -//! Destructor -QwtPlotTextLabel::~QwtPlotTextLabel() -{ - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotTextLabel -int QwtPlotTextLabel::rtti() const -{ - return QwtPlotItem::Rtti_PlotTextLabel; -} - -/*! - Set the text - - The label will be aligned to the plot canvas according to - the alignment flags of text. - - \param text Text to be displayed - - \sa text(), QwtText::renderFlags() -*/ -void QwtPlotTextLabel::setText( const QwtText &text ) -{ - if ( d_data->text != text ) - { - d_data->text = text; - - invalidateCache(); - itemChanged(); - } -} - -/*! - \return Text to be displayed - \sa setText() -*/ -QwtText QwtPlotTextLabel::text() const -{ - return d_data->text; -} - -/*! - Set the margin - - The margin is the distance between the contentsRect() - of the plot canvas and the rectangle where the label can - be displayed. - - \param margin Margin - - \sa margin(), textRect() - */ -void QwtPlotTextLabel::setMargin( int margin ) -{ - margin = qMax( margin, 0 ); - if ( d_data->margin != margin ) - { - d_data->margin = margin; - itemChanged(); - } -} - -/*! - \return Margin added to the contentsMargins() of the canvas - \sa setMargin() -*/ -int QwtPlotTextLabel::margin() const -{ - return d_data->margin; -} - -/*! - Draw the text label - - \param painter Painter - \param xMap x Scale Map - \param yMap y Scale Map - \param canvasRect Contents rectangle of the canvas in painter coordinates - - \sa textRect() -*/ - -void QwtPlotTextLabel::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - Q_UNUSED( xMap ); - Q_UNUSED( yMap ); - - const int m = d_data->margin; - - const QRectF rect = textRect( canvasRect.adjusted( m, m, -m, -m ), - d_data->text.textSize( painter->font() ) ); - - bool doCache = QwtPainter::roundingAlignment( painter ); - if ( doCache ) - { - switch( painter->paintEngine()->type() ) - { - case QPaintEngine::Picture: - case QPaintEngine::User: // usually QwtGraphic - { - // don't use a cache for record/replay devices - doCache = false; - break; - } - default:; - } - } - - if ( doCache ) - { - // when the paint device is aligning it is not one - // where scalability matters ( PDF, SVG ). - // As rendering a text label is an expensive operation - // we use a cache. - - int pw = 0; - if ( d_data->text.borderPen().style() != Qt::NoPen ) - pw = qMax( d_data->text.borderPen().width(), 1 ); - - QRect pixmapRect; - pixmapRect.setLeft( qFloor( rect.left() ) - pw ); - pixmapRect.setTop( qFloor( rect.top() ) - pw ); - pixmapRect.setRight( qCeil( rect.right() ) + pw ); - pixmapRect.setBottom( qCeil( rect.bottom() ) + pw ); - -#define QWT_HIGH_DPI 1 - -#if QT_VERSION >= 0x050100 && QWT_HIGH_DPI - const qreal pixelRatio = painter->device()->devicePixelRatio(); - const QSize scaledSize = pixmapRect.size() * pixelRatio; -#else - const QSize scaledSize = pixmapRect.size(); -#endif - if ( d_data->pixmap.isNull() || - ( scaledSize != d_data->pixmap.size() ) ) - { - d_data->pixmap = QPixmap( scaledSize ); -#if QT_VERSION >= 0x050100 && QWT_HIGH_DPI - d_data->pixmap.setDevicePixelRatio( pixelRatio ); -#endif - d_data->pixmap.fill( Qt::transparent ); - - const QRect r( pw, pw, - pixmapRect.width() - 2 * pw, pixmapRect.height() - 2 * pw ); - - QPainter pmPainter( &d_data->pixmap ); - d_data->text.draw( &pmPainter, r ); - } - - painter->drawPixmap( pixmapRect, d_data->pixmap ); - } - else - { - d_data->text.draw( painter, rect ); - } -} - -/*! - \brief Align the text label - - \param rect Canvas rectangle with margins subtracted - \param textSize Size required to draw the text - - \return A rectangle aligned according the the alignment flags of - the text. - - \sa setMargin(), QwtText::renderFlags(), QwtText::textSize() - */ -QRectF QwtPlotTextLabel::textRect( - const QRectF &rect, const QSizeF &textSize ) const -{ - return qwtItemRect( d_data->text.renderFlags(), rect, textSize ); -} - -//! Invalidate all internal cache -void QwtPlotTextLabel::invalidateCache() -{ - d_data->pixmap = QPixmap(); -} diff --git a/source/third_party/qwt/qwt_plot_tradingcurve.cpp b/source/third_party/qwt/qwt_plot_tradingcurve.cpp deleted file mode 100644 index b99d466ab4d8803af3a05d4334ae75cf4fd713b4..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_tradingcurve.cpp +++ /dev/null @@ -1,682 +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/qwt_plot_tradingcurve.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_clipper.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> - -static inline bool qwtIsSampleInside( const QwtOHLCSample &sample, - double tMin, double tMax, double vMin, double vMax ) -{ - const double t = sample.time; - const QwtInterval interval = sample.boundingInterval(); - - const bool isOffScreen = ( t < tMin ) || ( t > tMax ) - || ( interval.maxValue() < vMin ) || ( interval.minValue() > vMax ); - - return !isOffScreen; -} - -class QwtPlotTradingCurve::PrivateData -{ -public: - PrivateData(): - symbolStyle( QwtPlotTradingCurve::CandleStick ), - symbolExtent( 0.6 ), - minSymbolWidth( 2.0 ), - maxSymbolWidth( -1.0 ), - paintAttributes( QwtPlotTradingCurve::ClipSymbols ) - { - symbolBrush[0] = QBrush( Qt::white ); - symbolBrush[1] = QBrush( Qt::black ); - } - - QwtPlotTradingCurve::SymbolStyle symbolStyle; - double symbolExtent; - double minSymbolWidth; - double maxSymbolWidth; - - QPen symbolPen; - QBrush symbolBrush[2]; // Increasing/Decreasing - - QwtPlotTradingCurve::PaintAttributes paintAttributes; -}; - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotTradingCurve::QwtPlotTradingCurve( const QwtText &title ): - QwtPlotSeriesItem( title ) -{ - init(); -} - -/*! - Constructor - \param title Title of the curve -*/ -QwtPlotTradingCurve::QwtPlotTradingCurve( const QString &title ): - QwtPlotSeriesItem( QwtText( title ) ) -{ - init(); -} - -//! Destructor -QwtPlotTradingCurve::~QwtPlotTradingCurve() -{ - delete d_data; -} - -//! Initialize internal members -void QwtPlotTradingCurve::init() -{ - setItemAttribute( QwtPlotItem::Legend, true ); - setItemAttribute( QwtPlotItem::AutoScale, true ); - - d_data = new PrivateData; - setData( new QwtTradingChartData() ); - - setZ( 19.0 ); -} - -//! \return QwtPlotItem::Rtti_PlotTradingCurve -int QwtPlotTradingCurve::rtti() const -{ - return QwtPlotTradingCurve::Rtti_PlotTradingCurve; -} - -/*! - Specify an attribute how to draw the curve - - \param attribute Paint attribute - \param on On/Off - \sa testPaintAttribute() -*/ -void QwtPlotTradingCurve::setPaintAttribute( - PaintAttribute attribute, bool on ) -{ - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; -} - -/*! - \return True, when attribute is enabled - \sa PaintAttribute, setPaintAttribute() -*/ -bool QwtPlotTradingCurve::testPaintAttribute( - PaintAttribute attribute ) const -{ - return ( d_data->paintAttributes & attribute ); -} - -/*! - Initialize data with an array of samples. - \param samples Vector of samples - - \sa QwtPlotSeriesItem::setData() -*/ -void QwtPlotTradingCurve::setSamples( - const QVector<QwtOHLCSample> &samples ) -{ - setData( new QwtTradingChartData( samples ) ); -} - -/*! - Assign a series of samples - - setSamples() is just a wrapper for setData() without any additional - value - beside that it is easier to find for the developer. - - \param data Data - \warning The item takes ownership of the data object, deleting - it when its not used anymore. -*/ -void QwtPlotTradingCurve::setSamples( - QwtSeriesData<QwtOHLCSample> *data ) -{ - setData( data ); -} - -/*! - Set the symbol style - - \param style Symbol style - - \sa symbolStyle(), setSymbolExtent(), - setSymbolPen(), setSymbolBrush() -*/ -void QwtPlotTradingCurve::setSymbolStyle( SymbolStyle style ) -{ - if ( style != d_data->symbolStyle ) - { - d_data->symbolStyle = style; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Symbol style - \sa setSymbolStyle(), symbolExtent(), symbolPen(), symbolBrush() -*/ -QwtPlotTradingCurve::SymbolStyle QwtPlotTradingCurve::symbolStyle() const -{ - return d_data->symbolStyle; -} - -/*! - Build and assign the symbol pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotTradingCurve::setSymbolPen( - const QColor &color, qreal width, Qt::PenStyle style ) -{ - setSymbolPen( QPen( color, width, style ) ); -} - -/*! - \brief Set the symbol pen - - The symbol pen is used for rendering the lines of the - bar or candlestick symbols - - \sa symbolPen(), setSymbolBrush() -*/ -void QwtPlotTradingCurve::setSymbolPen( const QPen &pen ) -{ - if ( pen != d_data->symbolPen ) - { - d_data->symbolPen = pen; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Symbol pen - \sa setSymbolPen(), symbolBrush() -*/ -QPen QwtPlotTradingCurve::symbolPen() const -{ - return d_data->symbolPen; -} - -/*! - Set the symbol brush - - \param direction Direction type - \param brush Brush used to fill the body of all candlestick - symbols with the direction - - \sa symbolBrush(), setSymbolPen() -*/ -void QwtPlotTradingCurve::setSymbolBrush( - Direction direction, const QBrush &brush ) -{ - if ( direction < 0 || direction >= 2 ) - return; - - if ( brush != d_data->symbolBrush[ direction ] ) - { - d_data->symbolBrush[ direction ] = brush; - - legendChanged(); - itemChanged(); - } -} - -/*! - \param direction - \return Brush used to fill the body of all candlestick - symbols with the direction - - \sa setSymbolPen(), symbolBrush() -*/ -QBrush QwtPlotTradingCurve::symbolBrush( Direction direction ) const -{ - if ( direction < 0 || direction >= 2 ) - return QBrush(); - - return d_data->symbolBrush[ direction ]; -} - -/*! - \brief Set the extent of the symbol - - The width of the symbol is given in scale coordinates. When painting - a symbol the width is scaled into paint device coordinates - by scaledSymbolWidth(). The scaled width is bounded by - minSymbolWidth(), maxSymbolWidth() - - \param extent Symbol width in scale coordinates - - \sa symbolExtent(), scaledSymbolWidth(), - setMinSymbolWidth(), setMaxSymbolWidth() -*/ -void QwtPlotTradingCurve::setSymbolExtent( double extent ) -{ - extent = qMax( 0.0, extent ); - if ( extent != d_data->symbolExtent ) - { - d_data->symbolExtent = extent; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Extent of a symbol in scale coordinates - \sa setSymbolExtent(), scaledSymbolWidth(), - minSymbolWidth(), maxSymbolWidth() -*/ -double QwtPlotTradingCurve::symbolExtent() const -{ - return d_data->symbolExtent; -} - -/*! - Set a minimum for the symbol width - - \param width Width in paint device coordinates - \sa minSymbolWidth(), setMaxSymbolWidth(), setSymbolExtent() - */ -void QwtPlotTradingCurve::setMinSymbolWidth( double width ) -{ - width = qMax( width, 0.0 ); - if ( width != d_data->minSymbolWidth ) - { - d_data->minSymbolWidth = width; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Minmum for the symbol width - \sa setMinSymbolWidth(), maxSymbolWidth(), symbolExtent() - */ -double QwtPlotTradingCurve::minSymbolWidth() const -{ - return d_data->minSymbolWidth; -} - -/*! - Set a maximum for the symbol width - - A value <= 0.0 means an unlimited width - - \param width Width in paint device coordinates - \sa maxSymbolWidth(), setMinSymbolWidth(), setSymbolExtent() - */ -void QwtPlotTradingCurve::setMaxSymbolWidth( double width ) -{ - if ( width != d_data->maxSymbolWidth ) - { - d_data->maxSymbolWidth = width; - - legendChanged(); - itemChanged(); - } -} - -/*! - \return Maximum for the symbol width - \sa setMaxSymbolWidth(), minSymbolWidth(), symbolExtent() - */ -double QwtPlotTradingCurve::maxSymbolWidth() const -{ - return d_data->maxSymbolWidth; -} - -/*! - \return Bounding rectangle of all samples. - For an empty series the rectangle is invalid. -*/ -QRectF QwtPlotTradingCurve::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 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 canvasRect Contents rectangle 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 drawSymbols() -*/ -void QwtPlotTradingCurve::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; - - painter->save(); - - if ( d_data->symbolStyle != QwtPlotTradingCurve::NoSymbol ) - drawSymbols( painter, xMap, yMap, canvasRect, from, to ); - - painter->restore(); -} - -/*! - Draw symbols - - \param painter Painter - \param xMap x map - \param yMap y map - \param canvasRect Contents rectangle of the canvas - \param from Index of the first point to be painted - \param to Index of the last point to be painted - - \sa drawSeries() -*/ -void QwtPlotTradingCurve::drawSymbols( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect, int from, int to ) const -{ - const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect ); - - const QwtScaleMap *timeMap, *valueMap; - double tMin, tMax, vMin, vMax; - - const Qt::Orientation orient = orientation(); - if ( orient == Qt::Vertical ) - { - timeMap = &xMap; - valueMap = &yMap; - - tMin = tr.left(); - tMax = tr.right(); - vMin = tr.top(); - vMax = tr.bottom(); - } - else - { - timeMap = &yMap; - valueMap = &xMap; - - vMin = tr.left(); - vMax = tr.right(); - tMin = tr.top(); - tMax = tr.bottom(); - } - - const bool inverted = timeMap->isInverting(); - const bool doClip = d_data->paintAttributes & ClipSymbols; - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - double symbolWidth = scaledSymbolWidth( xMap, yMap, canvasRect ); - if ( doAlign ) - symbolWidth = qFloor( 0.5 * symbolWidth ) * 2.0; - - QPen pen = d_data->symbolPen; - pen.setCapStyle( Qt::FlatCap ); - - painter->setPen( pen ); - - for ( int i = from; i <= to; i++ ) - { - const QwtOHLCSample s = sample( i ); - - if ( !doClip || qwtIsSampleInside( s, tMin, tMax, vMin, vMax ) ) - { - QwtOHLCSample translatedSample; - - translatedSample.time = timeMap->transform( s.time ); - translatedSample.open = valueMap->transform( s.open ); - translatedSample.high = valueMap->transform( s.high ); - translatedSample.low = valueMap->transform( s.low ); - translatedSample.close = valueMap->transform( s.close ); - - const int brushIndex = ( s.open < s.close ) - ? QwtPlotTradingCurve::Increasing - : QwtPlotTradingCurve::Decreasing; - - if ( doAlign ) - { - translatedSample.time = qRound( translatedSample.time ); - translatedSample.open = qRound( translatedSample.open ); - translatedSample.high = qRound( translatedSample.high ); - translatedSample.low = qRound( translatedSample.low ); - translatedSample.close = qRound( translatedSample.close ); - } - - switch( d_data->symbolStyle ) - { - case Bar: - { - drawBar( painter, translatedSample, - orient, inverted, symbolWidth ); - break; - } - case CandleStick: - { - painter->setBrush( d_data->symbolBrush[ brushIndex ] ); - drawCandleStick( painter, translatedSample, - orient, symbolWidth ); - break; - } - default: - { - if ( d_data->symbolStyle >= UserSymbol ) - { - painter->setBrush( d_data->symbolBrush[ brushIndex ] ); - drawUserSymbol( painter, d_data->symbolStyle, - translatedSample, orient, inverted, symbolWidth ); - } - } - } - } - } -} - -/*! - \brief Draw a symbol for a symbol style >= UserSymbol - - The implementation does nothing and is intended to be overloaded - - \param painter Qt painter, initialized with pen/brush - \param symbolStyle Symbol style - \param sample Samples already translated into paint device coordinates - \param orientation Vertical or horizontal - \param inverted True, when the opposite scale - ( Qt::Vertical: x, Qt::Horizontal: y ) is increasing - in the opposite direction as QPainter coordinates. - \param symbolWidth Width of the symbol in paint device coordinates -*/ -void QwtPlotTradingCurve::drawUserSymbol( QPainter *painter, - SymbolStyle symbolStyle, const QwtOHLCSample &sample, - Qt::Orientation orientation, bool inverted, double symbolWidth ) const -{ - Q_UNUSED( painter ) - Q_UNUSED( symbolStyle ) - Q_UNUSED( orientation ) - Q_UNUSED( inverted ) - Q_UNUSED( symbolWidth ) - Q_UNUSED( sample ) -} - -/*! - \brief Draw a bar - - \param painter Qt painter, initialized with pen/brush - \param sample Sample, already translated into paint device coordinates - \param orientation Vertical or horizontal - \param inverted When inverted is false the open tick is painted - to the left/top, otherwise it is painted right/bottom. - The close tick is painted in the opposite direction - of the open tick. - painted in the opposite d - opposite direction. - \param width Width or height of the candle, depending on the orientation - - \sa Bar -*/ -void QwtPlotTradingCurve::drawBar( QPainter *painter, - const QwtOHLCSample &sample, Qt::Orientation orientation, - bool inverted, double width ) const -{ - double w2 = 0.5 * width; - if ( inverted ) - w2 *= -1; - - if ( orientation == Qt::Vertical ) - { - QwtPainter::drawLine( painter, - sample.time, sample.low, sample.time, sample.high ); - - QwtPainter::drawLine( painter, - sample.time - w2, sample.open, sample.time, sample.open ); - QwtPainter::drawLine( painter, - sample.time + w2, sample.close, sample.time, sample.close ); - } - else - { - QwtPainter::drawLine( painter, sample.low, sample.time, - sample.high, sample.time ); - QwtPainter::drawLine( painter, - sample.open, sample.time - w2, sample.open, sample.time ); - QwtPainter::drawLine( painter, - sample.close, sample.time + w2, sample.close, sample.time ); - } -} - -/*! - \brief Draw a candle stick - - \param painter Qt painter, initialized with pen/brush - \param sample Samples already translated into paint device coordinates - \param orientation Vertical or horizontal - \param width Width or height of the candle, depending on the orientation - - \sa CandleStick -*/ -void QwtPlotTradingCurve::drawCandleStick( QPainter *painter, - const QwtOHLCSample &sample, Qt::Orientation orientation, - double width ) const -{ - const double t = sample.time; - const double v1 = qMin( sample.low, sample.high ); - const double v2 = qMin( sample.open, sample.close ); - const double v3 = qMax( sample.low, sample.high ); - const double v4 = qMax( sample.open, sample.close ); - - if ( orientation == Qt::Vertical ) - { - QwtPainter::drawLine( painter, t, v1, t, v2 ); - QwtPainter::drawLine( painter, t, v3, t, v4 ); - - QRectF rect( t - 0.5 * width, sample.open, - width, sample.close - sample.open ); - - QwtPainter::drawRect( painter, rect ); - } - else - { - QwtPainter::drawLine( painter, v1, t, v2, t ); - QwtPainter::drawLine( painter, v3, t, v4, t ); - - const QRectF rect( sample.open, t - 0.5 * width, - sample.close - sample.open, width ); - - QwtPainter::drawRect( painter, rect ); - } -} - -/*! - \return A rectangle filled with the color of the symbol pen - - \param index Index of the legend entry - ( usually there is only one ) - \param size Icon size - - \sa setLegendIconSize(), legendData() -*/ -QwtGraphic QwtPlotTradingCurve::legendIcon( int index, - const QSizeF &size ) const -{ - Q_UNUSED( index ); - return defaultIcon( d_data->symbolPen.color(), size ); -} - -/*! - Calculate the symbol width in paint coordinates - - The width is calculated by scaling the symbol extent into - paint device coordinates bounded by the minimum/maximum - symbol width. - - \param xMap Maps x-values into pixel coordinates. - \param yMap Maps y-values into pixel coordinates. - \param canvasRect Contents rectangle of the canvas - - \return Symbol width in paint coordinates - - \sa symbolExtent(), minSymbolWidth(), maxSymbolWidth() -*/ -double QwtPlotTradingCurve::scaledSymbolWidth( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - Q_UNUSED( canvasRect ); - - if ( d_data->maxSymbolWidth > 0.0 && - d_data->minSymbolWidth >= d_data->maxSymbolWidth ) - { - return d_data->minSymbolWidth; - } - - const QwtScaleMap *map = - ( orientation() == Qt::Vertical ) ? &xMap : &yMap; - - const double pos = map->transform( map->s1() + d_data->symbolExtent ); - - double width = qAbs( pos - map->p1() ); - - width = qMax( width, d_data->minSymbolWidth ); - if ( d_data->maxSymbolWidth > 0.0 ) - width = qMin( width, d_data->maxSymbolWidth ); - - return width; -} diff --git a/source/third_party/qwt/qwt_plot_xml.cpp b/source/third_party/qwt/qwt_plot_xml.cpp deleted file mode 100644 index a62a0f04d23e9cfdb660cc8a052f45f87edffb20..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_xml.cpp +++ /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 - *****************************************************************************/ - -#include "qwt/qwt_plot.h" - -/*! - This method is intended for manipulating the plot widget - from a specific editor in the Qwt designer plugin. - - \warning The plot editor has never been implemented. -*/ -void QwtPlot::applyProperties( const QString & /* xmlDocument */ ) -{ -#if 0 - // Temporary dummy code, for designer tests - setTitle( xmlDocument ); - replot(); -#endif -} - -/*! - This method is intended for manipulating the plot widget - from a specific editor in the Qwt designer plugin. - - \return QString::null - \warning The plot editor has never been implemented. -*/ -QString QwtPlot::grabProperties() const -{ -#if 0 - // Temporary dummy code, for designer tests - return title().text(); -#else - return QString::null; -#endif -} diff --git a/source/third_party/qwt/qwt_plot_zoneitem.cpp b/source/third_party/qwt/qwt_plot_zoneitem.cpp deleted file mode 100644 index cf74a79f102c2a3cb54713a4d99814dc8f835210..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_zoneitem.cpp +++ /dev/null @@ -1,315 +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/qwt_plot_zoneitem.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_map.h" -#include <qpainter.h> - -class QwtPlotZoneItem::PrivateData -{ -public: - PrivateData(): - orientation( Qt::Vertical ), - pen( Qt::NoPen ) - { - QColor c( Qt::darkGray ); - c.setAlpha( 100 ); - brush = QBrush( c ); - } - - Qt::Orientation orientation; - QPen pen; - QBrush brush; - QwtInterval interval; -}; - -/*! - \brief Constructor - - Initializes the zone with no pen and a semi transparent gray brush - - Sets the following item attributes: - - - QwtPlotItem::AutoScale: false - - QwtPlotItem::Legend: false - - The z value is initialized by 5 - - \sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ() -*/ -QwtPlotZoneItem::QwtPlotZoneItem(): - QwtPlotItem( QwtText( "Zone" ) ) -{ - d_data = new PrivateData; - - setItemAttribute( QwtPlotItem::AutoScale, false ); - setItemAttribute( QwtPlotItem::Legend, false ); - - setZ( 5 ); -} - -//! Destructor -QwtPlotZoneItem::~QwtPlotZoneItem() -{ - delete d_data; -} - -//! \return QwtPlotItem::Rtti_PlotZone -int QwtPlotZoneItem::rtti() const -{ - return QwtPlotItem::Rtti_PlotZone; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it - non cosmetic ( see QPen::isCosmetic() ). This method has been introduced - to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtPlotZoneItem::setPen( const QColor &color, qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - \brief Assign a pen - - The pen is used to draw the border lines of the zone - - \param pen Pen - \sa pen(), setBrush() -*/ -void QwtPlotZoneItem::setPen( const QPen &pen ) -{ - if ( d_data->pen != pen ) - { - d_data->pen = pen; - itemChanged(); - } -} - -/*! - \return Pen used to draw the border lines - \sa setPen(), brush() -*/ -const QPen &QwtPlotZoneItem::pen() const -{ - return d_data->pen; -} - -/*! - \brief Assign a brush - - The brush is used to fill the zone - - \param brush Brush - \sa pen(), setBrush() -*/ -void QwtPlotZoneItem::setBrush( const QBrush &brush ) -{ - if ( d_data->brush != brush ) - { - d_data->brush = brush; - itemChanged(); - } -} - -/*! - \return Brush used to fill the zone - \sa setPen(), brush() -*/ -const QBrush &QwtPlotZoneItem::brush() const -{ - return d_data->brush; -} - -/*! - \brief Set the orientation of the zone - - A horizontal zone highlights an interval of the y axis, - a vertical zone of the x axis. It is unbounded in the - opposite direction. - - \sa orientation(), QwtPlotItem::setAxes() -*/ -void QwtPlotZoneItem::setOrientation( Qt::Orientation orientation ) -{ - if ( d_data->orientation != orientation ) - { - d_data->orientation = orientation; - itemChanged(); - } -} - -/*! - \return Orientation of the zone - \sa setOrientation() - */ -Qt::Orientation QwtPlotZoneItem::orientation() -{ - return d_data->orientation; -} - -/*! - Set the interval of the zone - - For a horizontal zone the interval is related to the y axis, - for a vertical zone it is related to the x axis. - - \param min Minimum of the interval - \param max Maximum of the interval - - \sa interval(), setOrientation() - */ -void QwtPlotZoneItem::setInterval( double min, double max ) -{ - setInterval( QwtInterval( min, max ) ); -} - -/*! - Set the interval of the zone - - For a horizontal zone the interval is related to the y axis, - for a vertical zone it is related to the x axis. - - \param interval Zone interval - - \sa interval(), setOrientation() - */ -void QwtPlotZoneItem::setInterval( const QwtInterval &interval ) -{ - if ( d_data->interval != interval ) - { - d_data->interval = interval; - itemChanged(); - } -} - -/*! - \return Zone interval - \sa setInterval(), orientation() - */ -QwtInterval QwtPlotZoneItem::interval() const -{ - return d_data->interval; -} - -/*! - Draw the zone - - \param painter Painter - \param xMap x Scale Map - \param yMap y Scale Map - \param canvasRect Contents rectangle of the canvas in painter coordinates -*/ - -void QwtPlotZoneItem::draw( QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRectF &canvasRect ) const -{ - if ( !d_data->interval.isValid() ) - return; - - QPen pen = d_data->pen; - pen.setCapStyle( Qt::FlatCap ); - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - if ( d_data->orientation == Qt::Horizontal ) - { - double y1 = yMap.transform( d_data->interval.minValue() ); - double y2 = yMap.transform( d_data->interval.maxValue() ); - - if ( doAlign ) - { - y1 = qRound( y1 ); - y2 = qRound( y2 ); - } - - QRectF r( canvasRect.left(), y1, canvasRect.width(), y2 - y1 ); - r = r.normalized(); - - if ( ( d_data->brush.style() != Qt::NoBrush ) && ( y1 != y2 ) ) - { - QwtPainter::fillRect( painter, r, d_data->brush ); - } - - if ( d_data->pen.style() != Qt::NoPen ) - { - painter->setPen( d_data->pen ); - - QwtPainter::drawLine( painter, r.left(), r.top(), r.right(), r.top() ); - QwtPainter::drawLine( painter, r.left(), r.bottom(), r.right(), r.bottom() ); - } - } - else - { - double x1 = xMap.transform( d_data->interval.minValue() ); - double x2 = xMap.transform( d_data->interval.maxValue() ); - - if ( doAlign ) - { - x1 = qRound( x1 ); - x2 = qRound( x2 ); - } - - QRectF r( x1, canvasRect.top(), x2 - x1, canvasRect.height() ); - r = r.normalized(); - - if ( ( d_data->brush.style() != Qt::NoBrush ) && ( x1 != x2 ) ) - { - QwtPainter::fillRect( painter, r, d_data->brush ); - } - - if ( d_data->pen.style() != Qt::NoPen ) - { - painter->setPen( d_data->pen ); - - QwtPainter::drawLine( painter, r.left(), r.top(), r.left(), r.bottom() ); - QwtPainter::drawLine( painter, r.right(), r.top(), r.right(), r.bottom() ); - } - } -} - -/*! - The bounding rectangle is build from the interval in one direction - and something invalid for the opposite direction. - - \return An invalid rectangle with valid boundaries in one direction -*/ -QRectF QwtPlotZoneItem::boundingRect() const -{ - QRectF br = QwtPlotItem::boundingRect(); - - const QwtInterval &intv = d_data->interval; - - if ( intv.isValid() ) - { - if ( d_data->orientation == Qt::Horizontal ) - { - br.setTop( intv.minValue() ); - br.setBottom( intv.maxValue() ); - } - else - { - br.setLeft( intv.minValue() ); - br.setRight( intv.maxValue() ); - } - } - - return br; -} diff --git a/source/third_party/qwt/qwt_plot_zoomer.cpp b/source/third_party/qwt/qwt_plot_zoomer.cpp deleted file mode 100644 index 4ea8f2ae562e4815df29f85639980c30dbbf9ef1..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_plot_zoomer.cpp +++ /dev/null @@ -1,664 +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/qwt_plot_zoomer.h" -#include "qwt/qwt_plot.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_picker_machine.h" -#include <qalgorithms.h> - -static QwtInterval qwtExpandedZoomInterval( double v1, double v2, - double minRange, const QwtTransform* transform ) -{ - double min = v1; - double max = v2; - - if ( max - min < minRange ) - { - min = 0.5 * ( min + max - minRange ); - max = min + minRange; - - if ( transform ) - { - // f.e the logarithmic scale doesn't allow values - // outside [QwtLogTransform::LogMin/QwtLogTransform::LogMax] - - double minBounded = transform->bounded( min ); - double maxBounded = transform->bounded( max ); - - if ( minBounded != min ) - { - maxBounded = transform->bounded( minBounded + minRange ); - } - else if ( maxBounded != max ) - { - minBounded = transform->bounded( maxBounded - minRange ); - } - - min = minBounded; - max = maxBounded; - } - } - - return QwtInterval( min, max ); -} - -static QRectF qwtExpandedZoomRect( const QRectF &zoomRect, const QSizeF &minSize, - const QwtTransform* transformX, const QwtTransform* transformY ) -{ - QRectF r = zoomRect; - - if ( minSize.width() > r.width() ) - { - const QwtInterval intv = qwtExpandedZoomInterval( - r.left(), r.right(), minSize.width(), transformX ); - - r.setLeft( intv.minValue() ); - r.setRight( intv.maxValue() ); - } - - if ( minSize.height() > r.height() ) - { - const QwtInterval intv = qwtExpandedZoomInterval( - zoomRect.top(), zoomRect.bottom(), minSize.height(), transformY ); - - r.setTop( intv.minValue() ); - r.setBottom( intv.maxValue() ); - } - - return r; -} - -class QwtPlotZoomer::PrivateData -{ -public: - uint zoomRectIndex; - QStack<QRectF> zoomStack; - - int maxStackDepth; -}; - -/*! - \brief Create a zoomer for a plot canvas. - - The zoomer is set to those x- and y-axis of the parent plot of the - canvas that are enabled. If both or no x-axis are enabled, the picker - is set to QwtPlot::xBottom. If both or no y-axis are - enabled, it is set to QwtPlot::yLeft. - - The zoomer is initialized with a QwtPickerDragRectMachine, - the tracker mode is set to QwtPicker::ActiveOnly and the rubber band - is set to QwtPicker::RectRubberBand - - \param canvas Plot canvas to observe, also the parent object - \param doReplot Call QwtPlot::replot() for the attached plot before initializing - the zoomer with its scales. This might be necessary, - when the plot is in a state with pending scale changes. - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase() -*/ -QwtPlotZoomer::QwtPlotZoomer( QWidget *canvas, bool doReplot ): - QwtPlotPicker( canvas ) -{ - if ( canvas ) - init( doReplot ); -} - -/*! - \brief Create a zoomer for a plot canvas. - - The zoomer is initialized with a QwtPickerDragRectMachine, - the tracker mode is set to QwtPicker::ActiveOnly and the rubber band - is set to QwtPicker;;RectRubberBand - - \param xAxis X axis of the zoomer - \param yAxis Y axis of the zoomer - \param canvas Plot canvas to observe, also the parent object - \param doReplot Call QwtPlot::replot() for the attached plot before initializing - the zoomer with its scales. This might be necessary, - when the plot is in a state with pending scale changes. - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase() -*/ - -QwtPlotZoomer::QwtPlotZoomer( int xAxis, int yAxis, - QWidget *canvas, bool doReplot ): - QwtPlotPicker( xAxis, yAxis, canvas ) -{ - if ( canvas ) - init( doReplot ); -} - -//! Init the zoomer, used by the constructors -void QwtPlotZoomer::init( bool doReplot ) -{ - d_data = new PrivateData; - - d_data->maxStackDepth = -1; - - setTrackerMode( ActiveOnly ); - setRubberBand( RectRubberBand ); - setStateMachine( new QwtPickerDragRectMachine() ); - - if ( doReplot && plot() ) - plot()->replot(); - - setZoomBase( scaleRect() ); -} - -QwtPlotZoomer::~QwtPlotZoomer() -{ - delete d_data; -} - -/*! - \brief Limit the number of recursive zoom operations to depth. - - A value of -1 set the depth to unlimited, 0 disables zooming. - If the current zoom rectangle is below depth, the plot is unzoomed. - - \param depth Maximum for the stack depth - \sa maxStackDepth() - \note depth doesn't include the zoom base, so zoomStack().count() might be - maxStackDepth() + 1. -*/ -void QwtPlotZoomer::setMaxStackDepth( int depth ) -{ - d_data->maxStackDepth = depth; - - if ( depth >= 0 ) - { - // unzoom if the current depth is below d_data->maxStackDepth - - const int zoomOut = - int( d_data->zoomStack.count() ) - 1 - depth; // -1 for the zoom base - - if ( zoomOut > 0 ) - { - zoom( -zoomOut ); - for ( int i = int( d_data->zoomStack.count() ) - 1; - i > int( d_data->zoomRectIndex ); i-- ) - { - ( void )d_data->zoomStack.pop(); // remove trailing rects - } - } - } -} - -/*! - \return Maximal depth of the zoom stack. - \sa setMaxStackDepth() -*/ -int QwtPlotZoomer::maxStackDepth() const -{ - return d_data->maxStackDepth; -} - -/*! - \return The zoom stack. zoomStack()[0] is the zoom base, - zoomStack()[1] the first zoomed rectangle. - - \sa setZoomStack(), zoomRectIndex() -*/ -const QStack<QRectF> &QwtPlotZoomer::zoomStack() const -{ - return d_data->zoomStack; -} - -/*! - \return Initial rectangle of the zoomer - \sa setZoomBase(), zoomRect() -*/ -QRectF QwtPlotZoomer::zoomBase() const -{ - return d_data->zoomStack[0]; -} - -/*! - Reinitialized the zoom stack with scaleRect() as base. - - \param doReplot Call QwtPlot::replot() for the attached plot before initializing - the zoomer with its scales. This might be necessary, - when the plot is in a state with pending scale changes. - - \sa zoomBase(), scaleRect() QwtPlot::autoReplot(), QwtPlot::replot(). -*/ -void QwtPlotZoomer::setZoomBase( bool doReplot ) -{ - QwtPlot *plt = plot(); - if ( plt == NULL ) - return; - - if ( doReplot ) - plt->replot(); - - d_data->zoomStack.clear(); - d_data->zoomStack.push( scaleRect() ); - d_data->zoomRectIndex = 0; - - rescale(); -} - -/*! - \brief Set the initial size of the zoomer. - - base is united with the current scaleRect() and the zoom stack is - reinitialized with it as zoom base. plot is zoomed to scaleRect(). - - \param base Zoom base - - \sa zoomBase(), scaleRect() -*/ -void QwtPlotZoomer::setZoomBase( const QRectF &base ) -{ - const QwtPlot *plt = plot(); - if ( !plt ) - return; - - const QRectF sRect = scaleRect(); - const QRectF bRect = base | sRect; - - d_data->zoomStack.clear(); - d_data->zoomStack.push( bRect ); - d_data->zoomRectIndex = 0; - - if ( base != sRect ) - { - d_data->zoomStack.push( sRect ); - d_data->zoomRectIndex++; - } - - rescale(); -} - -/*! - \return Rectangle at the current position on the zoom stack. - \sa zoomRectIndex(), scaleRect(). -*/ -QRectF QwtPlotZoomer::zoomRect() const -{ - return d_data->zoomStack[d_data->zoomRectIndex]; -} - -/*! - \return Index of current position of zoom stack. -*/ -uint QwtPlotZoomer::zoomRectIndex() const -{ - return d_data->zoomRectIndex; -} - -/*! - \brief Zoom in - - Clears all rectangles above the current position of the - zoom stack and pushes the normalized rectangle on it. - - \note If the maximal stack depth is reached, zoom is ignored. - \note The zoomed signal is emitted. -*/ - -void QwtPlotZoomer::zoom( const QRectF &rect ) -{ - if ( d_data->maxStackDepth >= 0 && - int( d_data->zoomRectIndex ) >= d_data->maxStackDepth ) - { - return; - } - - const QRectF zoomRect = rect.normalized(); - if ( zoomRect != d_data->zoomStack[d_data->zoomRectIndex] ) - { - for ( uint i = int( d_data->zoomStack.count() ) - 1; - i > d_data->zoomRectIndex; i-- ) - { - ( void )d_data->zoomStack.pop(); - } - - d_data->zoomStack.push( zoomRect ); - d_data->zoomRectIndex++; - - rescale(); - - Q_EMIT zoomed( zoomRect ); - } -} - -/*! - \brief Zoom in or out - - Activate a rectangle on the zoom stack with an offset relative - to the current position. Negative values of offset will zoom out, - positive zoom in. A value of 0 zooms out to the zoom base. - - \param offset Offset relative to the current position of the zoom stack. - \note The zoomed signal is emitted. - \sa zoomRectIndex() -*/ -void QwtPlotZoomer::zoom( int offset ) -{ - if ( offset == 0 ) - d_data->zoomRectIndex = 0; - else - { - int newIndex = d_data->zoomRectIndex + offset; - newIndex = qMax( 0, newIndex ); - newIndex = qMin( int( d_data->zoomStack.count() ) - 1, newIndex ); - - d_data->zoomRectIndex = uint( newIndex ); - } - - rescale(); - - Q_EMIT zoomed( zoomRect() ); -} - -/*! - \brief Assign a zoom stack - - In combination with other types of navigation it might be useful to - modify to manipulate the complete zoom stack. - - \param zoomStack New zoom stack - \param zoomRectIndex Index of the current position of zoom stack. - In case of -1 the current position is at the top - of the stack. - - \note The zoomed signal might be emitted. - \sa zoomStack(), zoomRectIndex() -*/ -void QwtPlotZoomer::setZoomStack( - const QStack<QRectF> &zoomStack, int zoomRectIndex ) -{ - if ( zoomStack.isEmpty() ) - return; - - if ( d_data->maxStackDepth >= 0 && - int( zoomStack.count() ) > d_data->maxStackDepth ) - { - return; - } - - if ( zoomRectIndex < 0 || zoomRectIndex > int( zoomStack.count() ) ) - zoomRectIndex = zoomStack.count() - 1; - - const bool doRescale = zoomStack[zoomRectIndex] != zoomRect(); - - d_data->zoomStack = zoomStack; - d_data->zoomRectIndex = uint( zoomRectIndex ); - - if ( doRescale ) - { - rescale(); - Q_EMIT zoomed( zoomRect() ); - } -} - -/*! - Adjust the observed plot to zoomRect() - - \note Initiates QwtPlot::replot() -*/ - -void QwtPlotZoomer::rescale() -{ - QwtPlot *plt = plot(); - if ( !plt ) - return; - - const QRectF &rect = d_data->zoomStack[d_data->zoomRectIndex]; - if ( rect != scaleRect() ) - { - const bool doReplot = plt->autoReplot(); - plt->setAutoReplot( false ); - - double x1 = rect.left(); - double x2 = rect.right(); - if ( !plt->axisScaleDiv( xAxis() ).isIncreasing() ) - qSwap( x1, x2 ); - - plt->setAxisScale( xAxis(), x1, x2 ); - - double y1 = rect.top(); - double y2 = rect.bottom(); - if ( !plt->axisScaleDiv( yAxis() ).isIncreasing() ) - qSwap( y1, y2 ); - - plt->setAxisScale( yAxis(), y1, y2 ); - - plt->setAutoReplot( doReplot ); - - plt->replot(); - } -} - -/*! - Reinitialize the axes, and set the zoom base to their scales. - - \param xAxis X axis - \param yAxis Y axis -*/ - -void QwtPlotZoomer::setAxis( int xAxis, int yAxis ) -{ - if ( xAxis != QwtPlotPicker::xAxis() || yAxis != QwtPlotPicker::yAxis() ) - { - QwtPlotPicker::setAxis( xAxis, yAxis ); - setZoomBase( scaleRect() ); - } -} - -/*! - Qt::MidButton zooms out one position on the zoom stack, - Qt::RightButton to the zoom base. - - Changes the current position on the stack, but doesn't pop - any rectangle. - - \note The mouse events can be changed, using - QwtEventPattern::setMousePattern: 2, 1 -*/ -void QwtPlotZoomer::widgetMouseReleaseEvent( QMouseEvent *me ) -{ - if ( mouseMatch( MouseSelect2, me ) ) - zoom( 0 ); - else if ( mouseMatch( MouseSelect3, me ) ) - zoom( -1 ); - else if ( mouseMatch( MouseSelect6, me ) ) - zoom( +1 ); - else - QwtPlotPicker::widgetMouseReleaseEvent( me ); -} - -/*! - Qt::Key_Plus zooms in, Qt::Key_Minus zooms out one position on the - zoom stack, Qt::Key_Escape zooms out to the zoom base. - - Changes the current position on the stack, but doesn't pop - any rectangle. - - \note The keys codes can be changed, using - QwtEventPattern::setKeyPattern: 3, 4, 5 -*/ - -void QwtPlotZoomer::widgetKeyPressEvent( QKeyEvent *ke ) -{ - if ( !isActive() ) - { - if ( keyMatch( KeyUndo, ke ) ) - zoom( -1 ); - else if ( keyMatch( KeyRedo, ke ) ) - zoom( +1 ); - else if ( keyMatch( KeyHome, ke ) ) - zoom( 0 ); - } - - QwtPlotPicker::widgetKeyPressEvent( ke ); -} - -/*! - Move the current zoom rectangle. - - \param dx X offset - \param dy Y offset - - \note The changed rectangle is limited by the zoom base -*/ -void QwtPlotZoomer::moveBy( double dx, double dy ) -{ - const QRectF &rect = d_data->zoomStack[d_data->zoomRectIndex]; - moveTo( QPointF( rect.left() + dx, rect.top() + dy ) ); -} - -/*! - Move the the current zoom rectangle. - - \param pos New position - - \sa QRectF::moveTo() - \note The changed rectangle is limited by the zoom base -*/ -void QwtPlotZoomer::moveTo( const QPointF &pos ) -{ - double x = pos.x(); - double y = pos.y(); - - if ( x < zoomBase().left() ) - x = zoomBase().left(); - if ( x > zoomBase().right() - zoomRect().width() ) - x = zoomBase().right() - zoomRect().width(); - - if ( y < zoomBase().top() ) - y = zoomBase().top(); - if ( y > zoomBase().bottom() - zoomRect().height() ) - y = zoomBase().bottom() - zoomRect().height(); - - if ( x != zoomRect().left() || y != zoomRect().top() ) - { - d_data->zoomStack[d_data->zoomRectIndex].moveTo( x, y ); - rescale(); - } -} - -/*! - \brief Check and correct a selected rectangle - - Reject rectangles with a height or width < 2, otherwise - expand the selected rectangle to a minimum size of 11x11 - and accept it. - - \return true If the rectangle is accepted, or has been changed - to an accepted one. -*/ - -bool QwtPlotZoomer::accept( QPolygon &pa ) const -{ - if ( pa.count() < 2 ) - return false; - - QRect rect = QRect( pa[0], pa[int( pa.count() ) - 1] ); - rect = rect.normalized(); - - const int minSize = 2; - if ( rect.width() < minSize && rect.height() < minSize ) - return false; - - const int minZoomSize = 11; - - const QPoint center = rect.center(); - rect.setSize( rect.size().expandedTo( QSize( minZoomSize, minZoomSize ) ) ); - rect.moveCenter( center ); - - pa.resize( 2 ); - pa[0] = rect.topLeft(); - pa[1] = rect.bottomRight(); - - return true; -} - -/*! - \brief Limit zooming by a minimum rectangle - - \return zoomBase().width() / 10e4, zoomBase().height() / 10e4 -*/ -QSizeF QwtPlotZoomer::minZoomSize() const -{ - return QSizeF( d_data->zoomStack[0].width() / 10e4, - d_data->zoomStack[0].height() / 10e4 ); -} - -/*! - Rejects selections, when the stack depth is too deep, or - the zoomed rectangle is minZoomSize(). - - \sa minZoomSize(), maxStackDepth() -*/ -void QwtPlotZoomer::begin() -{ - if ( d_data->maxStackDepth >= 0 ) - { - if ( d_data->zoomRectIndex >= uint( d_data->maxStackDepth ) ) - return; - } - - const QSizeF minSize = minZoomSize(); - if ( minSize.isValid() ) - { - const QSizeF sz = - d_data->zoomStack[d_data->zoomRectIndex].size() * 0.9999; - - if ( minSize.width() >= sz.width() && - minSize.height() >= sz.height() ) - { - return; - } - } - - QwtPlotPicker::begin(); -} - -/*! - Expand the selected rectangle to minZoomSize() and zoom in - if accepted. - - \param ok If true, complete the selection and emit selected signals - otherwise discard the selection. - - \sa accept(), minZoomSize() - \return True if the selection has been accepted, false otherwise -*/ -bool QwtPlotZoomer::end( bool ok ) -{ - ok = QwtPlotPicker::end( ok ); - if ( !ok ) - return false; - - QwtPlot *plot = QwtPlotZoomer::plot(); - if ( !plot ) - return false; - - const QPolygon &pa = selection(); - if ( pa.count() < 2 ) - return false; - - QRect rect = QRect( pa[0], pa[int( pa.count() - 1 )] ); - rect = rect.normalized(); - - const QwtScaleMap xMap = plot->canvasMap( xAxis() ); - const QwtScaleMap yMap = plot->canvasMap( yAxis() ); - - QRectF zoomRect = QwtScaleMap::invTransform( xMap, yMap, rect ).normalized(); - - zoomRect = qwtExpandedZoomRect( zoomRect, minZoomSize(), - xMap.transformation(), yMap.transformation() ); - - zoom( zoomRect ); - - return true; -} diff --git a/source/third_party/qwt/qwt_point_3d.cpp b/source/third_party/qwt/qwt_point_3d.cpp deleted file mode 100644 index d489a3b71f327f2f8d390f7b1411281c3bc72953..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_point_3d.cpp +++ /dev/null @@ -1,22 +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/qwt_point_3d.h" - -#ifndef QT_NO_DEBUG_STREAM - -QDebug operator<<( QDebug debug, const QwtPoint3D &point ) -{ - debug.nospace() << "QwtPoint3D(" << point.x() - << "," << point.y() << "," << point.z() << ")"; - return debug.space(); -} - -#endif - diff --git a/source/third_party/qwt/qwt_point_data.cpp b/source/third_party/qwt/qwt_point_data.cpp deleted file mode 100644 index 86cde212c3cacab0aab4898568d12b1efb9c79d4..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_point_data.cpp +++ /dev/null @@ -1,307 +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/qwt_point_data.h" -#include "qwt/qwt_math.h" -#include <string.h> - -/*! - Constructor - - \param x Array of x values - \param y Array of y values - - \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples() -*/ -QwtPointArrayData::QwtPointArrayData( - const QVector<double> &x, const QVector<double> &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(), QwtPlotCurve::setSamples() -*/ -QwtPointArrayData::QwtPointArrayData( const double *x, - const double *y, size_t size ) -{ - d_x.resize( size ); - ::memcpy( d_x.data(), x, size * sizeof( double ) ); - - d_y.resize( size ); - ::memcpy( d_y.data(), y, size * sizeof( double ) ); -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtPointArrayData::boundingRect() const -{ - if ( d_boundingRect.width() < 0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} - -//! \return Size of the data set -size_t QwtPointArrayData::size() const -{ - return qMin( d_x.size(), d_y.size() ); -} - -/*! - Return the sample at position i - - \param index Index - \return Sample at position i -*/ -QPointF QwtPointArrayData::sample( size_t index ) const -{ - return QPointF( d_x[int( index )], d_y[int( index )] ); -} - -//! \return Array of the x-values -const QVector<double> &QwtPointArrayData::xData() const -{ - return d_x; -} - -//! \return Array of the y-values -const QVector<double> &QwtPointArrayData::yData() const -{ - return d_y; -} - -/*! - 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::setRawSamples() -*/ -QwtCPointerData::QwtCPointerData( - const double *x, const double *y, size_t size ): - d_x( x ), - d_y( y ), - d_size( size ) -{ -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtCPointerData::boundingRect() const -{ - if ( d_boundingRect.width() < 0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} - -//! \return Size of the data set -size_t QwtCPointerData::size() const -{ - return d_size; -} - -/*! - Return the sample at position i - - \param index Index - \return Sample at position i -*/ -QPointF QwtCPointerData::sample( size_t index ) const -{ - return QPointF( d_x[int( index )], d_y[int( index )] ); -} - -//! \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; -} - -/*! - Constructor - - \param size Number of points - \param interval Bounding interval for the points - - \sa setInterval(), setSize() -*/ -QwtSyntheticPointData::QwtSyntheticPointData( - size_t size, const QwtInterval &interval ): - d_size( size ), - d_interval( interval ) -{ -} - -/*! - Change the number of points - - \param size Number of points - \sa size(), setInterval() -*/ -void QwtSyntheticPointData::setSize( size_t size ) -{ - d_size = size; -} - -/*! - \return Number of points - \sa setSize(), interval() -*/ -size_t QwtSyntheticPointData::size() const -{ - return d_size; -} - -/*! - Set the bounding interval - - \param interval Interval - \sa interval(), setSize() -*/ -void QwtSyntheticPointData::setInterval( const QwtInterval &interval ) -{ - d_interval = interval.normalized(); -} - -/*! - \return Bounding interval - \sa setInterval(), size() -*/ -QwtInterval QwtSyntheticPointData::interval() const -{ - return d_interval; -} - -/*! - Set a the "rectangle of interest" - - QwtPlotSeriesItem defines the current area of the plot canvas - as "rect of interest" ( QwtPlotSeriesItem::updateScaleDiv() ). - - If interval().isValid() == false the x values are calculated - in the interval rect.left() -> rect.right(). - - \sa rectOfInterest() -*/ -void QwtSyntheticPointData::setRectOfInterest( const QRectF &rect ) -{ - d_rectOfInterest = rect; - d_intervalOfInterest = QwtInterval( - rect.left(), rect.right() ).normalized(); -} - -/*! - \return "rectangle of interest" - \sa setRectOfInterest() -*/ -QRectF QwtSyntheticPointData::rectOfInterest() const -{ - return d_rectOfInterest; -} - -/*! - \brief Calculate the bounding rectangle - - This implementation iterates over all points, what could often - be implemented much faster using the characteristics of the series. - When there are many points it is recommended to overload and - reimplement this method using the characteristics of the series - ( if possible ). - - \return Bounding rectangle -*/ -QRectF QwtSyntheticPointData::boundingRect() const -{ - if ( d_size == 0 || - !( d_interval.isValid() || d_intervalOfInterest.isValid() ) ) - { - return QRectF( 1.0, 1.0, -2.0, -2.0 ); // something invalid - } - - return qwtBoundingRect( *this ); -} - -/*! - Calculate the point from an index - - \param index Index - \return QPointF(x(index), y(x(index))); - - \warning For invalid indices ( index < 0 || index >= size() ) - (0, 0) is returned. -*/ -QPointF QwtSyntheticPointData::sample( size_t index ) const -{ - if ( index >= d_size ) - return QPointF( 0, 0 ); - - const double xValue = x( index ); - const double yValue = y( xValue ); - - return QPointF( xValue, yValue ); -} - -/*! - Calculate a x-value from an index - - x values are calculated by dividing an interval into - equidistant steps. If !interval().isValid() the - interval is calculated from the "rectangle of interest". - - \param index Index of the requested point - \return Calculated x coordinate - - \sa interval(), rectOfInterest(), y() -*/ -double QwtSyntheticPointData::x( uint index ) const -{ - const QwtInterval &interval = d_interval.isValid() ? - d_interval : d_intervalOfInterest; - - if ( !interval.isValid() ) - return 0.0; - - if ( d_size <= 1 ) - return interval.minValue(); - - const double dx = interval.width() / ( d_size - 1 ); - return interval.minValue() + index * dx; -} diff --git a/source/third_party/qwt/qwt_point_mapper.cpp b/source/third_party/qwt/qwt_point_mapper.cpp deleted file mode 100644 index f537c1a687ed90bd426315b094e552e68de58013..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_point_mapper.cpp +++ /dev/null @@ -1,717 +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/qwt_point_mapper.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_pixel_matrix.h" -#include <qpolygon.h> -#include <qimage.h> -#include <qpen.h> -#include <qpainter.h> - -#if QT_VERSION >= 0x040400 - -#include <qthread.h> -#include <qfuture.h> -#include <QtConcurrent/qtconcurrentrun.h> - -#if !defined(QT_NO_QFUTURE) -#define QWT_USE_THREADS 0 -#endif - -#endif - -static QRectF qwtInvalidRect( 0.0, 0.0, -1.0, -1.0 ); - -// Helper class to work around the 5 parameters -// limitation of QtConcurrent::run() -class QwtDotsCommand -{ -public: - const QwtSeriesData<QPointF> *series; - int from; - int to; - QRgb rgb; -}; - -static void qwtRenderDots( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtDotsCommand command, const QPoint &pos, QImage *image ) -{ - const QRgb rgb = command.rgb; - QRgb *bits = reinterpret_cast<QRgb *>( image->bits() ); - - const int w = image->width(); - const int h = image->height(); - - const int x0 = pos.x(); - const int y0 = pos.y(); - - for ( int i = command.from; i <= command.to; i++ ) - { - const QPointF sample = command.series->sample( i ); - - const int x = static_cast<int>( xMap.transform( sample.x() ) + 0.5 ) - x0; - const int y = static_cast<int>( yMap.transform( sample.y() ) + 0.5 ) - y0; - - if ( x >= 0 && x < w && y >= 0 && y < h ) - bits[ y * w + x ] = rgb; - } -} - -static inline int qwtRoundValue( double value ) -{ - return qRound( value ); -} - -// some functors, so that the compile can inline -struct QwtRoundI -{ - inline int operator()( double value ) - { - return qwtRoundValue( value ); - } -}; - -struct QwtRoundF -{ - inline double operator()( double value ) - { -#if 1 - // MS Windows and at least IRIX does not have C99's nearbyint() function - return ( value >= 0.0 ) ? ::floor( value + 0.5 ) : ::ceil( value - 0.5 ); -#else - // slightly faster than the code above - return nearbyint( value ); -#endif - } -}; - -struct QwtNoRoundF -{ - inline double operator()( double value ) - { - return value; - } -}; - -// mapping points without any filtering - beside checking -// the bounding rectangle - -template<class Polygon, class Point, class Round> -static inline Polygon qwtToPoints( - const QRectF &boundingRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, - int from, int to, Round round ) -{ - Polygon polyline( to - from + 1 ); - Point *points = polyline.data(); - - int numPoints = 0; - - if ( boundingRect.isValid() ) - { - // iterating over all values - // filtering out all points outside of - // the bounding rectangle - - for ( int i = from; i <= to; i++ ) - { - const QPointF sample = series->sample( i ); - - const double x = xMap.transform( sample.x() ); - const double y = yMap.transform( sample.y() ); - - if ( boundingRect.contains( x, y ) ) - { - points[ numPoints ].rx() = round( x ); - points[ numPoints ].ry() = round( y ); - - numPoints++; - } - } - - polyline.resize( numPoints ); - } - else - { - // simply iterating over all values - // without any filtering - - for ( int i = from; i <= to; i++ ) - { - const QPointF sample = series->sample( i ); - - const double x = xMap.transform( sample.x() ); - const double y = yMap.transform( sample.y() ); - - points[ numPoints ].rx() = round( x ); - points[ numPoints ].ry() = round( y ); - - numPoints++; - } - } - - return polyline; -} - -static inline QPolygon qwtToPointsI( - const QRectF &boundingRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, - int from, int to ) -{ - return qwtToPoints<QPolygon, QPoint>( - boundingRect, xMap, yMap, series, from, to, QwtRoundI() ); -} - -template<class Round> -static inline QPolygonF qwtToPointsF( - const QRectF &boundingRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, - int from, int to, Round round ) -{ - return qwtToPoints<QPolygonF, QPointF>( - boundingRect, xMap, yMap, series, from, to, round ); -} - -// Mapping points with filtering out consecutive -// points mapped to the same position - -template<class Polygon, class Point, class Round> -static inline Polygon qwtToPolylineFiltered( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, - int from, int to, Round round ) -{ - // in curves with many points consecutive points - // are often mapped to the same position. As this might - // result in empty lines ( or symbols hidden by others ) - // we try to filter them out - - Polygon polyline( to - from + 1 ); - Point *points = polyline.data(); - - const QPointF sample0 = series->sample( from ); - - points[0].rx() = round( xMap.transform( sample0.x() ) ); - points[0].ry() = round( yMap.transform( sample0.y() ) ); - - int pos = 0; - for ( int i = from + 1; i <= to; i++ ) - { - const QPointF sample = series->sample( i ); - - const Point p( round( xMap.transform( sample.x() ) ), - round( yMap.transform( sample.y() ) ) ); - - if ( points[pos] != p ) - points[++pos] = p; - } - - polyline.resize( pos + 1 ); - return polyline; -} - -static inline QPolygon qwtToPolylineFilteredI( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, - int from, int to ) -{ - return qwtToPolylineFiltered<QPolygon, QPoint>( - xMap, yMap, series, from, to, QwtRoundI() ); -} - -template<class Round> -static inline QPolygonF qwtToPolylineFilteredF( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, - int from, int to, Round round ) -{ - return qwtToPolylineFiltered<QPolygonF, QPointF>( - xMap, yMap, series, from, to, round ); -} - -template<class Polygon, class Point> -static inline Polygon qwtToPointsFiltered( - const QRectF &boundingRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) -{ - // F.e. in scatter plots ( no connecting lines ) we - // can sort out all duplicates ( not only consecutive points ) - - Polygon polygon( to - from + 1 ); - Point *points = polygon.data(); - - QwtPixelMatrix pixelMatrix( boundingRect.toAlignedRect() ); - - int numPoints = 0; - for ( int i = from; i <= to; i++ ) - { - const QPointF sample = series->sample( i ); - - const int x = qwtRoundValue( xMap.transform( sample.x() ) ); - const int y = qwtRoundValue( yMap.transform( sample.y() ) ); - - if ( pixelMatrix.testAndSetPixel( x, y, true ) == false ) - { - points[ numPoints ].rx() = x; - points[ numPoints ].ry() = y; - - numPoints++; - } - } - - polygon.resize( numPoints ); - return polygon; -} - -static inline QPolygon qwtToPointsFilteredI( - const QRectF &boundingRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) -{ - return qwtToPointsFiltered<QPolygon, QPoint>( - boundingRect, xMap, yMap, series, from, to ); -} - -static inline QPolygonF qwtToPointsFilteredF( - const QRectF &boundingRect, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) -{ - return qwtToPointsFiltered<QPolygonF, QPointF>( - boundingRect, xMap, yMap, series, from, to ); -} - -class QwtPointMapper::PrivateData -{ -public: - PrivateData(): - boundingRect( qwtInvalidRect ) - { - } - - QRectF boundingRect; - QwtPointMapper::TransformationFlags flags; -}; - -//! Constructor -QwtPointMapper::QwtPointMapper() -{ - d_data = new PrivateData(); -} - -//! Destructor -QwtPointMapper::~QwtPointMapper() -{ - delete d_data; -} - -/*! - Set the flags affecting the transformation process - - \param flags Flags - \sa flags(), setFlag() - */ -void QwtPointMapper::setFlags( TransformationFlags flags ) -{ - d_data->flags = flags; -} - -/*! - \return Flags affecting the transformation process - \sa setFlags(), setFlag() - */ -QwtPointMapper::TransformationFlags QwtPointMapper::flags() const -{ - return d_data->flags; -} - -/*! - Modify a flag affecting the transformation process - - \param flag Flag type - \param on Value - - \sa flag(), setFlags() - */ -void QwtPointMapper::setFlag( TransformationFlag flag, bool on ) -{ - if ( on ) - d_data->flags |= flag; - else - d_data->flags &= ~flag; -} - -/*! - \return True, when the flag is set - \param flag Flag type - \sa setFlag(), setFlags() - */ -bool QwtPointMapper::testFlag( TransformationFlag flag ) const -{ - return d_data->flags & flag; -} - -/*! - Set a bounding rectangle for the point mapping algorithm - - A valid bounding rectangle can be used for optimizations - - \param rect Bounding rectangle - \sa boundingRect() - */ -void QwtPointMapper::setBoundingRect( const QRectF &rect ) -{ - d_data->boundingRect = rect; -} - -/*! - \return Bounding rectangle - \sa setBoundingRect() - */ -QRectF QwtPointMapper::boundingRect() const -{ - return d_data->boundingRect; -} - -/*! - \brief Translate a series of points into a QPolygonF - - When the WeedOutPoints flag is enabled consecutive points, - that are mapped to the same position will be one point. - - When RoundPoints is set all points are rounded to integers - but returned as PolygonF - what only makes sense - when the further processing of the values need a QPolygonF. - - \param xMap x map - \param yMap y map - \param series Series of points to be mapped - \param from Index of the first point to be painted - \param to Index of the last point to be painted - - \return Translated polygon -*/ -QPolygonF QwtPointMapper::toPolygonF( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const -{ - QPolygonF polyline; - - if ( d_data->flags & WeedOutPoints ) - { - if ( d_data->flags & RoundPoints ) - { - polyline = qwtToPolylineFilteredF( - xMap, yMap, series, from, to, QwtRoundF() ); - } - else - { - polyline = qwtToPolylineFilteredF( - xMap, yMap, series, from, to, QwtNoRoundF() ); - } - } - else - { - if ( d_data->flags & RoundPoints ) - { - polyline = qwtToPointsF( qwtInvalidRect, - xMap, yMap, series, from, to, QwtRoundF() ); - } - else - { - polyline = qwtToPointsF( qwtInvalidRect, - xMap, yMap, series, from, to, QwtNoRoundF() ); - } - } - - return polyline; -} - -/*! - \brief Translate a series of points into a QPolygon - - When the WeedOutPoints flag is enabled consecutive points, - that are mapped to the same position will be one point. - - \param xMap x map - \param yMap y map - \param series Series of points to be mapped - \param from Index of the first point to be painted - \param to Index of the last point to be painted - - \return Translated polygon -*/ -QPolygon QwtPointMapper::toPolygon( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const -{ - QPolygon polyline; - - if ( d_data->flags & WeedOutPoints ) - { - polyline = qwtToPolylineFilteredI( - xMap, yMap, series, from, to ); - } - else - { - polyline = qwtToPointsI( - qwtInvalidRect, xMap, yMap, series, from, to ); - } - - return polyline; -} - -/*! - \brief Translate a series into a QPolygonF - - - WeedOutPoints & RoundPoints & boundingRect().isValid() - All points that are mapped to the same position - will be one point. Points outside of the bounding - rectangle are ignored. - - - WeedOutPoints & RoundPoints & !boundingRect().isValid() - All consecutive points that are mapped to the same position - will one point - - - WeedOutPoints & !RoundPoints - All consecutive points that are mapped to the same position - will one point - - - !WeedOutPoints & boundingRect().isValid() - Points outside of the bounding rectangle are ignored. - - When RoundPoints is set all points are rounded to integers - but returned as PolygonF - what only makes sense - when the further processing of the values need a QPolygonF. - - \param xMap x map - \param yMap y map - \param series Series of points to be mapped - \param from Index of the first point to be painted - \param to Index of the last point to be painted - - \return Translated polygon -*/ -QPolygonF QwtPointMapper::toPointsF( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const -{ - QPolygonF points; - - if ( d_data->flags & WeedOutPoints ) - { - if ( d_data->flags & RoundPoints ) - { - if ( d_data->boundingRect.isValid() ) - { - points = qwtToPointsFilteredF( d_data->boundingRect, - xMap, yMap, series, from, to ); - } - else - { - // without a bounding rectangle all we can - // do is to filter out duplicates of - // consecutive points - - points = qwtToPolylineFilteredF( - xMap, yMap, series, from, to, QwtRoundF() ); - } - } - else - { - // when rounding is not allowed we can't use - // qwtToPointsFilteredF - - points = qwtToPolylineFilteredF( - xMap, yMap, series, from, to, QwtNoRoundF() ); - } - } - else - { - if ( d_data->flags & RoundPoints ) - { - points = qwtToPointsF( d_data->boundingRect, - xMap, yMap, series, from, to, QwtRoundF() ); - } - else - { - points = qwtToPointsF( d_data->boundingRect, - xMap, yMap, series, from, to, QwtNoRoundF() ); - } - } - - return points; -} - -/*! - \brief Translate a series of points into a QPolygon - - - WeedOutPoints & boundingRect().isValid() - All points that are mapped to the same position - will be one point. Points outside of the bounding - rectangle are ignored. - - - WeedOutPoints & !boundingRect().isValid() - All consecutive points that are mapped to the same position - will one point - - - !WeedOutPoints & boundingRect().isValid() - Points outside of the bounding rectangle are ignored. - - \param xMap x map - \param yMap y map - \param series Series of points to be mapped - \param from Index of the first point to be painted - \param to Index of the last point to be painted - - \return Translated polygon -*/ -QPolygon QwtPointMapper::toPoints( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to ) const -{ - QPolygon points; - - if ( d_data->flags & WeedOutPoints ) - { - if ( d_data->boundingRect.isValid() ) - { - points = qwtToPointsFilteredI( d_data->boundingRect, - xMap, yMap, series, from, to ); - } - else - { - // when we don't have the bounding rectangle all - // we can do is to filter out consecutive duplicates - - points = qwtToPolylineFilteredI( - xMap, yMap, series, from, to ); - } - } - else - { - points = qwtToPointsI( - d_data->boundingRect, xMap, yMap, series, from, to ); - } - - return points; -} - - -/*! - \brief Translate a series into a QImage - - \param xMap x map - \param yMap y map - \param series Series of points to be mapped - \param from Index of the first point to be painted - \param to Index of the last point to be painted - \param pen Pen used for drawing a point - of the image, where a point is mapped to - \param antialiased True, when the dots should be displayed - antialiased - \param numThreads Number of threads to be used for rendering. - If numThreads is set to 0, the system specific - ideal thread count is used. - - \return Image displaying the series -*/ -QImage QwtPointMapper::toImage( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtSeriesData<QPointF> *series, int from, int to, - const QPen &pen, bool antialiased, uint numThreads ) const -{ - Q_UNUSED( antialiased ) - -#if QWT_USE_THREADS - if ( numThreads == 0 ) - numThreads = QThread::idealThreadCount(); - - if ( numThreads <= 0 ) - numThreads = 1; -#else - Q_UNUSED( numThreads ) -#endif - - // a very special optimization for scatter plots - // where every sample is mapped to one pixel only. - - const QRect rect = d_data->boundingRect.toAlignedRect(); - - QImage image( rect.size(), QImage::Format_ARGB32 ); - image.fill( Qt::transparent ); - - if ( pen.width() <= 1 && pen.color().alpha() == 255 ) - { - QwtDotsCommand command; - command.series = series; - command.rgb = pen.color().rgba(); - -#if QWT_USE_THREADS - const int numPoints = ( to - from + 1 ) / numThreads; - - QList< QFuture<void> > futures; - for ( uint i = 0; i < numThreads; i++ ) - { - const QPoint pos = rect.topLeft(); - - const int index0 = from + i * numPoints; - if ( i == numThreads - 1 ) - { - command.from = index0; - command.to = to; - - qwtRenderDots( xMap, yMap, command, pos, &image ); - } - else - { - command.from = index0; - command.to = index0 + numPoints - 1; - - futures += QtConcurrent::run( &qwtRenderDots, - xMap, yMap, command, pos, &image ); - } - } - for ( int i = 0; i < futures.size(); i++ ) - futures[i].waitForFinished(); -#else - command.from = from; - command.to = to; - - qwtRenderDots( xMap, yMap, command, rect.topLeft(), &image ); -#endif - } - else - { - // fallback implementation: to be replaced later by - // setting the pixels of the image like above, TODO ... - - QPainter painter( &image ); - painter.setPen( pen ); - painter.setRenderHint( QPainter::Antialiasing, antialiased ); - - const int chunkSize = 1000; - for ( int i = from; i <= to; i += chunkSize ) - { - const int indexTo = qMin( i + chunkSize - 1, to ); - const QPolygon points = toPoints( - xMap, yMap, series, i, indexTo ); - - painter.drawPoints( points ); - } - } - - return image; -} diff --git a/source/third_party/qwt/qwt_point_polar.cpp b/source/third_party/qwt/qwt_point_polar.cpp deleted file mode 100644 index 220c1e0682b5f023e5cde3de97718dd93f970e4c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_point_polar.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** - * QwtPolar Widget Library - * Copyright (C) 2008 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/qwt_point_polar.h" -#include "qwt/qwt_math.h" - -#if QT_VERSION < 0x040601 -#define qAtan2(y, x) ::atan2(y, x) -#endif - -/*! - Convert and assign values from a point in Cartesian coordinates - - \param p Point in Cartesian coordinates - \sa setPoint(), toPoint() -*/ -QwtPointPolar::QwtPointPolar( const QPointF &p ) -{ - d_radius = qSqrt( qwtSqr( p.x() ) + qwtSqr( p.y() ) ); - d_azimuth = qAtan2( p.y(), p.x() ); -} - -/*! - Convert and assign values from a point in Cartesian coordinates - \param p Point in Cartesian coordinates -*/ -void QwtPointPolar::setPoint( const QPointF &p ) -{ - d_radius = qSqrt( qwtSqr( p.x() ) + qwtSqr( p.y() ) ); - d_azimuth = qAtan2( p.y(), p.x() ); -} - -/*! - Convert and return values in Cartesian coordinates - - \return Converted point in Cartesian coordinates - - \note Invalid or null points will be returned as QPointF(0.0, 0.0) - \sa isValid(), isNull() -*/ -QPointF QwtPointPolar::toPoint() const -{ - if ( d_radius <= 0.0 ) - return QPointF( 0.0, 0.0 ); - - const double x = d_radius * qCos( d_azimuth ); - const double y = d_radius * qSin( d_azimuth ); - - return QPointF( x, y ); -} - -/*! - \brief Compare 2 points - - Two points are equal to each other if radius and - azimuth-coordinates are the same. Points are not equal, when - the azimuth differs, but other.azimuth() == azimuth() % (2 * PI). - - \return True if the point is equal to other; otherwise return false. - - \sa normalized() -*/ -bool QwtPointPolar::operator==( const QwtPointPolar &other ) const -{ - return d_radius == other.d_radius && d_azimuth == other.d_azimuth; -} - -/*! - Compare 2 points - - Two points are equal to each other if radius and - azimuth-coordinates are the same. Points are not equal, when - the azimuth differs, but other.azimuth() == azimuth() % (2 * PI). - - \return True if the point is not equal to other; otherwise return false. - \sa normalized() -*/ -bool QwtPointPolar::operator!=( const QwtPointPolar &other ) const -{ - return d_radius != other.d_radius || d_azimuth != other.d_azimuth; -} - -/*! - Normalize radius and azimuth - - When the radius is < 0.0 it is set to 0.0. The azimuth is - a value >= 0.0 and < 2 * M_PI. - - \return Normalized point -*/ -QwtPointPolar QwtPointPolar::normalized() const -{ - const double radius = qMax( d_radius, 0.0 ); - - double azimuth = d_azimuth; - if ( azimuth < -2.0 * M_PI || azimuth >= 2 * M_PI ) - azimuth = ::fmod( d_azimuth, 2 * M_PI ); - - if ( azimuth < 0.0 ) - azimuth += 2 * M_PI; - - return QwtPointPolar( azimuth, radius ); -} - -#ifndef QT_NO_DEBUG_STREAM - -QDebug operator<<( QDebug debug, const QwtPointPolar &point ) -{ - debug.nospace() << "QwtPointPolar(" - << point.azimuth() << "," << point.radius() << ")"; - - return debug.space(); -} - -#endif - diff --git a/source/third_party/qwt/qwt_raster_data.cpp b/source/third_party/qwt/qwt_raster_data.cpp deleted file mode 100644 index 51de395e31664a6a8861c2adfc636548f26262ab..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_raster_data.cpp +++ /dev/null @@ -1,404 +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/qwt_raster_data.h" -#include "qwt/qwt_point_3d.h" -#include <qnumeric.h> - -class QwtRasterData::ContourPlane -{ -public: - inline ContourPlane( double z ): - d_z( z ) - { - } - - inline bool intersect( const QwtPoint3D vertex[3], - QPointF line[2], bool ignoreOnPlane ) const; - - inline double z() const { return d_z; } - -private: - inline int compare( double z ) const; - inline QPointF intersection( - const QwtPoint3D& p1, const QwtPoint3D &p2 ) const; - - double d_z; -}; - -inline bool QwtRasterData::ContourPlane::intersect( - const QwtPoint3D vertex[3], QPointF line[2], - bool ignoreOnPlane ) const -{ - bool found = true; - - // Are the vertices below (-1), on (0) or above (1) the plan ? - const int eq1 = compare( vertex[0].z() ); - const int eq2 = compare( vertex[1].z() ); - const int eq3 = compare( vertex[2].z() ); - - /* - (a) All the vertices lie below the contour level. - (b) Two vertices lie below and one on the contour level. - (c) Two vertices lie below and one above the contour level. - (d) One vertex lies below and two on the contour level. - (e) One vertex lies below, one on and one above the contour level. - (f) One vertex lies below and two above the contour level. - (g) Three vertices lie on the contour level. - (h) Two vertices lie on and one above the contour level. - (i) One vertex lies on and two above the contour level. - (j) All the vertices lie above the contour level. - */ - - static const int tab[3][3][3] = - { - // jump table to avoid nested case statements - { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } }, - { { 0, 3, 4 }, { 1, 10, 1 }, { 4, 3, 0 } }, - { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } } - }; - - const int edgeType = tab[eq1+1][eq2+1][eq3+1]; - switch ( edgeType ) - { - case 1: - // d(0,0,-1), h(0,0,1) - line[0] = vertex[0].toPoint(); - line[1] = vertex[1].toPoint(); - break; - case 2: - // d(-1,0,0), h(1,0,0) - line[0] = vertex[1].toPoint(); - line[1] = vertex[2].toPoint(); - break; - case 3: - // d(0,-1,0), h(0,1,0) - line[0] = vertex[2].toPoint(); - line[1] = vertex[0].toPoint(); - break; - case 4: - // e(0,-1,1), e(0,1,-1) - line[0] = vertex[0].toPoint(); - line[1] = intersection( vertex[1], vertex[2] ); - break; - case 5: - // e(-1,0,1), e(1,0,-1) - line[0] = vertex[1].toPoint(); - line[1] = intersection( vertex[2], vertex[0] ); - break; - case 6: - // e(-1,1,0), e(1,0,-1) - line[0] = vertex[2].toPoint(); - line[1] = intersection( vertex[0], vertex[1] ); - break; - case 7: - // c(-1,1,-1), f(1,1,-1) - line[0] = intersection( vertex[0], vertex[1] ); - line[1] = intersection( vertex[1], vertex[2] ); - break; - case 8: - // c(-1,-1,1), f(1,1,-1) - line[0] = intersection( vertex[1], vertex[2] ); - line[1] = intersection( vertex[2], vertex[0] ); - break; - case 9: - // f(-1,1,1), c(1,-1,-1) - line[0] = intersection( vertex[2], vertex[0] ); - line[1] = intersection( vertex[0], vertex[1] ); - break; - case 10: - // g(0,0,0) - // The CONREC algorithm has no satisfying solution for - // what to do, when all vertices are on the plane. - - if ( ignoreOnPlane ) - found = false; - else - { - line[0] = vertex[2].toPoint(); - line[1] = vertex[0].toPoint(); - } - break; - default: - found = false; - } - - return found; -} - -inline int QwtRasterData::ContourPlane::compare( double z ) const -{ - if ( z > d_z ) - return 1; - - if ( z < d_z ) - return -1; - - return 0; -} - -inline QPointF QwtRasterData::ContourPlane::intersection( - const QwtPoint3D& p1, const QwtPoint3D &p2 ) const -{ - const double h1 = p1.z() - d_z; - const double h2 = p2.z() - d_z; - - const double x = ( h2 * p1.x() - h1 * p2.x() ) / ( h2 - h1 ); - const double y = ( h2 * p1.y() - h1 * p2.y() ) / ( h2 - h1 ); - - return QPointF( x, y ); -} - -//! Constructor -QwtRasterData::QwtRasterData() -{ -} - -//! Destructor -QwtRasterData::~QwtRasterData() -{ -} - -/*! - Set the bounding interval for the x, y or z coordinates. - - \param axis Axis - \param interval Bounding interval - - \sa interval() -*/ -void QwtRasterData::setInterval( Qt::Axis axis, const QwtInterval &interval ) -{ - d_intervals[axis] = interval; -} - -/*! - \brief Initialize a raster - - Before the composition of an image QwtPlotSpectrogram calls initRaster(), - announcing the area and its resolution that will be requested. - - The default implementation does nothing, but for data sets that - are stored in files, it might be good idea to reimplement initRaster(), - where the data is resampled and loaded into memory. - - \param area Area of the raster - \param raster Number of horizontal and vertical pixels - - \sa initRaster(), value() -*/ -void QwtRasterData::initRaster( const QRectF &area, const QSize &raster ) -{ - Q_UNUSED( area ); - Q_UNUSED( raster ); -} - -/*! - \brief Discard a raster - - After the composition of an image QwtPlotSpectrogram calls discardRaster(). - - The default implementation does nothing, but if data has been loaded - in initRaster(), it could deleted now. - - \sa initRaster(), value() -*/ -void QwtRasterData::discardRaster() -{ -} - -/*! - \brief Pixel hint - - pixelHint() returns the geometry of a pixel, that can be used - to calculate the resolution and alignment of the plot item, that is - representing the data. - - Width and height of the hint need to be the horizontal - and vertical distances between 2 neighbored points. - The center of the hint has to be the position of any point - ( it doesn't matter which one ). - - An empty hint indicates, that there are values for any detail level. - - Limiting the resolution of the image might significantly improve - the performance and heavily reduce the amount of memory when rendering - a QImage from the raster data. - - The default implementation returns an empty rectangle recommending - to render in target device ( f.e. screen ) resolution. - - \param area In most implementations the resolution of the data doesn't - depend on the requested area. - - \return Bounding rectangle of a pixel -*/ -QRectF QwtRasterData::pixelHint( const QRectF &area ) const -{ - Q_UNUSED( area ); - return QRectF(); -} - -/*! - Calculate contour lines - - \param rect Bounding rectangle for the contour lines - \param raster Number of data pixels of the raster data - \param levels List of limits, where to insert contour lines - \param flags Flags to customize the contouring algorithm - - \return Calculated contour lines - - An adaption of CONREC, a simple contouring algorithm. - http://local.wasp.uwa.edu.au/~pbourke/papers/conrec/ -*/ -QwtRasterData::ContourLines QwtRasterData::contourLines( - const QRectF &rect, const QSize &raster, - const QList<double> &levels, ConrecFlags flags ) const -{ - ContourLines contourLines; - - if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() ) - return contourLines; - - const double dx = rect.width() / raster.width(); - const double dy = rect.height() / raster.height(); - - const bool ignoreOnPlane = - flags & QwtRasterData::IgnoreAllVerticesOnLevel; - - const QwtInterval range = interval( Qt::ZAxis ); - bool ignoreOutOfRange = false; - if ( range.isValid() ) - ignoreOutOfRange = flags & IgnoreOutOfRange; - - QwtRasterData *that = const_cast<QwtRasterData *>( this ); - that->initRaster( rect, raster ); - - for ( int y = 0; y < raster.height() - 1; y++ ) - { - enum Position - { - Center, - - TopLeft, - TopRight, - BottomRight, - BottomLeft, - - NumPositions - }; - - QwtPoint3D xy[NumPositions]; - - for ( int x = 0; x < raster.width() - 1; x++ ) - { - const QPointF pos( rect.x() + x * dx, rect.y() + y * dy ); - - if ( x == 0 ) - { - xy[TopRight].setX( pos.x() ); - xy[TopRight].setY( pos.y() ); - xy[TopRight].setZ( - value( xy[TopRight].x(), xy[TopRight].y() ) - ); - - xy[BottomRight].setX( pos.x() ); - xy[BottomRight].setY( pos.y() + dy ); - xy[BottomRight].setZ( - value( xy[BottomRight].x(), xy[BottomRight].y() ) - ); - } - - xy[TopLeft] = xy[TopRight]; - xy[BottomLeft] = xy[BottomRight]; - - xy[TopRight].setX( pos.x() + dx ); - xy[TopRight].setY( pos.y() ); - xy[BottomRight].setX( pos.x() + dx ); - xy[BottomRight].setY( pos.y() + dy ); - - xy[TopRight].setZ( - value( xy[TopRight].x(), xy[TopRight].y() ) - ); - xy[BottomRight].setZ( - value( xy[BottomRight].x(), xy[BottomRight].y() ) - ); - - double zMin = xy[TopLeft].z(); - double zMax = zMin; - double zSum = zMin; - - for ( int i = TopRight; i <= BottomLeft; i++ ) - { - const double z = xy[i].z(); - - zSum += z; - if ( z < zMin ) - zMin = z; - if ( z > zMax ) - zMax = z; - } - - if ( qIsNaN( zSum ) ) - { - // one of the points is NaN - continue; - } - - if ( ignoreOutOfRange ) - { - if ( !range.contains( zMin ) || !range.contains( zMax ) ) - continue; - } - - if ( zMax < levels[0] || - zMin > levels[levels.size() - 1] ) - { - continue; - } - - xy[Center].setX( pos.x() + 0.5 * dx ); - xy[Center].setY( pos.y() + 0.5 * dy ); - xy[Center].setZ( 0.25 * zSum ); - - const int numLevels = levels.size(); - for ( int l = 0; l < numLevels; l++ ) - { - const double level = levels[l]; - if ( level < zMin || level > zMax ) - continue; - QPolygonF &lines = contourLines[level]; - const ContourPlane plane( level ); - - QPointF line[2]; - QwtPoint3D vertex[3]; - - for ( int m = TopLeft; m < NumPositions; m++ ) - { - vertex[0] = xy[m]; - vertex[1] = xy[0]; - vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft]; - - const bool intersects = - plane.intersect( vertex, line, ignoreOnPlane ); - if ( intersects ) - { - lines += line[0]; - lines += line[1]; - } - } - } - } - } - - that->discardRaster(); - - return contourLines; -} diff --git a/source/third_party/qwt/qwt_round_scale_draw.cpp b/source/third_party/qwt/qwt_round_scale_draw.cpp deleted file mode 100644 index 7db1e81bcec877349cded04b2d4218689fdff859..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_round_scale_draw.cpp +++ /dev/null @@ -1,314 +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/qwt_round_scale_draw.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_math.h" -#include <qpen.h> -#include <qpainter.h> -#include <qfontmetrics.h> -#include <qmath.h> - -class QwtRoundScaleDraw::PrivateData -{ -public: - PrivateData(): - center( 50.0, 50.0 ), - radius( 50.0 ), - startAngle( -135.0 ), - endAngle( 135.0 ) - { - } - - QPointF center; - double radius; - - double startAngle; - double endAngle; -}; - -/*! - \brief Constructor - - The range of the scale is initialized to [0, 100], - The center is set to (50, 50) with a radius of 50. - The angle range is set to [-135, 135]. -*/ -QwtRoundScaleDraw::QwtRoundScaleDraw() -{ - d_data = new QwtRoundScaleDraw::PrivateData; - - setRadius( 50 ); - scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle ); -} - -//! Destructor -QwtRoundScaleDraw::~QwtRoundScaleDraw() -{ - delete d_data; -} - -/*! - Change of radius the scale - - Radius is the radius of the backbone without ticks and labels. - - \param radius New Radius - \sa moveCenter() -*/ -void QwtRoundScaleDraw::setRadius( double radius ) -{ - d_data->radius = radius; -} - -/*! - Get the radius - - Radius is the radius of the backbone without ticks and labels. - - \return Radius of the scale - \sa setRadius(), extent() -*/ -double QwtRoundScaleDraw::radius() const -{ - return d_data->radius; -} - -/*! - Move the center of the scale draw, leaving the radius unchanged - - \param center New center - \sa setRadius() -*/ -void QwtRoundScaleDraw::moveCenter( const QPointF ¢er ) -{ - d_data->center = center; -} - -//! Get the center of the scale -QPointF QwtRoundScaleDraw::center() const -{ - return d_data->center; -} - -/*! - \brief Adjust the baseline circle segment for round scales. - - The baseline will be drawn from min(angle1,angle2) to max(angle1, angle2). - The default setting is [ -135, 135 ]. - An angle of 0 degrees corresponds to the 12 o'clock position, - and positive angles count in a clockwise direction. - \param angle1 - \param angle2 boundaries of the angle interval in degrees. - \warning <ul> - <li>The angle range is limited to [-360, 360] degrees. Angles exceeding - this range will be clipped. - <li>For angles more or equal than 360 degrees above or below min(angle1, angle2), - scale marks will not be drawn. - <li>If you need a counterclockwise scale, use QwtScaleDiv::setInterval() - </ul> -*/ -void QwtRoundScaleDraw::setAngleRange( double angle1, double angle2 ) -{ -#if 0 - angle1 = qBound( -360.0, angle1, 360.0 ); - angle2 = qBound( -360.0, angle2, 360.0 ); -#endif - - d_data->startAngle = angle1; - d_data->endAngle = angle2; - - if ( d_data->startAngle == d_data->endAngle ) - { - d_data->startAngle -= 1; - d_data->endAngle += 1; - } - - scaleMap().setPaintInterval( d_data->startAngle, d_data->endAngle ); -} - -/*! - Draws the label for a major scale tick - - \param painter Painter - \param value Value - - \sa drawTick(), drawBackbone() -*/ -void QwtRoundScaleDraw::drawLabel( QPainter *painter, double value ) const -{ - const double tval = scaleMap().transform( value ); - if ( ( tval >= d_data->startAngle + 360.0 ) - || ( tval <= d_data->startAngle - 360.0 ) ) - { - return; - } - - const QwtText label = tickLabel( painter->font(), value ); - if ( label.isEmpty() ) - return; - - double radius = d_data->radius; - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) || - hasComponent( QwtAbstractScaleDraw::Backbone ) ) - { - radius += spacing(); - } - - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) - radius += tickLength( QwtScaleDiv::MajorTick ); - - const QSizeF sz = label.textSize( painter->font() ); - const double arc = qwtRadians( tval ); - - const double x = d_data->center.x() + - ( radius + sz.width() / 2.0 ) * qSin( arc ); - const double y = d_data->center.y() - - ( radius + sz.height() / 2.0 ) * qCos( arc ); - - const QRectF r( x - sz.width() / 2, y - sz.height() / 2, - sz.width(), sz.height() ); - label.draw( painter, r ); -} - -/*! - Draw a tick - - \param painter Painter - \param value Value of the tick - \param len Lenght of the tick - - \sa drawBackbone(), drawLabel() -*/ -void QwtRoundScaleDraw::drawTick( QPainter *painter, double value, double len ) const -{ - if ( len <= 0 ) - return; - - const double tval = scaleMap().transform( value ); - - const double cx = d_data->center.x(); - const double cy = d_data->center.y(); - const double radius = d_data->radius; - - if ( ( tval < d_data->startAngle + 360.0 ) - && ( tval > d_data->startAngle - 360.0 ) ) - { - const double arc = qwtRadians( tval ); - - const double sinArc = qSin( arc ); - const double cosArc = qCos( arc ); - - const double x1 = cx + radius * sinArc; - const double x2 = cx + ( radius + len ) * sinArc; - const double y1 = cy - radius * cosArc; - const double y2 = cy - ( radius + len ) * cosArc; - - QwtPainter::drawLine( painter, x1, y1, x2, y2 ); - } -} - -/*! - Draws the baseline of the scale - \param painter Painter - - \sa drawTick(), drawLabel() -*/ -void QwtRoundScaleDraw::drawBackbone( QPainter *painter ) const -{ - const double deg1 = scaleMap().p1(); - const double deg2 = scaleMap().p2(); - - const int a1 = qRound( qMin( deg1, deg2 ) - 90 ); - const int a2 = qRound( qMax( deg1, deg2 ) - 90 ); - - const double radius = d_data->radius; - const double x = d_data->center.x() - radius; - const double y = d_data->center.y() - radius; - - painter->drawArc( QRectF( x, y, 2 * radius, 2 * radius ), - -a2 * 16, ( a2 - a1 + 1 ) * 16 ); // counterclockwise -} - -/*! - Calculate the extent of the scale - - The extent is the distance between the baseline to the outermost - pixel of the scale draw. radius() + extent() is an upper limit - for the radius of the bounding circle. - - \param font Font used for painting the labels - \return Calculated extent - - \sa setMinimumExtent(), minimumExtent() - \warning The implemented algorithm is not too smart and - calculates only an upper limit, that might be a - few pixels too large -*/ -double QwtRoundScaleDraw::extent( const QFont &font ) const -{ - double d = 0.0; - - if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) - { - const QwtScaleDiv &sd = scaleDiv(); - const QList<double> &ticks = sd.ticks( QwtScaleDiv::MajorTick ); - for ( int i = 0; i < ticks.count(); i++ ) - { - const double value = ticks[i]; - if ( !sd.contains( value ) ) - continue; - - const double tval = scaleMap().transform( value ); - if ( ( tval < d_data->startAngle + 360 ) - && ( tval > d_data->startAngle - 360 ) ) - { - const QwtText label = tickLabel( font, value ); - if ( label.isEmpty() ) - continue; - - const double arc = qwtRadians( tval ); - - const QSizeF sz = label.textSize( font ); - const double off = qMax( sz.width(), sz.height() ); - - double x = off * qSin( arc ); - double y = off * qCos( arc ); - - const double dist = qSqrt( x * x + y * y ); - if ( dist > d ) - d = dist; - } - } - } - - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) - { - d += maxTickLength(); - } - - if ( hasComponent( QwtAbstractScaleDraw::Backbone ) ) - { - const double pw = qMax( 1, penWidth() ); // pen width can be zero - d += pw; - } - - if ( hasComponent( QwtAbstractScaleDraw::Labels ) && - ( hasComponent( QwtAbstractScaleDraw::Ticks ) || - hasComponent( QwtAbstractScaleDraw::Backbone ) ) ) - { - d += spacing(); - } - - d = qMax( d, minimumExtent() ); - - return d; -} diff --git a/source/third_party/qwt/qwt_sampling_thread.cpp b/source/third_party/qwt/qwt_sampling_thread.cpp deleted file mode 100644 index 51e981b66a3ae5e1028c79bb093fddc960fd582f..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_sampling_thread.cpp +++ /dev/null @@ -1,106 +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/qwt_sampling_thread.h" -#include "qwt/qwt_system_clock.h" - -class QwtSamplingThread::PrivateData -{ -public: - QwtSystemClock clock; - - double interval; - bool isStopped; -}; - - -//! Constructor -QwtSamplingThread::QwtSamplingThread( QObject *parent ): - QThread( parent ) -{ - d_data = new PrivateData; - d_data->interval = 1000; // 1 second - d_data->isStopped = true; -} - -//! Destructor -QwtSamplingThread::~QwtSamplingThread() -{ - delete d_data; -} - -/*! - Change the interval (in ms), when sample() is called. - The default interval is 1000.0 ( = 1s ) - - \param interval Interval - \sa interval() -*/ -void QwtSamplingThread::setInterval( double interval ) -{ - if ( interval < 0.0 ) - interval = 0.0; - - d_data->interval = interval; -} - -/*! - \return Interval (in ms), between 2 calls of sample() - \sa setInterval() -*/ -double QwtSamplingThread::interval() const -{ - return d_data->interval; -} - -/*! - \return Time (in ms) since the thread was started - \sa QThread::start(), run() -*/ -double QwtSamplingThread::elapsed() const -{ - if ( d_data->isStopped ) - return 0.0; - - return d_data->clock.elapsed(); -} - -/*! - Terminate the collecting thread - \sa QThread::start(), run() -*/ -void QwtSamplingThread::stop() -{ - d_data->isStopped = true; -} - -/*! - Loop collecting samples started from QThread::start() - \sa stop() -*/ -void QwtSamplingThread::run() -{ - d_data->clock.start(); - d_data->isStopped = false; - - while ( !d_data->isStopped ) - { - const double elapsed = d_data->clock.elapsed(); - sample( elapsed / 1000.0 ); - - if ( d_data->interval > 0.0 ) - { - const double msecs = - d_data->interval - ( d_data->clock.elapsed() - elapsed ); - - if ( msecs > 0.0 ) - usleep( qRound( 1000.0 * msecs ) ); - } - } -} diff --git a/source/third_party/qwt/qwt_scale_div.cpp b/source/third_party/qwt/qwt_scale_div.cpp deleted file mode 100644 index a24006509c4653c920b03fa5f3fc85b058e2d338..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_scale_div.cpp +++ /dev/null @@ -1,331 +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/qwt_scale_div.h" -#include "qwt/qwt_math.h" -#include <qalgorithms.h> - -/*! - Construct a division without ticks - - \param lowerBound First boundary - \param upperBound Second boundary - - \note lowerBound might be greater than upperBound for inverted scales - */ -QwtScaleDiv::QwtScaleDiv( double lowerBound, double upperBound ): - d_lowerBound( lowerBound ), - d_upperBound( upperBound ) -{ -} - -/*! - Construct a scale division - - \param interval Interval - \param ticks List of major, medium and minor ticks -*/ -QwtScaleDiv::QwtScaleDiv( const QwtInterval &interval, - QList<double> ticks[NTickTypes] ): - d_lowerBound( interval.minValue() ), - d_upperBound( interval.maxValue() ) -{ - for ( int i = 0; i < NTickTypes; i++ ) - d_ticks[i] = ticks[i]; -} - -/*! - Construct a scale division - - \param lowerBound First boundary - \param upperBound Second boundary - \param ticks List of major, medium and minor ticks - - \note lowerBound might be greater than upperBound for inverted scales -*/ -QwtScaleDiv::QwtScaleDiv( double lowerBound, double upperBound, - QList<double> ticks[NTickTypes] ): - d_lowerBound( lowerBound ), - d_upperBound( upperBound ) -{ - for ( int i = 0; i < NTickTypes; i++ ) - d_ticks[i] = ticks[i]; -} - -/*! - Construct a scale division - - \param lowerBound First boundary - \param upperBound Second boundary - \param minorTicks List of minor ticks - \param mediumTicks List medium ticks - \param majorTicks List of major ticks - - \note lowerBound might be greater than upperBound for inverted scales -*/ -QwtScaleDiv::QwtScaleDiv( double lowerBound, double upperBound, - const QList<double> &minorTicks, - const QList<double> &mediumTicks, - const QList<double> &majorTicks ): - d_lowerBound( lowerBound ), - d_upperBound( upperBound ) -{ - d_ticks[ MinorTick ] = minorTicks; - d_ticks[ MediumTick ] = mediumTicks; - d_ticks[ MajorTick ] = majorTicks; -} - -/*! - Change the interval - - \param lowerBound First boundary - \param upperBound Second boundary - - \note lowerBound might be greater than upperBound for inverted scales -*/ -void QwtScaleDiv::setInterval( double lowerBound, double upperBound ) -{ - d_lowerBound = lowerBound; - d_upperBound = upperBound; -} - -/*! - Change the interval - - \param interval Interval -*/ -void QwtScaleDiv::setInterval( const QwtInterval &interval ) -{ - d_lowerBound = interval.minValue(); - d_upperBound = interval.maxValue(); -} - -/*! - \return lowerBound -> upperBound -*/ -QwtInterval QwtScaleDiv::interval() const -{ - return QwtInterval( d_lowerBound, d_upperBound ); -} - -/*! - Set the first boundary - - \param lowerBound First boundary - \sa lowerBiound(), setUpperBound() - */ -void QwtScaleDiv::setLowerBound( double lowerBound ) -{ - d_lowerBound = lowerBound; -} - -/*! - \return First boundary - \sa upperBound() -*/ -double QwtScaleDiv::lowerBound() const -{ - return d_lowerBound; -} - -/*! - Set the second boundary - - \param upperBound Second boundary - \sa upperBound(), setLowerBound() - */ -void QwtScaleDiv::setUpperBound( double upperBound ) -{ - d_upperBound = upperBound; -} - -/*! - \return upper bound - \sa lowerBound() -*/ -double QwtScaleDiv::upperBound() const -{ - return d_upperBound; -} - -/*! - \return upperBound() - lowerBound() -*/ -double QwtScaleDiv::range() const -{ - return d_upperBound - d_lowerBound; -} - -/*! - \brief Equality operator - \return true if this instance is equal to other -*/ -bool QwtScaleDiv::operator==( const QwtScaleDiv &other ) const -{ - if ( d_lowerBound != other.d_lowerBound || - d_upperBound != other.d_upperBound ) - { - return false; - } - - for ( int i = 0; i < NTickTypes; i++ ) - { - if ( d_ticks[i] != other.d_ticks[i] ) - return false; - } - - return true; -} - -/*! - \brief Inequality - \return true if this instance is not equal to other -*/ -bool QwtScaleDiv::operator!=( const QwtScaleDiv &other ) const -{ - return ( !( *this == other ) ); -} - -//! Check if the scale division is empty( lowerBound() == upperBound() ) -bool QwtScaleDiv::isEmpty() const -{ - return ( d_lowerBound == d_upperBound ); -} - -//! Check if the scale division is increasing( lowerBound() <= upperBound() ) -bool QwtScaleDiv::isIncreasing() const -{ - return d_lowerBound <= d_upperBound; -} - -/*! - Return if a value is between lowerBound() and upperBound() - - \param value Value - \return true/false -*/ -bool QwtScaleDiv::contains( double value ) const -{ - const double min = qMin( d_lowerBound, d_upperBound ); - const double max = qMax( d_lowerBound, d_upperBound ); - - return value >= min && value <= max; -} - -/*! - Invert the scale division - \sa inverted() - */ -void QwtScaleDiv::invert() -{ - qSwap( d_lowerBound, d_upperBound ); - - for ( int i = 0; i < NTickTypes; i++ ) - { - QList<double>& ticks = d_ticks[i]; - - const int size = ticks.count(); - const int size2 = size / 2; - - for ( int j = 0; j < size2; j++ ) - qSwap( ticks[j], ticks[size - 1 - j] ); - } -} - -/*! - \return A scale division with inverted boundaries and ticks - \sa invert() - */ -QwtScaleDiv QwtScaleDiv::inverted() const -{ - QwtScaleDiv other = *this; - other.invert(); - - return other; -} - -/*! - Return a scale division with an interval [lowerBound, upperBound] - where all ticks outside this interval are removed - - \param lowerBound Lower bound - \param upperBound Upper bound - - \return Scale division with all ticks inside of the given interval - - \note lowerBound might be greater than upperBound for inverted scales -*/ -QwtScaleDiv QwtScaleDiv::bounded( - double lowerBound, double upperBound ) const -{ - const double min = qMin( lowerBound, upperBound ); - const double max = qMax( lowerBound, upperBound ); - - QwtScaleDiv sd; - sd.setInterval( lowerBound, upperBound ); - - for ( int tickType = 0; tickType < QwtScaleDiv::NTickTypes; tickType++ ) - { - const QList<double> &ticks = d_ticks[ tickType ]; - - QList<double> boundedTicks; - for ( int i = 0; i < ticks.size(); i++ ) - { - const double tick = ticks[i]; - if ( tick >= min && tick <= max ) - boundedTicks += tick; - } - - sd.setTicks( tickType, boundedTicks ); - } - - return sd; - -} - -/*! - Assign ticks - - \param type MinorTick, MediumTick or MajorTick - \param ticks Values of the tick positions -*/ -void QwtScaleDiv::setTicks( int type, const QList<double> &ticks ) -{ - if ( type >= 0 && type < NTickTypes ) - d_ticks[type] = ticks; -} - -/*! - Return a list of ticks - - \param type MinorTick, MediumTick or MajorTick - \return Tick list -*/ -QList<double> QwtScaleDiv::ticks( int type ) const -{ - if ( type >= 0 && type < NTickTypes ) - return d_ticks[type]; - - return QList<double>(); -} - -#ifndef QT_NO_DEBUG_STREAM - -QDebug operator<<( QDebug debug, const QwtScaleDiv &scaleDiv ) -{ - debug << scaleDiv.lowerBound() << "<->" << scaleDiv.upperBound(); - debug << "Major: " << scaleDiv.ticks( QwtScaleDiv::MajorTick ); - debug << "Medium: " << scaleDiv.ticks( QwtScaleDiv::MediumTick ); - debug << "Minor: " << scaleDiv.ticks( QwtScaleDiv::MinorTick ); - - return debug; -} - -#endif - diff --git a/source/third_party/qwt/qwt_scale_draw.cpp b/source/third_party/qwt/qwt_scale_draw.cpp deleted file mode 100644 index f27b7e1bb841984ced97a72105fd058ed0b06852..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_scale_draw.cpp +++ /dev/null @@ -1,926 +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/qwt_scale_draw.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include <qpen.h> -#include <qpainter.h> -#include <qmath.h> - -#if QT_VERSION < 0x040601 -#define qFastSin(x) qSin(x) -#define qFastCos(x) qCos(x) -#endif - -class QwtScaleDraw::PrivateData -{ -public: - PrivateData(): - len( 0 ), - alignment( QwtScaleDraw::BottomScale ), - labelAlignment( 0 ), - labelRotation( 0.0 ) - { - } - - QPointF pos; - double len; - - Alignment alignment; - - Qt::Alignment labelAlignment; - double labelRotation; -}; - -/*! - \brief Constructor - - The range of the scale is initialized to [0, 100], - The position is at (0, 0) with a length of 100. - The orientation is QwtAbstractScaleDraw::Bottom. -*/ -QwtScaleDraw::QwtScaleDraw() -{ - d_data = new QwtScaleDraw::PrivateData; - setLength( 100 ); -} - -//! Destructor -QwtScaleDraw::~QwtScaleDraw() -{ - delete d_data; -} - -/*! - Return alignment of the scale - \sa setAlignment() - \return Alignment of the scale -*/ -QwtScaleDraw::Alignment QwtScaleDraw::alignment() const -{ - return d_data->alignment; -} - -/*! - Set the alignment of the scale - - \param align Alignment of the scale - - The default alignment is QwtScaleDraw::BottomScale - \sa alignment() -*/ -void QwtScaleDraw::setAlignment( Alignment align ) -{ - d_data->alignment = align; -} - -/*! - Return the orientation - - TopScale, BottomScale are horizontal (Qt::Horizontal) scales, - LeftScale, RightScale are vertical (Qt::Vertical) scales. - - \return Orientation of the scale - - \sa alignment() -*/ -Qt::Orientation QwtScaleDraw::orientation() const -{ - switch ( d_data->alignment ) - { - case TopScale: - case BottomScale: - return Qt::Horizontal; - case LeftScale: - case RightScale: - default: - return Qt::Vertical; - } -} - -/*! - \brief Determine the minimum border distance - - This member function returns the minimum space - needed to draw the mark labels at the scale's endpoints. - - \param font Font - \param start Start border distance - \param end End border distance -*/ -void QwtScaleDraw::getBorderDistHint( - const QFont &font, int &start, int &end ) const -{ - start = 0; - end = 1.0; - - if ( !hasComponent( QwtAbstractScaleDraw::Labels ) ) - return; - - const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); - if ( ticks.count() == 0 ) - return; - - // Find the ticks, that are mapped to the borders. - // minTick is the tick, that is mapped to the top/left-most position - // in widget coordinates. - - double minTick = ticks[0]; - double minPos = scaleMap().transform( minTick ); - double maxTick = minTick; - double maxPos = minPos; - - for ( int i = 1; i < ticks.count(); i++ ) - { - const double tickPos = scaleMap().transform( ticks[i] ); - if ( tickPos < minPos ) - { - minTick = ticks[i]; - minPos = tickPos; - } - if ( tickPos > scaleMap().transform( maxTick ) ) - { - maxTick = ticks[i]; - maxPos = tickPos; - } - } - - double e = 0.0; - double s = 0.0; - if ( orientation() == Qt::Vertical ) - { - s = -labelRect( font, minTick ).top(); - s -= qAbs( minPos - qRound( scaleMap().p2() ) ); - - e = labelRect( font, maxTick ).bottom(); - e -= qAbs( maxPos - scaleMap().p1() ); - } - else - { - s = -labelRect( font, minTick ).left(); - s -= qAbs( minPos - scaleMap().p1() ); - - e = labelRect( font, maxTick ).right(); - e -= qAbs( maxPos - scaleMap().p2() ); - } - - if ( s < 0.0 ) - s = 0.0; - if ( e < 0.0 ) - e = 0.0; - - start = qCeil( s ); - end = qCeil( e ); -} - -/*! - Determine the minimum distance between two labels, that is necessary - that the texts don't overlap. - - \param font Font - \return The maximum width of a label - - \sa getBorderDistHint() -*/ - -int QwtScaleDraw::minLabelDist( const QFont &font ) const -{ - if ( !hasComponent( QwtAbstractScaleDraw::Labels ) ) - return 0; - - const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); - if ( ticks.isEmpty() ) - return 0; - - const QFontMetrics fm( font ); - - const bool vertical = ( orientation() == Qt::Vertical ); - - QRectF bRect1; - QRectF bRect2 = labelRect( font, ticks[0] ); - if ( vertical ) - { - bRect2.setRect( -bRect2.bottom(), 0.0, bRect2.height(), bRect2.width() ); - } - - double maxDist = 0.0; - - for ( int i = 1; i < ticks.count(); i++ ) - { - bRect1 = bRect2; - bRect2 = labelRect( font, ticks[i] ); - if ( vertical ) - { - bRect2.setRect( -bRect2.bottom(), 0.0, - bRect2.height(), bRect2.width() ); - } - - double dist = fm.leading(); // space between the labels - if ( bRect1.right() > 0 ) - dist += bRect1.right(); - if ( bRect2.left() < 0 ) - dist += -bRect2.left(); - - if ( dist > maxDist ) - maxDist = dist; - } - - double angle = qwtRadians( labelRotation() ); - if ( vertical ) - angle += M_PI / 2; - - const double sinA = qFastSin( angle ); // qreal -> double - if ( qFuzzyCompare( sinA + 1.0, 1.0 ) ) - return qCeil( maxDist ); - - const int fmHeight = fm.ascent() - 2; - - // The distance we need until there is - // the height of the label font. This height is needed - // for the neighbored label. - - double labelDist = fmHeight / qFastSin( angle ) * qFastCos( angle ); - if ( labelDist < 0 ) - labelDist = -labelDist; - - // For text orientations close to the scale orientation - - if ( labelDist > maxDist ) - labelDist = maxDist; - - // For text orientations close to the opposite of the - // scale orientation - - if ( labelDist < fmHeight ) - labelDist = fmHeight; - - return qCeil( labelDist ); -} - -/*! - Calculate the width/height that is needed for a - vertical/horizontal scale. - - The extent is calculated from the pen width of the backbone, - the major tick length, the spacing and the maximum width/height - of the labels. - - \param font Font used for painting the labels - \return Extent - - \sa minLength() -*/ -double QwtScaleDraw::extent( const QFont &font ) const -{ - double d = 0; - - if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) - { - if ( orientation() == Qt::Vertical ) - d = maxLabelWidth( font ); - else - d = maxLabelHeight( font ); - - if ( d > 0 ) - d += spacing(); - } - - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) - { - d += maxTickLength(); - } - - if ( hasComponent( QwtAbstractScaleDraw::Backbone ) ) - { - const double pw = qMax( 1, penWidth() ); // pen width can be zero - d += pw; - } - - d = qMax( d, minimumExtent() ); - return d; -} - -/*! - Calculate the minimum length that is needed to draw the scale - - \param font Font used for painting the labels - \return Minimum length that is needed to draw the scale - - \sa extent() -*/ -int QwtScaleDraw::minLength( const QFont &font ) const -{ - int startDist, endDist; - getBorderDistHint( font, startDist, endDist ); - - const QwtScaleDiv &sd = scaleDiv(); - - const uint minorCount = - sd.ticks( QwtScaleDiv::MinorTick ).count() + - sd.ticks( QwtScaleDiv::MediumTick ).count(); - const uint majorCount = - sd.ticks( QwtScaleDiv::MajorTick ).count(); - - int lengthForLabels = 0; - if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) - lengthForLabels = minLabelDist( font ) * majorCount; - - int lengthForTicks = 0; - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) - { - const double pw = qMax( 1, penWidth() ); // penwidth can be zero - lengthForTicks = qCeil( ( majorCount + minorCount ) * ( pw + 1.0 ) ); - } - - return startDist + endDist + qMax( lengthForLabels, lengthForTicks ); -} - -/*! - Find the position, where to paint a label - - The position has a distance that depends on the length of the ticks - in direction of the alignment(). - - \param value Value - \return Position, where to paint a label -*/ -QPointF QwtScaleDraw::labelPosition( double value ) const -{ - const double tval = scaleMap().transform( value ); - double dist = spacing(); - if ( hasComponent( QwtAbstractScaleDraw::Backbone ) ) - dist += qMax( 1, penWidth() ); - - if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) - dist += tickLength( QwtScaleDiv::MajorTick ); - - double px = 0; - double py = 0; - - switch ( alignment() ) - { - case RightScale: - { - px = d_data->pos.x() + dist; - py = tval; - break; - } - case LeftScale: - { - px = d_data->pos.x() - dist; - py = tval; - break; - } - case BottomScale: - { - px = tval; - py = d_data->pos.y() + dist; - break; - } - case TopScale: - { - px = tval; - py = d_data->pos.y() - dist; - break; - } - } - - return QPointF( px, py ); -} - -/*! - Draw a tick - - \param painter Painter - \param value Value of the tick - \param len Length of the tick - - \sa drawBackbone(), drawLabel() -*/ -void QwtScaleDraw::drawTick( QPainter *painter, double value, double len ) const -{ - if ( len <= 0 ) - return; - - const bool roundingAlignment = QwtPainter::roundingAlignment( painter ); - - QPointF pos = d_data->pos; - - double tval = scaleMap().transform( value ); - if ( roundingAlignment ) - tval = qRound( tval ); - - const int pw = penWidth(); - int a = 0; - if ( pw > 1 && roundingAlignment ) - a = 1; - - switch ( alignment() ) - { - case LeftScale: - { - double x1 = pos.x() + a; - double x2 = pos.x() + a - pw - len; - if ( roundingAlignment ) - { - x1 = qRound( x1 ); - x2 = qRound( x2 ); - } - - QwtPainter::drawLine( painter, x1, tval, x2, tval ); - break; - } - - case RightScale: - { - double x1 = pos.x(); - double x2 = pos.x() + pw + len; - if ( roundingAlignment ) - { - x1 = qRound( x1 ); - x2 = qRound( x2 ); - } - - QwtPainter::drawLine( painter, x1, tval, x2, tval ); - break; - } - - case BottomScale: - { - double y1 = pos.y(); - double y2 = pos.y() + pw + len; - if ( roundingAlignment ) - { - y1 = qRound( y1 ); - y2 = qRound( y2 ); - } - - QwtPainter::drawLine( painter, tval, y1, tval, y2 ); - break; - } - - case TopScale: - { - double y1 = pos.y() + a; - double y2 = pos.y() - pw - len + a; - if ( roundingAlignment ) - { - y1 = qRound( y1 ); - y2 = qRound( y2 ); - } - - QwtPainter::drawLine( painter, tval, y1, tval, y2 ); - break; - } - } -} - -/*! - Draws the baseline of the scale - \param painter Painter - - \sa drawTick(), drawLabel() -*/ -void QwtScaleDraw::drawBackbone( QPainter *painter ) const -{ - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - const QPointF &pos = d_data->pos; - const double len = d_data->len; - const int pw = qMax( penWidth(), 1 ); - - // pos indicates a border not the center of the backbone line - // so we need to shift its position depending on the pen width - // and the alignment of the scale - - double off; - if ( doAlign ) - { - if ( alignment() == LeftScale || alignment() == TopScale ) - off = ( pw - 1 ) / 2; - else - off = pw / 2; - } - else - { - off = 0.5 * penWidth(); - } - - switch ( alignment() ) - { - case LeftScale: - { - double x = pos.x() - off; - if ( doAlign ) - x = qRound( x ); - - QwtPainter::drawLine( painter, x, pos.y(), x, pos.y() + len ); - break; - } - case RightScale: - { - double x = pos.x() + off; - if ( doAlign ) - x = qRound( x ); - - QwtPainter::drawLine( painter, x, pos.y(), x, pos.y() + len ); - break; - } - case TopScale: - { - double y = pos.y() - off; - if ( doAlign ) - y = qRound( y ); - - QwtPainter::drawLine( painter, pos.x(), y, pos.x() + len, y ); - break; - } - case BottomScale: - { - double y = pos.y() + off; - if ( doAlign ) - y = qRound( y ); - - QwtPainter::drawLine( painter, pos.x(), y, pos.x() + len, y ); - break; - } - } -} - -/*! - \brief Move the position of the scale - - The meaning of the parameter pos depends on the alignment: - <dl> - <dt>QwtScaleDraw::LeftScale - <dd>The origin is the topmost point of the - backbone. The backbone is a vertical line. - Scale marks and labels are drawn - at the left of the backbone. - <dt>QwtScaleDraw::RightScale - <dd>The origin is the topmost point of the - backbone. The backbone is a vertical line. - Scale marks and labels are drawn - at the right of the backbone. - <dt>QwtScaleDraw::TopScale - <dd>The origin is the leftmost point of the - backbone. The backbone is a horizontal line. - Scale marks and labels are drawn - above the backbone. - <dt>QwtScaleDraw::BottomScale - <dd>The origin is the leftmost point of the - backbone. The backbone is a horizontal line - Scale marks and labels are drawn - below the backbone. - </dl> - - \param pos Origin of the scale - - \sa pos(), setLength() -*/ -void QwtScaleDraw::move( const QPointF &pos ) -{ - d_data->pos = pos; - updateMap(); -} - -/*! - \return Origin of the scale - \sa move(), length() -*/ -QPointF QwtScaleDraw::pos() const -{ - return d_data->pos; -} - -/*! - Set the length of the backbone. - - The length doesn't include the space needed for - overlapping labels. - - \param length Length of the backbone - - \sa move(), minLabelDist() -*/ -void QwtScaleDraw::setLength( double length ) -{ -#if 1 - if ( length >= 0 && length < 10 ) - length = 10; - - // why should we accept negative lengths ??? - if ( length < 0 && length > -10 ) - length = -10; -#else - length = qMax( length, 10 ); -#endif - - d_data->len = length; - updateMap(); -} - -/*! - \return the length of the backbone - \sa setLength(), pos() -*/ -double QwtScaleDraw::length() const -{ - return d_data->len; -} - -/*! - Draws the label for a major scale tick - - \param painter Painter - \param value Value - - \sa drawTick(), drawBackbone(), boundingLabelRect() -*/ -void QwtScaleDraw::drawLabel( QPainter *painter, double value ) const -{ - QwtText lbl = tickLabel( painter->font(), value ); - if ( lbl.isEmpty() ) - return; - - QPointF pos = labelPosition( value ); - - QSizeF labelSize = lbl.textSize( painter->font() ); - - const QTransform transform = labelTransformation( pos, labelSize ); - - painter->save(); - painter->setWorldTransform( transform, true ); - - lbl.draw ( painter, QRect( QPoint( 0, 0 ), labelSize.toSize() ) ); - - painter->restore(); -} - -/*! - \brief Find the bounding rectangle for the label. - - The coordinates of the rectangle are absolute ( calculated from pos() ). - in direction of the tick. - - \param font Font used for painting - \param value Value - - \return Bounding rectangle - \sa labelRect() -*/ -QRect QwtScaleDraw::boundingLabelRect( const QFont &font, double value ) const -{ - QwtText lbl = tickLabel( font, value ); - if ( lbl.isEmpty() ) - return QRect(); - - const QPointF pos = labelPosition( value ); - QSizeF labelSize = lbl.textSize( font ); - - const QTransform transform = labelTransformation( pos, labelSize ); - return transform.mapRect( QRect( QPoint( 0, 0 ), labelSize.toSize() ) ); -} - -/*! - Calculate the transformation that is needed to paint a label - depending on its alignment and rotation. - - \param pos Position where to paint the label - \param size Size of the label - - \return Transformation matrix - \sa setLabelAlignment(), setLabelRotation() -*/ -QTransform QwtScaleDraw::labelTransformation( - const QPointF &pos, const QSizeF &size ) const -{ - QTransform transform; - transform.translate( pos.x(), pos.y() ); - transform.rotate( labelRotation() ); - - int flags = labelAlignment(); - if ( flags == 0 ) - { - switch ( alignment() ) - { - case RightScale: - { - if ( flags == 0 ) - flags = Qt::AlignRight | Qt::AlignVCenter; - break; - } - case LeftScale: - { - if ( flags == 0 ) - flags = Qt::AlignLeft | Qt::AlignVCenter; - break; - } - case BottomScale: - { - if ( flags == 0 ) - flags = Qt::AlignHCenter | Qt::AlignBottom; - break; - } - case TopScale: - { - if ( flags == 0 ) - flags = Qt::AlignHCenter | Qt::AlignTop; - break; - } - } - } - - double x, y; - - if ( flags & Qt::AlignLeft ) - x = -size.width(); - else if ( flags & Qt::AlignRight ) - x = 0.0; - else // Qt::AlignHCenter - x = -( 0.5 * size.width() ); - - if ( flags & Qt::AlignTop ) - y = -size.height(); - else if ( flags & Qt::AlignBottom ) - y = 0; - else // Qt::AlignVCenter - y = -( 0.5 * size.height() ); - - transform.translate( x, y ); - - return transform; -} - -/*! - Find the bounding rectangle for the label. The coordinates of - the rectangle are relative to spacing + tick length from the backbone - in direction of the tick. - - \param font Font used for painting - \param value Value - - \return Bounding rectangle that is needed to draw a label -*/ -QRectF QwtScaleDraw::labelRect( const QFont &font, double value ) const -{ - QwtText lbl = tickLabel( font, value ); - if ( lbl.isEmpty() ) - return QRectF( 0.0, 0.0, 0.0, 0.0 ); - - const QPointF pos = labelPosition( value ); - - const QSizeF labelSize = lbl.textSize( font ); - const QTransform transform = labelTransformation( pos, labelSize ); - - QRectF br = transform.mapRect( QRectF( QPointF( 0, 0 ), labelSize ) ); - br.translate( -pos.x(), -pos.y() ); - - return br; -} - -/*! - Calculate the size that is needed to draw a label - - \param font Label font - \param value Value - - \return Size that is needed to draw a label -*/ -QSizeF QwtScaleDraw::labelSize( const QFont &font, double value ) const -{ - return labelRect( font, value ).size(); -} - -/*! - Rotate all labels. - - When changing the rotation, it might be necessary to - adjust the label flags too. Finding a useful combination is - often the result of try and error. - - \param rotation Angle in degrees. When changing the label rotation, - the label flags often needs to be adjusted too. - - \sa setLabelAlignment(), labelRotation(), labelAlignment(). - -*/ -void QwtScaleDraw::setLabelRotation( double rotation ) -{ - d_data->labelRotation = rotation; -} - -/*! - \return the label rotation - \sa setLabelRotation(), labelAlignment() -*/ -double QwtScaleDraw::labelRotation() const -{ - return d_data->labelRotation; -} - -/*! - \brief Change the label flags - - Labels are aligned to the point tick length + spacing away from the backbone. - - The alignment is relative to the orientation of the label text. - In case of an flags of 0 the label will be aligned - depending on the orientation of the scale: - - QwtScaleDraw::TopScale: Qt::AlignHCenter | Qt::AlignTop\n - QwtScaleDraw::BottomScale: Qt::AlignHCenter | Qt::AlignBottom\n - QwtScaleDraw::LeftScale: Qt::AlignLeft | Qt::AlignVCenter\n - QwtScaleDraw::RightScale: Qt::AlignRight | Qt::AlignVCenter\n - - Changing the alignment is often necessary for rotated labels. - - \param alignment Or'd Qt::AlignmentFlags see <qnamespace.h> - - \sa setLabelRotation(), labelRotation(), labelAlignment() - \warning The various alignments might be confusing. - The alignment of the label is not the alignment - of the scale and is not the alignment of the flags - ( QwtText::flags() ) returned from QwtAbstractScaleDraw::label(). -*/ - -void QwtScaleDraw::setLabelAlignment( Qt::Alignment alignment ) -{ - d_data->labelAlignment = alignment; -} - -/*! - \return the label flags - \sa setLabelAlignment(), labelRotation() -*/ -Qt::Alignment QwtScaleDraw::labelAlignment() const -{ - return d_data->labelAlignment; -} - -/*! - \param font Font - \return the maximum width of a label -*/ -int QwtScaleDraw::maxLabelWidth( const QFont &font ) const -{ - double maxWidth = 0.0; - - const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); - for ( int i = 0; i < ticks.count(); i++ ) - { - const double v = ticks[i]; - if ( scaleDiv().contains( v ) ) - { - const double w = labelSize( font, ticks[i] ).width(); - if ( w > maxWidth ) - maxWidth = w; - } - } - - return qCeil( maxWidth ); -} - -/*! - \param font Font - \return the maximum height of a label -*/ -int QwtScaleDraw::maxLabelHeight( const QFont &font ) const -{ - double maxHeight = 0.0; - - const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); - for ( int i = 0; i < ticks.count(); i++ ) - { - const double v = ticks[i]; - if ( scaleDiv().contains( v ) ) - { - const double h = labelSize( font, ticks[i] ).height(); - if ( h > maxHeight ) - maxHeight = h; - } - } - - return qCeil( maxHeight ); -} - -void QwtScaleDraw::updateMap() -{ - const QPointF pos = d_data->pos; - double len = d_data->len; - - QwtScaleMap &sm = scaleMap(); - if ( orientation() == Qt::Vertical ) - sm.setPaintInterval( pos.y() + len, pos.y() ); - else - sm.setPaintInterval( pos.x(), pos.x() + len ); -} diff --git a/source/third_party/qwt/qwt_scale_engine.cpp b/source/third_party/qwt/qwt_scale_engine.cpp deleted file mode 100644 index a44dba691b846e57e54b51f6e48f4cd2d0d6d675..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_scale_engine.cpp +++ /dev/null @@ -1,1140 +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/qwt_scale_engine.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_scale_map.h" -#include <qalgorithms.h> -#include <qmath.h> -#include <float.h> -#include <limits> - -#if QT_VERSION < 0x040601 -#define qFabs(x) ::fabs(x) -#define qExp(x) ::exp(x) -#endif - -static inline double qwtLog( double base, double value ) -{ - return log( value ) / log( base ); -} - -static inline QwtInterval qwtLogInterval( double base, const QwtInterval &interval ) -{ - return QwtInterval( qwtLog( base, interval.minValue() ), - qwtLog( base, interval.maxValue() ) ); -} - -static inline QwtInterval qwtPowInterval( double base, const QwtInterval &interval ) -{ - return QwtInterval( qPow( base, interval.minValue() ), - qPow( base, interval.maxValue() ) ); -} - -static inline long double qwtIntervalWidthL( const QwtInterval &interval ) -{ - if ( !interval.isValid() ) - return 0.0; - - return static_cast<long double>( interval.maxValue() ) - - static_cast<long double>( interval.minValue() ); -} - -#if 1 - -// this version often doesn't find the best ticks: f.e for 15: 5, 10 -static double qwtStepSize( double intervalSize, int maxSteps, uint base ) -{ - const double minStep = - QwtScaleArithmetic::divideInterval( intervalSize, maxSteps, base ); - - if ( minStep != 0.0 ) - { - // # ticks per interval - const int numTicks = qCeil( qAbs( intervalSize / minStep ) ) - 1; - - // Do the minor steps fit into the interval? - if ( qwtFuzzyCompare( ( numTicks + 1 ) * qAbs( minStep ), - qAbs( intervalSize ), intervalSize ) > 0 ) - { - // The minor steps doesn't fit into the interval - return 0.5 * intervalSize; - } - } - - return minStep; -} - -#else - -static double qwtStepSize( double intervalSize, int maxSteps, uint base ) -{ - if ( maxSteps <= 0 ) - return 0.0; - - if ( maxSteps > 2 ) - { - for ( int numSteps = maxSteps; numSteps > 1; numSteps-- ) - { - const double stepSize = intervalSize / numSteps; - - const double p = ::floor( ::log( stepSize ) / ::log( base ) ); - const double fraction = qPow( base, p ); - - for ( uint n = base; n > 1; n /= 2 ) - { - if ( qFuzzyCompare( stepSize, n * fraction ) ) - return stepSize; - - if ( n == 3 && ( base % 2 ) == 0 ) - { - if ( qFuzzyCompare( stepSize, 2 * fraction ) ) - return stepSize; - } - } - } - } - - return intervalSize * 0.5; -} - -#endif - -static const double _eps = 1.0e-6; - -/*! - Ceil a value, relative to an interval - - \param value Value to be ceiled - \param intervalSize Interval size - - \return Rounded value - - \sa floorEps() -*/ -double QwtScaleArithmetic::ceilEps( double value, - double intervalSize ) -{ - const double eps = _eps * intervalSize; - - value = ( value - eps ) / intervalSize; - return ::ceil( value ) * intervalSize; -} - -/*! - Floor a value, relative to an interval - - \param value Value to be floored - \param intervalSize Interval size - - \return Rounded value - \sa floorEps() -*/ -double QwtScaleArithmetic::floorEps( double value, double intervalSize ) -{ - const double eps = _eps * intervalSize; - - value = ( value + eps ) / intervalSize; - return ::floor( value ) * intervalSize; -} - -/*! - \brief Divide an interval into steps - - \f$stepSize = (intervalSize - intervalSize * 10e^{-6}) / numSteps\f$ - - \param intervalSize Interval size - \param numSteps Number of steps - \return Step size -*/ -double QwtScaleArithmetic::divideEps( double intervalSize, double numSteps ) -{ - if ( numSteps == 0.0 || intervalSize == 0.0 ) - return 0.0; - - return ( intervalSize - ( _eps * intervalSize ) ) / numSteps; -} - -/*! - Calculate a step size for a given interval - - \param intervalSize Interval size - \param numSteps Number of steps - \param base Base for the division ( usually 10 ) - - \return Calculated step size - */ -double QwtScaleArithmetic::divideInterval( - double intervalSize, int numSteps, uint base ) -{ - if ( numSteps <= 0 ) - return 0.0; - - const double v = QwtScaleArithmetic::divideEps( intervalSize, numSteps ); - if ( v == 0.0 ) - return 0.0; - - const double lx = qwtLog( base, qFabs( v ) ); - const double p = ::floor( lx ); - - const double fraction = qPow( base, lx - p ); - - uint n = base; - while ( ( n > 1 ) && ( fraction <= n / 2 ) ) - n /= 2; - - double stepSize = n * qPow( base, p ); - if ( v < 0 ) - stepSize = -stepSize; - - return stepSize; -} - -class QwtScaleEngine::PrivateData -{ -public: - PrivateData(): - attributes( QwtScaleEngine::NoAttribute ), - lowerMargin( 0.0 ), - upperMargin( 0.0 ), - referenceValue( 0.0 ), - base( 10 ), - transform( NULL ) - { - } - - ~PrivateData() - { - delete transform; - } - - QwtScaleEngine::Attributes attributes; - - double lowerMargin; - double upperMargin; - - double referenceValue; - - uint base; - - QwtTransform* transform; -}; - -/*! - Constructor - - \param base Base of the scale engine - \sa setBase() - */ -QwtScaleEngine::QwtScaleEngine( uint base ) -{ - d_data = new PrivateData; - setBase( base ); -} - - -//! Destructor -QwtScaleEngine::~QwtScaleEngine () -{ - delete d_data; -} - -/*! - Assign a transformation - - \param transform Transformation - - The transformation object is used as factory for clones - that are returned by transformation() - - The scale engine takes ownership of the transformation. - - \sa QwtTransform::copy(), transformation() - - */ -void QwtScaleEngine::setTransformation( QwtTransform *transform ) -{ - if ( transform != d_data->transform ) - { - delete d_data->transform; - d_data->transform = transform; - } -} - -/*! - Create and return a clone of the transformation - of the engine. When the engine has no special transformation - NULL is returned, indicating no transformation. - - \return A clone of the transfomation - \sa setTransformation() - */ -QwtTransform *QwtScaleEngine::transformation() const -{ - QwtTransform *transform = NULL; - if ( d_data->transform ) - transform = d_data->transform->copy(); - - return transform; -} - -/*! - \return the margin at the lower end of the scale - The default margin is 0. - - \sa setMargins() -*/ -double QwtScaleEngine::lowerMargin() const -{ - return d_data->lowerMargin; -} - -/*! - \return the margin at the upper end of the scale - The default margin is 0. - - \sa setMargins() -*/ -double QwtScaleEngine::upperMargin() const -{ - return d_data->upperMargin; -} - -/*! - \brief Specify margins at the scale's endpoints - \param lower minimum distance between the scale's lower boundary and the - smallest enclosed value - \param upper minimum distance between the scale's upper boundary and the - greatest enclosed value - - Margins can be used to leave a minimum amount of space between - the enclosed intervals and the boundaries of the scale. - - \warning - \li QwtLogScaleEngine measures the margins in decades. - - \sa upperMargin(), lowerMargin() -*/ - -void QwtScaleEngine::setMargins( double lower, double upper ) -{ - d_data->lowerMargin = qMax( lower, 0.0 ); - d_data->upperMargin = qMax( upper, 0.0 ); -} - -/*! - Calculate a step size for an interval size - - \param intervalSize Interval size - \param numSteps Number of steps - - \return Step size -*/ -double QwtScaleEngine::divideInterval( - double intervalSize, int numSteps ) const -{ - return QwtScaleArithmetic::divideInterval( - intervalSize, numSteps, d_data->base ); -} - -/*! - Check if an interval "contains" a value - - \param interval Interval - \param value Value - - \return True, when the value is inside the interval -*/ -bool QwtScaleEngine::contains( - const QwtInterval &interval, double value ) const -{ - if ( !interval.isValid() ) - return false; - - if ( qwtFuzzyCompare( value, interval.minValue(), interval.width() ) < 0 ) - return false; - - if ( qwtFuzzyCompare( value, interval.maxValue(), interval.width() ) > 0 ) - return false; - - return true; -} - -/*! - Remove ticks from a list, that are not inside an interval - - \param ticks Tick list - \param interval Interval - - \return Stripped tick list -*/ -QList<double> QwtScaleEngine::strip( const QList<double>& ticks, - const QwtInterval &interval ) const -{ - if ( !interval.isValid() || ticks.count() == 0 ) - return QList<double>(); - - if ( contains( interval, ticks.first() ) - && contains( interval, ticks.last() ) ) - { - return ticks; - } - - QList<double> strippedTicks; - for ( int i = 0; i < ticks.count(); i++ ) - { - if ( contains( interval, ticks[i] ) ) - strippedTicks += ticks[i]; - } - return strippedTicks; -} - -/*! - \brief Build an interval around a value - - In case of v == 0.0 the interval is [-0.5, 0.5], - otherwide it is [0.5 * v, 1.5 * v] - - \param value Initial value - \return Calculated interval -*/ - -QwtInterval QwtScaleEngine::buildInterval( double value ) const -{ - const double delta = ( value == 0.0 ) ? 0.5 : qAbs( 0.5 * value ); - - if ( DBL_MAX - delta < value ) - return QwtInterval( DBL_MAX - delta, DBL_MAX ); - - if ( -DBL_MAX + delta > value ) - return QwtInterval( -DBL_MAX, -DBL_MAX + delta ); - - return QwtInterval( value - delta, value + delta ); -} - -/*! - Change a scale attribute - - \param attribute Attribute to change - \param on On/Off - - \sa Attribute, testAttribute() -*/ -void QwtScaleEngine::setAttribute( Attribute attribute, bool on ) -{ - if ( on ) - d_data->attributes |= attribute; - else - d_data->attributes &= ~attribute; -} - -/*! - \return True, if attribute is enabled. - - \param attribute Attribute to be tested - \sa Attribute, setAttribute() -*/ -bool QwtScaleEngine::testAttribute( Attribute attribute ) const -{ - return ( d_data->attributes & attribute ); -} - -/*! - Change the scale attribute - - \param attributes Set scale attributes - \sa Attribute, attributes() -*/ -void QwtScaleEngine::setAttributes( Attributes attributes ) -{ - d_data->attributes = attributes; -} - -/*! - \return Scale attributes - \sa Attribute, setAttributes(), testAttribute() -*/ -QwtScaleEngine::Attributes QwtScaleEngine::attributes() const -{ - return d_data->attributes; -} - -/*! - \brief Specify a reference point - \param r new reference value - - The reference point is needed if options IncludeReference or - Symmetric are active. Its default value is 0.0. - - \sa Attribute -*/ -void QwtScaleEngine::setReference( double r ) -{ - d_data->referenceValue = r; -} - -/*! - \return the reference value - \sa setReference(), setAttribute() -*/ -double QwtScaleEngine::reference() const -{ - return d_data->referenceValue; -} - -/*! - Set the base of the scale engine - - While a base of 10 is what 99.9% of all applications need - certain scales might need a different base: f.e 2 - - The default setting is 10 - - \param base Base of the engine - - \sa base() - */ -void QwtScaleEngine::setBase( uint base ) -{ - d_data->base = qMax( base, 2U ); -} - -/*! - \return base Base of the scale engine - \sa setBase() - */ -uint QwtScaleEngine::base() const -{ - return d_data->base; -} - -/*! - Constructor - - \param base Base of the scale engine - \sa setBase() - */ -QwtLinearScaleEngine::QwtLinearScaleEngine( uint base ): - QwtScaleEngine( base ) -{ -} - -//! Destructor -QwtLinearScaleEngine::~QwtLinearScaleEngine() -{ -} - -/*! - Align and divide an interval - - \param maxNumSteps Max. number of steps - \param x1 First limit of the interval (In/Out) - \param x2 Second limit of the interval (In/Out) - \param stepSize Step size (Out) - - \sa setAttribute() -*/ -void QwtLinearScaleEngine::autoScale( int maxNumSteps, - double &x1, double &x2, double &stepSize ) const -{ - QwtInterval interval( x1, x2 ); - interval = interval.normalized(); - - interval.setMinValue( interval.minValue() - lowerMargin() ); - interval.setMaxValue( interval.maxValue() + upperMargin() ); - - if ( testAttribute( QwtScaleEngine::Symmetric ) ) - interval = interval.symmetrize( reference() ); - - if ( testAttribute( QwtScaleEngine::IncludeReference ) ) - interval = interval.extend( reference() ); - - if ( interval.width() == 0.0 ) - interval = buildInterval( interval.minValue() ); - - stepSize = QwtScaleArithmetic::divideInterval( - interval.width(), qMax( maxNumSteps, 1 ), base() ); - - if ( !testAttribute( QwtScaleEngine::Floating ) ) - interval = align( interval, stepSize ); - - x1 = interval.minValue(); - x2 = interval.maxValue(); - - if ( testAttribute( QwtScaleEngine::Inverted ) ) - { - qSwap( x1, x2 ); - stepSize = -stepSize; - } -} - -/*! - \brief Calculate a scale division for an interval - - \param x1 First interval limit - \param x2 Second interval limit - \param maxMajorSteps Maximum for the number of major steps - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size. If stepSize == 0, the engine - calculates one. - - \return Calculated scale division -*/ -QwtScaleDiv QwtLinearScaleEngine::divideScale( double x1, double x2, - int maxMajorSteps, int maxMinorSteps, double stepSize ) const -{ - QwtInterval interval = QwtInterval( x1, x2 ).normalized(); - - if ( qwtIntervalWidthL( interval ) > std::numeric_limits<double>::max() ) - { - qWarning() << "QwtLinearScaleEngine::divideScale: overflow"; - return QwtScaleDiv(); - } - - if ( interval.width() <= 0 ) - return QwtScaleDiv(); - - stepSize = qAbs( stepSize ); - if ( stepSize == 0.0 ) - { - if ( maxMajorSteps < 1 ) - maxMajorSteps = 1; - - stepSize = QwtScaleArithmetic::divideInterval( - interval.width(), maxMajorSteps, base() ); - } - - QwtScaleDiv scaleDiv; - - if ( stepSize != 0.0 ) - { - QList<double> ticks[QwtScaleDiv::NTickTypes]; - buildTicks( interval, stepSize, maxMinorSteps, ticks ); - - scaleDiv = QwtScaleDiv( interval, ticks ); - } - - if ( x1 > x2 ) - scaleDiv.invert(); - - return scaleDiv; -} - -/*! - \brief Calculate ticks for an interval - - \param interval Interval - \param stepSize Step size - \param maxMinorSteps Maximum number of minor steps - \param ticks Arrays to be filled with the calculated ticks - - \sa buildMajorTicks(), buildMinorTicks -*/ -void QwtLinearScaleEngine::buildTicks( - const QwtInterval& interval, double stepSize, int maxMinorSteps, - QList<double> ticks[QwtScaleDiv::NTickTypes] ) const -{ - const QwtInterval boundingInterval = align( interval, stepSize ); - - ticks[QwtScaleDiv::MajorTick] = - buildMajorTicks( boundingInterval, stepSize ); - - if ( maxMinorSteps > 0 ) - { - buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize, - ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] ); - } - - for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) - { - ticks[i] = strip( ticks[i], interval ); - - // ticks very close to 0.0 are - // explicitely set to 0.0 - - for ( int j = 0; j < ticks[i].count(); j++ ) - { - if ( qwtFuzzyCompare( ticks[i][j], 0.0, stepSize ) == 0 ) - ticks[i][j] = 0.0; - } - } -} - -/*! - \brief Calculate major ticks for an interval - - \param interval Interval - \param stepSize Step size - - \return Calculated ticks -*/ -QList<double> QwtLinearScaleEngine::buildMajorTicks( - const QwtInterval &interval, double stepSize ) const -{ - int numTicks = qRound( interval.width() / stepSize ) + 1; - if ( numTicks > 10000 ) - numTicks = 10000; - - QList<double> ticks; - - ticks += interval.minValue(); - for ( int i = 1; i < numTicks - 1; i++ ) - ticks += interval.minValue() + i * stepSize; - ticks += interval.maxValue(); - - return ticks; -} - -/*! - \brief Calculate minor/medium ticks for major ticks - - \param majorTicks Major ticks - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size - \param minorTicks Array to be filled with the calculated minor ticks - \param mediumTicks Array to be filled with the calculated medium ticks - -*/ -void QwtLinearScaleEngine::buildMinorTicks( - const QList<double>& majorTicks, - int maxMinorSteps, double stepSize, - QList<double> &minorTicks, - QList<double> &mediumTicks ) const -{ - double minStep = qwtStepSize( stepSize, maxMinorSteps, base() ); - if ( minStep == 0.0 ) - return; - - // # ticks per interval - const int numTicks = qCeil( qAbs( stepSize / minStep ) ) - 1; - - int medIndex = -1; - if ( numTicks % 2 ) - medIndex = numTicks / 2; - - // calculate minor ticks - - for ( int i = 0; i < majorTicks.count(); i++ ) - { - double val = majorTicks[i]; - for ( int k = 0; k < numTicks; k++ ) - { - val += minStep; - - double alignedValue = val; - if ( qwtFuzzyCompare( val, 0.0, stepSize ) == 0 ) - alignedValue = 0.0; - - if ( k == medIndex ) - mediumTicks += alignedValue; - else - minorTicks += alignedValue; - } - } -} - -/*! - \brief Align an interval to a step size - - The limits of an interval are aligned that both are integer - multiples of the step size. - - \param interval Interval - \param stepSize Step size - - \return Aligned interval -*/ -QwtInterval QwtLinearScaleEngine::align( - const QwtInterval &interval, double stepSize ) const -{ - double x1 = interval.minValue(); - double x2 = interval.maxValue(); - - // when there is no rounding beside some effect, when - // calculating with doubles, we keep the original value - - const double eps = 0.000000000001; // since Qt 4.8: qFuzzyIsNull - if ( -DBL_MAX + stepSize <= x1 ) - { - const double x = QwtScaleArithmetic::floorEps( x1, stepSize ); - if ( qAbs(x) <= eps || !qFuzzyCompare( x1, x ) ) - x1 = x; - } - - if ( DBL_MAX - stepSize >= x2 ) - { - const double x = QwtScaleArithmetic::ceilEps( x2, stepSize ); - if ( qAbs(x) <= eps || !qFuzzyCompare( x2, x ) ) - x2 = x; - } - - return QwtInterval( x1, x2 ); -} - -/*! - Constructor - - \param base Base of the scale engine - \sa setBase() - */ -QwtLogScaleEngine::QwtLogScaleEngine( uint base ): - QwtScaleEngine( base ) -{ - setTransformation( new QwtLogTransform() ); -} - -//! Destructor -QwtLogScaleEngine::~QwtLogScaleEngine() -{ -} - -/*! - Align and divide an interval - - \param maxNumSteps Max. number of steps - \param x1 First limit of the interval (In/Out) - \param x2 Second limit of the interval (In/Out) - \param stepSize Step size (Out) - - \sa QwtScaleEngine::setAttribute() -*/ -void QwtLogScaleEngine::autoScale( int maxNumSteps, - double &x1, double &x2, double &stepSize ) const -{ - if ( x1 > x2 ) - qSwap( x1, x2 ); - - const double logBase = base(); - - QwtInterval interval( x1 / qPow( logBase, lowerMargin() ), - x2 * qPow( logBase, upperMargin() ) ); - - if ( interval.maxValue() / interval.minValue() < logBase ) - { - // scale width is less than one step -> try to build a linear scale - - QwtLinearScaleEngine linearScaler; - linearScaler.setAttributes( attributes() ); - linearScaler.setReference( reference() ); - linearScaler.setMargins( lowerMargin(), upperMargin() ); - - linearScaler.autoScale( maxNumSteps, x1, x2, stepSize ); - - QwtInterval linearInterval = QwtInterval( x1, x2 ).normalized(); - linearInterval = linearInterval.limited( LOG_MIN, LOG_MAX ); - - if ( linearInterval.maxValue() / linearInterval.minValue() < logBase ) - { - // the aligned scale is still less than one step - -#if 1 - // this code doesn't make any sense, but for compatibility - // reasons we keep it until 6.2. But it will be ignored - // in divideScale - - if ( stepSize < 0.0 ) - stepSize = -qwtLog( logBase, qAbs( stepSize ) ); - else - stepSize = qwtLog( logBase, stepSize ); -#endif - - return; - } - } - - double logRef = 1.0; - if ( reference() > LOG_MIN / 2 ) - logRef = qMin( reference(), LOG_MAX / 2 ); - - if ( testAttribute( QwtScaleEngine::Symmetric ) ) - { - const double delta = qMax( interval.maxValue() / logRef, - logRef / interval.minValue() ); - interval.setInterval( logRef / delta, logRef * delta ); - } - - if ( testAttribute( QwtScaleEngine::IncludeReference ) ) - interval = interval.extend( logRef ); - - interval = interval.limited( LOG_MIN, LOG_MAX ); - - if ( interval.width() == 0.0 ) - interval = buildInterval( interval.minValue() ); - - stepSize = divideInterval( qwtLogInterval( logBase, interval ).width(), - qMax( maxNumSteps, 1 ) ); - if ( stepSize < 1.0 ) - stepSize = 1.0; - - if ( !testAttribute( QwtScaleEngine::Floating ) ) - interval = align( interval, stepSize ); - - x1 = interval.minValue(); - x2 = interval.maxValue(); - - if ( testAttribute( QwtScaleEngine::Inverted ) ) - { - qSwap( x1, x2 ); - stepSize = -stepSize; - } -} - -/*! - \brief Calculate a scale division for an interval - - \param x1 First interval limit - \param x2 Second interval limit - \param maxMajorSteps Maximum for the number of major steps - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size. If stepSize == 0, the engine - calculates one. - - \return Calculated scale division -*/ -QwtScaleDiv QwtLogScaleEngine::divideScale( double x1, double x2, - int maxMajorSteps, int maxMinorSteps, double stepSize ) const -{ - QwtInterval interval = QwtInterval( x1, x2 ).normalized(); - interval = interval.limited( LOG_MIN, LOG_MAX ); - - if ( interval.width() <= 0 ) - return QwtScaleDiv(); - - const double logBase = base(); - - if ( interval.maxValue() / interval.minValue() < logBase ) - { - // scale width is less than one decade -> build linear scale - - QwtLinearScaleEngine linearScaler; - linearScaler.setAttributes( attributes() ); - linearScaler.setReference( reference() ); - linearScaler.setMargins( lowerMargin(), upperMargin() ); - - return linearScaler.divideScale( x1, x2, - maxMajorSteps, maxMinorSteps, 0.0 ); - } - - stepSize = qAbs( stepSize ); - if ( stepSize == 0.0 ) - { - if ( maxMajorSteps < 1 ) - maxMajorSteps = 1; - - stepSize = divideInterval( - qwtLogInterval( logBase, interval ).width(), maxMajorSteps ); - if ( stepSize < 1.0 ) - stepSize = 1.0; // major step must be >= 1 decade - } - - QwtScaleDiv scaleDiv; - if ( stepSize != 0.0 ) - { - QList<double> ticks[QwtScaleDiv::NTickTypes]; - buildTicks( interval, stepSize, maxMinorSteps, ticks ); - - scaleDiv = QwtScaleDiv( interval, ticks ); - } - - if ( x1 > x2 ) - scaleDiv.invert(); - - return scaleDiv; -} - -/*! - \brief Calculate ticks for an interval - - \param interval Interval - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size - \param ticks Arrays to be filled with the calculated ticks - - \sa buildMajorTicks(), buildMinorTicks -*/ -void QwtLogScaleEngine::buildTicks( - const QwtInterval& interval, double stepSize, int maxMinorSteps, - QList<double> ticks[QwtScaleDiv::NTickTypes] ) const -{ - const QwtInterval boundingInterval = align( interval, stepSize ); - - ticks[QwtScaleDiv::MajorTick] = - buildMajorTicks( boundingInterval, stepSize ); - - if ( maxMinorSteps > 0 ) - { - buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize, - ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] ); - } - - for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) - ticks[i] = strip( ticks[i], interval ); -} - -/*! - \brief Calculate major ticks for an interval - - \param interval Interval - \param stepSize Step size - - \return Calculated ticks -*/ -QList<double> QwtLogScaleEngine::buildMajorTicks( - const QwtInterval &interval, double stepSize ) const -{ - double width = qwtLogInterval( base(), interval ).width(); - - int numTicks = qRound( width / stepSize ) + 1; - if ( numTicks > 10000 ) - numTicks = 10000; - - const double lxmin = ::log( interval.minValue() ); - const double lxmax = ::log( interval.maxValue() ); - const double lstep = ( lxmax - lxmin ) / double( numTicks - 1 ); - - QList<double> ticks; - - ticks += interval.minValue(); - - for ( int i = 1; i < numTicks - 1; i++ ) - ticks += qExp( lxmin + double( i ) * lstep ); - - ticks += interval.maxValue(); - - return ticks; -} - -/*! - \brief Calculate minor/medium ticks for major ticks - - \param majorTicks Major ticks - \param maxMinorSteps Maximum number of minor steps - \param stepSize Step size - \param minorTicks Array to be filled with the calculated minor ticks - \param mediumTicks Array to be filled with the calculated medium ticks -*/ -void QwtLogScaleEngine::buildMinorTicks( - const QList<double> &majorTicks, - int maxMinorSteps, double stepSize, - QList<double> &minorTicks, - QList<double> &mediumTicks ) const -{ - const double logBase = base(); - - if ( stepSize < 1.1 ) // major step width is one base - { - double minStep = divideInterval( stepSize, maxMinorSteps + 1 ); - if ( minStep == 0.0 ) - return; - - const int numSteps = qRound( stepSize / minStep ); - - int mediumTickIndex = -1; - if ( ( numSteps > 2 ) && ( numSteps % 2 == 0 ) ) - mediumTickIndex = numSteps / 2; - - for ( int i = 0; i < majorTicks.count() - 1; i++ ) - { - const double v = majorTicks[i]; - const double s = logBase / numSteps; - - if ( s >= 1.0 ) - { - if ( !qFuzzyCompare( s, 1.0 ) ) - minorTicks += v * s; - - for ( int j = 2; j < numSteps; j++ ) - { - minorTicks += v * j * s; - } - } - else - { - for ( int j = 1; j < numSteps; j++ ) - { - const double tick = v + j * v * ( logBase - 1 ) / numSteps; - if ( j == mediumTickIndex ) - mediumTicks += tick; - else - minorTicks += tick; - } - } - } - } - else - { - double minStep = divideInterval( stepSize, maxMinorSteps ); - if ( minStep == 0.0 ) - return; - - if ( minStep < 1.0 ) - minStep = 1.0; - - // # subticks per interval - int numTicks = qRound( stepSize / minStep ) - 1; - - // Do the minor steps fit into the interval? - if ( qwtFuzzyCompare( ( numTicks + 1 ) * minStep, - stepSize, stepSize ) > 0 ) - { - numTicks = 0; - } - - if ( numTicks < 1 ) - return; - - int mediumTickIndex = -1; - if ( ( numTicks > 2 ) && ( numTicks % 2 ) ) - mediumTickIndex = numTicks / 2; - - // substep factor = base^substeps - const qreal minFactor = qMax( qPow( logBase, minStep ), qreal( logBase ) ); - - for ( int i = 0; i < majorTicks.count(); i++ ) - { - double tick = majorTicks[i]; - for ( int j = 0; j < numTicks; j++ ) - { - tick *= minFactor; - - if ( j == mediumTickIndex ) - mediumTicks += tick; - else - minorTicks += tick; - } - } - } -} - -/*! - \brief Align an interval to a step size - - The limits of an interval are aligned that both are integer - multiples of the step size. - - \param interval Interval - \param stepSize Step size - - \return Aligned interval -*/ -QwtInterval QwtLogScaleEngine::align( - const QwtInterval &interval, double stepSize ) const -{ - const QwtInterval intv = qwtLogInterval( base(), interval ); - - double x1 = QwtScaleArithmetic::floorEps( intv.minValue(), stepSize ); - if ( qwtFuzzyCompare( interval.minValue(), x1, stepSize ) == 0 ) - x1 = interval.minValue(); - - double x2 = QwtScaleArithmetic::ceilEps( intv.maxValue(), stepSize ); - if ( qwtFuzzyCompare( interval.maxValue(), x2, stepSize ) == 0 ) - x2 = interval.maxValue(); - - return qwtPowInterval( base(), QwtInterval( x1, x2 ) ); -} diff --git a/source/third_party/qwt/qwt_scale_map.cpp b/source/third_party/qwt/qwt_scale_map.cpp deleted file mode 100644 index 5eec915ff20817369502299cccf240a7bb045136..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_scale_map.cpp +++ /dev/null @@ -1,248 +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/qwt_scale_map.h" -#include "qwt/qwt_math.h" -#include <qrect.h> -#include <qdebug.h> - -/*! - \brief Constructor - - The scale and paint device intervals are both set to [0,1]. -*/ -QwtScaleMap::QwtScaleMap(): - d_s1( 0.0 ), - d_s2( 1.0 ), - d_p1( 0.0 ), - d_p2( 1.0 ), - d_cnv( 1.0 ), - d_ts1( 0.0 ), - d_transform( NULL ) -{ -} - -//! Copy constructor -QwtScaleMap::QwtScaleMap( const QwtScaleMap& other ): - d_s1( other.d_s1 ), - d_s2( other.d_s2 ), - d_p1( other.d_p1 ), - d_p2( other.d_p2 ), - d_cnv( other.d_cnv ), - d_ts1( other.d_ts1 ), - d_transform( NULL ) -{ - if ( other.d_transform ) - d_transform = other.d_transform->copy(); -} - -/*! - Destructor -*/ -QwtScaleMap::~QwtScaleMap() -{ - delete d_transform; -} - -//! Assignment operator -QwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other ) -{ - d_s1 = other.d_s1; - d_s2 = other.d_s2; - d_p1 = other.d_p1; - d_p2 = other.d_p2; - d_cnv = other.d_cnv; - d_ts1 = other.d_ts1; - - delete d_transform; - d_transform = NULL; - - if ( other.d_transform ) - d_transform = other.d_transform->copy(); - - return *this; -} - -/*! - Initialize the map with a transformation -*/ -void QwtScaleMap::setTransformation( QwtTransform *transform ) -{ - if ( transform != d_transform ) - { - delete d_transform; - d_transform = transform; - } - - setScaleInterval( d_s1, d_s2 ); -} - -//! Get the transformation -const QwtTransform *QwtScaleMap::transformation() const -{ - return d_transform; -} - -/*! - \brief Specify the borders of the scale interval - \param s1 first border - \param s2 second border - \warning scales might be aligned to - transformation depending boundaries -*/ -void QwtScaleMap::setScaleInterval( double s1, double s2 ) -{ - d_s1 = s1; - d_s2 = s2; - - if ( d_transform ) - { - d_s1 = d_transform->bounded( d_s1 ); - d_s2 = d_transform->bounded( d_s2 ); - } - - updateFactor(); -} - -/*! - \brief Specify the borders of the paint device interval - \param p1 first border - \param p2 second border -*/ -void QwtScaleMap::setPaintInterval( double p1, double p2 ) -{ - d_p1 = p1; - d_p2 = p2; - - updateFactor(); -} - -void QwtScaleMap::updateFactor() -{ - d_ts1 = d_s1; - double ts2 = d_s2; - - if ( d_transform ) - { - d_ts1 = d_transform->transform( d_ts1 ); - ts2 = d_transform->transform( ts2 ); - } - - d_cnv = 1.0; - if ( d_ts1 != ts2 ) - d_cnv = ( d_p2 - d_p1 ) / ( ts2 - d_ts1 ); -} - -/*! - Transform a rectangle from scale to paint coordinates - - \param xMap X map - \param yMap Y map - \param rect Rectangle in scale coordinates - \return Rectangle in paint coordinates - - \sa invTransform() -*/ -QRectF QwtScaleMap::transform( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRectF &rect ) -{ - double x1 = xMap.transform( rect.left() ); - double x2 = xMap.transform( rect.right() ); - double y1 = yMap.transform( rect.top() ); - double y2 = yMap.transform( rect.bottom() ); - - if ( x2 < x1 ) - qSwap( x1, x2 ); - if ( y2 < y1 ) - qSwap( y1, y2 ); - - if ( qwtFuzzyCompare( x1, 0.0, x2 - x1 ) == 0 ) - x1 = 0.0; - if ( qwtFuzzyCompare( x2, 0.0, x2 - x1 ) == 0 ) - x2 = 0.0; - if ( qwtFuzzyCompare( y1, 0.0, y2 - y1 ) == 0 ) - y1 = 0.0; - if ( qwtFuzzyCompare( y2, 0.0, y2 - y1 ) == 0 ) - y2 = 0.0; - - return QRectF( 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 pos Position in paint coordinates - \return Position in scale coordinates - \sa transform() -*/ -QPointF QwtScaleMap::invTransform( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QPointF &pos ) -{ - return QPointF( - xMap.invTransform( pos.x() ), - yMap.invTransform( pos.y() ) - ); -} - -/*! - Transform a point from scale to paint coordinates - - \param xMap X map - \param yMap Y map - \param pos Position in scale coordinates - \return Position in paint coordinates - - \sa invTransform() -*/ -QPointF QwtScaleMap::transform( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QPointF &pos ) -{ - return QPointF( - xMap.transform( pos.x() ), - yMap.transform( pos.y() ) - ); -} - -/*! - 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() -*/ -QRectF QwtScaleMap::invTransform( const QwtScaleMap &xMap, - const QwtScaleMap &yMap, const QRectF &rect ) -{ - const double x1 = xMap.invTransform( rect.left() ); - const double x2 = xMap.invTransform( rect.right() - 1 ); - const double y1 = yMap.invTransform( rect.top() ); - const double y2 = yMap.invTransform( rect.bottom() - 1 ); - - const QRectF r( x1, y1, x2 - x1, y2 - y1 ); - return r.normalized(); -} - -#ifndef QT_NO_DEBUG_STREAM - -QDebug operator<<( QDebug debug, const QwtScaleMap &map ) -{ - debug.nospace() << "QwtScaleMap(" - << map.transformation() - << ", s:" << map.s1() << "->" << map.s2() - << ", p:" << map.p1() << "->" << map.p2() - << ")"; - - return debug.space(); -} - -#endif diff --git a/source/third_party/qwt/qwt_scale_widget.cpp b/source/third_party/qwt/qwt_scale_widget.cpp deleted file mode 100644 index 27b483d27a85cee181c6da3d4c6eeff057ba3482..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_scale_widget.cpp +++ /dev/null @@ -1,942 +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/qwt_scale_widget.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_color_map.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_scale_div.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_scale_engine.h" -#include <qpainter.h> -#include <qevent.h> -#include <qmath.h> -#include <qstyle.h> -#include <qstyleoption.h> - -class QwtScaleWidget::PrivateData -{ -public: - PrivateData(): - scaleDraw( NULL ) - { - colorBar.colorMap = NULL; - } - - ~PrivateData() - { - delete scaleDraw; - delete colorBar.colorMap; - } - - QwtScaleDraw *scaleDraw; - - int borderDist[2]; - int minBorderDist[2]; - int scaleLength; - int margin; - - int titleOffset; - int spacing; - QwtText title; - - QwtScaleWidget::LayoutFlags layoutFlags; - - struct t_colorBar - { - bool isEnabled; - int width; - QwtInterval interval; - QwtColorMap *colorMap; - } colorBar; -}; - -/*! - \brief Create a scale with the position QwtScaleWidget::Left - \param parent Parent widget -*/ -QwtScaleWidget::QwtScaleWidget( QWidget *parent ): - QWidget( parent ) -{ - initScale( QwtScaleDraw::LeftScale ); -} - -/*! - \brief Constructor - \param align Alignment. - \param parent Parent widget -*/ -QwtScaleWidget::QwtScaleWidget( - QwtScaleDraw::Alignment align, QWidget *parent ): - QWidget( parent ) -{ - initScale( align ); -} - -//! Destructor -QwtScaleWidget::~QwtScaleWidget() -{ - delete d_data; -} - -//! Initialize the scale -void QwtScaleWidget::initScale( QwtScaleDraw::Alignment align ) -{ - d_data = new PrivateData; - - d_data->layoutFlags = 0; - if ( align == QwtScaleDraw::RightScale ) - d_data->layoutFlags |= TitleInverted; - - d_data->borderDist[0] = 0; - d_data->borderDist[1] = 0; - d_data->minBorderDist[0] = 0; - d_data->minBorderDist[1] = 0; - d_data->margin = 4; - d_data->titleOffset = 0; - d_data->spacing = 2; - - d_data->scaleDraw = new QwtScaleDraw; - d_data->scaleDraw->setAlignment( align ); - d_data->scaleDraw->setLength( 10 ); - - d_data->scaleDraw->setScaleDiv( - QwtLinearScaleEngine().divideScale( 0.0, 100.0, 10, 5 ) ); - - d_data->colorBar.colorMap = new QwtLinearColorMap(); - d_data->colorBar.isEnabled = false; - d_data->colorBar.width = 10; - - const int flags = Qt::AlignHCenter - | Qt::TextExpandTabs | Qt::TextWordWrap; - d_data->title.setRenderFlags( flags ); - d_data->title.setFont( font() ); - - QSizePolicy policy( QSizePolicy::MinimumExpanding, - QSizePolicy::Fixed ); - if ( d_data->scaleDraw->orientation() == Qt::Vertical ) - policy.transpose(); - - setSizePolicy( policy ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); -} - -/*! - Toggle an layout flag - - \param flag Layout flag - \param on true/false - - \sa testLayoutFlag(), LayoutFlag -*/ -void QwtScaleWidget::setLayoutFlag( LayoutFlag flag, bool on ) -{ - if ( ( ( d_data->layoutFlags & flag ) != 0 ) != on ) - { - if ( on ) - d_data->layoutFlags |= flag; - else - d_data->layoutFlags &= ~flag; - } -} - -/*! - Test a layout flag - - \param flag Layout flag - \return true/false - \sa setLayoutFlag(), LayoutFlag -*/ -bool QwtScaleWidget::testLayoutFlag( LayoutFlag flag ) const -{ - return ( d_data->layoutFlags & flag ); -} - -/*! - Give title new text contents - - \param title New title - \sa title(), setTitle(const QwtText &); -*/ -void QwtScaleWidget::setTitle( const QString &title ) -{ - if ( d_data->title.text() != title ) - { - d_data->title.setText( title ); - layoutScale(); - } -} - -/*! - Give title new text contents - - \param title New title - \sa title() - \warning The title flags are interpreted in - direction of the label, AlignTop, AlignBottom can't be set - as the title will always be aligned to the scale. -*/ -void QwtScaleWidget::setTitle( const QwtText &title ) -{ - QwtText t = title; - const int flags = title.renderFlags() & ~( Qt::AlignTop | Qt::AlignBottom ); - t.setRenderFlags( flags ); - - if ( t != d_data->title ) - { - d_data->title = t; - layoutScale(); - } -} - -/*! - Change the alignment - - \param alignment New alignment - \sa alignment() -*/ -void QwtScaleWidget::setAlignment( QwtScaleDraw::Alignment alignment ) -{ - if ( d_data->scaleDraw ) - d_data->scaleDraw->setAlignment( alignment ); - - if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) ) - { - QSizePolicy policy( QSizePolicy::MinimumExpanding, - QSizePolicy::Fixed ); - if ( d_data->scaleDraw->orientation() == Qt::Vertical ) - policy.transpose(); - - setSizePolicy( policy ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); - } - - layoutScale(); -} - - -/*! - \return position - \sa setPosition() -*/ -QwtScaleDraw::Alignment QwtScaleWidget::alignment() const -{ - if ( !scaleDraw() ) - return QwtScaleDraw::LeftScale; - - return scaleDraw()->alignment(); -} - -/*! - Specify distances of the scale's endpoints from the - widget's borders. The actual borders will never be less - than minimum border distance. - \param dist1 Left or top Distance - \param dist2 Right or bottom distance - \sa borderDist() -*/ -void QwtScaleWidget::setBorderDist( int dist1, int dist2 ) -{ - if ( dist1 != d_data->borderDist[0] || dist2 != d_data->borderDist[1] ) - { - d_data->borderDist[0] = dist1; - d_data->borderDist[1] = dist2; - layoutScale(); - } -} - -/*! - \brief Specify the margin to the colorBar/base line. - \param margin Margin - \sa margin() -*/ -void QwtScaleWidget::setMargin( int margin ) -{ - margin = qMax( 0, margin ); - if ( margin != d_data->margin ) - { - d_data->margin = margin; - layoutScale(); - } -} - -/*! - \brief Specify the distance between color bar, scale and title - \param spacing Spacing - \sa spacing() -*/ -void QwtScaleWidget::setSpacing( int spacing ) -{ - spacing = qMax( 0, spacing ); - if ( spacing != d_data->spacing ) - { - d_data->spacing = spacing; - layoutScale(); - } -} - -/*! - \brief Change the alignment for the labels. - - \sa QwtScaleDraw::setLabelAlignment(), setLabelRotation() -*/ -void QwtScaleWidget::setLabelAlignment( Qt::Alignment alignment ) -{ - d_data->scaleDraw->setLabelAlignment( alignment ); - layoutScale(); -} - -/*! - \brief Change the rotation for the labels. - See QwtScaleDraw::setLabelRotation(). - - \param rotation Rotation - \sa QwtScaleDraw::setLabelRotation(), setLabelFlags() -*/ -void QwtScaleWidget::setLabelRotation( double rotation ) -{ - d_data->scaleDraw->setLabelRotation( rotation ); - layoutScale(); -} - -/*! - Set a scale draw - - scaleDraw has to be created with new and will be deleted in - ~QwtScaleWidget() or the next call of setScaleDraw(). - scaleDraw will be initialized with the attributes of - the previous scaleDraw object. - - \param scaleDraw ScaleDraw object - \sa scaleDraw() -*/ -void QwtScaleWidget::setScaleDraw( QwtScaleDraw *scaleDraw ) -{ - if ( ( scaleDraw == NULL ) || ( scaleDraw == d_data->scaleDraw ) ) - return; - - const QwtScaleDraw* sd = d_data->scaleDraw; - if ( sd ) - { - scaleDraw->setAlignment( sd->alignment() ); - scaleDraw->setScaleDiv( sd->scaleDiv() ); - - QwtTransform *transform = NULL; - if ( sd->scaleMap().transformation() ) - transform = sd->scaleMap().transformation()->copy(); - - scaleDraw->setTransformation( transform ); - } - - delete d_data->scaleDraw; - d_data->scaleDraw = scaleDraw; - - layoutScale(); -} - -/*! - \return scaleDraw of this scale - \sa setScaleDraw(), QwtScaleDraw::setScaleDraw() -*/ -const QwtScaleDraw *QwtScaleWidget::scaleDraw() const -{ - return d_data->scaleDraw; -} - -/*! - \return scaleDraw of this scale - \sa QwtScaleDraw::setScaleDraw() -*/ -QwtScaleDraw *QwtScaleWidget::scaleDraw() -{ - return d_data->scaleDraw; -} - -/*! - \return title - \sa setTitle() -*/ -QwtText QwtScaleWidget::title() const -{ - return d_data->title; -} - -/*! - \return start border distance - \sa setBorderDist() -*/ -int QwtScaleWidget::startBorderDist() const -{ - return d_data->borderDist[0]; -} - -/*! - \return end border distance - \sa setBorderDist() -*/ -int QwtScaleWidget::endBorderDist() const -{ - return d_data->borderDist[1]; -} - -/*! - \return margin - \sa setMargin() -*/ -int QwtScaleWidget::margin() const -{ - return d_data->margin; -} - -/*! - \return distance between scale and title - \sa setMargin() -*/ -int QwtScaleWidget::spacing() const -{ - return d_data->spacing; -} - -/*! - \brief paintEvent -*/ -void QwtScaleWidget::paintEvent( QPaintEvent *event ) -{ - QPainter painter( this ); - painter.setClipRegion( event->region() ); - - QStyleOption opt; - opt.init(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); - - draw( &painter ); -} - -/*! - \brief draw the scale -*/ -void QwtScaleWidget::draw( QPainter *painter ) const -{ - d_data->scaleDraw->draw( painter, palette() ); - - if ( d_data->colorBar.isEnabled && d_data->colorBar.width > 0 && - d_data->colorBar.interval.isValid() ) - { - drawColorBar( painter, colorBarRect( contentsRect() ) ); - } - - QRect r = contentsRect(); - if ( d_data->scaleDraw->orientation() == Qt::Horizontal ) - { - r.setLeft( r.left() + d_data->borderDist[0] ); - r.setWidth( r.width() - d_data->borderDist[1] ); - } - else - { - r.setTop( r.top() + d_data->borderDist[0] ); - r.setHeight( r.height() - d_data->borderDist[1] ); - } - - if ( !d_data->title.isEmpty() ) - drawTitle( painter, d_data->scaleDraw->alignment(), r ); -} - -/*! - Calculate the the rectangle for the color bar - - \param rect Bounding rectangle for all components of the scale - \return Rectangle for the color bar -*/ -QRectF QwtScaleWidget::colorBarRect( const QRectF& rect ) const -{ - QRectF cr = rect; - - if ( d_data->scaleDraw->orientation() == Qt::Horizontal ) - { - cr.setLeft( cr.left() + d_data->borderDist[0] ); - cr.setWidth( cr.width() - d_data->borderDist[1] + 1 ); - } - else - { - cr.setTop( cr.top() + d_data->borderDist[0] ); - cr.setHeight( cr.height() - d_data->borderDist[1] + 1 ); - } - - switch ( d_data->scaleDraw->alignment() ) - { - case QwtScaleDraw::LeftScale: - { - cr.setLeft( cr.right() - d_data->margin - - d_data->colorBar.width ); - cr.setWidth( d_data->colorBar.width ); - break; - } - - case QwtScaleDraw::RightScale: - { - cr.setLeft( cr.left() + d_data->margin ); - cr.setWidth( d_data->colorBar.width ); - break; - } - - case QwtScaleDraw::BottomScale: - { - cr.setTop( cr.top() + d_data->margin ); - cr.setHeight( d_data->colorBar.width ); - break; - } - - case QwtScaleDraw::TopScale: - { - cr.setTop( cr.bottom() - d_data->margin - - d_data->colorBar.width ); - cr.setHeight( d_data->colorBar.width ); - break; - } - } - - return cr; -} - -/*! - Event handler for resize events - \param event Resize event -*/ -void QwtScaleWidget::resizeEvent( QResizeEvent *event ) -{ - Q_UNUSED( event ); - layoutScale( false ); -} - -/*! - Recalculate the scale's geometry and layout based on - the current geometry and fonts. - - \param update_geometry Notify the layout system and call update - to redraw the scale -*/ - -void QwtScaleWidget::layoutScale( bool update_geometry ) -{ - int bd0, bd1; - getBorderDistHint( bd0, bd1 ); - if ( d_data->borderDist[0] > bd0 ) - bd0 = d_data->borderDist[0]; - if ( d_data->borderDist[1] > bd1 ) - bd1 = d_data->borderDist[1]; - - int colorBarWidth = 0; - if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() ) - colorBarWidth = d_data->colorBar.width + d_data->spacing; - - const QRectF r = contentsRect(); - double x, y, length; - - if ( d_data->scaleDraw->orientation() == Qt::Vertical ) - { - y = r.top() + bd0; - length = r.height() - ( bd0 + bd1 ); - - if ( d_data->scaleDraw->alignment() == QwtScaleDraw::LeftScale ) - x = r.right() - 1.0 - d_data->margin - colorBarWidth; - else - x = r.left() + d_data->margin + colorBarWidth; - } - else - { - x = r.left() + bd0; - length = r.width() - ( bd0 + bd1 ); - - if ( d_data->scaleDraw->alignment() == QwtScaleDraw::BottomScale ) - y = r.top() + d_data->margin + colorBarWidth; - else - y = r.bottom() - 1.0 - d_data->margin - colorBarWidth; - } - - d_data->scaleDraw->move( x, y ); - d_data->scaleDraw->setLength( length ); - - const int extent = qCeil( d_data->scaleDraw->extent( font() ) ); - - d_data->titleOffset = - d_data->margin + d_data->spacing + colorBarWidth + extent; - - if ( update_geometry ) - { - updateGeometry(); - update(); - } -} - -/*! - Draw the color bar of the scale widget - - \param painter Painter - \param rect Bounding rectangle for the color bar - - \sa setColorBarEnabled() -*/ -void QwtScaleWidget::drawColorBar( QPainter *painter, const QRectF& rect ) const -{ - if ( !d_data->colorBar.interval.isValid() ) - return; - - const QwtScaleDraw* sd = d_data->scaleDraw; - - QwtPainter::drawColorBar( painter, *d_data->colorBar.colorMap, - d_data->colorBar.interval.normalized(), sd->scaleMap(), - sd->orientation(), rect ); -} - -/*! - Rotate and paint a title according to its position into a given rectangle. - - \param painter Painter - \param align Alignment - \param rect Bounding rectangle -*/ - -void QwtScaleWidget::drawTitle( QPainter *painter, - QwtScaleDraw::Alignment align, const QRectF &rect ) const -{ - QRectF r = rect; - double angle; - int flags = d_data->title.renderFlags() & - ~( Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter ); - - switch ( align ) - { - case QwtScaleDraw::LeftScale: - angle = -90.0; - flags |= Qt::AlignTop; - r.setRect( r.left(), r.bottom(), - r.height(), r.width() - d_data->titleOffset ); - break; - - case QwtScaleDraw::RightScale: - angle = -90.0; - flags |= Qt::AlignTop; - r.setRect( r.left() + d_data->titleOffset, r.bottom(), - r.height(), r.width() - d_data->titleOffset ); - break; - - case QwtScaleDraw::BottomScale: - angle = 0.0; - flags |= Qt::AlignBottom; - r.setTop( r.top() + d_data->titleOffset ); - break; - - case QwtScaleDraw::TopScale: - default: - angle = 0.0; - flags |= Qt::AlignTop; - r.setBottom( r.bottom() - d_data->titleOffset ); - break; - } - - if ( d_data->layoutFlags & TitleInverted ) - { - if ( align == QwtScaleDraw::LeftScale - || align == QwtScaleDraw::RightScale ) - { - angle = -angle; - r.setRect( r.x() + r.height(), r.y() - r.width(), - r.width(), r.height() ); - } - } - - painter->save(); - painter->setFont( font() ); - painter->setPen( palette().color( QPalette::Text ) ); - - painter->translate( r.x(), r.y() ); - if ( angle != 0.0 ) - painter->rotate( angle ); - - QwtText title = d_data->title; - title.setRenderFlags( flags ); - title.draw( painter, QRectF( 0.0, 0.0, r.width(), r.height() ) ); - - painter->restore(); -} - -/*! - \brief Notify a change of the scale - - This virtual function can be overloaded by derived - classes. The default implementation updates the geometry - and repaints the widget. -*/ - -void QwtScaleWidget::scaleChange() -{ - layoutScale(); -} - -/*! - \return a size hint -*/ -QSize QwtScaleWidget::sizeHint() const -{ - return minimumSizeHint(); -} - -/*! - \return a minimum size hint -*/ -QSize QwtScaleWidget::minimumSizeHint() const -{ - const Qt::Orientation o = d_data->scaleDraw->orientation(); - - // Border Distance cannot be less than the scale borderDistHint - // Note, the borderDistHint is already included in minHeight/minWidth - int length = 0; - int mbd1, mbd2; - getBorderDistHint( mbd1, mbd2 ); - length += qMax( 0, d_data->borderDist[0] - mbd1 ); - length += qMax( 0, d_data->borderDist[1] - mbd2 ); - length += d_data->scaleDraw->minLength( font() ); - - int dim = dimForLength( length, font() ); - if ( length < dim ) - { - // compensate for long titles - length = dim; - dim = dimForLength( length, font() ); - } - - QSize size( length + 2, dim ); - if ( o == Qt::Vertical ) - size.transpose(); - - int left, right, top, bottom; - getContentsMargins( &left, &top, &right, &bottom ); - return size + QSize( left + right, top + bottom ); -} - -/*! - \brief Find the height of the title for a given width. - \param width Width - \return height Height - */ - -int QwtScaleWidget::titleHeightForWidth( int width ) const -{ - return qCeil( d_data->title.heightForWidth( width, font() ) ); -} - -/*! - \brief Find the minimum dimension for a given length. - dim is the height, length the width seen in - direction of the title. - \param length width for horizontal, height for vertical scales - \param scaleFont Font of the scale - \return height for horizontal, width for vertical scales -*/ - -int QwtScaleWidget::dimForLength( int length, const QFont &scaleFont ) const -{ - const int extent = qCeil( d_data->scaleDraw->extent( scaleFont ) ); - - int dim = d_data->margin + extent + 1; - - if ( !d_data->title.isEmpty() ) - dim += titleHeightForWidth( length ) + d_data->spacing; - - if ( d_data->colorBar.isEnabled && d_data->colorBar.interval.isValid() ) - dim += d_data->colorBar.width + d_data->spacing; - - return dim; -} - -/*! - \brief Calculate a hint for the border distances. - - This member function calculates the distance - of the scale's endpoints from the widget borders which - is required for the mark labels to fit into the widget. - The maximum of this distance an the minimum border distance - is returned. - - \param start Return parameter for the border width at - the beginning of the scale - \param end Return parameter for the border width at the - end of the scale - - \warning - <ul> <li>The minimum border distance depends on the font.</ul> - \sa setMinBorderDist(), getMinBorderDist(), setBorderDist() -*/ -void QwtScaleWidget::getBorderDistHint( int &start, int &end ) const -{ - d_data->scaleDraw->getBorderDistHint( font(), start, end ); - - if ( start < d_data->minBorderDist[0] ) - start = d_data->minBorderDist[0]; - - if ( end < d_data->minBorderDist[1] ) - end = d_data->minBorderDist[1]; -} - -/*! - Set a minimum value for the distances of the scale's endpoints from - the widget borders. This is useful to avoid that the scales - are "jumping", when the tick labels or their positions change - often. - - \param start Minimum for the start border - \param end Minimum for the end border - \sa getMinBorderDist(), getBorderDistHint() -*/ -void QwtScaleWidget::setMinBorderDist( int start, int end ) -{ - d_data->minBorderDist[0] = start; - d_data->minBorderDist[1] = end; -} - -/*! - Get the minimum value for the distances of the scale's endpoints from - the widget borders. - - \param start Return parameter for the border width at - the beginning of the scale - \param end Return parameter for the border width at the - end of the scale - - \sa setMinBorderDist(), getBorderDistHint() -*/ -void QwtScaleWidget::getMinBorderDist( int &start, int &end ) const -{ - start = d_data->minBorderDist[0]; - end = d_data->minBorderDist[1]; -} - -/*! - \brief Assign a scale division - - The scale division determines where to set the tick marks. - - \param scaleDiv Scale Division - \sa For more information about scale divisions, see QwtScaleDiv. -*/ -void QwtScaleWidget::setScaleDiv( const QwtScaleDiv &scaleDiv ) -{ - QwtScaleDraw *sd = d_data->scaleDraw; - if ( sd->scaleDiv() != scaleDiv ) - { - sd->setScaleDiv( scaleDiv ); - layoutScale(); - - Q_EMIT scaleDivChanged(); - } -} - -/*! - Set the transformation - - \param transformation Transformation - \sa QwtAbstractScaleDraw::scaleDraw(), QwtScaleMap - */ -void QwtScaleWidget::setTransformation( QwtTransform *transformation ) -{ - d_data->scaleDraw->setTransformation( transformation ); - layoutScale(); -} - -/*! - En/disable a color bar associated to the scale - \sa isColorBarEnabled(), setColorBarWidth() -*/ -void QwtScaleWidget::setColorBarEnabled( bool on ) -{ - if ( on != d_data->colorBar.isEnabled ) - { - d_data->colorBar.isEnabled = on; - layoutScale(); - } -} - -/*! - \return true, when the color bar is enabled - \sa setColorBarEnabled(), setColorBarWidth() -*/ -bool QwtScaleWidget::isColorBarEnabled() const -{ - return d_data->colorBar.isEnabled; -} - -/*! - Set the width of the color bar - - \param width Width - \sa colorBarWidth(), setColorBarEnabled() -*/ -void QwtScaleWidget::setColorBarWidth( int width ) -{ - if ( width != d_data->colorBar.width ) - { - d_data->colorBar.width = width; - if ( isColorBarEnabled() ) - layoutScale(); - } -} - -/*! - \return Width of the color bar - \sa setColorBarEnabled(), setColorBarEnabled() -*/ -int QwtScaleWidget::colorBarWidth() const -{ - return d_data->colorBar.width; -} - -/*! - \return Value interval for the color bar - \sa setColorMap(), colorMap() -*/ -QwtInterval QwtScaleWidget::colorBarInterval() const -{ - return d_data->colorBar.interval; -} - -/*! - Set the color map and value interval, that are used for displaying - the color bar. - - \param interval Value interval - \param colorMap Color map - - \sa colorMap(), colorBarInterval() -*/ -void QwtScaleWidget::setColorMap( - const QwtInterval &interval, QwtColorMap *colorMap ) -{ - d_data->colorBar.interval = interval; - - if ( colorMap != d_data->colorBar.colorMap ) - { - delete d_data->colorBar.colorMap; - d_data->colorBar.colorMap = colorMap; - } - - if ( isColorBarEnabled() ) - layoutScale(); -} - -/*! - \return Color map - \sa setColorMap(), colorBarInterval() -*/ -const QwtColorMap *QwtScaleWidget::colorMap() const -{ - return d_data->colorBar.colorMap; -} diff --git a/source/third_party/qwt/qwt_series_data.cpp b/source/third_party/qwt/qwt_series_data.cpp deleted file mode 100644 index 46661393d74045f53146ed530241c644e23b2279..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_series_data.cpp +++ /dev/null @@ -1,346 +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/qwt_series_data.h" -#include "qwt/qwt_math.h" - -static inline QRectF qwtBoundingRect( const QPointF &sample ) -{ - return QRectF( sample.x(), sample.y(), 0.0, 0.0 ); -} - -static inline QRectF qwtBoundingRect( const QwtPoint3D &sample ) -{ - return QRectF( sample.x(), sample.y(), 0.0, 0.0 ); -} - -static inline QRectF qwtBoundingRect( const QwtPointPolar &sample ) -{ - return QRectF( sample.azimuth(), sample.radius(), 0.0, 0.0 ); -} - -static inline QRectF qwtBoundingRect( const QwtIntervalSample &sample ) -{ - return QRectF( sample.interval.minValue(), sample.value, - sample.interval.maxValue() - sample.interval.minValue(), 0.0 ); -} - -static inline QRectF qwtBoundingRect( const QwtSetSample &sample ) -{ - double minY = sample.set[0]; - double maxY = sample.set[0]; - - for ( int i = 1; i < sample.set.size(); i++ ) - { - if ( sample.set[i] < minY ) - minY = sample.set[i]; - if ( sample.set[i] > maxY ) - maxY = sample.set[i]; - } - - double minX = sample.value; - double maxX = sample.value; - - return QRectF( minX, minY, maxX - minX, maxY - minY ); -} - -static inline QRectF qwtBoundingRect( const QwtOHLCSample &sample ) -{ - const QwtInterval interval = sample.boundingInterval(); - return QRectF( interval.minValue(), sample.time, interval.width(), 0.0 ); -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ - -template <class T> -QRectF qwtBoundingRectT( - const QwtSeriesData<T>& series, int from, int to ) -{ - QRectF boundingRect( 1.0, 1.0, -2.0, -2.0 ); // invalid; - - if ( from < 0 ) - from = 0; - - if ( to < 0 ) - to = series.size() - 1; - - if ( to < from ) - return boundingRect; - - int i; - for ( i = from; i <= to; i++ ) - { - const QRectF rect = qwtBoundingRect( series.sample( i ) ); - if ( rect.width() >= 0.0 && rect.height() >= 0.0 ) - { - boundingRect = rect; - i++; - break; - } - } - - for ( ; i <= to; i++ ) - { - const QRectF rect = qwtBoundingRect( series.sample( i ) ); - if ( rect.width() >= 0.0 && rect.height() >= 0.0 ) - { - boundingRect.setLeft( qMin( boundingRect.left(), rect.left() ) ); - boundingRect.setRight( qMax( boundingRect.right(), rect.right() ) ); - boundingRect.setTop( qMin( boundingRect.top(), rect.top() ) ); - boundingRect.setBottom( qMax( boundingRect.bottom(), rect.bottom() ) ); - } - } - - return boundingRect; -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ -QRectF qwtBoundingRect( - const QwtSeriesData<QPointF> &series, int from, int to ) -{ - return qwtBoundingRectT<QPointF>( series, from, to ); -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ -QRectF qwtBoundingRect( - const QwtSeriesData<QwtPoint3D> &series, int from, int to ) -{ - return qwtBoundingRectT<QwtPoint3D>( series, from, to ); -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - The horizontal coordinates represent the azimuth, the - vertical coordinates the radius. - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ -QRectF qwtBoundingRect( - const QwtSeriesData<QwtPointPolar> &series, int from, int to ) -{ - return qwtBoundingRectT<QwtPointPolar>( series, from, to ); -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ -QRectF qwtBoundingRect( - const QwtSeriesData<QwtIntervalSample>& series, int from, int to ) -{ - return qwtBoundingRectT<QwtIntervalSample>( series, from, to ); -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ -QRectF qwtBoundingRect( - const QwtSeriesData<QwtOHLCSample>& series, int from, int to ) -{ - return qwtBoundingRectT<QwtOHLCSample>( series, from, to ); -} - -/*! - \brief Calculate the bounding rectangle of a series subset - - Slow implementation, that iterates over the series. - - \param series Series - \param from Index of the first sample, <= 0 means from the beginning - \param to Index of the last sample, < 0 means to the end - - \return Bounding rectangle -*/ -QRectF qwtBoundingRect( - const QwtSeriesData<QwtSetSample>& series, int from, int to ) -{ - return qwtBoundingRectT<QwtSetSample>( series, from, to ); -} - -/*! - Constructor - \param samples Samples -*/ -QwtPointSeriesData::QwtPointSeriesData( - const QVector<QPointF> &samples ): - QwtArraySeriesData<QPointF>( samples ) -{ -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtPointSeriesData::boundingRect() const -{ - if ( d_boundingRect.width() < 0.0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} - -/*! - Constructor - \param samples Samples -*/ -QwtPoint3DSeriesData::QwtPoint3DSeriesData( - const QVector<QwtPoint3D> &samples ): - QwtArraySeriesData<QwtPoint3D>( samples ) -{ -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtPoint3DSeriesData::boundingRect() const -{ - if ( d_boundingRect.width() < 0.0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} - -/*! - Constructor - \param samples Samples -*/ -QwtIntervalSeriesData::QwtIntervalSeriesData( - const QVector<QwtIntervalSample> &samples ): - QwtArraySeriesData<QwtIntervalSample>( samples ) -{ -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtIntervalSeriesData::boundingRect() const -{ - if ( d_boundingRect.width() < 0.0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} - -/*! - Constructor - \param samples Samples -*/ -QwtSetSeriesData::QwtSetSeriesData( - const QVector<QwtSetSample> &samples ): - QwtArraySeriesData<QwtSetSample>( samples ) -{ -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtSetSeriesData::boundingRect() const -{ - if ( d_boundingRect.width() < 0.0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} - -/*! - Constructor - \param samples Samples -*/ -QwtTradingChartData::QwtTradingChartData( - const QVector<QwtOHLCSample> &samples ): - QwtArraySeriesData<QwtOHLCSample>( samples ) -{ -} - -/*! - \brief Calculate the bounding rectangle - - The bounding rectangle is calculated once by iterating over all - points and is stored for all following requests. - - \return Bounding rectangle -*/ -QRectF QwtTradingChartData::boundingRect() const -{ - if ( d_boundingRect.width() < 0.0 ) - d_boundingRect = qwtBoundingRect( *this ); - - return d_boundingRect; -} diff --git a/source/third_party/qwt/qwt_slider.cpp b/source/third_party/qwt/qwt_slider.cpp deleted file mode 100644 index 9a399372c87681098cf48b4ea69c330d3b271da6..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_slider.cpp +++ /dev/null @@ -1,1004 +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/qwt_slider.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_scale_draw.h" -#include "qwt/qwt_scale_map.h" -#include <qevent.h> -#include <qdrawutil.h> -#include <qpainter.h> -#include <qalgorithms.h> -#include <qmath.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qapplication.h> - -static QSize qwtHandleSize( const QSize &size, - Qt::Orientation orientation, bool hasTrough ) -{ - QSize handleSize = size; - - if ( handleSize.isEmpty() ) - { - const int handleThickness = 16; - handleSize.setWidth( 2 * handleThickness ); - handleSize.setHeight( handleThickness ); - - if ( !hasTrough ) - handleSize.transpose(); - - if ( orientation == Qt::Vertical ) - handleSize.transpose(); - } - - return handleSize; -} - -static QwtScaleDraw::Alignment qwtScaleDrawAlignment( - Qt::Orientation orientation, QwtSlider::ScalePosition scalePos ) -{ - QwtScaleDraw::Alignment align; - - if ( orientation == Qt::Vertical ) - { - // NoScale lays out like Left - if ( scalePos == QwtSlider::LeadingScale ) - align = QwtScaleDraw::RightScale; - else - align = QwtScaleDraw::LeftScale; - } - else - { - // NoScale lays out like Bottom - if ( scalePos == QwtSlider::TrailingScale ) - align = QwtScaleDraw::TopScale; - else - align = QwtScaleDraw::BottomScale; - } - - return align; -} - -class QwtSlider::PrivateData -{ -public: - PrivateData(): - repeatTimerId( 0 ), - updateInterval( 150 ), - stepsIncrement( 0 ), - pendingValueChange( false ), - borderWidth( 2 ), - spacing( 4 ), - scalePosition( QwtSlider::TrailingScale ), - hasTrough( true ), - hasGroove( false ), - mouseOffset( 0 ) - { - } - - int repeatTimerId; - bool timerTick; - int updateInterval; - int stepsIncrement; - bool pendingValueChange; - - QRect sliderRect; - - QSize handleSize; - int borderWidth; - int spacing; - - Qt::Orientation orientation; - QwtSlider::ScalePosition scalePosition; - - bool hasTrough; - bool hasGroove; - - int mouseOffset; - - mutable QSize sizeHintCache; -}; -/*! - Construct vertical slider in QwtSlider::Trough style - with a scale to the left. - - The scale is initialized to [0.0, 100.0] and the value set to 0.0. - - \param parent Parent widget - - \sa setOrientation(), setScalePosition(), setBackgroundStyle() -*/ -QwtSlider::QwtSlider( QWidget *parent ): - QwtAbstractSlider( parent ) -{ - initSlider( Qt::Vertical ); -} - -/*! - Construct a slider in QwtSlider::Trough style - - When orientation is Qt::Vertical the scale will be aligned to - the left - otherwise at the the top of the slider. - - The scale is initialized to [0.0, 100.0] and the value set to 0.0. - - \param parent Parent widget - \param orientation Orientation of the slider. -*/ -QwtSlider::QwtSlider( Qt::Orientation orientation, QWidget *parent ): - QwtAbstractSlider( parent ) -{ - initSlider( orientation ); -} - -//! Destructor -QwtSlider::~QwtSlider() -{ - delete d_data; -} - -void QwtSlider::initSlider( Qt::Orientation orientation ) -{ - if ( orientation == Qt::Vertical ) - setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ); - else - setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); - - d_data = new QwtSlider::PrivateData; - - d_data->orientation = orientation; - - scaleDraw()->setAlignment( - qwtScaleDrawAlignment( orientation, d_data->scalePosition ) ); - scaleDraw()->setLength( 100 ); - - setScale( 0.0, 100.0 ); - setValue( 0.0 ); -} - -/*! - \brief Set the orientation. - \param orientation Allowed values are Qt::Horizontal and Qt::Vertical. - - \sa orientation(), scalePosition() -*/ -void QwtSlider::setOrientation( Qt::Orientation orientation ) -{ - if ( orientation == d_data->orientation ) - return; - - d_data->orientation = orientation; - - scaleDraw()->setAlignment( - qwtScaleDrawAlignment( orientation, d_data->scalePosition ) ); - - if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) ) - { - QSizePolicy sp = sizePolicy(); - sp.transpose(); - setSizePolicy( sp ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); - } - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); -} - -/*! - \return Orientation - \sa setOrientation() -*/ -Qt::Orientation QwtSlider::orientation() const -{ - return d_data->orientation; -} - -/*! - \brief Change the position of the scale - \param scalePosition Position of the scale. - - \sa ScalePosition, scalePosition() -*/ -void QwtSlider::setScalePosition( ScalePosition scalePosition ) -{ - if ( d_data->scalePosition == scalePosition ) - return; - - d_data->scalePosition = scalePosition; - scaleDraw()->setAlignment( - qwtScaleDrawAlignment( d_data->orientation, scalePosition ) ); - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); -} - -/*! - \return Position of the scale - \sa setScalePosition() - */ -QwtSlider::ScalePosition QwtSlider::scalePosition() const -{ - return d_data->scalePosition; -} - -/*! - \brief Change the slider's border width - - The border width is used for drawing the slider handle and the - trough. - - \param width Border width - \sa borderWidth() -*/ -void QwtSlider::setBorderWidth( int width ) -{ - if ( width < 0 ) - width = 0; - - if ( width != d_data->borderWidth ) - { - d_data->borderWidth = width; - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); - } -} - -/*! - \return the border width. - \sa setBorderWidth() -*/ -int QwtSlider::borderWidth() const -{ - return d_data->borderWidth; -} - -/*! - \brief Change the spacing between trough and scale - - A spacing of 0 means, that the backbone of the scale is covered - by the trough. - - The default setting is 4 pixels. - - \param spacing Number of pixels - \sa spacing(); -*/ -void QwtSlider::setSpacing( int spacing ) -{ - if ( spacing <= 0 ) - spacing = 0; - - if ( spacing != d_data->spacing ) - { - d_data->spacing = spacing; - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); - } -} - -/*! - \return Number of pixels between slider and scale - \sa setSpacing() -*/ -int QwtSlider::spacing() const -{ - return d_data->spacing; -} - -/*! - \brief Set the slider's handle size - - When the size is empty the slider handle will be painted with a - default size depending on its orientation() and backgroundStyle(). - - \param size New size - - \sa handleSize() -*/ -void QwtSlider::setHandleSize( const QSize &size ) -{ - if ( size != d_data->handleSize ) - { - d_data->handleSize = size; - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); - } -} - -/*! - \return Size of the handle. - \sa setHandleSize() -*/ -QSize QwtSlider::handleSize() const -{ - return d_data->handleSize; -} - -/*! - \brief Set a scale draw - - For changing the labels of the scales, it - is necessary to derive from QwtScaleDraw and - overload QwtScaleDraw::label(). - - \param scaleDraw ScaleDraw object, that has to be created with - new and will be deleted in ~QwtSlider() or the next - call of setScaleDraw(). - - \sa scaleDraw() -*/ -void QwtSlider::setScaleDraw( QwtScaleDraw *scaleDraw ) -{ - const QwtScaleDraw *previousScaleDraw = this->scaleDraw(); - if ( scaleDraw == NULL || scaleDraw == previousScaleDraw ) - return; - - if ( previousScaleDraw ) - scaleDraw->setAlignment( previousScaleDraw->alignment() ); - - setAbstractScaleDraw( scaleDraw ); - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); -} - -/*! - \return the scale draw of the slider - \sa setScaleDraw() -*/ -const QwtScaleDraw *QwtSlider::scaleDraw() const -{ - return static_cast<const QwtScaleDraw *>( abstractScaleDraw() ); -} - -/*! - \return the scale draw of the slider - \sa setScaleDraw() -*/ -QwtScaleDraw *QwtSlider::scaleDraw() -{ - return static_cast<QwtScaleDraw *>( abstractScaleDraw() ); -} - -//! Notify changed scale -void QwtSlider::scaleChange() -{ - QwtAbstractSlider::scaleChange(); - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); -} - -/*! - \brief Specify the update interval for automatic scrolling - - The minimal accepted value is 50 ms. - - \param interval Update interval in milliseconds - - \sa setUpdateInterval() -*/ -void QwtSlider::setUpdateInterval( int interval ) -{ - d_data->updateInterval = qMax( interval, 50 ); -} - -/*! - \return Update interval in milliseconds for automatic scrolling - \sa setUpdateInterval() - */ -int QwtSlider::updateInterval() const -{ - return d_data->updateInterval; -} - -/*! - Draw the slider into the specified rectangle. - - \param painter Painter - \param sliderRect Bounding rectangle of the slider -*/ -void QwtSlider::drawSlider( - QPainter *painter, const QRect &sliderRect ) const -{ - QRect innerRect( sliderRect ); - - if ( d_data->hasTrough ) - { - const int bw = d_data->borderWidth; - innerRect = sliderRect.adjusted( bw, bw, -bw, -bw ); - - painter->fillRect( innerRect, palette().brush( QPalette::Mid ) ); - qDrawShadePanel( painter, sliderRect, palette(), true, bw, NULL ); - } - - const QSize handleSize = qwtHandleSize( d_data->handleSize, - d_data->orientation, d_data->hasTrough ); - - if ( d_data->hasGroove ) - { - const int slotExtent = 4; - const int slotMargin = 4; - - QRect slotRect; - if ( orientation() == Qt::Horizontal ) - { - int slotOffset = qMax( 1, handleSize.width() / 2 - slotMargin ); - int slotHeight = slotExtent + ( innerRect.height() % 2 ); - - slotRect.setWidth( innerRect.width() - 2 * slotOffset ); - slotRect.setHeight( slotHeight ); - } - else - { - int slotOffset = qMax( 1, handleSize.height() / 2 - slotMargin ); - int slotWidth = slotExtent + ( innerRect.width() % 2 ); - - slotRect.setWidth( slotWidth ); - slotRect.setHeight( innerRect.height() - 2 * slotOffset ); - - } - - slotRect.moveCenter( innerRect.center() ); - - QBrush brush = palette().brush( QPalette::Dark ); - qDrawShadePanel( painter, slotRect, palette(), true, 1 , &brush ); - } - - if ( isValid() ) - drawHandle( painter, handleRect(), transform( value() ) ); -} - -/*! - Draw the thumb at a position - - \param painter Painter - \param handleRect Bounding rectangle of the handle - \param pos Position of the handle marker in widget coordinates -*/ -void QwtSlider::drawHandle( QPainter *painter, - const QRect &handleRect, int pos ) const -{ - const int bw = d_data->borderWidth; - - qDrawShadePanel( painter, - handleRect, palette(), false, bw, - &palette().brush( QPalette::Button ) ); - - pos++; // shade line points one pixel below - if ( orientation() == Qt::Horizontal ) - { - qDrawShadeLine( painter, pos, handleRect.top() + bw, - pos, handleRect.bottom() - bw, palette(), true, 1 ); - } - else // Vertical - { - qDrawShadeLine( painter, handleRect.left() + bw, pos, - handleRect.right() - bw, pos, palette(), true, 1 ); - } -} - -/*! - \brief Determine what to do when the user presses a mouse button. - - \param pos Mouse position - - \retval True, when handleRect() contains pos - \sa scrolledTo() -*/ -bool QwtSlider::isScrollPosition( const QPoint &pos ) const -{ - if ( handleRect().contains( pos ) ) - { - const double v = ( orientation() == Qt::Horizontal ) - ? pos.x() : pos.y(); - - d_data->mouseOffset = v - transform( value() ); - return true; - } - - return false; -} - -/*! - \brief Determine the value for a new position of the - slider handle. - - \param pos Mouse position - - \return Value for the mouse position - \sa isScrollPosition() -*/ -double QwtSlider::scrolledTo( const QPoint &pos ) const -{ - int p = ( orientation() == Qt::Horizontal ) - ? pos.x() : pos.y(); - - p -= d_data->mouseOffset; - - int min = transform( lowerBound() ); - int max = transform( upperBound() ); - if ( min > max ) - qSwap( min, max ); - - p = qBound( min, p, max ); - - return scaleMap().invTransform( p ); -} - -/*! - Mouse press event handler - \param event Mouse event -*/ -void QwtSlider::mousePressEvent( QMouseEvent *event ) -{ - if ( isReadOnly() ) - { - event->ignore(); - return; - } - - const QPoint pos = event->pos(); - - if ( isValid() && d_data->sliderRect.contains( pos ) ) - { - if ( !handleRect().contains( pos ) ) - { - const int markerPos = transform( value() ); - - d_data->stepsIncrement = pageSteps(); - - if ( d_data->orientation == Qt::Horizontal ) - { - if ( pos.x() < markerPos ) - d_data->stepsIncrement = -d_data->stepsIncrement; - } - else - { - if ( pos.y() < markerPos ) - d_data->stepsIncrement = -d_data->stepsIncrement; - } - - if ( isInverted() ) - d_data->stepsIncrement = -d_data->stepsIncrement; - - const double v = value(); - incrementValue( d_data->stepsIncrement ); - - if ( v != value() ) - { - if ( isTracking() ) - Q_EMIT valueChanged( value() ); - else - d_data->pendingValueChange = true; - - Q_EMIT sliderMoved( value() ); - } - - d_data->timerTick = false; - d_data->repeatTimerId = startTimer( qMax( 250, 2 * updateInterval() ) ); - - return; - } - } - - QwtAbstractSlider::mousePressEvent( event ); -} - -/*! - Mouse release event handler - \param event Mouse event -*/ -void QwtSlider::mouseReleaseEvent( QMouseEvent *event ) -{ - if ( d_data->repeatTimerId > 0 ) - { - killTimer( d_data->repeatTimerId ); - d_data->repeatTimerId = 0; - d_data->timerTick = false; - d_data->stepsIncrement = 0; - } - - if ( d_data->pendingValueChange ) - { - d_data->pendingValueChange = false; - Q_EMIT valueChanged( value() ); - } - - QwtAbstractSlider::mouseReleaseEvent( event ); -} - -/*! - Timer event handler - - Handles the timer, when the mouse stays pressed - inside the sliderRect(). - - \param event Mouse event -*/ -void QwtSlider::timerEvent( QTimerEvent *event ) -{ - if ( event->timerId() != d_data->repeatTimerId ) - { - QwtAbstractSlider::timerEvent( event ); - return; - } - - if ( !isValid() ) - { - killTimer( d_data->repeatTimerId ); - d_data->repeatTimerId = 0; - return; - } - - const double v = value(); - incrementValue( d_data->stepsIncrement ); - - if ( v != value() ) - { - if ( isTracking() ) - Q_EMIT valueChanged( value() ); - else - d_data->pendingValueChange = true; - - Q_EMIT sliderMoved( value() ); - } - - if ( !d_data->timerTick ) - { - // restart the timer with a shorter interval - killTimer( d_data->repeatTimerId ); - d_data->repeatTimerId = startTimer( updateInterval() ); - - d_data->timerTick = true; - } -} - -/*! - Qt paint event handler - \param event Paint event -*/ -void QwtSlider::paintEvent( QPaintEvent *event ) -{ - QPainter painter( this ); - painter.setClipRegion( event->region() ); - - QStyleOption opt; - opt.init(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); - - if ( d_data->scalePosition != QwtSlider::NoScale ) - { - if ( !d_data->sliderRect.contains( event->rect() ) ) - scaleDraw()->draw( &painter, palette() ); - } - - drawSlider( &painter, d_data->sliderRect ); - - if ( hasFocus() ) - QwtPainter::drawFocusRect( &painter, this, d_data->sliderRect ); -} - -/*! - Qt resize event handler - \param event Resize event -*/ -void QwtSlider::resizeEvent( QResizeEvent *event ) -{ - Q_UNUSED( event ); - - layoutSlider( false ); -} - -/*! - Handles QEvent::StyleChange and QEvent::FontChange events - \param event Change event -*/ -void QwtSlider::changeEvent( QEvent *event ) -{ - if ( event->type() == QEvent::StyleChange || - event->type() == QEvent::FontChange ) - { - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); - } - - QwtAbstractSlider::changeEvent( event ); -} - -/*! - Recalculate the slider's geometry and layout based on - the current geometry and fonts. - - \param update_geometry notify the layout system and call update - to redraw the scale -*/ -void QwtSlider::layoutSlider( bool update_geometry ) -{ - int bw = 0; - if ( d_data->hasTrough ) - bw = d_data->borderWidth; - - const QSize handleSize = qwtHandleSize( d_data->handleSize, - d_data->orientation, d_data->hasTrough ); - - QRect sliderRect = contentsRect(); - - /* - The marker line of the handle needs to be aligned to - the scale. But the marker is in the center - and we need space enough to display the rest of the handle. - - But the scale itself usually needs margins for displaying - the tick labels, that also might needs space beyond the - backbone. - - Now it depends on what needs more margins. If it is the - slider the scale gets shrunk, otherwise the slider. - */ - - int scaleMargin = 0; - if ( d_data->scalePosition != QwtSlider::NoScale ) - { - int d1, d2; - scaleDraw()->getBorderDistHint( font(), d1, d2 ); - - scaleMargin = qMax( d1, d2 ) - bw; - } - - int scaleX, scaleY, scaleLength; - - if ( d_data->orientation == Qt::Horizontal ) - { - const int handleMargin = handleSize.width() / 2 - 1; - if ( scaleMargin > handleMargin ) - { - int off = scaleMargin - handleMargin; - sliderRect.adjust( off, 0, -off, 0 ); - } - - scaleX = sliderRect.left() + bw + handleSize.width() / 2 - 1; - scaleLength = sliderRect.width() - handleSize.width(); - } - else - { - int handleMargin = handleSize.height() / 2 - 1; - if ( scaleMargin > handleMargin ) - { - int off = scaleMargin - handleMargin; - sliderRect.adjust( 0, off, 0, -off ); - } - - scaleY = sliderRect.top() + bw + handleSize.height() / 2 - 1; - scaleLength = sliderRect.height() - handleSize.height(); - } - - scaleLength -= 2 * bw; - - // now align slider and scale according to the ScalePosition - - if ( d_data->orientation == Qt::Horizontal ) - { - const int h = handleSize.height() + 2 * bw; - - if ( d_data->scalePosition == QwtSlider::TrailingScale ) - { - sliderRect.setTop( sliderRect.bottom() + 1 - h ); - scaleY = sliderRect.top() - d_data->spacing; - } - else - { - sliderRect.setHeight( h ); - scaleY = sliderRect.bottom() + 1 + d_data->spacing; - } - } - else // Qt::Vertical - { - const int w = handleSize.width() + 2 * bw; - - if ( d_data->scalePosition == QwtSlider::LeadingScale ) - { - sliderRect.setWidth( w ); - scaleX = sliderRect.right() + 1 + d_data->spacing; - } - else - { - sliderRect.setLeft( sliderRect.right() + 1 - w ); - scaleX = sliderRect.left() - d_data->spacing; - } - } - - d_data->sliderRect = sliderRect; - - scaleDraw()->move( scaleX, scaleY ); - scaleDraw()->setLength( scaleLength ); - - if ( update_geometry ) - { - d_data->sizeHintCache = QSize(); // invalidate - updateGeometry(); - update(); - } -} - -/*! - En/Disable the trough - - The slider can be cutomized by showing a trough for the - handle. - - \param on When true, the groove is visible - \sa hasTrough(), setGroove() - */ -void QwtSlider::setTrough( bool on ) -{ - if ( d_data->hasTrough != on ) - { - d_data->hasTrough = on; - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); - } -} - -/*! - \return True, when the trough is visisble - \sa setTrough(), hasGroove() - */ -bool QwtSlider::hasTrough() const -{ - return d_data->hasTrough; -} - -/*! - En/Disable the groove - - The slider can be cutomized by showing a groove for the - handle. - - \param on When true, the groove is visible - \sa hasGroove(), setThrough() - */ -void QwtSlider::setGroove( bool on ) -{ - if ( d_data->hasGroove != on ) - { - d_data->hasGroove = on; - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutSlider( true ); - } -} - -/*! - \return True, when the groove is visisble - \sa setGroove(), hasTrough() - */ -bool QwtSlider::hasGroove() const -{ - return d_data->hasGroove; -} - -/*! - \return minimumSizeHint() -*/ -QSize QwtSlider::sizeHint() const -{ - const QSize hint = minimumSizeHint(); - return hint.expandedTo( QApplication::globalStrut() ); -} - -/*! - \return Minimum size hint - \sa sizeHint() -*/ -QSize QwtSlider::minimumSizeHint() const -{ - if ( !d_data->sizeHintCache.isEmpty() ) - return d_data->sizeHintCache; - - const QSize handleSize = qwtHandleSize( d_data->handleSize, - d_data->orientation, d_data->hasTrough ); - - int bw = 0; - if ( d_data->hasTrough ) - bw = d_data->borderWidth; - - int sliderLength = 0; - int scaleExtent = 0; - - if ( d_data->scalePosition != QwtSlider::NoScale ) - { - int d1, d2; - scaleDraw()->getBorderDistHint( font(), d1, d2 ); - - const int scaleBorderDist = 2 * ( qMax( d1, d2 ) - bw ); - - int handleBorderDist; - if ( d_data->orientation == Qt::Horizontal ) - handleBorderDist = handleSize.width(); - else - handleBorderDist = handleSize.height(); - - sliderLength = scaleDraw()->minLength( font() ); - if ( handleBorderDist > scaleBorderDist ) - { - // We need additional space for the overlapping handle - sliderLength += handleBorderDist - scaleBorderDist; - } - - scaleExtent += d_data->spacing; - scaleExtent += qCeil( scaleDraw()->extent( font() ) ); - } - - sliderLength = qMax( sliderLength, 84 ); // from QSlider - - int w = 0; - int h = 0; - - if ( d_data->orientation == Qt::Horizontal ) - { - w = sliderLength; - h = handleSize.height() + 2 * bw + scaleExtent; - } - else - { - w = handleSize.width() + 2 * bw + scaleExtent; - h = sliderLength; - } - - // finally add margins - int left, right, top, bottom; - getContentsMargins( &left, &top, &right, &bottom ); - - w += left + right; - h += top + bottom; - - d_data->sizeHintCache = QSize( w, h ); - return d_data->sizeHintCache; -} - -/*! - \return Bounding rectangle of the slider handle - */ -QRect QwtSlider::handleRect() const -{ - if ( !isValid() ) - return QRect(); - - const int markerPos = transform( value() ); - - QPoint center = d_data->sliderRect.center(); - if ( d_data->orientation == Qt::Horizontal ) - center.setX( markerPos ); - else - center.setY( markerPos ); - - QRect rect; - rect.setSize( qwtHandleSize( d_data->handleSize, - d_data->orientation, d_data->hasTrough ) ); - rect.moveCenter( center ); - - return rect; -} - -/*! - \return Bounding rectangle of the slider - without the scale - */ -QRect QwtSlider::sliderRect() const -{ - return d_data->sliderRect; -} diff --git a/source/third_party/qwt/qwt_spline.cpp b/source/third_party/qwt/qwt_spline.cpp deleted file mode 100644 index 0ca92253d81dcf2c90075bf042879d7581e17d9d..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_spline.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/qwt_spline.h" -#include "qwt/qwt_math.h" - -class QwtSpline::PrivateData -{ -public: - PrivateData(): - splineType( QwtSpline::Natural ) - { - } - - QwtSpline::SplineType splineType; - - // coefficient vectors - QVector<double> a; - QVector<double> b; - QVector<double> c; - - // control points - QPolygonF points; -}; - -static int lookup( double x, const QPolygonF &values ) -{ -#if 0 -//qLowerBound/qHigherBound ??? -#endif - int i1; - const int size = values.size(); - - if ( x <= values[0].x() ) - i1 = 0; - else if ( x >= values[size - 2].x() ) - i1 = size - 2; - else - { - i1 = 0; - int i2 = size - 2; - int i3 = 0; - - while ( i2 - i1 > 1 ) - { - i3 = i1 + ( ( i2 - i1 ) >> 1 ); - - if ( values[i3].x() > x ) - i2 = i3; - else - i1 = i3; - } - } - return i1; -} - -//! Constructor -QwtSpline::QwtSpline() -{ - d_data = new PrivateData; -} - -/*! - Copy constructor - \param other Spline used for initialization -*/ -QwtSpline::QwtSpline( const QwtSpline& other ) -{ - d_data = new PrivateData( *other.d_data ); -} - -/*! - Assignment operator - \param other Spline used for initialization - \return *this -*/ -QwtSpline &QwtSpline::operator=( const QwtSpline & other ) -{ - *d_data = *other.d_data; - return *this; -} - -//! Destructor -QwtSpline::~QwtSpline() -{ - delete d_data; -} - -/*! - Select the algorithm used for calculating the spline - - \param splineType Spline type - \sa splineType() -*/ -void QwtSpline::setSplineType( SplineType splineType ) -{ - d_data->splineType = splineType; -} - -/*! - \return the spline type - \sa setSplineType() -*/ -QwtSpline::SplineType QwtSpline::splineType() const -{ - return d_data->splineType; -} - -/*! - \brief Calculate the spline coefficients - - Depending on the value of \a periodic, this function - will determine the coefficients for a natural or a periodic - spline and store them internally. - - \param points Points - \return true if successful - \warning The sequence of x (but not y) values has to be strictly monotone - increasing, which means <code>points[i].x() < points[i+1].x()</code>. - If this is not the case, the function will return false -*/ -bool QwtSpline::setPoints( const QPolygonF& points ) -{ - const int size = points.size(); - if ( size <= 2 ) - { - reset(); - return false; - } - - d_data->points = points; - - d_data->a.resize( size - 1 ); - d_data->b.resize( size - 1 ); - d_data->c.resize( size - 1 ); - - bool ok; - if ( d_data->splineType == Periodic ) - ok = buildPeriodicSpline( points ); - else - ok = buildNaturalSpline( points ); - - if ( !ok ) - reset(); - - return ok; -} - -/*! - \return Points, that have been by setPoints() -*/ -QPolygonF QwtSpline::points() const -{ - return d_data->points; -} - -//! \return A coefficients -const QVector<double> &QwtSpline::coefficientsA() const -{ - return d_data->a; -} - -//! \return B coefficients -const QVector<double> &QwtSpline::coefficientsB() const -{ - return d_data->b; -} - -//! \return C coefficients -const QVector<double> &QwtSpline::coefficientsC() const -{ - return d_data->c; -} - - -//! Free allocated memory and set size to 0 -void QwtSpline::reset() -{ - d_data->a.resize( 0 ); - d_data->b.resize( 0 ); - d_data->c.resize( 0 ); - d_data->points.resize( 0 ); -} - -//! True if valid -bool QwtSpline::isValid() const -{ - return d_data->a.size() > 0; -} - -/*! - Calculate the interpolated function value corresponding - to a given argument x. - - \param x Coordinate - \return Interpolated coordinate -*/ -double QwtSpline::value( double x ) const -{ - if ( d_data->a.size() == 0 ) - return 0.0; - - const int i = lookup( x, d_data->points ); - - const double delta = x - d_data->points[i].x(); - return( ( ( ( d_data->a[i] * delta ) + d_data->b[i] ) - * delta + d_data->c[i] ) * delta + d_data->points[i].y() ); -} - -/*! - \brief Determines the coefficients for a natural spline - \return true if successful -*/ -bool QwtSpline::buildNaturalSpline( const QPolygonF &points ) -{ - int i; - - const QPointF *p = points.data(); - const int size = points.size(); - - double *a = d_data->a.data(); - double *b = d_data->b.data(); - double *c = d_data->c.data(); - - // set up tridiagonal equation system; use coefficient - // vectors as temporary buffers - QVector<double> h( size - 1 ); - for ( i = 0; i < size - 1; i++ ) - { - h[i] = p[i+1].x() - p[i].x(); - if ( h[i] <= 0 ) - return false; - } - - QVector<double> d( size - 1 ); - double dy1 = ( p[1].y() - p[0].y() ) / h[0]; - for ( i = 1; i < size - 1; i++ ) - { - b[i] = c[i] = h[i]; - a[i] = 2.0 * ( h[i-1] + h[i] ); - - const double dy2 = ( p[i+1].y() - p[i].y() ) / h[i]; - d[i] = 6.0 * ( dy1 - dy2 ); - dy1 = dy2; - } - - // - // solve it - // - - // L-U Factorization - for ( i = 1; i < size - 2; i++ ) - { - c[i] /= a[i]; - a[i+1] -= b[i] * c[i]; - } - - // forward elimination - QVector<double> s( size ); - s[1] = d[1]; - for ( i = 2; i < size - 1; i++ ) - s[i] = d[i] - c[i-1] * s[i-1]; - - // backward elimination - s[size - 2] = - s[size - 2] / a[size - 2]; - for ( i = size - 3; i > 0; i-- ) - s[i] = - ( s[i] + b[i] * s[i+1] ) / a[i]; - s[size - 1] = s[0] = 0.0; - - // - // Finally, determine the spline coefficients - // - for ( i = 0; i < size - 1; i++ ) - { - a[i] = ( s[i+1] - s[i] ) / ( 6.0 * h[i] ); - b[i] = 0.5 * s[i]; - c[i] = ( p[i+1].y() - p[i].y() ) / h[i] - - ( s[i+1] + 2.0 * s[i] ) * h[i] / 6.0; - } - - return true; -} - -/*! - \brief Determines the coefficients for a periodic spline - \return true if successful -*/ -bool QwtSpline::buildPeriodicSpline( const QPolygonF &points ) -{ - int i; - - const QPointF *p = points.data(); - const int size = points.size(); - - double *a = d_data->a.data(); - double *b = d_data->b.data(); - double *c = d_data->c.data(); - - QVector<double> d( size - 1 ); - QVector<double> h( size - 1 ); - QVector<double> s( size ); - - // - // setup equation system; use coefficient - // vectors as temporary buffers - // - for ( i = 0; i < size - 1; i++ ) - { - h[i] = p[i+1].x() - p[i].x(); - if ( h[i] <= 0.0 ) - return false; - } - - const int imax = size - 2; - double htmp = h[imax]; - double dy1 = ( p[0].y() - p[imax].y() ) / htmp; - for ( i = 0; i <= imax; i++ ) - { - b[i] = c[i] = h[i]; - a[i] = 2.0 * ( htmp + h[i] ); - const double dy2 = ( p[i+1].y() - p[i].y() ) / h[i]; - d[i] = 6.0 * ( dy1 - dy2 ); - dy1 = dy2; - htmp = h[i]; - } - - // - // solve it - // - - // L-U Factorization - a[0] = qSqrt( a[0] ); - c[0] = h[imax] / a[0]; - double sum = 0; - - for ( i = 0; i < imax - 1; i++ ) - { - b[i] /= a[i]; - if ( i > 0 ) - c[i] = - c[i-1] * b[i-1] / a[i]; - a[i+1] = qSqrt( a[i+1] - qwtSqr( b[i] ) ); - sum += qwtSqr( c[i] ); - } - b[imax-1] = ( b[imax-1] - c[imax-2] * b[imax-2] ) / a[imax-1]; - a[imax] = qSqrt( a[imax] - qwtSqr( b[imax-1] ) - sum ); - - - // forward elimination - s[0] = d[0] / a[0]; - sum = 0; - for ( i = 1; i < imax; i++ ) - { - s[i] = ( d[i] - b[i-1] * s[i-1] ) / a[i]; - sum += c[i-1] * s[i-1]; - } - s[imax] = ( d[imax] - b[imax-1] * s[imax-1] - sum ) / a[imax]; - - - // backward elimination - s[imax] = - s[imax] / a[imax]; - s[imax-1] = -( s[imax-1] + b[imax-1] * s[imax] ) / a[imax-1]; - for ( i = imax - 2; i >= 0; i-- ) - s[i] = - ( s[i] + b[i] * s[i+1] + c[i] * s[imax] ) / a[i]; - - // - // Finally, determine the spline coefficients - // - s[size-1] = s[0]; - for ( i = 0; i < size - 1; i++ ) - { - a[i] = ( s[i+1] - s[i] ) / ( 6.0 * h[i] ); - b[i] = 0.5 * s[i]; - c[i] = ( p[i+1].y() - p[i].y() ) - / h[i] - ( s[i+1] + 2.0 * s[i] ) * h[i] / 6.0; - } - - return true; -} diff --git a/source/third_party/qwt/qwt_symbol.cpp b/source/third_party/qwt/qwt_symbol.cpp deleted file mode 100644 index eae8b0538898fe1cf3189f340aae7a54a20dd27c..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_symbol.cpp +++ /dev/null @@ -1,1770 +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/qwt_symbol.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_graphic.h" -#include <qapplication.h> -#include <qpainter.h> -#include <qpainterpath.h> -#include <qpixmap.h> -#include <qpaintengine.h> -#include <qmath.h> -#ifndef QWT_NO_SVG -#include <QtSvg/qsvgrenderer.h> -#endif - -namespace QwtTriangle -{ - enum Type - { - Left, - Right, - Up, - Down - }; -} - -static QwtGraphic qwtPathGraphic( const QPainterPath &path, - const QPen &pen, const QBrush& brush ) -{ - QwtGraphic graphic; - graphic.setRenderHint( QwtGraphic::RenderPensUnscaled ); - - QPainter painter( &graphic ); - painter.setPen( pen ); - painter.setBrush( brush ); - painter.drawPath( path ); - painter.end(); - - return graphic; -} - -static inline QRectF qwtScaledBoundingRect( - const QwtGraphic &graphic, const QSizeF size ) -{ - QSizeF scaledSize = size; - if ( scaledSize.isEmpty() ) - scaledSize = graphic.defaultSize(); - - const QSizeF sz = graphic.controlPointRect().size(); - - double sx = 1.0; - if ( sz.width() > 0.0 ) - sx = scaledSize.width() / sz.width(); - - double sy = 1.0; - if ( sz.height() > 0.0 ) - sy = scaledSize.height() / sz.height(); - - return graphic.scaledBoundingRect( sx, sy ); -} - -static inline void qwtDrawPixmapSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - QSize size = symbol.size(); - if ( size.isEmpty() ) - size = symbol.pixmap().size(); - - const QTransform transform = painter->transform(); - if ( transform.isScaling() ) - { - const QRect r( 0, 0, size.width(), size.height() ); - size = transform.mapRect( r ).size(); - } - - QPixmap pm = symbol.pixmap(); - if ( pm.size() != size ) - pm = pm.scaled( size ); - - QPointF pinPoint( 0.5 * size.width(), 0.5 * size.height() ); - if ( symbol.isPinPointEnabled() ) - pinPoint = symbol.pinPoint(); - - painter->resetTransform(); - - for ( int i = 0; i < numPoints; i++ ) - { - const QPointF pos = transform.map( points[i] ) - pinPoint; - - QwtPainter::drawPixmap( painter, - QRect( pos.toPoint(), pm.size() ), pm ); - } -} - -#ifndef QWT_NO_SVG - -static inline void qwtDrawSvgSymbols( QPainter *painter, - const QPointF *points, int numPoints, - QSvgRenderer *renderer, const QwtSymbol &symbol ) -{ - if ( renderer == NULL || !renderer->isValid() ) - return; - - const QRectF viewBox = renderer->viewBoxF(); - if ( viewBox.isEmpty() ) - return; - - QSizeF sz = symbol.size(); - if ( !sz.isValid() ) - sz = viewBox.size(); - - const double sx = sz.width() / viewBox.width(); - const double sy = sz.height() / viewBox.height(); - - QPointF pinPoint = viewBox.center(); - if ( symbol.isPinPointEnabled() ) - pinPoint = symbol.pinPoint(); - - const double dx = sx * ( pinPoint.x() - viewBox.left() ); - const double dy = sy * ( pinPoint.y() - viewBox.top() ); - - for ( int i = 0; i < numPoints; i++ ) - { - const double x = points[i].x() - dx; - const double y = points[i].y() - dy; - - renderer->render( painter, - QRectF( x, y, sz.width(), sz.height() ) ); - } -} - -#endif - -static inline void qwtDrawGraphicSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtGraphic &graphic, - const QwtSymbol &symbol ) -{ - const QRectF pointRect = graphic.controlPointRect(); - if ( pointRect.isEmpty() ) - return; - - double sx = 1.0; - double sy = 1.0; - - const QSize sz = symbol.size(); - if ( sz.isValid() ) - { - sx = sz.width() / pointRect.width(); - sy = sz.height() / pointRect.height(); - } - - QPointF pinPoint = pointRect.center(); - if ( symbol.isPinPointEnabled() ) - pinPoint = symbol.pinPoint(); - - const QTransform transform = painter->transform(); - - for ( int i = 0; i < numPoints; i++ ) - { - QTransform tr = transform; - tr.translate( points[i].x(), points[i].y() ); - tr.scale( sx, sy ); - tr.translate( -pinPoint.x(), -pinPoint.y() ); - - painter->setTransform( tr ); - - graphic.render( painter ); - } - - painter->setTransform( transform ); -} - -static inline void qwtDrawEllipseSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - painter->setBrush( symbol.brush() ); - painter->setPen( symbol.pen() ); - - const QSize size = symbol.size(); - - if ( QwtPainter::roundingAlignment( painter ) ) - { - const int sw = size.width(); - const int sh = size.height(); - const int sw2 = size.width() / 2; - const int sh2 = size.height() / 2; - - for ( int i = 0; i < numPoints; i++ ) - { - const int x = qRound( points[i].x() ); - const int y = qRound( points[i].y() ); - - const QRectF r( x - sw2, y - sh2, sw, sh ); - QwtPainter::drawEllipse( painter, r ); - } - } - else - { - const double sw = size.width(); - const double sh = size.height(); - const double sw2 = 0.5 * size.width(); - const double sh2 = 0.5 * size.height(); - - for ( int i = 0; i < numPoints; i++ ) - { - const double x = points[i].x(); - const double y = points[i].y(); - - const QRectF r( x - sw2, y - sh2, sw, sh ); - QwtPainter::drawEllipse( painter, r ); - } - } -} - -static inline void qwtDrawRectSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - const QSize size = symbol.size(); - - QPen pen = symbol.pen(); - pen.setJoinStyle( Qt::MiterJoin ); - painter->setPen( pen ); - painter->setBrush( symbol.brush() ); - painter->setRenderHint( QPainter::Antialiasing, false ); - - if ( QwtPainter::roundingAlignment( painter ) ) - { - const int sw = size.width(); - const int sh = size.height(); - const int sw2 = size.width() / 2; - const int sh2 = size.height() / 2; - - for ( int i = 0; i < numPoints; i++ ) - { - const int x = qRound( points[i].x() ); - const int y = qRound( points[i].y() ); - - const QRect r( x - sw2, y - sh2, sw, sh ); - QwtPainter::drawRect( painter, r ); - } - } - else - { - const double sw = size.width(); - const double sh = size.height(); - const double sw2 = 0.5 * size.width(); - const double sh2 = 0.5 * size.height(); - - for ( int i = 0; i < numPoints; i++ ) - { - const double x = points[i].x(); - const double y = points[i].y(); - - const QRectF r( x - sw2, y - sh2, sw, sh ); - QwtPainter::drawRect( painter, r ); - } - } -} - -static inline void qwtDrawDiamondSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - const QSize size = symbol.size(); - - QPen pen = symbol.pen(); - pen.setJoinStyle( Qt::MiterJoin ); - painter->setPen( pen ); - painter->setBrush( symbol.brush() ); - - if ( QwtPainter::roundingAlignment( painter ) ) - { - for ( int i = 0; i < numPoints; i++ ) - { - const int x = qRound( points[i].x() ); - const int y = qRound( points[i].y() ); - - const int x1 = x - size.width() / 2; - const int y1 = y - size.height() / 2; - const int x2 = x1 + size.width(); - const int y2 = y1 + size.height(); - - QPolygonF polygon; - polygon += QPointF( x, y1 ); - polygon += QPointF( x1, y ); - polygon += QPointF( x, y2 ); - polygon += QPointF( x2, y ); - - QwtPainter::drawPolygon( painter, polygon ); - } - } - else - { - for ( int i = 0; i < numPoints; i++ ) - { - const QPointF &pos = points[i]; - - const double x1 = pos.x() - 0.5 * size.width(); - const double y1 = pos.y() - 0.5 * size.height(); - const double x2 = x1 + size.width(); - const double y2 = y1 + size.height(); - - QPolygonF polygon; - polygon += QPointF( pos.x(), y1 ); - polygon += QPointF( x2, pos.y() ); - polygon += QPointF( pos.x(), y2 ); - polygon += QPointF( x1, pos.y() ); - - QwtPainter::drawPolygon( painter, polygon ); - } - } -} - -static inline void qwtDrawTriangleSymbols( - QPainter *painter, QwtTriangle::Type type, - const QPointF *points, int numPoints, - const QwtSymbol &symbol ) -{ - const QSize size = symbol.size(); - - QPen pen = symbol.pen(); - pen.setJoinStyle( Qt::MiterJoin ); - painter->setPen( pen ); - - painter->setBrush( symbol.brush() ); - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - double sw2 = 0.5 * size.width(); - double sh2 = 0.5 * size.height(); - - if ( doAlign ) - { - sw2 = qFloor( sw2 ); - sh2 = qFloor( sh2 ); - } - - QPolygonF triangle( 3 ); - QPointF *trianglePoints = triangle.data(); - - for ( int i = 0; i < numPoints; i++ ) - { - const QPointF &pos = points[i]; - - double x = pos.x(); - double y = pos.y(); - - if ( doAlign ) - { - x = qRound( x ); - y = qRound( y ); - } - - const double x1 = x - sw2; - const double x2 = x1 + size.width(); - const double y1 = y - sh2; - const double y2 = y1 + size.height(); - - switch ( type ) - { - case QwtTriangle::Left: - { - trianglePoints[0].rx() = x2; - trianglePoints[0].ry() = y1; - - trianglePoints[1].rx() = x1; - trianglePoints[1].ry() = y; - - trianglePoints[2].rx() = x2; - trianglePoints[2].ry() = y2; - - break; - } - case QwtTriangle::Right: - { - trianglePoints[0].rx() = x1; - trianglePoints[0].ry() = y1; - - trianglePoints[1].rx() = x2; - trianglePoints[1].ry() = y; - - trianglePoints[2].rx() = x1; - trianglePoints[2].ry() = y2; - - break; - } - case QwtTriangle::Up: - { - trianglePoints[0].rx() = x1; - trianglePoints[0].ry() = y2; - - trianglePoints[1].rx() = x; - trianglePoints[1].ry() = y1; - - trianglePoints[2].rx() = x2; - trianglePoints[2].ry() = y2; - - break; - } - case QwtTriangle::Down: - { - trianglePoints[0].rx() = x1; - trianglePoints[0].ry() = y1; - - trianglePoints[1].rx() = x; - trianglePoints[1].ry() = y2; - - trianglePoints[2].rx() = x2; - trianglePoints[2].ry() = y1; - - break; - } - } - QwtPainter::drawPolygon( painter, triangle ); - } -} - -static inline void qwtDrawLineSymbols( - QPainter *painter, int orientations, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - const QSize size = symbol.size(); - - int off = 0; - - QPen pen = symbol.pen(); - if ( pen.width() > 1 ) - { - pen.setCapStyle( Qt::FlatCap ); - off = 1; - } - - painter->setPen( pen ); - painter->setRenderHint( QPainter::Antialiasing, false ); - - if ( QwtPainter::roundingAlignment( painter ) ) - { - const int sw = qFloor( size.width() ); - const int sh = qFloor( size.height() ); - const int sw2 = size.width() / 2; - const int sh2 = size.height() / 2; - - for ( int i = 0; i < numPoints; i++ ) - { - if ( orientations & Qt::Horizontal ) - { - const int x = qRound( points[i].x() ) - sw2; - const int y = qRound( points[i].y() ); - - QwtPainter::drawLine( painter, x, y, x + sw + off, y ); - } - if ( orientations & Qt::Vertical ) - { - const int x = qRound( points[i].x() ); - const int y = qRound( points[i].y() ) - sh2; - - QwtPainter::drawLine( painter, x, y, x, y + sh + off ); - } - } - } - else - { - const double sw = size.width(); - const double sh = size.height(); - const double sw2 = 0.5 * size.width(); - const double sh2 = 0.5 * size.height(); - - for ( int i = 0; i < numPoints; i++ ) - { - if ( orientations & Qt::Horizontal ) - { - const double x = points[i].x() - sw2; - const double y = points[i].y(); - - QwtPainter::drawLine( painter, x, y, x + sw, y ); - } - if ( orientations & Qt::Vertical ) - { - const double y = points[i].y() - sh2; - const double x = points[i].x(); - - QwtPainter::drawLine( painter, x, y, x, y + sh ); - } - } - } -} - -static inline void qwtDrawXCrossSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - const QSize size = symbol.size(); - int off = 0; - - QPen pen = symbol.pen(); - if ( pen.width() > 1 ) - { - pen.setCapStyle( Qt::FlatCap ); - off = 1; - } - painter->setPen( pen ); - - - if ( QwtPainter::roundingAlignment( painter ) ) - { - const int sw = size.width(); - const int sh = size.height(); - const int sw2 = size.width() / 2; - const int sh2 = size.height() / 2; - - for ( int i = 0; i < numPoints; i++ ) - { - const QPointF &pos = points[i]; - - const int x = qRound( pos.x() ); - const int y = qRound( pos.y() ); - - const int x1 = x - sw2; - const int x2 = x1 + sw + off; - const int y1 = y - sh2; - const int y2 = y1 + sh + off; - - QwtPainter::drawLine( painter, x1, y1, x2, y2 ); - QwtPainter::drawLine( painter, x2, y1, x1, y2 ); - } - } - else - { - const double sw = size.width(); - const double sh = size.height(); - const double sw2 = 0.5 * size.width(); - const double sh2 = 0.5 * size.height(); - - for ( int i = 0; i < numPoints; i++ ) - { - const QPointF &pos = points[i]; - - const double x1 = pos.x() - sw2; - const double x2 = x1 + sw; - const double y1 = pos.y() - sh2; - const double y2 = y1 + sh; - - QwtPainter::drawLine( painter, x1, y1, x2, y2 ); - QwtPainter::drawLine( painter, x1, y2, x2, y1 ); - } - } -} - -static inline void qwtDrawStar1Symbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - const QSize size = symbol.size(); - painter->setPen( symbol.pen() ); - - if ( QwtPainter::roundingAlignment( painter ) ) - { - QRect r( 0, 0, size.width(), size.height() ); - - for ( int i = 0; i < numPoints; i++ ) - { - r.moveCenter( points[i].toPoint() ); - - const double sqrt1_2 = 0.70710678118654752440; /* 1/sqrt(2) */ - - const double d1 = r.width() / 2.0 * ( 1.0 - sqrt1_2 ); - - QwtPainter::drawLine( painter, - qRound( r.left() + d1 ), qRound( r.top() + d1 ), - qRound( r.right() - d1 ), qRound( r.bottom() - d1 ) ); - QwtPainter::drawLine( painter, - qRound( r.left() + d1 ), qRound( r.bottom() - d1 ), - qRound( r .right() - d1), qRound( r.top() + d1 ) ); - - const QPoint c = r.center(); - - QwtPainter::drawLine( painter, - c.x(), r.top(), c.x(), r.bottom() ); - QwtPainter::drawLine( painter, - r.left(), c.y(), r.right(), c.y() ); - } - } - else - { - QRectF r( 0, 0, size.width(), size.height() ); - - for ( int i = 0; i < numPoints; i++ ) - { - r.moveCenter( points[i] ); - - const double sqrt1_2 = 0.70710678118654752440; /* 1/sqrt(2) */ - - const QPointF c = r.center(); - const double d1 = r.width() / 2.0 * ( 1.0 - sqrt1_2 ); - - QwtPainter::drawLine( painter, - r.left() + d1, r.top() + d1, - r.right() - d1, r.bottom() - d1 ); - QwtPainter::drawLine( painter, - r.left() + d1, r.bottom() - d1, - r.right() - d1, r.top() + d1 ); - QwtPainter::drawLine( painter, - c.x(), r.top(), - c.x(), r.bottom() ); - QwtPainter::drawLine( painter, - r.left(), c.y(), - r.right(), c.y() ); - } - } -} - -static inline void qwtDrawStar2Symbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - QPen pen = symbol.pen(); - if ( pen.width() > 1 ) - pen.setCapStyle( Qt::FlatCap ); - pen.setJoinStyle( Qt::MiterJoin ); - painter->setPen( pen ); - - painter->setBrush( symbol.brush() ); - - const double cos30 = 0.866025; // cos(30°) - - const double dy = 0.25 * symbol.size().height(); - const double dx = 0.5 * symbol.size().width() * cos30 / 3.0; - - QPolygonF star( 12 ); - QPointF *starPoints = star.data(); - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - for ( int i = 0; i < numPoints; i++ ) - { - double x = points[i].x(); - double y = points[i].y(); - if ( doAlign ) - { - x = qRound( x ); - y = qRound( y ); - } - - double x1 = x - 3 * dx; - double y1 = y - 2 * dy; - if ( doAlign ) - { - x1 = qRound( x - 3 * dx ); - y1 = qRound( y - 2 * dy ); - } - - const double x2 = x1 + 1 * dx; - const double x3 = x1 + 2 * dx; - const double x4 = x1 + 3 * dx; - const double x5 = x1 + 4 * dx; - const double x6 = x1 + 5 * dx; - const double x7 = x1 + 6 * dx; - - const double y2 = y1 + 1 * dy; - const double y3 = y1 + 2 * dy; - const double y4 = y1 + 3 * dy; - const double y5 = y1 + 4 * dy; - - starPoints[0].rx() = x4; - starPoints[0].ry() = y1; - - starPoints[1].rx() = x5; - starPoints[1].ry() = y2; - - starPoints[2].rx() = x7; - starPoints[2].ry() = y2; - - starPoints[3].rx() = x6; - starPoints[3].ry() = y3; - - starPoints[4].rx() = x7; - starPoints[4].ry() = y4; - - starPoints[5].rx() = x5; - starPoints[5].ry() = y4; - - starPoints[6].rx() = x4; - starPoints[6].ry() = y5; - - starPoints[7].rx() = x3; - starPoints[7].ry() = y4; - - starPoints[8].rx() = x1; - starPoints[8].ry() = y4; - - starPoints[9].rx() = x2; - starPoints[9].ry() = y3; - - starPoints[10].rx() = x1; - starPoints[10].ry() = y2; - - starPoints[11].rx() = x3; - starPoints[11].ry() = y2; - - QwtPainter::drawPolygon( painter, star ); - } -} - -static inline void qwtDrawHexagonSymbols( QPainter *painter, - const QPointF *points, int numPoints, const QwtSymbol &symbol ) -{ - painter->setBrush( symbol.brush() ); - painter->setPen( symbol.pen() ); - - const double cos30 = 0.866025; // cos(30°) - const double dx = 0.5 * ( symbol.size().width() - cos30 ); - - const double dy = 0.25 * symbol.size().height(); - - QPolygonF hexaPolygon( 6 ); - QPointF *hexaPoints = hexaPolygon.data(); - - const bool doAlign = QwtPainter::roundingAlignment( painter ); - - for ( int i = 0; i < numPoints; i++ ) - { - double x = points[i].x(); - double y = points[i].y(); - if ( doAlign ) - { - x = qRound( x ); - y = qRound( y ); - } - - double x1 = x - dx; - double y1 = y - 2 * dy; - if ( doAlign ) - { - x1 = qCeil( x1 ); - y1 = qCeil( y1 ); - } - - const double x2 = x1 + 1 * dx; - const double x3 = x1 + 2 * dx; - - const double y2 = y1 + 1 * dy; - const double y3 = y1 + 3 * dy; - const double y4 = y1 + 4 * dy; - - hexaPoints[0].rx() = x2; - hexaPoints[0].ry() = y1; - - hexaPoints[1].rx() = x3; - hexaPoints[1].ry() = y2; - - hexaPoints[2].rx() = x3; - hexaPoints[2].ry() = y3; - - hexaPoints[3].rx() = x2; - hexaPoints[3].ry() = y4; - - hexaPoints[4].rx() = x1; - hexaPoints[4].ry() = y3; - - hexaPoints[5].rx() = x1; - hexaPoints[5].ry() = y2; - - QwtPainter::drawPolygon( painter, hexaPolygon ); - } -} - -class QwtSymbol::PrivateData -{ -public: - PrivateData( QwtSymbol::Style st, const QBrush &br, - const QPen &pn, const QSize &sz ): - style( st ), - size( sz ), - brush( br ), - pen( pn ), - isPinPointEnabled( false ) - { - cache.policy = QwtSymbol::AutoCache; -#ifndef QWT_NO_SVG - svg.renderer = NULL; -#endif - } - - ~PrivateData() - { -#ifndef QWT_NO_SVG - delete svg.renderer; -#endif - } - - Style style; - QSize size; - QBrush brush; - QPen pen; - - bool isPinPointEnabled; - QPointF pinPoint; - - struct Path - { - QPainterPath path; - QwtGraphic graphic; - - } path; - - struct Pixmap - { - QPixmap pixmap; - - } pixmap; - - struct Graphic - { - QwtGraphic graphic; - - } graphic; - -#ifndef QWT_NO_SVG - struct SVG - { - QSvgRenderer *renderer; - } svg; -#endif - - struct PaintCache - { - QwtSymbol::CachePolicy policy; - QPixmap pixmap; - - } cache; -}; - -/*! - Default Constructor - \param style Symbol Style - - The symbol is constructed with gray interior, - black outline with zero width, no size and style 'NoSymbol'. -*/ -QwtSymbol::QwtSymbol( Style style ) -{ - d_data = new PrivateData( style, QBrush( Qt::gray ), - QPen( Qt::black, 0 ), QSize() ); -} - -/*! - \brief Constructor - \param style Symbol Style - \param brush brush to fill the interior - \param pen outline pen - \param size size - - \sa setStyle(), setBrush(), setPen(), setSize() -*/ -QwtSymbol::QwtSymbol( QwtSymbol::Style style, const QBrush &brush, - const QPen &pen, const QSize &size ) -{ - d_data = new PrivateData( style, brush, pen, size ); -} - -/*! - \brief Constructor - - The symbol gets initialized by a painter path. The style is - set to QwtSymbol::Path, the size is set to empty ( the path - is displayed unscaled ). - - \param path painter path - \param brush brush to fill the interior - \param pen outline pen - - \sa setPath(), setBrush(), setPen(), setSize() -*/ - -QwtSymbol::QwtSymbol( const QPainterPath &path, - const QBrush &brush, const QPen &pen ) -{ - d_data = new PrivateData( QwtSymbol::Path, brush, pen, QSize() ); - setPath( path ); -} - -//! Destructor -QwtSymbol::~QwtSymbol() -{ - delete d_data; -} - -/*! - Change the cache policy - - The default policy is AutoCache - - \param policy Cache policy - \sa CachePolicy, cachePolicy() -*/ -void QwtSymbol::setCachePolicy( - QwtSymbol::CachePolicy policy ) -{ - if ( d_data->cache.policy != policy ) - { - d_data->cache.policy = policy; - invalidateCache(); - } -} - -/*! - \return Cache policy - \sa CachePolicy, setCachePolicy() -*/ -QwtSymbol::CachePolicy QwtSymbol::cachePolicy() const -{ - return d_data->cache.policy; -} - -/*! - \brief Set a painter path as symbol - - The symbol is represented by a painter path, where the - origin ( 0, 0 ) of the path coordinate system is mapped to - the position of the symbol. - - When the symbol has valid size the painter path gets scaled - to fit into the size. Otherwise the symbol size depends on - the bounding rectangle of the path. - - The following code defines a symbol drawing an arrow: - - \verbatim -#include <qwt_symbol.h> - -QwtSymbol *symbol = new QwtSymbol(); - -QPen pen( Qt::black, 2 ); -pen.setJoinStyle( Qt::MiterJoin ); - -symbol->setPen( pen ); -symbol->setBrush( Qt::red ); - -QPainterPath path; -path.moveTo( 0, 8 ); -path.lineTo( 0, 5 ); -path.lineTo( -3, 5 ); -path.lineTo( 0, 0 ); -path.lineTo( 3, 5 ); -path.lineTo( 0, 5 ); - -QTransform transform; -transform.rotate( -30.0 ); -path = transform.map( path ); - -symbol->setPath( path ); -symbol->setPinPoint( QPointF( 0.0, 0.0 ) ); - -setSize( 10, 14 ); -\endverbatim - - \param path Painter path - - \note The style is implicitely set to QwtSymbol::Path. - \sa path(), setSize() - */ -void QwtSymbol::setPath( const QPainterPath &path ) -{ - d_data->style = QwtSymbol::Path; - d_data->path.path = path; - d_data->path.graphic.reset(); -} - -/*! - \return Painter path for displaying the symbol - \sa setPath() -*/ -const QPainterPath &QwtSymbol::path() const -{ - return d_data->path.path; -} - -/*! - Set a pixmap as symbol - - \param pixmap Pixmap - - \sa pixmap(), setGraphic() - - \note the style() is set to QwtSymbol::Pixmap - \note brush() and pen() have no effect - */ -void QwtSymbol::setPixmap( const QPixmap &pixmap ) -{ - d_data->style = QwtSymbol::Pixmap; - d_data->pixmap.pixmap = pixmap; -} - -/*! - \return Assigned pixmap - \sa setPixmap() - */ -const QPixmap &QwtSymbol::pixmap() const -{ - return d_data->pixmap.pixmap; -} - -/*! - Set a graphic as symbol - - \param graphic Graphic - - \sa graphic(), setPixmap() - - \note the style() is set to QwtSymbol::Graphic - \note brush() and pen() have no effect - */ -void QwtSymbol::setGraphic( const QwtGraphic &graphic ) -{ - d_data->style = QwtSymbol::Graphic; - d_data->graphic.graphic = graphic; -} - -/*! - \return Assigned graphic - \sa setGraphic() - */ -const QwtGraphic &QwtSymbol::graphic() const -{ - return d_data->graphic.graphic; -} - -#ifndef QWT_NO_SVG - -/*! - Set a SVG icon as symbol - - \param svgDocument SVG icon - - \sa setGraphic(), setPixmap() - - \note the style() is set to QwtSymbol::SvgDocument - \note brush() and pen() have no effect - */ -void QwtSymbol::setSvgDocument( const QByteArray &svgDocument ) -{ - d_data->style = QwtSymbol::SvgDocument; - if ( d_data->svg.renderer == NULL ) - d_data->svg.renderer = new QSvgRenderer(); - - d_data->svg.renderer->load( svgDocument ); -} - -#endif - -/*! - \brief Specify the symbol's size - - If the 'h' parameter is left out or less than 0, - and the 'w' parameter is greater than or equal to 0, - the symbol size will be set to (w,w). - - \param width Width - \param height Height (defaults to -1) - - \sa size() -*/ -void QwtSymbol::setSize( int width, int height ) -{ - if ( ( width >= 0 ) && ( height < 0 ) ) - height = width; - - setSize( QSize( width, height ) ); -} - -/*! - Set the symbol's size - \param size Size - - \sa size() -*/ -void QwtSymbol::setSize( const QSize &size ) -{ - if ( size.isValid() && size != d_data->size ) - { - d_data->size = size; - invalidateCache(); - } -} - -/*! - \return Size - \sa setSize() -*/ -const QSize& QwtSymbol::size() const -{ - return d_data->size; -} - -/*! - \brief Assign a brush - - The brush is used to draw the interior of the symbol. - \param brush Brush - - \sa brush() -*/ -void QwtSymbol::setBrush( const QBrush &brush ) -{ - if ( brush != d_data->brush ) - { - d_data->brush = brush; - invalidateCache(); - - if ( d_data->style == QwtSymbol::Path ) - d_data->path.graphic.reset(); - } -} - -/*! - \return Brush - \sa setBrush() -*/ -const QBrush& QwtSymbol::brush() const -{ - return d_data->brush; -} - -/*! - Build and assign a pen - - In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) - what makes it non cosmetic ( see QPen::isCosmetic() ). - This method has been introduced to hide this incompatibility. - - \param color Pen color - \param width Pen width - \param style Pen style - - \sa pen(), brush() - */ -void QwtSymbol::setPen( const QColor &color, - qreal width, Qt::PenStyle style ) -{ - setPen( QPen( color, width, style ) ); -} - -/*! - Assign a pen - - The pen is used to draw the symbol's outline. - - \param pen Pen - \sa pen(), setBrush() -*/ -void QwtSymbol::setPen( const QPen &pen ) -{ - if ( pen != d_data->pen ) - { - d_data->pen = pen; - invalidateCache(); - - if ( d_data->style == QwtSymbol::Path ) - d_data->path.graphic.reset(); - } -} - -/*! - \return Pen - \sa setPen(), brush() -*/ -const QPen& QwtSymbol::pen() const -{ - return d_data->pen; -} - -/*! - \brief Set the color of the symbol - - Change the color of the brush for symbol types with a filled area. - For all other symbol types the color will be assigned to the pen. - - \param color Color - - \sa setBrush(), setPen(), brush(), pen() -*/ -void QwtSymbol::setColor( const QColor &color ) -{ - switch ( d_data->style ) - { - case QwtSymbol::Ellipse: - case QwtSymbol::Rect: - case QwtSymbol::Diamond: - case QwtSymbol::Triangle: - case QwtSymbol::UTriangle: - case QwtSymbol::DTriangle: - case QwtSymbol::RTriangle: - case QwtSymbol::LTriangle: - case QwtSymbol::Star2: - case QwtSymbol::Hexagon: - { - if ( d_data->brush.color() != color ) - { - d_data->brush.setColor( color ); - invalidateCache(); - } - break; - } - case QwtSymbol::Cross: - case QwtSymbol::XCross: - case QwtSymbol::HLine: - case QwtSymbol::VLine: - case QwtSymbol::Star1: - { - if ( d_data->pen.color() != color ) - { - d_data->pen.setColor( color ); - invalidateCache(); - } - break; - } - default: - { - if ( d_data->brush.color() != color || - d_data->pen.color() != color ) - { - invalidateCache(); - } - - d_data->brush.setColor( color ); - d_data->pen.setColor( color ); - } - } -} - -/*! - \brief Set and enable a pin point - - The position of a complex symbol is not always aligned to its center - ( f.e an arrow, where the peak points to a position ). The pin point - defines the position inside of a Pixmap, Graphic, SvgDocument - or PainterPath symbol where the represented point has to - be aligned to. - - \param pos Position - \param enable En/Disable the pin point alignment - - \sa pinPoint(), setPinPointEnabled() - */ -void QwtSymbol::setPinPoint( const QPointF &pos, bool enable ) -{ - if ( d_data->pinPoint != pos ) - { - d_data->pinPoint = pos; - if ( d_data->isPinPointEnabled ) - { - invalidateCache(); - } - } - - setPinPointEnabled( enable ); -} - -/*! - \return Pin point - \sa setPinPoint(), setPinPointEnabled() - */ -QPointF QwtSymbol::pinPoint() const -{ - return d_data->pinPoint; -} - -/*! - En/Disable the pin point alignment - - \param on Enabled, when on is true - \sa setPinPoint(), isPinPointEnabled() - */ -void QwtSymbol::setPinPointEnabled( bool on ) -{ - if ( d_data->isPinPointEnabled != on ) - { - d_data->isPinPointEnabled = on; - invalidateCache(); - } -} - -/*! - \return True, when the pin point translation is enabled - \sa setPinPoint(), setPinPointEnabled() - */ -bool QwtSymbol::isPinPointEnabled() const -{ - return d_data->isPinPointEnabled; -} - -/*! - Render an array of symbols - - Painting several symbols is more effective than drawing symbols - one by one, as a couple of layout calculations and setting of pen/brush - can be done once for the complete array. - - \param painter Painter - \param points Array of points - \param numPoints Number of points -*/ -void QwtSymbol::drawSymbols( QPainter *painter, - const QPointF *points, int numPoints ) const -{ - if ( numPoints <= 0 ) - return; - - bool useCache = false; - - // Don't use the pixmap, when the paint device - // could generate scalable vectors - - if ( QwtPainter::roundingAlignment( painter ) && - !painter->transform().isScaling() ) - { - if ( d_data->cache.policy == QwtSymbol::Cache ) - { - useCache = true; - } - else if ( d_data->cache.policy == QwtSymbol::AutoCache ) - { - if ( painter->paintEngine()->type() == QPaintEngine::Raster ) - { - useCache = true; - } - else - { - switch( d_data->style ) - { - case QwtSymbol::XCross: - case QwtSymbol::HLine: - case QwtSymbol::VLine: - case QwtSymbol::Cross: - break; - - case QwtSymbol::Pixmap: - { - if ( !d_data->size.isEmpty() && - d_data->size != d_data->pixmap.pixmap.size() ) - { - useCache = true; - } - break; - } - default: - useCache = true; - } - } - } - } - - if ( useCache ) - { - const QRect br = boundingRect(); - - const QRect rect( 0, 0, br.width(), br.height() ); - - if ( d_data->cache.pixmap.isNull() ) - { - d_data->cache.pixmap = QwtPainter::backingStore( NULL, br.size() ); - d_data->cache.pixmap.fill( Qt::transparent ); - - QPainter p( &d_data->cache.pixmap ); - p.setRenderHints( painter->renderHints() ); - p.translate( -br.topLeft() ); - - const QPointF pos; - renderSymbols( &p, &pos, 1 ); - } - - const int dx = br.left(); - const int dy = br.top(); - - for ( int i = 0; i < numPoints; i++ ) - { - const int left = qRound( points[i].x() ) + dx; - const int top = qRound( points[i].y() ) + dy; - - painter->drawPixmap( left, top, d_data->cache.pixmap ); - } - } - else - { - painter->save(); - renderSymbols( painter, points, numPoints ); - painter->restore(); - } -} - -/*! - \brief Draw the symbol into a rectangle - - The symbol is painted centered and scaled into the target rectangle. - It is always painted uncached and the pin point is ignored. - - This method is primarily intended for drawing a symbol to - the legend. - - \param painter Painter - \param rect Target rectangle for the symbol -*/ -void QwtSymbol::drawSymbol( QPainter *painter, const QRectF &rect ) const -{ - if ( d_data->style == QwtSymbol::NoSymbol ) - return; - - if ( d_data->style == QwtSymbol::Graphic ) - { - d_data->graphic.graphic.render( - painter, rect, Qt::KeepAspectRatio ); - } - else if ( d_data->style == QwtSymbol::Path ) - { - if ( d_data->path.graphic.isNull() ) - { - d_data->path.graphic = qwtPathGraphic( - d_data->path.path, d_data->pen, d_data->brush ); - } - - d_data->path.graphic.render( - painter, rect, Qt::KeepAspectRatio ); - return; - } - else if ( d_data->style == QwtSymbol::SvgDocument ) - { -#ifndef QWT_NO_SVG - if ( d_data->svg.renderer ) - { - QRectF scaledRect; - - QSizeF sz = d_data->svg.renderer->viewBoxF().size(); - if ( !sz.isEmpty() ) - { - sz.scale( rect.size(), Qt::KeepAspectRatio ); - scaledRect.setSize( sz ); - scaledRect.moveCenter( rect.center() ); - } - else - { - scaledRect = rect; - } - - d_data->svg.renderer->render( - painter, scaledRect ); - } -#endif - } - else - { - const QRect br = boundingRect(); - - // scale the symbol size to fit into rect. - - const double ratio = qMin( rect.width() / br.width(), - rect.height() / br.height() ); - - painter->save(); - - painter->translate( rect.center() ); - painter->scale( ratio, ratio ); - - const bool isPinPointEnabled = d_data->isPinPointEnabled; - d_data->isPinPointEnabled = false; - - const QPointF pos; - renderSymbols( painter, &pos, 1 ); - - d_data->isPinPointEnabled = isPinPointEnabled; - - painter->restore(); - } -} - -/*! - Render the symbol to series of points - - \param painter Qt painter - \param points Positions of the symbols - \param numPoints Number of points - */ -void QwtSymbol::renderSymbols( QPainter *painter, - const QPointF *points, int numPoints ) const -{ - switch ( d_data->style ) - { - case QwtSymbol::Ellipse: - { - qwtDrawEllipseSymbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Rect: - { - qwtDrawRectSymbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Diamond: - { - qwtDrawDiamondSymbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Cross: - { - qwtDrawLineSymbols( painter, Qt::Horizontal | Qt::Vertical, - points, numPoints, *this ); - break; - } - case QwtSymbol::XCross: - { - qwtDrawXCrossSymbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Triangle: - case QwtSymbol::UTriangle: - { - qwtDrawTriangleSymbols( painter, QwtTriangle::Up, - points, numPoints, *this ); - break; - } - case QwtSymbol::DTriangle: - { - qwtDrawTriangleSymbols( painter, QwtTriangle::Down, - points, numPoints, *this ); - break; - } - case QwtSymbol::RTriangle: - { - qwtDrawTriangleSymbols( painter, QwtTriangle::Right, - points, numPoints, *this ); - break; - } - case QwtSymbol::LTriangle: - { - qwtDrawTriangleSymbols( painter, QwtTriangle::Left, - points, numPoints, *this ); - break; - } - case QwtSymbol::HLine: - { - qwtDrawLineSymbols( painter, Qt::Horizontal, - points, numPoints, *this ); - break; - } - case QwtSymbol::VLine: - { - qwtDrawLineSymbols( painter, Qt::Vertical, - points, numPoints, *this ); - break; - } - case QwtSymbol::Star1: - { - qwtDrawStar1Symbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Star2: - { - qwtDrawStar2Symbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Hexagon: - { - qwtDrawHexagonSymbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Path: - { - if ( d_data->path.graphic.isNull() ) - { - d_data->path.graphic = qwtPathGraphic( d_data->path.path, - d_data->pen, d_data->brush ); - } - - qwtDrawGraphicSymbols( painter, points, numPoints, - d_data->path.graphic, *this ); - break; - } - case QwtSymbol::Pixmap: - { - qwtDrawPixmapSymbols( painter, points, numPoints, *this ); - break; - } - case QwtSymbol::Graphic: - { - qwtDrawGraphicSymbols( painter, points, numPoints, - d_data->graphic.graphic, *this ); - break; - } - case QwtSymbol::SvgDocument: - { -#ifndef QWT_NO_SVG - qwtDrawSvgSymbols( painter, points, numPoints, - d_data->svg.renderer, *this ); -#endif - break; - } - default:; - } -} - -/*! - Calculate the bounding rectangle for a symbol - at position (0,0). - - \return Bounding rectangle - */ -QRect QwtSymbol::boundingRect() const -{ - QRectF rect; - - bool pinPointTranslation = false; - - switch ( d_data->style ) - { - case QwtSymbol::Ellipse: - case QwtSymbol::Rect: - case QwtSymbol::Hexagon: - { - qreal pw = 0.0; - if ( d_data->pen.style() != Qt::NoPen ) - pw = qMax( d_data->pen.widthF(), qreal( 1.0 ) ); - - rect.setSize( d_data->size + QSizeF( pw, pw ) ); - rect.moveCenter( QPointF( 0.0, 0.0 ) ); - - break; - } - case QwtSymbol::XCross: - case QwtSymbol::Diamond: - case QwtSymbol::Triangle: - case QwtSymbol::UTriangle: - case QwtSymbol::DTriangle: - case QwtSymbol::RTriangle: - case QwtSymbol::LTriangle: - case QwtSymbol::Star1: - case QwtSymbol::Star2: - { - qreal pw = 0.0; - if ( d_data->pen.style() != Qt::NoPen ) - pw = qMax( d_data->pen.widthF(), qreal( 1.0 ) ); - - rect.setSize( d_data->size + QSizeF( 2 * pw, 2 * pw ) ); - rect.moveCenter( QPointF( 0.0, 0.0 ) ); - break; - } - case QwtSymbol::Path: - { - if ( d_data->path.graphic.isNull() ) - { - d_data->path.graphic = qwtPathGraphic( - d_data->path.path, d_data->pen, d_data->brush ); - } - - rect = qwtScaledBoundingRect( - d_data->path.graphic, d_data->size ); - pinPointTranslation = true; - - break; - } - case QwtSymbol::Pixmap: - { - if ( d_data->size.isEmpty() ) - rect.setSize( d_data->pixmap.pixmap.size() ); - else - rect.setSize( d_data->size ); - - pinPointTranslation = true; - - break; - } - case QwtSymbol::Graphic: - { - rect = qwtScaledBoundingRect( - d_data->graphic.graphic, d_data->size ); - pinPointTranslation = true; - - break; - } -#ifndef QWT_NO_SVG - case QwtSymbol::SvgDocument: - { - if ( d_data->svg.renderer ) - rect = d_data->svg.renderer->viewBoxF(); - - if ( d_data->size.isValid() && !rect.isEmpty() ) - { - QSizeF sz = rect.size(); - - const double sx = d_data->size.width() / sz.width(); - const double sy = d_data->size.height() / sz.height(); - - QTransform transform; - transform.scale( sx, sy ); - - rect = transform.mapRect( rect ); - } - pinPointTranslation = true; - break; - } -#endif - default: - { - rect.setSize( d_data->size ); - rect.moveCenter( QPointF( 0.0, 0.0 ) ); - } - } - - if ( pinPointTranslation ) - { - QPointF pinPoint( 0.0, 0.0 ); - if ( d_data->isPinPointEnabled ) - pinPoint = rect.center() - d_data->pinPoint; - - rect.moveCenter( pinPoint ); - } - - QRect r; - r.setLeft( qFloor( rect.left() ) ); - r.setTop( qFloor( rect.top() ) ); - r.setRight( qCeil( rect.right() ) ); - r.setBottom( qCeil( rect.bottom() ) ); - - if ( d_data->style != QwtSymbol::Pixmap ) - r.adjust( -1, -1, 1, 1 ); // for antialiasing - - return r; -} - -/*! - Invalidate the cached symbol pixmap - - The symbol invalidates its cache, whenever an attribute is changed - that has an effect ob how to display a symbol. In case of derived - classes with individual styles ( >= QwtSymbol::UserStyle ) it - might be necessary to call invalidateCache() for attributes - that are relevant for this style. - - \sa CachePolicy, setCachePolicy(), drawSymbols() - */ -void QwtSymbol::invalidateCache() -{ - if ( !d_data->cache.pixmap.isNull() ) - d_data->cache.pixmap = QPixmap(); -} - -/*! - Specify the symbol style - - \param style Style - \sa style() -*/ -void QwtSymbol::setStyle( QwtSymbol::Style style ) -{ - if ( d_data->style != style ) - { - d_data->style = style; - invalidateCache(); - } -} - -/*! - \return Current symbol style - \sa setStyle() -*/ -QwtSymbol::Style QwtSymbol::style() const -{ - return d_data->style; -} diff --git a/source/third_party/qwt/qwt_system_clock.cpp b/source/third_party/qwt/qwt_system_clock.cpp deleted file mode 100644 index 5d31b065e20bd1fdec18b0bc9439bbd454faf88b..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_system_clock.cpp +++ /dev/null @@ -1,396 +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/qwt_system_clock.h" - -#if QT_VERSION >= 0x040800 -#define USE_ELAPSED_TIMER 1 -#endif - -#if USE_ELAPSED_TIMER - -#include <qelapsedtimer.h> - -class QwtSystemClock::PrivateData -{ -public: - QElapsedTimer timer; -}; - -QwtSystemClock::QwtSystemClock() -{ - d_data = new PrivateData(); -} - -QwtSystemClock::~QwtSystemClock() -{ - delete d_data; -} - -bool QwtSystemClock::isNull() const -{ - return d_data->timer.isValid(); -} - -void QwtSystemClock::start() -{ - d_data->timer.start(); -} - -double QwtSystemClock::restart() -{ - const qint64 nsecs = d_data->timer.restart(); - return nsecs / 1e6; -} - -double QwtSystemClock::elapsed() const -{ - const qint64 nsecs = d_data->timer.nsecsElapsed(); - return nsecs / 1e6; -} - -#else // !USE_ELAPSED_TIMER - -#include <qdatetime.h> - -#if !defined(Q_OS_WIN) -#include <unistd.h> -#endif - -#if defined(Q_OS_MAC) -#include <stdint.h> -#include <mach/mach_time.h> -#define QWT_HIGH_RESOLUTION_CLOCK -#elif defined(_POSIX_TIMERS) -#include <time.h> -#define QWT_HIGH_RESOLUTION_CLOCK -#elif defined(Q_OS_WIN) -#define QWT_HIGH_RESOLUTION_CLOCK -#include <qt_windows.h> -#endif - -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - -class QwtHighResolutionClock -{ -public: - QwtHighResolutionClock(); - - void start(); - double restart(); - double elapsed() const; - - bool isNull() const; - - static double precision(); - -private: - -#if defined(Q_OS_MAC) - static double msecsTo( uint64_t, uint64_t ); - - uint64_t d_timeStamp; -#elif defined(_POSIX_TIMERS) - - static double msecsTo( const struct timespec &, - const struct timespec & ); - - static bool isMonotonic(); - - struct timespec d_timeStamp; - clockid_t d_clockId; - -#elif defined(Q_OS_WIN) - - LARGE_INTEGER d_startTicks; - LARGE_INTEGER d_ticksPerSecond; -#endif -}; - -#if defined(Q_OS_MAC) -QwtHighResolutionClock::QwtHighResolutionClock(): - d_timeStamp( 0 ) -{ -} - -double QwtHighResolutionClock::precision() -{ - return 1e-6; -} - -void QwtHighResolutionClock::start() -{ - d_timeStamp = mach_absolute_time(); -} - -double QwtHighResolutionClock::restart() -{ - const uint64_t timeStamp = mach_absolute_time(); - const double elapsed = msecsTo( d_timeStamp, timeStamp ); - d_timeStamp = timeStamp; - - return elapsed; -} - -double QwtHighResolutionClock::elapsed() const -{ - return msecsTo( d_timeStamp, mach_absolute_time() ); -} - -bool QwtHighResolutionClock::isNull() const -{ - return d_timeStamp == 0; -} - -double QwtHighResolutionClock::msecsTo( - uint64_t from, uint64_t to ) -{ - const uint64_t difference = to - from; - - static double conversion = 0.0; - if ( conversion == 0.0 ) - { - mach_timebase_info_data_t info; - kern_return_t err = mach_timebase_info( &info ); - - // convert the timebase into ms - if ( err == 0 ) - conversion = 1e-6 * ( double ) info.numer / ( double ) info.denom; - } - - return conversion * ( double ) difference; -} - -#elif defined(_POSIX_TIMERS) - -QwtHighResolutionClock::QwtHighResolutionClock() -{ - d_clockId = isMonotonic() ? CLOCK_MONOTONIC : CLOCK_REALTIME; - d_timeStamp.tv_sec = d_timeStamp.tv_nsec = 0; -} - -double QwtHighResolutionClock::precision() -{ - struct timespec resolution; - - int clockId = isMonotonic() ? CLOCK_MONOTONIC : CLOCK_REALTIME; - ::clock_getres( clockId, &resolution ); - - return resolution.tv_nsec / 1e3; -} - -inline bool QwtHighResolutionClock::isNull() const -{ - return d_timeStamp.tv_sec <= 0 && d_timeStamp.tv_nsec <= 0; -} - -inline void QwtHighResolutionClock::start() -{ - ::clock_gettime( d_clockId, &d_timeStamp ); -} - -double QwtHighResolutionClock::restart() -{ - struct timespec timeStamp; - ::clock_gettime( d_clockId, &timeStamp ); - - const double elapsed = msecsTo( d_timeStamp, timeStamp ); - - d_timeStamp = timeStamp; - return elapsed; -} - -inline double QwtHighResolutionClock::elapsed() const -{ - struct timespec timeStamp; - ::clock_gettime( d_clockId, &timeStamp ); - - return msecsTo( d_timeStamp, timeStamp ); -} - -inline double QwtHighResolutionClock::msecsTo( - const struct timespec &t1, const struct timespec &t2 ) -{ - return ( t2.tv_sec - t1.tv_sec ) * 1e3 - + ( t2.tv_nsec - t1.tv_nsec ) * 1e-6; -} - -bool QwtHighResolutionClock::isMonotonic() -{ - // code copied from qcore_unix.cpp - -#if (_POSIX_MONOTONIC_CLOCK-0 > 0) - return true; -#else - static int returnValue = 0; - - if ( returnValue == 0 ) - { -#if (_POSIX_MONOTONIC_CLOCK-0 < 0) || !defined(_SC_MONOTONIC_CLOCK) - returnValue = -1; -#elif (_POSIX_MONOTONIC_CLOCK == 0) - // detect if the system support monotonic timers - const long x = sysconf( _SC_MONOTONIC_CLOCK ); - returnValue = ( x >= 200112L ) ? 1 : -1; -#endif - } - - return returnValue != -1; -#endif -} - -#elif defined(Q_OS_WIN) - -QwtHighResolutionClock::QwtHighResolutionClock() -{ - d_startTicks.QuadPart = 0; - QueryPerformanceFrequency( &d_ticksPerSecond ); -} - -double QwtHighResolutionClock::precision() -{ - LARGE_INTEGER ticks; - if ( QueryPerformanceFrequency( &ticks ) && ticks.QuadPart > 0 ) - return 1e3 / ticks.QuadPart; - - return 0.0; -} - -inline bool QwtHighResolutionClock::isNull() const -{ - return d_startTicks.QuadPart <= 0; -} - -inline void QwtHighResolutionClock::start() -{ - QueryPerformanceCounter( &d_startTicks ); -} - -inline double QwtHighResolutionClock::restart() -{ - LARGE_INTEGER ticks; - QueryPerformanceCounter( &ticks ); - - const double dt = ticks.QuadPart - d_startTicks.QuadPart; - d_startTicks = ticks; - - return dt / d_ticksPerSecond.QuadPart * 1e3; -} - -inline double QwtHighResolutionClock::elapsed() const -{ - LARGE_INTEGER ticks; - QueryPerformanceCounter( &ticks ); - - const double dt = ticks.QuadPart - d_startTicks.QuadPart; - return dt / d_ticksPerSecond.QuadPart * 1e3; -} - -#endif - -#endif // QWT_HIGH_RESOLUTION_CLOCK - -class QwtSystemClock::PrivateData -{ -public: -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - QwtHighResolutionClock *clock; -#endif - QTime time; -}; - -//! Constructs a null clock object. -QwtSystemClock::QwtSystemClock() -{ - d_data = new PrivateData; - -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - d_data->clock = NULL; - if ( QwtHighResolutionClock::precision() > 0.0 ) - d_data->clock = new QwtHighResolutionClock; -#endif -} - -//! Destructor -QwtSystemClock::~QwtSystemClock() -{ -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - delete d_data->clock; -#endif - delete d_data; -} - -/*! - \return true if the clock has never been started. -*/ -bool QwtSystemClock::isNull() const -{ -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - if ( d_data->clock ) - return d_data->clock->isNull(); -#endif - - return d_data->time.isNull(); -} - -/*! - Sets the start time to the current time. -*/ -void QwtSystemClock::start() -{ -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - if ( d_data->clock ) - { - d_data->clock->start(); - return; - } -#endif - - d_data->time.start(); -} - -/*! - Set the start time to the current time - \return Time, that is elapsed since the previous start time. -*/ -double QwtSystemClock::restart() -{ -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - if ( d_data->clock ) - return d_data->clock->restart(); -#endif - - return d_data->time.restart(); -} - -/*! - \return Number of milliseconds that have elapsed since the last time - start() or restart() was called or 0.0 for null clocks. -*/ -double QwtSystemClock::elapsed() const -{ - double elapsed = 0.0; - -#if defined(QWT_HIGH_RESOLUTION_CLOCK) - if ( d_data->clock ) - { - if ( !d_data->clock->isNull() ) - elapsed = d_data->clock->elapsed(); - - return elapsed; - } -#endif - - if ( !d_data->time.isNull() ) - elapsed = d_data->time.elapsed(); - - return elapsed; -} - -#endif diff --git a/source/third_party/qwt/qwt_text.cpp b/source/third_party/qwt/qwt_text.cpp deleted file mode 100644 index 0fff644f260800f30521690ea14ee1ad98b1222a..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_text.cpp +++ /dev/null @@ -1,676 +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/qwt_text.h" -#include "qwt/qwt_painter.h" -#include "qwt/qwt_text_engine.h" -#include <qmap.h> -#include <qfont.h> -#include <qcolor.h> -#include <qpen.h> -#include <qbrush.h> -#include <qpainter.h> -#include <qapplication.h> -#include <qdesktopwidget.h> -#include <qmath.h> - -class QwtTextEngineDict -{ -public: - static QwtTextEngineDict &dict(); - - void setTextEngine( QwtText::TextFormat, QwtTextEngine * ); - - const QwtTextEngine *textEngine( QwtText::TextFormat ) const; - const QwtTextEngine *textEngine( const QString &, - QwtText::TextFormat ) const; - -private: - QwtTextEngineDict(); - ~QwtTextEngineDict(); - - typedef QMap<int, QwtTextEngine *> EngineMap; - - inline const QwtTextEngine *engine( EngineMap::const_iterator &it ) const - { - return it.value(); - } - - EngineMap d_map; -}; - -QwtTextEngineDict &QwtTextEngineDict::dict() -{ - static QwtTextEngineDict engineDict; - return engineDict; -} - -QwtTextEngineDict::QwtTextEngineDict() -{ - d_map.insert( QwtText::PlainText, new QwtPlainTextEngine() ); -#ifndef QT_NO_RICHTEXT - d_map.insert( QwtText::RichText, new QwtRichTextEngine() ); -#endif -} - -QwtTextEngineDict::~QwtTextEngineDict() -{ - for ( EngineMap::const_iterator it = d_map.begin(); - it != d_map.end(); ++it ) - { - const QwtTextEngine *textEngine = engine( it ); - delete textEngine; - } -} - -const QwtTextEngine *QwtTextEngineDict::textEngine( const QString& text, - QwtText::TextFormat format ) const -{ - if ( format == QwtText::AutoText ) - { - for ( EngineMap::const_iterator it = d_map.begin(); - it != d_map.end(); ++it ) - { - if ( it.key() != QwtText::PlainText ) - { - const QwtTextEngine *e = engine( it ); - if ( e && e->mightRender( text ) ) - return e; - } - } - } - - EngineMap::const_iterator it = d_map.find( format ); - if ( it != d_map.end() ) - { - const QwtTextEngine *e = engine( it ); - if ( e ) - return e; - } - - it = d_map.find( QwtText::PlainText ); - return engine( it ); -} - -void QwtTextEngineDict::setTextEngine( QwtText::TextFormat format, - QwtTextEngine *engine ) -{ - if ( format == QwtText::AutoText ) - return; - - if ( format == QwtText::PlainText && engine == NULL ) - return; - - EngineMap::const_iterator it = d_map.find( format ); - if ( it != d_map.end() ) - { - const QwtTextEngine *e = this->engine( it ); - if ( e ) - delete e; - - d_map.remove( format ); - } - - if ( engine != NULL ) - d_map.insert( format, engine ); -} - -const QwtTextEngine *QwtTextEngineDict::textEngine( - QwtText::TextFormat format ) const -{ - const QwtTextEngine *e = NULL; - - EngineMap::const_iterator it = d_map.find( format ); - if ( it != d_map.end() ) - e = engine( it ); - - return e; -} - -class QwtText::PrivateData -{ -public: - PrivateData(): - renderFlags( Qt::AlignCenter ), - borderRadius( 0 ), - borderPen( Qt::NoPen ), - backgroundBrush( Qt::NoBrush ), - paintAttributes( 0 ), - layoutAttributes( 0 ), - textEngine( NULL ) - { - } - - int renderFlags; - QString text; - QFont font; - QColor color; - double borderRadius; - QPen borderPen; - QBrush backgroundBrush; - - QwtText::PaintAttributes paintAttributes; - QwtText::LayoutAttributes layoutAttributes; - - const QwtTextEngine *textEngine; -}; - -class QwtText::LayoutCache -{ -public: - void invalidate() - { - textSize = QSizeF(); - } - - QFont font; - QSizeF textSize; -}; - -/*! - Constructor - - \param text Text content - \param textFormat Text format -*/ -QwtText::QwtText( const QString &text, QwtText::TextFormat textFormat ) -{ - d_data = new PrivateData; - d_data->text = text; - d_data->textEngine = textEngine( text, textFormat ); - - d_layoutCache = new LayoutCache; -} - -//! Copy constructor -QwtText::QwtText( const QwtText &other ) -{ - d_data = new PrivateData; - *d_data = *other.d_data; - - d_layoutCache = new LayoutCache; - *d_layoutCache = *other.d_layoutCache; -} - -//! Destructor -QwtText::~QwtText() -{ - delete d_data; - delete d_layoutCache; -} - -//! Assignment operator -QwtText &QwtText::operator=( const QwtText & other ) -{ - *d_data = *other.d_data; - *d_layoutCache = *other.d_layoutCache; - return *this; -} - -//! Relational operator -bool QwtText::operator==( const QwtText &other ) const -{ - return d_data->renderFlags == other.d_data->renderFlags && - d_data->text == other.d_data->text && - d_data->font == other.d_data->font && - d_data->color == other.d_data->color && - d_data->borderRadius == other.d_data->borderRadius && - d_data->borderPen == other.d_data->borderPen && - d_data->backgroundBrush == other.d_data->backgroundBrush && - d_data->paintAttributes == other.d_data->paintAttributes && - d_data->textEngine == other.d_data->textEngine; -} - -//! Relational operator -bool QwtText::operator!=( const QwtText &other ) const // invalidate -{ - return !( other == *this ); -} - -/*! - Assign a new text content - - \param text Text content - \param textFormat Text format - - \sa text() -*/ -void QwtText::setText( const QString &text, - QwtText::TextFormat textFormat ) -{ - d_data->text = text; - d_data->textEngine = textEngine( text, textFormat ); - d_layoutCache->invalidate(); -} - -/*! - \return Text as QString. - \sa setText() -*/ -QString QwtText::text() const -{ - return d_data->text; -} - -/*! - \brief Change the render flags - - The default setting is Qt::AlignCenter - - \param renderFlags Bitwise OR of the flags used like in QPainter::drawText() - - \sa renderFlags(), QwtTextEngine::draw() - \note Some renderFlags might have no effect, depending on the text format. -*/ -void QwtText::setRenderFlags( int renderFlags ) -{ - if ( renderFlags != d_data->renderFlags ) - { - d_data->renderFlags = renderFlags; - d_layoutCache->invalidate(); - } -} - -/*! - \return Render flags - \sa setRenderFlags() -*/ -int QwtText::renderFlags() const -{ - return d_data->renderFlags; -} - -/*! - Set the font. - - \param font Font - \note Setting the font might have no effect, when - the text contains control sequences for setting fonts. -*/ -void QwtText::setFont( const QFont &font ) -{ - d_data->font = font; - setPaintAttribute( PaintUsingTextFont ); -} - -//! Return the font. -QFont QwtText::font() const -{ - return d_data->font; -} - -/*! - Return the font of the text, if it has one. - Otherwise return defaultFont. - - \param defaultFont Default font - \return Font used for drawing the text - - \sa setFont(), font(), PaintAttributes -*/ -QFont QwtText::usedFont( const QFont &defaultFont ) const -{ - if ( d_data->paintAttributes & PaintUsingTextFont ) - return d_data->font; - - return defaultFont; -} - -/*! - Set the pen color used for drawing the text. - - \param color Color - \note Setting the color might have no effect, when - the text contains control sequences for setting colors. -*/ -void QwtText::setColor( const QColor &color ) -{ - d_data->color = color; - setPaintAttribute( PaintUsingTextColor ); -} - -//! Return the pen color, used for painting the text -QColor QwtText::color() const -{ - return d_data->color; -} - -/*! - Return the color of the text, if it has one. - Otherwise return defaultColor. - - \param defaultColor Default color - \return Color used for drawing the text - - \sa setColor(), color(), PaintAttributes -*/ -QColor QwtText::usedColor( const QColor &defaultColor ) const -{ - if ( d_data->paintAttributes & PaintUsingTextColor ) - return d_data->color; - - return defaultColor; -} - -/*! - Set the radius for the corners of the border frame - - \param radius Radius of a rounded corner - \sa borderRadius(), setBorderPen(), setBackgroundBrush() -*/ -void QwtText::setBorderRadius( double radius ) -{ - d_data->borderRadius = qMax( 0.0, radius ); -} - -/*! - \return Radius for the corners of the border frame - \sa setBorderRadius(), borderPen(), backgroundBrush() -*/ -double QwtText::borderRadius() const -{ - return d_data->borderRadius; -} - -/*! - Set the background pen - - \param pen Background pen - \sa borderPen(), setBackgroundBrush() -*/ -void QwtText::setBorderPen( const QPen &pen ) -{ - d_data->borderPen = pen; - setPaintAttribute( PaintBackground ); -} - -/*! - \return Background pen - \sa setBorderPen(), backgroundBrush() -*/ -QPen QwtText::borderPen() const -{ - return d_data->borderPen; -} - -/*! - Set the background brush - - \param brush Background brush - \sa backgroundBrush(), setBorderPen() -*/ -void QwtText::setBackgroundBrush( const QBrush &brush ) -{ - d_data->backgroundBrush = brush; - setPaintAttribute( PaintBackground ); -} - -/*! - \return Background brush - \sa setBackgroundBrush(), borderPen() -*/ -QBrush QwtText::backgroundBrush() const -{ - return d_data->backgroundBrush; -} - -/*! - Change a paint attribute - - \param attribute Paint attribute - \param on On/Off - - \note Used by setFont(), setColor(), - setBorderPen() and setBackgroundBrush() - \sa testPaintAttribute() -*/ -void QwtText::setPaintAttribute( PaintAttribute attribute, bool on ) -{ - if ( on ) - d_data->paintAttributes |= attribute; - else - d_data->paintAttributes &= ~attribute; -} - -/*! - Test a paint attribute - - \param attribute Paint attribute - \return true, if attribute is enabled - - \sa setPaintAttribute() -*/ -bool QwtText::testPaintAttribute( PaintAttribute attribute ) const -{ - return d_data->paintAttributes & attribute; -} - -/*! - Change a layout attribute - - \param attribute Layout attribute - \param on On/Off - \sa testLayoutAttribute() -*/ -void QwtText::setLayoutAttribute( LayoutAttribute attribute, bool on ) -{ - if ( on ) - d_data->layoutAttributes |= attribute; - else - d_data->layoutAttributes &= ~attribute; -} - -/*! - Test a layout attribute - - \param attribute Layout attribute - \return true, if attribute is enabled - - \sa setLayoutAttribute() -*/ -bool QwtText::testLayoutAttribute( LayoutAttribute attribute ) const -{ - return d_data->layoutAttributes | attribute; -} - -/*! - Find the height for a given width - - \param defaultFont Font, used for the calculation if the text has no font - \param width Width - - \return Calculated height -*/ -double QwtText::heightForWidth( double width, const QFont &defaultFont ) const -{ - // We want to calculate in screen metrics. So - // we need a font that uses screen metrics - - const QFont font( usedFont( defaultFont ), QApplication::desktop() ); - - double h = 0; - - if ( d_data->layoutAttributes & MinimumLayout ) - { - double left, right, top, bottom; - d_data->textEngine->textMargins( font, d_data->text, - left, right, top, bottom ); - - h = d_data->textEngine->heightForWidth( - font, d_data->renderFlags, d_data->text, - width + left + right ); - - h -= top + bottom; - } - else - { - h = d_data->textEngine->heightForWidth( - font, d_data->renderFlags, d_data->text, width ); - } - - return h; -} - -/*! - Returns the size, that is needed to render text - - \param defaultFont Font of the text - \return Calculated size -*/ -QSizeF QwtText::textSize( const QFont &defaultFont ) const -{ - // We want to calculate in screen metrics. So - // we need a font that uses screen metrics - - const QFont font( usedFont( defaultFont ), QApplication::desktop() ); - - if ( !d_layoutCache->textSize.isValid() - || d_layoutCache->font != font ) - { - d_layoutCache->textSize = d_data->textEngine->textSize( - font, d_data->renderFlags, d_data->text ); - d_layoutCache->font = font; - } - - QSizeF sz = d_layoutCache->textSize; - - if ( d_data->layoutAttributes & MinimumLayout ) - { - double left, right, top, bottom; - d_data->textEngine->textMargins( font, d_data->text, - left, right, top, bottom ); - sz -= QSizeF( left + right, top + bottom ); - } - - return sz; -} - -/*! - Draw a text into a rectangle - - \param painter Painter - \param rect Rectangle -*/ -void QwtText::draw( QPainter *painter, const QRectF &rect ) const -{ - if ( d_data->paintAttributes & PaintBackground ) - { - if ( d_data->borderPen != Qt::NoPen || - d_data->backgroundBrush != Qt::NoBrush ) - { - painter->save(); - - painter->setPen( d_data->borderPen ); - painter->setBrush( d_data->backgroundBrush ); - - if ( d_data->borderRadius == 0 ) - { - QwtPainter::drawRect( painter, rect ); - } - else - { - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->drawRoundedRect( rect, - d_data->borderRadius, d_data->borderRadius ); - } - - painter->restore(); - } - } - - painter->save(); - - if ( d_data->paintAttributes & PaintUsingTextFont ) - { - painter->setFont( d_data->font ); - } - - if ( d_data->paintAttributes & PaintUsingTextColor ) - { - if ( d_data->color.isValid() ) - painter->setPen( d_data->color ); - } - - QRectF expandedRect = rect; - if ( d_data->layoutAttributes & MinimumLayout ) - { - // We want to calculate in screen metrics. So - // we need a font that uses screen metrics - - const QFont font( painter->font(), QApplication::desktop() ); - - double left, right, top, bottom; - d_data->textEngine->textMargins( - font, d_data->text, left, right, top, bottom ); - - expandedRect.setTop( rect.top() - top ); - expandedRect.setBottom( rect.bottom() + bottom ); - expandedRect.setLeft( rect.left() - left ); - expandedRect.setRight( rect.right() + right ); - } - - d_data->textEngine->draw( painter, expandedRect, - d_data->renderFlags, d_data->text ); - - painter->restore(); -} - -/*! - Find the text engine for a text format - - In case of QwtText::AutoText the first text engine - (beside QwtPlainTextEngine) is returned, where QwtTextEngine::mightRender - returns true. If there is none QwtPlainTextEngine is returned. - - If no text engine is registered for the format QwtPlainTextEngine - is returnd. - - \param text Text, needed in case of AutoText - \param format Text format - - \return Corresponding text engine -*/ -const QwtTextEngine *QwtText::textEngine( const QString &text, - QwtText::TextFormat format ) -{ - return QwtTextEngineDict::dict().textEngine( text, format ); -} - -/*! - Assign/Replace a text engine for a text format - - With setTextEngine it is possible to extend Qwt with - other types of text formats. - - For QwtText::PlainText it is not allowed to assign a engine == NULL. - - \param format Text format - \param engine Text engine - - \sa QwtMathMLTextEngine - \warning Using QwtText::AutoText does nothing. -*/ -void QwtText::setTextEngine( QwtText::TextFormat format, - QwtTextEngine *engine ) -{ - QwtTextEngineDict::dict().setTextEngine( format, engine ); -} - -/*! - \brief Find the text engine for a text format - - textEngine can be used to find out if a text format is supported. - - \param format Text format - \return The text engine, or NULL if no engine is available. -*/ -const QwtTextEngine *QwtText::textEngine( QwtText::TextFormat format ) -{ - return QwtTextEngineDict::dict().textEngine( format ); -} diff --git a/source/third_party/qwt/qwt_text_engine.cpp b/source/third_party/qwt/qwt_text_engine.cpp deleted file mode 100644 index e2e244b880a7bb14850281715ddbbb3e9e60d18d..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_text_engine.cpp +++ /dev/null @@ -1,345 +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/qwt_text_engine.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qpixmap.h> -#include <qimage.h> -#include <qmap.h> -#include <qwidget.h> -#include <qtextobject.h> -#include <qtextdocument.h> -#include <qabstracttextdocumentlayout.h> - -static QString taggedRichText( const QString &text, int flags ) -{ - QString richText = text; - - // By default QSimpleRichText is Qt::AlignLeft - if ( flags & Qt::AlignJustify ) - { - richText.prepend( QString::fromLatin1( "<div align=\"justify\">" ) ); - richText.append( QString::fromLatin1( "</div>" ) ); - } - else if ( flags & Qt::AlignRight ) - { - richText.prepend( QString::fromLatin1( "<div align=\"right\">" ) ); - richText.append( QString::fromLatin1( "</div>" ) ); - } - else if ( flags & Qt::AlignHCenter ) - { - richText.prepend( QString::fromLatin1( "<div align=\"center\">" ) ); - richText.append( QString::fromLatin1( "</div>" ) ); - } - - return richText; -} - -class QwtRichTextDocument: public QTextDocument -{ -public: - QwtRichTextDocument( const QString &text, int flags, const QFont &font ) - { - setUndoRedoEnabled( false ); - setDefaultFont( font ); - setHtml( text ); - - // make sure we have a document layout - ( void )documentLayout(); - - QTextOption option = defaultTextOption(); - if ( flags & Qt::TextWordWrap ) - option.setWrapMode( QTextOption::WordWrap ); - else - option.setWrapMode( QTextOption::NoWrap ); - - option.setAlignment( static_cast<Qt::Alignment>( flags ) ); - setDefaultTextOption( option ); - - QTextFrame *root = rootFrame(); - QTextFrameFormat fm = root->frameFormat(); - fm.setBorder( 0 ); - fm.setMargin( 0 ); - fm.setPadding( 0 ); - fm.setBottomMargin( 0 ); - fm.setLeftMargin( 0 ); - root->setFrameFormat( fm ); - - adjustSize(); - } -}; - -class QwtPlainTextEngine::PrivateData -{ -public: - int effectiveAscent( const QFont &font ) const - { - const QString fontKey = font.key(); - - QMap<QString, int>::const_iterator it = - d_ascentCache.find( fontKey ); - if ( it == d_ascentCache.end() ) - { - int ascent = findAscent( font ); - it = d_ascentCache.insert( fontKey, ascent ); - } - - return ( *it ); - } - -private: - int findAscent( const QFont &font ) const - { - static const QString dummy( "E" ); - static const QColor white( Qt::white ); - - const QFontMetrics fm( font ); - QPixmap pm( fm.width( dummy ), fm.height() ); - pm.fill( white ); - - QPainter p( &pm ); - p.setFont( font ); - p.drawText( 0, 0, pm.width(), pm.height(), 0, dummy ); - p.end(); - - const QImage img = pm.toImage(); - - int row = 0; - for ( row = 0; row < img.height(); row++ ) - { - const QRgb *line = reinterpret_cast<const QRgb *>( - img.scanLine( row ) ); - - const int w = pm.width(); - for ( int col = 0; col < w; col++ ) - { - if ( line[col] != white.rgb() ) - return fm.ascent() - row + 1; - } - } - - return fm.ascent(); - } - - mutable QMap<QString, int> d_ascentCache; -}; - -//! Constructor -QwtTextEngine::QwtTextEngine() -{ -} - -//! Destructor -QwtTextEngine::~QwtTextEngine() -{ -} - -//! Constructor -QwtPlainTextEngine::QwtPlainTextEngine() -{ - d_data = new PrivateData; -} - -//! Destructor -QwtPlainTextEngine::~QwtPlainTextEngine() -{ - delete d_data; -} - -/*! - Find the height for a given width - - \param font Font of the text - \param flags Bitwise OR of the flags used like in QPainter::drawText - \param text Text to be rendered - \param width Width - - \return Calculated height -*/ -double QwtPlainTextEngine::heightForWidth( const QFont& font, int flags, - const QString& text, double width ) const -{ - const QFontMetricsF fm( font ); - const QRectF rect = fm.boundingRect( - QRectF( 0, 0, width, QWIDGETSIZE_MAX ), flags, text ); - - return rect.height(); -} - -/*! - Returns the size, that is needed to render text - - \param font Font of the text - \param flags Bitwise OR of the flags used like in QPainter::drawText - \param text Text to be rendered - - \return Calculated size -*/ -QSizeF QwtPlainTextEngine::textSize( const QFont &font, - int flags, const QString& text ) const -{ - const QFontMetricsF fm( font ); - const QRectF rect = fm.boundingRect( - QRectF( 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ), flags, text ); - - return rect.size(); -} - -/*! - Return margins around the texts - - \param font Font of the text - \param left Return 0 - \param right Return 0 - \param top Return value for the top margin - \param bottom Return value for the bottom margin -*/ -void QwtPlainTextEngine::textMargins( const QFont &font, const QString &, - double &left, double &right, double &top, double &bottom ) const -{ - left = right = top = 0; - - const QFontMetricsF fm( font ); - top = fm.ascent() - d_data->effectiveAscent( font ); - bottom = fm.descent(); -} - -/*! - \brief Draw the text in a clipping rectangle - - A wrapper for QPainter::drawText. - - \param painter Painter - \param rect Clipping rectangle - \param flags Bitwise OR of the flags used like in QPainter::drawText - \param text Text to be rendered -*/ -void QwtPlainTextEngine::draw( QPainter *painter, const QRectF &rect, - int flags, const QString& text ) const -{ - QwtPainter::drawText( painter, rect, flags, text ); -} - -/*! - Test if a string can be rendered by this text engine. - \return Always true. All texts can be rendered by QwtPlainTextEngine -*/ -bool QwtPlainTextEngine::mightRender( const QString & ) const -{ - return true; -} - -#ifndef QT_NO_RICHTEXT - -//! Constructor -QwtRichTextEngine::QwtRichTextEngine() -{ -} - -/*! - Find the height for a given width - - \param font Font of the text - \param flags Bitwise OR of the flags used like in QPainter::drawText() - \param text Text to be rendered - \param width Width - - \return Calculated height -*/ -double QwtRichTextEngine::heightForWidth( const QFont& font, int flags, - const QString& text, double width ) const -{ - QwtRichTextDocument doc( text, flags, font ); - - doc.setPageSize( QSizeF( width, QWIDGETSIZE_MAX ) ); - return doc.documentLayout()->documentSize().height(); -} - -/*! - Returns the size, that is needed to render text - - \param font Font of the text - \param flags Bitwise OR of the flags used like in QPainter::drawText() - \param text Text to be rendered - - \return Calculated size -*/ - -QSizeF QwtRichTextEngine::textSize( const QFont &font, - int flags, const QString& text ) const -{ - QwtRichTextDocument doc( text, flags, font ); - - QTextOption option = doc.defaultTextOption(); - if ( option.wrapMode() != QTextOption::NoWrap ) - { - option.setWrapMode( QTextOption::NoWrap ); - doc.setDefaultTextOption( option ); - doc.adjustSize(); - } - - return doc.size(); -} - -/*! - Draw the text in a clipping rectangle - - \param painter Painter - \param rect Clipping rectangle - \param flags Bitwise OR of the flags like in for QPainter::drawText() - \param text Text to be rendered -*/ -void QwtRichTextEngine::draw( QPainter *painter, const QRectF &rect, - int flags, const QString& text ) const -{ - QwtRichTextDocument doc( text, flags, painter->font() ); - QwtPainter::drawSimpleRichText( painter, rect, flags, doc ); -} - -/*! - Wrap text into <div align=...> </div> tags according flags - - \param text Text - \param flags Bitwise OR of the flags like in for QPainter::drawText() - - \return Tagged text -*/ -QString QwtRichTextEngine::taggedText( const QString &text, int flags ) const -{ - return taggedRichText( text, flags ); -} - -/*! - Test if a string can be rendered by this text engine - - \param text Text to be tested - \return Qt::mightBeRichText(text); -*/ -bool QwtRichTextEngine::mightRender( const QString &text ) const -{ - return Qt::mightBeRichText( text ); -} - -/*! - Return margins around the texts - - \param left Return 0 - \param right Return 0 - \param top Return 0 - \param bottom Return 0 -*/ -void QwtRichTextEngine::textMargins( const QFont &, const QString &, - double &left, double &right, double &top, double &bottom ) const -{ - left = right = top = bottom = 0; -} - -#endif // !QT_NO_RICHTEXT diff --git a/source/third_party/qwt/qwt_text_label.cpp b/source/third_party/qwt/qwt_text_label.cpp deleted file mode 100644 index e77a3ea67bb19c5652d5fcb757430f567dd489e6..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_text_label.cpp +++ /dev/null @@ -1,324 +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/qwt_text_label.h" -#include "qwt/qwt_text.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qevent.h> -#include <qmath.h> - -class QwtTextLabel::PrivateData -{ -public: - PrivateData(): - indent( 4 ), - margin( 0 ) - { - } - - int indent; - int margin; - QwtText text; -}; - -/*! - Constructs an empty label. - \param parent Parent widget -*/ -QwtTextLabel::QwtTextLabel( QWidget *parent ): - QFrame( parent ) -{ - init(); -} - -/*! - Constructs a label that displays the text, text - \param parent Parent widget - \param text Text -*/ -QwtTextLabel::QwtTextLabel( const QwtText &text, QWidget *parent ): - QFrame( parent ) -{ - init(); - d_data->text = text; -} - -//! Destructor -QwtTextLabel::~QwtTextLabel() -{ - delete d_data; -} - -void QwtTextLabel::init() -{ - d_data = new PrivateData(); - setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); -} - -/*! - Interface for the designer plugin - does the same as setText() - \sa plainText() - */ -void QwtTextLabel::setPlainText( const QString &text ) -{ - setText( QwtText( text ) ); -} - -/*! - Interface for the designer plugin - - \return Text as plain text - \sa setPlainText(), text() - */ -QString QwtTextLabel::plainText() const -{ - return d_data->text.text(); -} - -/*! - Change the label's text, keeping all other QwtText attributes - \param text New text - \param textFormat Format of text - - \sa QwtText -*/ -void QwtTextLabel::setText( const QString &text, - QwtText::TextFormat textFormat ) -{ - d_data->text.setText( text, textFormat ); - - update(); - updateGeometry(); -} - -/*! - Change the label's text - \param text New text -*/ -void QwtTextLabel::setText( const QwtText &text ) -{ - d_data->text = text; - - update(); - updateGeometry(); -} - -//! Return the text -const QwtText &QwtTextLabel::text() const -{ - return d_data->text; -} - -//! Clear the text and all QwtText attributes -void QwtTextLabel::clear() -{ - d_data->text = QwtText(); - - update(); - updateGeometry(); -} - -//! Return label's text indent in pixels -int QwtTextLabel::indent() const -{ - return d_data->indent; -} - -/*! - Set label's text indent in pixels - \param indent Indentation in pixels -*/ -void QwtTextLabel::setIndent( int indent ) -{ - if ( indent < 0 ) - indent = 0; - - d_data->indent = indent; - - update(); - updateGeometry(); -} - -//! Return label's text margin in pixels -int QwtTextLabel::margin() const -{ - return d_data->margin; -} - -/*! - Set label's margin in pixels - \param margin Margin in pixels -*/ -void QwtTextLabel::setMargin( int margin ) -{ - d_data->margin = margin; - - update(); - updateGeometry(); -} - -//! Return a size hint -QSize QwtTextLabel::sizeHint() const -{ - return minimumSizeHint(); -} - -//! Return a minimum size hint -QSize QwtTextLabel::minimumSizeHint() const -{ - QSizeF sz = d_data->text.textSize( font() ); - - int mw = 2 * ( frameWidth() + d_data->margin ); - int mh = mw; - - int indent = d_data->indent; - if ( indent <= 0 ) - indent = defaultIndent(); - - if ( indent > 0 ) - { - const int align = d_data->text.renderFlags(); - if ( align & Qt::AlignLeft || align & Qt::AlignRight ) - mw += d_data->indent; - else if ( align & Qt::AlignTop || align & Qt::AlignBottom ) - mh += d_data->indent; - } - - sz += QSizeF( mw, mh ); - - return QSize( qCeil( sz.width() ), qCeil( sz.height() ) ); -} - -/*! - \param width Width - \return Preferred height for this widget, given the width. -*/ -int QwtTextLabel::heightForWidth( int width ) const -{ - const int renderFlags = d_data->text.renderFlags(); - - int indent = d_data->indent; - if ( indent <= 0 ) - indent = defaultIndent(); - - width -= 2 * frameWidth(); - if ( renderFlags & Qt::AlignLeft || renderFlags & Qt::AlignRight ) - width -= indent; - - int height = qCeil( d_data->text.heightForWidth( width, font() ) ); - if ( ( renderFlags & Qt::AlignTop ) || ( renderFlags & Qt::AlignBottom ) ) - height += indent; - - height += 2 * frameWidth(); - - return height; -} - -/*! - Qt paint event - \param event Paint event -*/ -void QwtTextLabel::paintEvent( QPaintEvent *event ) -{ - QPainter painter( this ); - - if ( !contentsRect().contains( event->rect() ) ) - { - painter.save(); - painter.setClipRegion( event->region() & frameRect() ); - drawFrame( &painter ); - painter.restore(); - } - - painter.setClipRegion( event->region() & contentsRect() ); - - drawContents( &painter ); -} - -//! Redraw the text and focus indicator -void QwtTextLabel::drawContents( QPainter *painter ) -{ - const QRect r = textRect(); - if ( r.isEmpty() ) - return; - - painter->setFont( font() ); - painter->setPen( palette().color( QPalette::Active, QPalette::Text ) ); - - drawText( painter, QRectF( r ) ); - - if ( hasFocus() ) - { - const int m = 2; - - QRect focusRect = contentsRect().adjusted( m, m, -m + 1, -m + 1); - - QwtPainter::drawFocusRect( painter, this, focusRect ); - } -} - -//! Redraw the text -void QwtTextLabel::drawText( QPainter *painter, const QRectF &textRect ) -{ - d_data->text.draw( painter, textRect ); -} - -/*! - Calculate geometry for the text in widget coordinates - \return Geometry for the text -*/ -QRect QwtTextLabel::textRect() const -{ - QRect r = contentsRect(); - - if ( !r.isEmpty() && d_data->margin > 0 ) - { - r.setRect( r.x() + d_data->margin, r.y() + d_data->margin, - r.width() - 2 * d_data->margin, r.height() - 2 * d_data->margin ); - } - - if ( !r.isEmpty() ) - { - int indent = d_data->indent; - if ( indent <= 0 ) - indent = defaultIndent(); - - if ( indent > 0 ) - { - const int renderFlags = d_data->text.renderFlags(); - - if ( renderFlags & Qt::AlignLeft ) - r.setX( r.x() + indent ); - else if ( renderFlags & Qt::AlignRight ) - r.setWidth( r.width() - indent ); - else if ( renderFlags & Qt::AlignTop ) - r.setY( r.y() + indent ); - else if ( renderFlags & Qt::AlignBottom ) - r.setHeight( r.height() - indent ); - } - } - - return r; -} - -int QwtTextLabel::defaultIndent() const -{ - if ( frameWidth() <= 0 ) - return 0; - - QFont fnt; - if ( d_data->text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) - fnt = d_data->text.font(); - else - fnt = font(); - - return QFontMetrics( fnt ).width( 'x' ) / 2; -} - diff --git a/source/third_party/qwt/qwt_thermo.cpp b/source/third_party/qwt/qwt_thermo.cpp deleted file mode 100644 index 71eb188fa8136b700a4b60fb086be271824c69e8..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_thermo.cpp +++ /dev/null @@ -1,1005 +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/qwt_thermo.h" -#include "qwt/qwt_scale_engine.h" -#include "qwt/qwt_scale_draw.h" -#include "qwt/qwt_scale_map.h" -#include "qwt/qwt_color_map.h" -#include <qpainter.h> -#include <qevent.h> -#include <qdrawutil.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qmath.h> - -static inline void qwtDrawLine( QPainter *painter, int pos, - const QColor &color, const QRect &pipeRect, const QRect &liquidRect, - Qt::Orientation orientation ) -{ - painter->setPen( color ); - if ( orientation == Qt::Horizontal ) - { - if ( pos >= liquidRect.left() && pos < liquidRect.right() ) - painter->drawLine( pos, pipeRect.top(), pos, pipeRect.bottom() ); - } - else - { - if ( pos >= liquidRect.top() && pos < liquidRect.bottom() ) - painter->drawLine( pipeRect.left(), pos, pipeRect.right(), pos ); - } -} - -QVector<double> qwtTickList( const QwtScaleDiv &scaleDiv ) -{ - QVector<double> values; - - double lowerLimit = scaleDiv.interval().minValue(); - double upperLimit = scaleDiv.interval().maxValue(); - - if ( upperLimit < lowerLimit ) - qSwap( lowerLimit, upperLimit ); - - values += lowerLimit; - - for ( int tickType = QwtScaleDiv::MinorTick; - tickType < QwtScaleDiv::NTickTypes; tickType++ ) - { - const QList<double> ticks = scaleDiv.ticks( tickType ); - - for ( int i = 0; i < ticks.count(); i++ ) - { - const double v = ticks[i]; - if ( v > lowerLimit && v < upperLimit ) - values += v; - } - } - - values += upperLimit; - - return values; -} - -class QwtThermo::PrivateData -{ -public: - PrivateData(): - orientation( Qt::Vertical ), - scalePosition( QwtThermo::TrailingScale ), - spacing( 3 ), - borderWidth( 2 ), - pipeWidth( 10 ), - alarmLevel( 0.0 ), - alarmEnabled( false ), - autoFillPipe( true ), - originMode( QwtThermo::OriginMinimum ), - origin( 0.0 ), - colorMap( NULL ), - value( 0.0 ) - { - rangeFlags = QwtInterval::IncludeBorders; - } - - ~PrivateData() - { - delete colorMap; - } - - Qt::Orientation orientation; - QwtThermo::ScalePosition scalePosition; - - int spacing; - int borderWidth; - int pipeWidth; - - QwtInterval::BorderFlags rangeFlags; - double alarmLevel; - bool alarmEnabled; - bool autoFillPipe; - QwtThermo::OriginMode originMode; - double origin; - - QwtColorMap *colorMap; - - double value; -}; - -/*! - Constructor - \param parent Parent widget -*/ -QwtThermo::QwtThermo( QWidget *parent ): - QwtAbstractScale( parent ) -{ - d_data = new PrivateData; - - QSizePolicy policy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ); - if ( d_data->orientation == Qt::Vertical ) - policy.transpose(); - - setSizePolicy( policy ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); - layoutThermo( true ); -} - -//! Destructor -QwtThermo::~QwtThermo() -{ - delete d_data; -} - -/*! - \brief Exclude/Include min/max values - - According to the flags minValue() and maxValue() - are included/excluded from the pipe. In case of an - excluded value the corresponding tick is painted - 1 pixel off of the pipeRect(). - - F.e. when a minimum - of 0.0 has to be displayed as an empty pipe the minValue() - needs to be excluded. - - \param flags Range flags - \sa rangeFlags() -*/ -void QwtThermo::setRangeFlags( QwtInterval::BorderFlags flags ) -{ - if ( d_data->rangeFlags != flags ) - { - d_data->rangeFlags = flags; - update(); - } -} - -/*! - \return Range flags - \sa setRangeFlags() -*/ -QwtInterval::BorderFlags QwtThermo::rangeFlags() const -{ - return d_data->rangeFlags; -} - -/*! - Set the current value. - - \param value New Value - \sa value() -*/ -void QwtThermo::setValue( double value ) -{ - if ( d_data->value != value ) - { - d_data->value = value; - update(); - } -} - -//! Return the value. -double QwtThermo::value() const -{ - return d_data->value; -} - -/*! - \brief Set a scale draw - - For changing the labels of the scales, it - is necessary to derive from QwtScaleDraw and - overload QwtScaleDraw::label(). - - \param scaleDraw ScaleDraw object, that has to be created with - new and will be deleted in ~QwtThermo() or the next - call of setScaleDraw(). -*/ -void QwtThermo::setScaleDraw( QwtScaleDraw *scaleDraw ) -{ - setAbstractScaleDraw( scaleDraw ); - layoutThermo( true ); -} - -/*! - \return the scale draw of the thermo - \sa setScaleDraw() -*/ -const QwtScaleDraw *QwtThermo::scaleDraw() const -{ - return static_cast<const QwtScaleDraw *>( abstractScaleDraw() ); -} - -/*! - \return the scale draw of the thermo - \sa setScaleDraw() -*/ -QwtScaleDraw *QwtThermo::scaleDraw() -{ - return static_cast<QwtScaleDraw *>( abstractScaleDraw() ); -} - -/*! - Paint event handler - \param event Paint event -*/ -void QwtThermo::paintEvent( QPaintEvent *event ) -{ - QPainter painter( this ); - painter.setClipRegion( event->region() ); - - QStyleOption opt; - opt.init(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); - - const QRect tRect = pipeRect(); - - if ( !tRect.contains( event->rect() ) ) - { - if ( d_data->scalePosition != QwtThermo::NoScale ) - scaleDraw()->draw( &painter, palette() ); - } - - const int bw = d_data->borderWidth; - - const QBrush brush = palette().brush( QPalette::Base ); - qDrawShadePanel( &painter, - tRect.adjusted( -bw, -bw, bw, bw ), - palette(), true, bw, - d_data->autoFillPipe ? &brush : NULL ); - - drawLiquid( &painter, tRect ); -} - -/*! - Resize event handler - \param event Resize event -*/ -void QwtThermo::resizeEvent( QResizeEvent *event ) -{ - Q_UNUSED( event ); - layoutThermo( false ); -} - -/*! - Qt change event handler - \param event Event -*/ -void QwtThermo::changeEvent( QEvent *event ) -{ - switch( event->type() ) - { - case QEvent::StyleChange: - case QEvent::FontChange: - { - layoutThermo( true ); - break; - } - default: - break; - } -} - -/*! - Recalculate the QwtThermo geometry and layout based on - pipeRect() and the fonts. - - \param update_geometry notify the layout system and call update - to redraw the scale -*/ -void QwtThermo::layoutThermo( bool update_geometry ) -{ - const QRect tRect = pipeRect(); - const int bw = d_data->borderWidth + d_data->spacing; - const bool inverted = ( upperBound() < lowerBound() ); - - int from, to; - - if ( d_data->orientation == Qt::Horizontal ) - { - from = tRect.left(); - to = tRect.right(); - - if ( d_data->rangeFlags & QwtInterval::ExcludeMinimum ) - { - if ( inverted ) - to++; - else - from--; - } - if ( d_data->rangeFlags & QwtInterval::ExcludeMaximum ) - { - if ( inverted ) - from--; - else - to++; - } - - if ( d_data->scalePosition == QwtThermo::TrailingScale ) - { - scaleDraw()->setAlignment( QwtScaleDraw::TopScale ); - scaleDraw()->move( from, tRect.top() - bw ); - } - else - { - scaleDraw()->setAlignment( QwtScaleDraw::BottomScale ); - scaleDraw()->move( from, tRect.bottom() + bw ); - } - - scaleDraw()->setLength( qMax( to - from, 0 ) ); - } - else // Qt::Vertical - { - from = tRect.top(); - to = tRect.bottom(); - - if ( d_data->rangeFlags & QwtInterval::ExcludeMinimum ) - { - if ( inverted ) - from--; - else - to++; - } - if ( d_data->rangeFlags & QwtInterval::ExcludeMaximum ) - { - if ( inverted ) - to++; - else - from--; - } - - if ( d_data->scalePosition == QwtThermo::LeadingScale ) - { - scaleDraw()->setAlignment( QwtScaleDraw::RightScale ); - scaleDraw()->move( tRect.right() + bw, from ); - } - else - { - scaleDraw()->setAlignment( QwtScaleDraw::LeftScale ); - scaleDraw()->move( tRect.left() - bw, from ); - } - - scaleDraw()->setLength( qMax( to - from, 0 ) ); - } - - if ( update_geometry ) - { - updateGeometry(); - update(); - } -} - -/*! - \return Bounding rectangle of the pipe ( without borders ) - in widget coordinates -*/ -QRect QwtThermo::pipeRect() const -{ - int mbd = 0; - if ( d_data->scalePosition != QwtThermo::NoScale ) - { - int d1, d2; - scaleDraw()->getBorderDistHint( font(), d1, d2 ); - mbd = qMax( d1, d2 ); - } - const int bw = d_data->borderWidth; - const int scaleOff = bw + mbd; - - const QRect cr = contentsRect(); - - QRect pipeRect = cr; - if ( d_data->orientation == Qt::Horizontal ) - { - pipeRect.adjust( scaleOff, 0, -scaleOff, 0 ); - - if ( d_data->scalePosition == QwtThermo::TrailingScale ) - pipeRect.setTop( cr.top() + cr.height() - bw - d_data->pipeWidth ); - else - pipeRect.setTop( bw ); - - pipeRect.setHeight( d_data->pipeWidth ); - } - else // Qt::Vertical - { - pipeRect.adjust( 0, scaleOff, 0, -scaleOff ); - - if ( d_data->scalePosition == QwtThermo::LeadingScale ) - pipeRect.setLeft( bw ); - else - pipeRect.setLeft( cr.left() + cr.width() - bw - d_data->pipeWidth ); - - pipeRect.setWidth( d_data->pipeWidth ); - } - - return pipeRect; -} - -/*! - \brief Set the orientation. - \param orientation Allowed values are Qt::Horizontal and Qt::Vertical. - - \sa orientation(), scalePosition() -*/ -void QwtThermo::setOrientation( Qt::Orientation orientation ) -{ - if ( orientation == d_data->orientation ) - return; - - d_data->orientation = orientation; - - if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) ) - { - QSizePolicy sp = sizePolicy(); - sp.transpose(); - setSizePolicy( sp ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); - } - - layoutThermo( true ); -} - -/*! - \return Orientation - \sa setOrientation() -*/ -Qt::Orientation QwtThermo::orientation() const -{ - return d_data->orientation; -} - -/*! - \brief Change how the origin is determined. - \sa originMode(), serOrigin(), origin() - */ -void QwtThermo::setOriginMode( OriginMode m ) -{ - if ( m == d_data->originMode ) - return; - - d_data->originMode = m; - update(); -} - -/*! - \return Mode, how the origin is determined. - \sa setOriginMode(), serOrigin(), origin() - */ -QwtThermo::OriginMode QwtThermo::originMode() const -{ - return d_data->originMode; -} - -/*! - \brief Specifies the custom origin. - - If originMode is set to OriginCustom this property controls where the - liquid starts. - - \param origin New origin level - \sa setOriginMode(), originMode(), origin() - */ -void QwtThermo::setOrigin( double origin ) -{ - if ( origin == d_data->origin ) - return; - - d_data->origin = origin; - update(); -} - -/*! - \return Origin of the thermo, when OriginCustom is enabled - \sa setOrigin(), setOriginMode(), originMode() - */ -double QwtThermo::origin() const -{ - return d_data->origin; -} - -/*! - \brief Change the position of the scale - \param scalePosition Position of the scale. - - \sa ScalePosition, scalePosition() -*/ -void QwtThermo::setScalePosition( ScalePosition scalePosition ) -{ - if ( d_data->scalePosition == scalePosition ) - return; - - d_data->scalePosition = scalePosition; - - if ( testAttribute( Qt::WA_WState_Polished ) ) - layoutThermo( true ); -} - -/*! - \return Scale position. - \sa setScalePosition() -*/ -QwtThermo::ScalePosition QwtThermo::scalePosition() const -{ - return d_data->scalePosition; -} - -//! Notify a scale change. -void QwtThermo::scaleChange() -{ - layoutThermo( true ); -} - -/*! - Redraw the liquid in thermometer pipe. - \param painter Painter - \param pipeRect Bounding rectangle of the pipe without borders -*/ -void QwtThermo::drawLiquid( - QPainter *painter, const QRect &pipeRect ) const -{ - painter->save(); - painter->setClipRect( pipeRect, Qt::IntersectClip ); - painter->setPen( Qt::NoPen ); - - const QwtScaleMap scaleMap = scaleDraw()->scaleMap(); - - QRect liquidRect = fillRect( pipeRect ); - - if ( d_data->colorMap != NULL ) - { - const QwtInterval interval = scaleDiv().interval().normalized(); - - // Because the positions of the ticks are rounded - // we calculate the colors for the rounded tick values - - QVector<double> values = qwtTickList( scaleDraw()->scaleDiv() ); - - if ( scaleMap.isInverting() ) - qSort( values.begin(), values.end(), qGreater<double>() ); - else - qSort( values.begin(), values.end(), qLess<double>() ); - - int from; - if ( !values.isEmpty() ) - { - from = qRound( scaleMap.transform( values[0] ) ); - qwtDrawLine( painter, from, - d_data->colorMap->color( interval, values[0] ), - pipeRect, liquidRect, d_data->orientation ); - } - - for ( int i = 1; i < values.size(); i++ ) - { - const int to = qRound( scaleMap.transform( values[i] ) ); - - for ( int pos = from + 1; pos < to; pos++ ) - { - const double v = scaleMap.invTransform( pos ); - - qwtDrawLine( painter, pos, - d_data->colorMap->color( interval, v ), - pipeRect, liquidRect, d_data->orientation ); - } - - qwtDrawLine( painter, to, - d_data->colorMap->color( interval, values[i] ), - pipeRect, liquidRect, d_data->orientation ); - - from = to; - } - } - else - { - if ( !liquidRect.isEmpty() && d_data->alarmEnabled ) - { - const QRect r = alarmRect( liquidRect ); - if ( !r.isEmpty() ) - { - painter->fillRect( r, palette().brush( QPalette::Highlight ) ); - liquidRect = QRegion( liquidRect ).subtracted( r ).boundingRect(); - } - } - - painter->fillRect( liquidRect, palette().brush( QPalette::ButtonText ) ); - } - - painter->restore(); -} - -/*! - \brief Change the spacing between pipe and scale - - A spacing of 0 means, that the backbone of the scale is below - the pipe. - - The default setting is 3 pixels. - - \param spacing Number of pixels - \sa spacing(); -*/ -void QwtThermo::setSpacing( int spacing ) -{ - if ( spacing <= 0 ) - spacing = 0; - - if ( spacing != d_data->spacing ) - { - d_data->spacing = spacing; - layoutThermo( true ); - } -} - -/*! - \return Number of pixels between pipe and scale - \sa setSpacing() -*/ -int QwtThermo::spacing() const -{ - return d_data->spacing; -} - -/*! - Set the border width of the pipe. - \param width Border width - \sa borderWidth() -*/ -void QwtThermo::setBorderWidth( int width ) -{ - if ( width <= 0 ) - width = 0; - - if ( width != d_data->borderWidth ) - { - d_data->borderWidth = width; - layoutThermo( true ); - } -} - -/*! - \return Border width of the thermometer pipe. - \sa setBorderWidth() -*/ -int QwtThermo::borderWidth() const -{ - return d_data->borderWidth; -} - -/*! - \brief Assign a color map for the fill color - - \param colorMap Color map - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -void QwtThermo::setColorMap( QwtColorMap *colorMap ) -{ - if ( colorMap != d_data->colorMap ) - { - delete d_data->colorMap; - d_data->colorMap = colorMap; - } -} - -/*! - \return Color map for the fill color - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -QwtColorMap *QwtThermo::colorMap() -{ - return d_data->colorMap; -} - -/*! - \return Color map for the fill color - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -const QwtColorMap *QwtThermo::colorMap() const -{ - return d_data->colorMap; -} - -/*! - \brief Change the brush of the liquid. - - Changes the QPalette::ButtonText brush of the palette. - - \param brush New brush. - \sa fillBrush(), QWidget::setPalette() -*/ -void QwtThermo::setFillBrush( const QBrush& brush ) -{ - QPalette pal = palette(); - pal.setBrush( QPalette::ButtonText, brush ); - setPalette( pal ); -} - -/*! - \return Liquid ( QPalette::ButtonText ) brush. - \sa setFillBrush(), QWidget::palette() -*/ -QBrush QwtThermo::fillBrush() const -{ - return palette().brush( QPalette::ButtonText ); -} - -/*! - \brief Specify the liquid brush above the alarm threshold - - Changes the QPalette::Highlight brush of the palette. - - \param brush New brush. - \sa alarmBrush(), QWidget::setPalette() - - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -void QwtThermo::setAlarmBrush( const QBrush& brush ) -{ - QPalette pal = palette(); - pal.setBrush( QPalette::Highlight, brush ); - setPalette( pal ); -} - -/*! - \return Liquid brush ( QPalette::Highlight ) above the alarm threshold. - \sa setAlarmBrush(), QWidget::palette() - - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -QBrush QwtThermo::alarmBrush() const -{ - return palette().brush( QPalette::Highlight ); -} - -/*! - Specify the alarm threshold. - - \param level Alarm threshold - \sa alarmLevel() - - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -void QwtThermo::setAlarmLevel( double level ) -{ - d_data->alarmLevel = level; - d_data->alarmEnabled = 1; - update(); -} - -/*! - \return Alarm threshold. - \sa setAlarmLevel() - - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -double QwtThermo::alarmLevel() const -{ - return d_data->alarmLevel; -} - -/*! - Change the width of the pipe. - - \param width Width of the pipe - \sa pipeWidth() -*/ -void QwtThermo::setPipeWidth( int width ) -{ - if ( width > 0 ) - { - d_data->pipeWidth = width; - layoutThermo( true ); - } -} - -/*! - \return Width of the pipe. - \sa setPipeWidth() -*/ -int QwtThermo::pipeWidth() const -{ - return d_data->pipeWidth; -} - -/*! - \brief Enable or disable the alarm threshold - \param on true (disabled) or false (enabled) - - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -void QwtThermo::setAlarmEnabled( bool on ) -{ - d_data->alarmEnabled = on; - update(); -} - -/*! - \return True, when the alarm threshold is enabled. - - \warning The alarm threshold has no effect, when - a color map has been assigned -*/ -bool QwtThermo::alarmEnabled() const -{ - return d_data->alarmEnabled; -} - -/*! - \return the minimum size hint - \sa minimumSizeHint() -*/ -QSize QwtThermo::sizeHint() const -{ - return minimumSizeHint(); -} - -/*! - \return Minimum size hint - \warning The return value depends on the font and the scale. - \sa sizeHint() -*/ -QSize QwtThermo::minimumSizeHint() const -{ - int w = 0, h = 0; - - if ( d_data->scalePosition != NoScale ) - { - const int sdExtent = qCeil( scaleDraw()->extent( font() ) ); - const int sdLength = scaleDraw()->minLength( font() ); - - w = sdLength; - h = d_data->pipeWidth + sdExtent + d_data->spacing; - - } - else // no scale - { - w = 200; - h = d_data->pipeWidth; - } - - if ( d_data->orientation == Qt::Vertical ) - qSwap( w, h ); - - w += 2 * d_data->borderWidth; - h += 2 * d_data->borderWidth; - - // finally add the margins - int left, right, top, bottom; - getContentsMargins( &left, &top, &right, &bottom ); - w += left + right; - h += top + bottom; - - return QSize( w, h ); -} - -/*! - \brief Calculate the filled rectangle of the pipe - - \param pipeRect Rectangle of the pipe - \return Rectangle to be filled ( fill and alarm brush ) - - \sa pipeRect(), alarmRect() - */ -QRect QwtThermo::fillRect( const QRect &pipeRect ) const -{ - double origin; - if ( d_data->originMode == OriginMinimum ) - { - origin = qMin( lowerBound(), upperBound() ); - } - else if ( d_data->originMode == OriginMaximum ) - { - origin = qMax( lowerBound(), upperBound() ); - } - else // OriginCustom - { - origin = d_data->origin; - } - - const QwtScaleMap scaleMap = scaleDraw()->scaleMap(); - - int from = qRound( scaleMap.transform( d_data->value ) ); - int to = qRound( scaleMap.transform( origin ) ); - - if ( to < from ) - qSwap( from, to ); - - QRect fillRect = pipeRect; - if ( d_data->orientation == Qt::Horizontal ) - { - fillRect.setLeft( from ); - fillRect.setRight( to ); - } - else // Qt::Vertical - { - fillRect.setTop( from ); - fillRect.setBottom( to ); - } - - return fillRect.normalized(); -} - -/*! - \brief Calculate the alarm rectangle of the pipe - - \param fillRect Filled rectangle in the pipe - \return Rectangle to be filled with the alarm brush - - \sa pipeRect(), fillRect(), alarmLevel(), alarmBrush() - */ -QRect QwtThermo::alarmRect( const QRect &fillRect ) const -{ - QRect alarmRect( 0, 0, -1, -1); // something invalid - - if ( !d_data->alarmEnabled ) - return alarmRect; - - const bool inverted = ( upperBound() < lowerBound() ); - - bool increasing; - if ( d_data->originMode == OriginCustom ) - { - increasing = d_data->value > d_data->origin; - } - else - { - increasing = d_data->originMode == OriginMinimum; - } - - const QwtScaleMap map = scaleDraw()->scaleMap(); - const int alarmPos = qRound( map.transform( d_data->alarmLevel ) ); - const int valuePos = qRound( map.transform( d_data->value ) ); - - if ( d_data->orientation == Qt::Horizontal ) - { - int v1, v2; - if ( inverted ) - { - v1 = fillRect.left(); - - v2 = alarmPos - 1; - v2 = qMin( v2, increasing ? fillRect.right() : valuePos ); - } - else - { - v1 = alarmPos + 1; - v1 = qMax( v1, increasing ? fillRect.left() : valuePos ); - - v2 = fillRect.right(); - - } - alarmRect.setRect( v1, fillRect.top(), v2 - v1 + 1, fillRect.height() ); - } - else - { - int v1, v2; - if ( inverted ) - { - v1 = alarmPos + 1; - v1 = qMax( v1, increasing ? fillRect.top() : valuePos ); - - v2 = fillRect.bottom(); - } - else - { - v1 = fillRect.top(); - - v2 = alarmPos - 1; - v2 = qMin( v2, increasing ? fillRect.bottom() : valuePos ); - } - alarmRect.setRect( fillRect.left(), v1, fillRect.width(), v2 - v1 + 1 ); - } - - return alarmRect; -} diff --git a/source/third_party/qwt/qwt_transform.cpp b/source/third_party/qwt/qwt_transform.cpp deleted file mode 100644 index 9395854474179e0d7d351f64071894312abfb234..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_transform.cpp +++ /dev/null @@ -1,177 +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/qwt_transform.h" -#include "qwt/qwt_math.h" - -#if QT_VERSION < 0x040601 -#define qExp(x) ::exp(x) -#endif - -#if QT_VERSION >= 0x050400 - -//! Smallest allowed value for logarithmic scales: 1.0e-150 -const double QwtLogTransform::LogMin = 1.0e-150; - -//! Largest allowed value for logarithmic scales: 1.0e150 -const double QwtLogTransform::LogMax = 1.0e150; - -#else - -//! Smallest allowed value for logarithmic scales: 1.0e-150 -QT_STATIC_CONST_IMPL double QwtLogTransform::LogMin = 1.0e-150; - -//! Largest allowed value for logarithmic scales: 1.0e150 -QT_STATIC_CONST_IMPL double QwtLogTransform::LogMax = 1.0e150; - -#endif - -//! Constructor -QwtTransform::QwtTransform() -{ -} - -//! Destructor -QwtTransform::~QwtTransform() -{ -} - -/*! - \param value Value to be bounded - \return value unmodified - */ -double QwtTransform::bounded( double value ) const -{ - return value; -} - -//! Constructor -QwtNullTransform::QwtNullTransform(): - QwtTransform() -{ -} - -//! Destructor -QwtNullTransform::~QwtNullTransform() -{ -} - -/*! - \param value Value to be transformed - \return value unmodified - */ -double QwtNullTransform::transform( double value ) const -{ - return value; -} - -/*! - \param value Value to be transformed - \return value unmodified - */ -double QwtNullTransform::invTransform( double value ) const -{ - return value; -} - -//! \return Clone of the transformation -QwtTransform *QwtNullTransform::copy() const -{ - return new QwtNullTransform(); -} - -//! Constructor -QwtLogTransform::QwtLogTransform(): - QwtTransform() -{ -} - -//! Destructor -QwtLogTransform::~QwtLogTransform() -{ -} - -/*! - \param value Value to be transformed - \return log( value ) - */ -double QwtLogTransform::transform( double value ) const -{ - return ::log( value ); -} - -/*! - \param value Value to be transformed - \return exp( value ) - */ -double QwtLogTransform::invTransform( double value ) const -{ - return qExp( value ); -} - -/*! - \param value Value to be bounded - \return qBound( LogMin, value, LogMax ) - */ -double QwtLogTransform::bounded( double value ) const -{ - return qBound( LogMin, value, LogMax ); -} - -//! \return Clone of the transformation -QwtTransform *QwtLogTransform::copy() const -{ - return new QwtLogTransform(); -} - -/*! - Constructor - \param exponent Exponent -*/ -QwtPowerTransform::QwtPowerTransform( double exponent ): - QwtTransform(), - d_exponent( exponent ) -{ -} - -//! Destructor -QwtPowerTransform::~QwtPowerTransform() -{ -} - -/*! - \param value Value to be transformed - \return Exponentiation preserving the sign - */ -double QwtPowerTransform::transform( double value ) const -{ - if ( value < 0.0 ) - return -qPow( -value, 1.0 / d_exponent ); - else - return qPow( value, 1.0 / d_exponent ); - -} - -/*! - \param value Value to be transformed - \return Inverse exponentiation preserving the sign - */ -double QwtPowerTransform::invTransform( double value ) const -{ - if ( value < 0.0 ) - return -qPow( -value, d_exponent ); - else - return qPow( value, d_exponent ); -} - -//! \return Clone of the transformation -QwtTransform *QwtPowerTransform::copy() const -{ - return new QwtPowerTransform( d_exponent ); -} diff --git a/source/third_party/qwt/qwt_wheel.cpp b/source/third_party/qwt/qwt_wheel.cpp deleted file mode 100644 index e3ea3fc6483550b379fdbebd406ab4775e72fba0..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_wheel.cpp +++ /dev/null @@ -1,1299 +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/qwt_wheel.h" -#include "qwt/qwt_math.h" -#include "qwt/qwt_painter.h" -#include <qevent.h> -#include <qdrawutil.h> -#include <qpainter.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qapplication.h> -#include <qdatetime.h> - -#if QT_VERSION < 0x040601 -#define qFabs(x) ::fabs(x) -#define qFastSin(x) ::sin(x) -#define qExp(x) ::exp(x) -#endif - -class QwtWheel::PrivateData -{ -public: - PrivateData(): - orientation( Qt::Horizontal ), - viewAngle( 175.0 ), - totalAngle( 360.0 ), - tickCount( 10 ), - wheelBorderWidth( 2 ), - borderWidth( 2 ), - wheelWidth( 20 ), - isScrolling( false ), - mouseOffset( 0.0 ), - tracking( true ), - pendingValueChanged( false ), - updateInterval( 50 ), - mass( 0.0 ), - timerId( 0 ), - speed( 0.0 ), - mouseValue( 0.0 ), - flyingValue( 0.0 ), - minimum( 0.0 ), - maximum( 100.0 ), - singleStep( 1.0 ), - pageStepCount( 1 ), - stepAlignment( true ), - value( 0.0 ), - inverted( false ), - wrapping( false ) - { - }; - - Qt::Orientation orientation; - double viewAngle; - double totalAngle; - int tickCount; - int wheelBorderWidth; - int borderWidth; - int wheelWidth; - - bool isScrolling; - double mouseOffset; - - bool tracking; - bool pendingValueChanged; // when not tracking - - int updateInterval; - double mass; - - // for the flying wheel effect - int timerId; - QTime time; - double speed; - double mouseValue; - double flyingValue; - - double minimum; - double maximum; - - double singleStep; - int pageStepCount; - bool stepAlignment; - - double value; - - bool inverted; - bool wrapping; -}; - -//! Constructor -QwtWheel::QwtWheel( QWidget *parent ): - QWidget( parent ) -{ - d_data = new PrivateData; - - setFocusPolicy( Qt::StrongFocus ); - setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ); - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); -} - -//! Destructor -QwtWheel::~QwtWheel() -{ - delete d_data; -} - -/*! - \brief En/Disable tracking - - If tracking is enabled (the default), the wheel emits the valueChanged() - signal while the wheel is moving. If tracking is disabled, the wheel - emits the valueChanged() signal only when the wheel movement is terminated. - - The wheelMoved() signal is emitted regardless id tracking is enabled or not. - - \param enable On/Off - \sa isTracking() - */ -void QwtWheel::setTracking( bool enable ) -{ - d_data->tracking = enable; -} - -/*! - \return True, when tracking is enabled - \sa setTracking(), valueChanged(), wheelMoved() -*/ -bool QwtWheel::isTracking() const -{ - return d_data->tracking; -} - -/*! - \brief Specify the update interval when the wheel is flying - - Default and minimum value is 50 ms. - - \param interval Interval in milliseconds - \sa updateInterval(), setMass(), setTracking() -*/ -void QwtWheel::setUpdateInterval( int interval ) -{ - d_data->updateInterval = qMax( interval, 50 ); -} - -/*! - \return Update interval when the wheel is flying - \sa setUpdateInterval(), mass(), isTracking() - */ -int QwtWheel::updateInterval() const -{ - return d_data->updateInterval; -} - -/*! - \brief Mouse press event handler - - Start movement of the wheel. - - \param event Mouse event -*/ -void QwtWheel::mousePressEvent( QMouseEvent *event ) -{ - stopFlying(); - - d_data->isScrolling = wheelRect().contains( event->pos() ); - - if ( d_data->isScrolling ) - { - d_data->time.start(); - d_data->speed = 0.0; - d_data->mouseValue = valueAt( event->pos() ); - d_data->mouseOffset = d_data->mouseValue - d_data->value; - d_data->pendingValueChanged = false; - - Q_EMIT wheelPressed(); - } -} - -/*! - \brief Mouse Move Event handler - - Turn the wheel according to the mouse position - - \param event Mouse event -*/ -void QwtWheel::mouseMoveEvent( QMouseEvent *event ) -{ - if ( !d_data->isScrolling ) - return; - - double mouseValue = valueAt( event->pos() ); - - if ( d_data->mass > 0.0 ) - { - double ms = d_data->time.restart(); - - // the interval when mouse move events are posted are somehow - // random. To avoid unrealistic speed values we limit ms - - ms = qMax( ms, 5.0 ); - - d_data->speed = ( mouseValue - d_data->mouseValue ) / ms; - } - - d_data->mouseValue = mouseValue; - - double value = boundedValue( mouseValue - d_data->mouseOffset ); - if ( d_data->stepAlignment ) - value = alignedValue( value ); - - if ( value != d_data->value ) - { - d_data->value = value; - - update(); - - Q_EMIT wheelMoved( d_data->value ); - - if ( d_data->tracking ) - Q_EMIT valueChanged( d_data->value ); - else - d_data->pendingValueChanged = true; - } -} - -/*! - \brief Mouse Release Event handler - - When the wheel has no mass the movement of the wheel stops, otherwise - it starts flying. - - \param event Mouse event -*/ - -void QwtWheel::mouseReleaseEvent( QMouseEvent *event ) -{ - Q_UNUSED( event ); - - if ( !d_data->isScrolling ) - return; - - d_data->isScrolling = false; - - bool startFlying = false; - - if ( d_data->mass > 0.0 ) - { - const int ms = d_data->time.elapsed(); - if ( ( qFabs( d_data->speed ) > 0.0 ) && ( ms < 50 ) ) - startFlying = true; - } - - if ( startFlying ) - { - d_data->flyingValue = - boundedValue( d_data->mouseValue - d_data->mouseOffset ); - - d_data->timerId = startTimer( d_data->updateInterval ); - } - else - { - if ( d_data->pendingValueChanged ) - Q_EMIT valueChanged( d_data->value ); - } - - d_data->pendingValueChanged = false; - d_data->mouseOffset = 0.0; - - Q_EMIT wheelReleased(); -} - -/*! - \brief Qt timer event - - The flying wheel effect is implemented using a timer - - \param event Timer event - - \sa updateInterval() - */ -void QwtWheel::timerEvent( QTimerEvent *event ) -{ - if ( event->timerId() != d_data->timerId ) - { - QWidget::timerEvent( event ); - return; - } - - d_data->speed *= qExp( -d_data->updateInterval * 0.001 / d_data->mass ); - - d_data->flyingValue += d_data->speed * d_data->updateInterval; - d_data->flyingValue = boundedValue( d_data->flyingValue ); - - double value = d_data->flyingValue; - if ( d_data->stepAlignment ) - value = alignedValue( value ); - - if ( qFabs( d_data->speed ) < 0.001 * d_data->singleStep ) - { - // stop if d_data->speed < one step per second - stopFlying(); - } - - if ( value != d_data->value ) - { - d_data->value = value; - update(); - - if ( d_data->tracking || d_data->timerId == 0 ) - Q_EMIT valueChanged( d_data->value ); - } -} - - -/*! - \brief Handle wheel events - - In/Decrement the value - - \param event Wheel event -*/ -void QwtWheel::wheelEvent( QWheelEvent *event ) -{ - if ( !wheelRect().contains( event->pos() ) ) - { - event->ignore(); - return; - } - - if ( d_data->isScrolling ) - return; - - stopFlying(); - - double increment = 0.0; - - if ( ( event->modifiers() & Qt::ControlModifier) || - ( event->modifiers() & Qt::ShiftModifier ) ) - { - // one page regardless of delta - increment = d_data->singleStep * d_data->pageStepCount; - if ( event->delta() < 0 ) - increment = -increment; - } - else - { - const int numSteps = event->delta() / 120; - increment = d_data->singleStep * numSteps; - } - - if ( d_data->orientation == Qt::Vertical && d_data->inverted ) - increment = -increment; - - double value = boundedValue( d_data->value + increment ); - - if ( d_data->stepAlignment ) - value = alignedValue( value ); - - if ( value != d_data->value ) - { - d_data->value = value; - update(); - - Q_EMIT valueChanged( d_data->value ); - Q_EMIT wheelMoved( d_data->value ); - } -} - -/*! - Handle key events - - - Qt::Key_Home\n - Step to minimum() - - - Qt::Key_End\n - Step to maximum() - - - Qt::Key_Up\n - In case of a horizontal or not inverted vertical wheel the value - will be incremented by the step size. For an inverted vertical wheel - the value will be decremented by the step size. - - - Qt::Key_Down\n - In case of a horizontal or not inverted vertical wheel the value - will be decremented by the step size. For an inverted vertical wheel - the value will be incremented by the step size. - - - Qt::Key_PageUp\n - The value will be incremented by pageStepSize() * singleStepSize(). - - - Qt::Key_PageDown\n - The value will be decremented by pageStepSize() * singleStepSize(). - - \param event Key event -*/ -void QwtWheel::keyPressEvent( QKeyEvent *event ) -{ - if ( d_data->isScrolling ) - { - // don't interfere mouse scrolling - return; - } - - double value = d_data->value; - double increment = 0.0; - - switch ( event->key() ) - { - case Qt::Key_Down: - { - if ( d_data->orientation == Qt::Vertical && d_data->inverted ) - increment = d_data->singleStep; - else - increment = -d_data->singleStep; - - break; - } - case Qt::Key_Up: - { - if ( d_data->orientation == Qt::Vertical && d_data->inverted ) - increment = -d_data->singleStep; - else - increment = d_data->singleStep; - - break; - } - case Qt::Key_Left: - { - if ( d_data->orientation == Qt::Horizontal ) - { - if ( d_data->inverted ) - increment = d_data->singleStep; - else - increment = -d_data->singleStep; - } - break; - } - case Qt::Key_Right: - { - if ( d_data->orientation == Qt::Horizontal ) - { - if ( d_data->inverted ) - increment = -d_data->singleStep; - else - increment = d_data->singleStep; - } - break; - } - case Qt::Key_PageUp: - { - increment = d_data->pageStepCount * d_data->singleStep; - break; - } - case Qt::Key_PageDown: - { - increment = -d_data->pageStepCount * d_data->singleStep; - break; - } - case Qt::Key_Home: - { - value = d_data->minimum; - break; - } - case Qt::Key_End: - { - value = d_data->maximum; - break; - } - default:; - { - event->ignore(); - } - } - - if ( event->isAccepted() ) - stopFlying(); - - if ( increment != 0.0 ) - { - value = boundedValue( d_data->value + increment ); - - if ( d_data->stepAlignment ) - value = alignedValue( value ); - } - - if ( value != d_data->value ) - { - d_data->value = value; - update(); - - Q_EMIT valueChanged( d_data->value ); - Q_EMIT wheelMoved( d_data->value ); - } -} - -/*! - \brief Adjust the number of grooves in the wheel's surface. - - The number of grooves is limited to 6 <= count <= 50. - Values outside this range will be clipped. - The default value is 10. - - \param count Number of grooves per 360 degrees - \sa tickCount() -*/ -void QwtWheel::setTickCount( int count ) -{ - count = qBound( 6, count, 50 ); - - if ( count != d_data->tickCount ) - { - d_data->tickCount = qBound( 6, count, 50 ); - update(); - } -} - -/*! - \return Number of grooves in the wheel's surface. - \sa setTickCnt() -*/ -int QwtWheel::tickCount() const -{ - return d_data->tickCount; -} - -/*! - \brief Set the wheel border width of the wheel. - - The wheel border must not be smaller than 1 - and is limited in dependence on the wheel's size. - Values outside the allowed range will be clipped. - - The wheel border defaults to 2. - - \param borderWidth Border width - \sa internalBorder() -*/ -void QwtWheel::setWheelBorderWidth( int borderWidth ) -{ - const int d = qMin( width(), height() ) / 3; - borderWidth = qMin( borderWidth, d ); - d_data->wheelBorderWidth = qMax( borderWidth, 1 ); - update(); -} - -/*! - \return Wheel border width - \sa setWheelBorderWidth() -*/ -int QwtWheel::wheelBorderWidth() const -{ - return d_data->wheelBorderWidth; -} - -/*! - \brief Set the border width - - The border defaults to 2. - - \param width Border width - \sa borderWidth() -*/ -void QwtWheel::setBorderWidth( int width ) -{ - d_data->borderWidth = qMax( width, 0 ); - update(); -} - -/*! - \return Border width - \sa setBorderWidth() -*/ -int QwtWheel::borderWidth() const -{ - return d_data->borderWidth; -} - -/*! - \return Rectangle of the wheel without the outer border -*/ -QRect QwtWheel::wheelRect() const -{ - const int bw = d_data->borderWidth; - return contentsRect().adjusted( bw, bw, -bw, -bw ); -} - -/*! - \brief Set the total angle which the wheel can be turned. - - One full turn of the wheel corresponds to an angle of - 360 degrees. A total angle of n*360 degrees means - that the wheel has to be turned n times around its axis - to get from the minimum value to the maximum value. - - The default setting of the total angle is 360 degrees. - - \param angle total angle in degrees - \sa totalAngle() -*/ -void QwtWheel::setTotalAngle( double angle ) -{ - if ( angle < 0.0 ) - angle = 0.0; - - d_data->totalAngle = angle; - update(); -} - -/*! - \return Total angle which the wheel can be turned. - \sa setTotalAngle() -*/ -double QwtWheel::totalAngle() const -{ - return d_data->totalAngle; -} - -/*! - \brief Set the wheel's orientation. - - The default orientation is Qt::Horizontal. - - \param orientation Qt::Horizontal or Qt::Vertical. - \sa orientation() -*/ -void QwtWheel::setOrientation( Qt::Orientation orientation ) -{ - if ( d_data->orientation == orientation ) - return; - - if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) ) - { - QSizePolicy sp = sizePolicy(); - sp.transpose(); - setSizePolicy( sp ); - - setAttribute( Qt::WA_WState_OwnSizePolicy, false ); - } - - d_data->orientation = orientation; - update(); -} - -/*! - \return Orientation - \sa setOrientation() -*/ -Qt::Orientation QwtWheel::orientation() const -{ - return d_data->orientation; -} - -/*! - \brief Specify the visible portion of the wheel. - - You may use this function for fine-tuning the appearance of - the wheel. The default value is 175 degrees. The value is - limited from 10 to 175 degrees. - - \param angle Visible angle in degrees - \sa viewAngle(), setTotalAngle() -*/ -void QwtWheel::setViewAngle( double angle ) -{ - d_data->viewAngle = qBound( 10.0, angle, 175.0 ); - update(); -} - -/*! - \return Visible portion of the wheel - \sa setViewAngle(), totalAngle() -*/ -double QwtWheel::viewAngle() const -{ - return d_data->viewAngle; -} - -/*! - Determine the value corresponding to a specified point - - \param pos Position - \return Value corresponding to pos -*/ -double QwtWheel::valueAt( const QPoint &pos ) const -{ - const QRectF rect = wheelRect(); - - double w, dx; - if ( d_data->orientation == Qt::Vertical ) - { - w = rect.height(); - dx = rect.top() - pos.y(); - } - else - { - w = rect.width(); - dx = pos.x() - rect.left(); - } - - if ( w == 0.0 ) - return 0.0; - - if ( d_data->inverted ) - { - dx = w - dx; - } - - // w pixels is an arc of viewAngle degrees, - // so we convert change in pixels to change in angle - const double ang = dx * d_data->viewAngle / w; - - // value range maps to totalAngle degrees, - // so convert the change in angle to a change in value - const double val = ang * ( maximum() - minimum() ) / d_data->totalAngle; - - return val; -} - -/*! - \brief Qt Paint Event - \param event Paint event -*/ -void QwtWheel::paintEvent( QPaintEvent *event ) -{ - QPainter painter( this ); - painter.setClipRegion( event->region() ); - - QStyleOption opt; - opt.init(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); - - qDrawShadePanel( &painter, - contentsRect(), palette(), true, d_data->borderWidth ); - - drawWheelBackground( &painter, wheelRect() ); - drawTicks( &painter, wheelRect() ); - - if ( hasFocus() ) - QwtPainter::drawFocusRect( &painter, this ); -} - -/*! - Draw the Wheel's background gradient - - \param painter Painter - \param rect Geometry for the wheel -*/ -void QwtWheel::drawWheelBackground( - QPainter *painter, const QRectF &rect ) -{ - painter->save(); - - QPalette pal = palette(); - - // draw shaded background - QLinearGradient gradient( rect.topLeft(), - ( d_data->orientation == Qt::Horizontal ) ? rect.topRight() : rect.bottomLeft() ); - gradient.setColorAt( 0.0, pal.color( QPalette::Button ) ); - gradient.setColorAt( 0.2, pal.color( QPalette::Midlight ) ); - gradient.setColorAt( 0.7, pal.color( QPalette::Mid ) ); - gradient.setColorAt( 1.0, pal.color( QPalette::Dark ) ); - - painter->fillRect( rect, gradient ); - - // draw internal border - - const QPen lightPen( palette().color( QPalette::Light ), - d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap ); - const QPen darkPen( pal.color( QPalette::Dark ), - d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap ); - - const double bw2 = 0.5 * d_data->wheelBorderWidth; - - if ( d_data->orientation == Qt::Horizontal ) - { - painter->setPen( lightPen ); - painter->drawLine( QPointF( rect.left(), rect.top() + bw2 ), - QPointF( rect.right(), rect.top() + bw2 ) ); - - painter->setPen( darkPen ); - painter->drawLine( QPointF( rect.left(), rect.bottom() - bw2 ), - QPointF( rect.right(), rect.bottom() - bw2 ) ); - } - else // Qt::Vertical - { - painter->setPen( lightPen ); - painter->drawLine( QPointF( rect.left() + bw2, rect.top() ), - QPointF( rect.left() + bw2, rect.bottom() ) ); - - painter->setPen( darkPen ); - painter->drawLine( QPointF( rect.right() - bw2, rect.top() ), - QPointF( rect.right() - bw2, rect.bottom() ) ); - } - - painter->restore(); -} - -/*! - Draw the Wheel's ticks - - \param painter Painter - \param rect Geometry for the wheel -*/ -void QwtWheel::drawTicks( QPainter *painter, const QRectF &rect ) -{ - const double range = d_data->maximum - d_data->minimum; - - if ( range == 0.0 || d_data->totalAngle == 0.0 ) - { - return; - } - - const QPen lightPen( palette().color( QPalette::Light ), - 0, Qt::SolidLine, Qt::FlatCap ); - const QPen darkPen( palette().color( QPalette::Dark ), - 0, Qt::SolidLine, Qt::FlatCap ); - - const double cnvFactor = qAbs( d_data->totalAngle / range ); - const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor; - const double loValue = value() - halfIntv; - const double hiValue = value() + halfIntv; - const double tickWidth = 360.0 / double( d_data->tickCount ) / cnvFactor; - const double sinArc = qFastSin( d_data->viewAngle * M_PI / 360.0 ); - - if ( d_data->orientation == Qt::Horizontal ) - { - const double radius = rect.width() * 0.5; - - double l1 = rect.top() + d_data->wheelBorderWidth; - double l2 = rect.bottom() - d_data->wheelBorderWidth - 1; - - // draw one point over the border if border > 1 - if ( d_data->wheelBorderWidth > 1 ) - { - l1--; - l2++; - } - - const double maxpos = rect.right() - 2; - const double minpos = rect.left() + 2; - - // draw tick marks - for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth; - tickValue < hiValue; tickValue += tickWidth ) - { - const double angle = qwtRadians( tickValue - value() ); - const double s = qFastSin( angle * cnvFactor ); - - const double off = radius * ( sinArc + s ) / sinArc; - - double tickPos; - if ( d_data->inverted ) - tickPos = rect.left() + off; - else - tickPos = rect.right() - off; - - if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) ) - { - painter->setPen( darkPen ); - painter->drawLine( QPointF( tickPos - 1 , l1 ), - QPointF( tickPos - 1, l2 ) ); - painter->setPen( lightPen ); - painter->drawLine( QPointF( tickPos, l1 ), - QPointF( tickPos, l2 ) ); - } - } - } - else // Qt::Vertical - { - const double radius = rect.height() * 0.5; - - double l1 = rect.left() + d_data->wheelBorderWidth; - double l2 = rect.right() - d_data->wheelBorderWidth - 1; - - if ( d_data->wheelBorderWidth > 1 ) - { - l1--; - l2++; - } - - const double maxpos = rect.bottom() - 2; - const double minpos = rect.top() + 2; - - for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth; - tickValue < hiValue; tickValue += tickWidth ) - { - const double angle = qwtRadians( tickValue - value() ); - const double s = qFastSin( angle * cnvFactor ); - - const double off = radius * ( sinArc + s ) / sinArc; - - double tickPos; - - if ( d_data->inverted ) - tickPos = rect.bottom() - off; - else - tickPos = rect.top() + off; - - if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) ) - { - painter->setPen( darkPen ); - painter->drawLine( QPointF( l1, tickPos - 1 ), - QPointF( l2, tickPos - 1 ) ); - painter->setPen( lightPen ); - painter->drawLine( QPointF( l1, tickPos ), - QPointF( l2, tickPos ) ); - } - } - } -} - -/*! - \brief Set the width of the wheel - - Corresponds to the wheel height for horizontal orientation, - and the wheel width for vertical orientation. - - \param width the wheel's width - \sa wheelWidth() -*/ -void QwtWheel::setWheelWidth( int width ) -{ - d_data->wheelWidth = width; - update(); -} - -/*! - \return Width of the wheel - \sa setWheelWidth() -*/ -int QwtWheel::wheelWidth() const -{ - return d_data->wheelWidth; -} - -/*! - \return a size hint -*/ -QSize QwtWheel::sizeHint() const -{ - const QSize hint = minimumSizeHint(); - return hint.expandedTo( QApplication::globalStrut() ); -} - -/*! - \return Minimum size hint - \warning The return value is based on the wheel width. -*/ -QSize QwtWheel::minimumSizeHint() const -{ - QSize sz( 3 * d_data->wheelWidth + 2 * d_data->borderWidth, - d_data->wheelWidth + 2 * d_data->borderWidth ); - if ( d_data->orientation != Qt::Horizontal ) - sz.transpose(); - - return sz; -} - -/*! - \brief Set the step size of the counter - - A value <= 0.0 disables stepping - - \param stepSize Single step size - \sa singleStep(), setPageStepCount() -*/ -void QwtWheel::setSingleStep( double stepSize ) -{ - d_data->singleStep = qMax( stepSize, 0.0 ); -} - -/*! - \return Single step size - \sa setSingleStep() - */ -double QwtWheel::singleStep() const -{ - return d_data->singleStep; -} - -/*! - \brief En/Disable step alignment - - When step alignment is enabled value changes initiated by - user input ( mouse, keyboard, wheel ) are aligned to - the multiples of the single step. - - \param on On/Off - \sa stepAlignment(), setSingleStep() - */ -void QwtWheel::setStepAlignment( bool on ) -{ - if ( on != d_data->stepAlignment ) - { - d_data->stepAlignment = on; - } -} - -/*! - \return True, when the step alignment is enabled - \sa setStepAlignment(), singleStep() - */ -bool QwtWheel::stepAlignment() const -{ - return d_data->stepAlignment; -} - -/*! - \brief Set the page step count - - pageStepCount is a multiplicator for the single step size - that typically corresponds to the user pressing PageUp or PageDown. - - A value of 0 disables page stepping. - - The default value is 1. - - \param count Multiplicator for the single step size - \sa pageStepCount(), setSingleStep() - */ -void QwtWheel::setPageStepCount( int count ) -{ - d_data->pageStepCount = qMax( 0, count ); -} - -/*! - \return Page step count - \sa setPageStepCount(), singleStep() - */ -int QwtWheel::pageStepCount() const -{ - return d_data->pageStepCount; -} - -/*! - \brief Set the minimum and maximum values - - The maximum is adjusted if necessary to ensure that the range remains valid. - The value might be modified to be inside of the range. - - \param min Minimum value - \param max Maximum value - - \sa minimum(), maximum() - */ -void QwtWheel::setRange( double min, double max ) -{ - max = qMax( min, max ); - - if ( d_data->minimum == min && d_data->maximum == max ) - return; - - d_data->minimum = min; - d_data->maximum = max; - - if ( d_data->value < min || d_data->value > max ) - { - d_data->value = qBound( min, d_data->value, max ); - - update(); - Q_EMIT valueChanged( d_data->value ); - } -} -/*! - Set the minimum value of the range - - \param value Minimum value - \sa setRange(), setMaximum(), minimum() - - \note The maximum is adjusted if necessary to ensure that the range remains valid. -*/ -void QwtWheel::setMinimum( double value ) -{ - setRange( value, maximum() ); -} - -/*! - \return The minimum of the range - \sa setRange(), setMinimum(), maximum() -*/ -double QwtWheel::minimum() const -{ - return d_data->minimum; -} - -/*! - Set the maximum value of the range - - \param value Maximum value - \sa setRange(), setMinimum(), maximum() -*/ -void QwtWheel::setMaximum( double value ) -{ - setRange( minimum(), value ); -} - -/*! - \return The maximum of the range - \sa setRange(), setMaximum(), minimum() -*/ -double QwtWheel::maximum() const -{ - return d_data->maximum; -} - -/*! - \brief Set a new value without adjusting to the step raster - - \param value New value - - \sa value(), valueChanged() - \warning The value is clipped when it lies outside the range. -*/ -void QwtWheel::setValue( double value ) -{ - stopFlying(); - d_data->isScrolling = false; - - value = qBound( d_data->minimum, value, d_data->maximum ); - - if ( d_data->value != value ) - { - d_data->value = value; - - update(); - Q_EMIT valueChanged( d_data->value ); - } -} - -/*! - \return Current value of the wheel - \sa setValue(), valueChanged() - */ -double QwtWheel::value() const -{ - return d_data->value; -} - -/*! - \brief En/Disable inverted appearance - - An inverted wheel increases its values in the opposite direction. - The direction of an inverted horizontal wheel will be from right to left - an inverted vertical wheel will increase from bottom to top. - - \param on En/Disable inverted appearance - \sa isInverted() - - */ -void QwtWheel::setInverted( bool on ) -{ - if ( d_data->inverted != on ) - { - d_data->inverted = on; - update(); - } -} - -/*! - \return True, when the wheel is inverted - \sa setInverted() - */ -bool QwtWheel::isInverted() const -{ - return d_data->inverted; -} - -/*! - \brief En/Disable wrapping - - If wrapping is true stepping up from maximum() value will take - you to the minimum() value and vice versa. - - \param on En/Disable wrapping - \sa wrapping() - */ -void QwtWheel::setWrapping( bool on ) -{ - d_data->wrapping = on; -} - -/*! - \return True, when wrapping is set - \sa setWrapping() - */ -bool QwtWheel::wrapping() const -{ - return d_data->wrapping; -} - -/*! - \brief Set the slider's mass for flywheel effect. - - If the slider's mass is greater then 0, it will continue - to move after the mouse button has been released. Its speed - decreases with time at a rate depending on the slider's mass. - A large mass means that it will continue to move for a - long time. - - Derived widgets may overload this function to make it public. - - \param mass New mass in kg - - \bug If the mass is smaller than 1g, it is set to zero. - The maximal mass is limited to 100kg. - \sa mass() -*/ -void QwtWheel::setMass( double mass ) -{ - if ( mass < 0.001 ) - { - d_data->mass = 0.0; - } - else - { - d_data->mass = qMin( 100.0, mass ); - } - - if ( d_data->mass <= 0.0 ) - stopFlying(); -} - -/*! - \return mass - \sa setMass() -*/ -double QwtWheel::mass() const -{ - return d_data->mass; -} - -//! Stop the flying movement of the wheel -void QwtWheel::stopFlying() -{ - if ( d_data->timerId != 0 ) - { - killTimer( d_data->timerId ); - d_data->timerId = 0; - d_data->speed = 0.0; - } -} - -double QwtWheel::boundedValue( double value ) const -{ - const double range = d_data->maximum - d_data->minimum; - - if ( d_data->wrapping && range >= 0.0 ) - { - if ( value < d_data->minimum ) - { - value += ::ceil( ( d_data->minimum - value ) / range ) * range; - } - else if ( value > d_data->maximum ) - { - value -= ::ceil( ( value - d_data->maximum ) / range ) * range; - } - } - else - { - value = qBound( d_data->minimum, value, d_data->maximum ); - } - - return value; -} - -double QwtWheel::alignedValue( double value ) const -{ - const double stepSize = d_data->singleStep; - - if ( stepSize > 0.0 ) - { - value = d_data->minimum + - qRound( ( value - d_data->minimum ) / stepSize ) * stepSize; - - if ( stepSize > 1e-12 ) - { - if ( qFuzzyCompare( value + 1.0, 1.0 ) ) - { - // correct rounding error if value = 0 - value = 0.0; - } - else if ( qFuzzyCompare( value, d_data->maximum ) ) - { - // correct rounding error at the border - value = d_data->maximum; - } - } - } - - return value; -} - diff --git a/source/third_party/qwt/qwt_widget_overlay.cpp b/source/third_party/qwt/qwt_widget_overlay.cpp deleted file mode 100644 index 18de451733fef2d9d8dbd98440a59cfff62a0cd0..0000000000000000000000000000000000000000 --- a/source/third_party/qwt/qwt_widget_overlay.cpp +++ /dev/null @@ -1,376 +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/qwt_widget_overlay.h" -#include "qwt/qwt_painter.h" -#include <qpainter.h> -#include <qpaintengine.h> -#include <qimage.h> -#include <qevent.h> - -static QImage::Format qwtMaskImageFormat() -{ - if ( QwtPainter::isX11GraphicsSystem() ) - return QImage::Format_ARGB32; - - return QImage::Format_ARGB32_Premultiplied; -} - -static QRegion qwtAlphaMask( - const QImage& image, const QVector<QRect> rects ) -{ - const int w = image.width(); - const int h = image.height(); - - QRegion region; - QRect rect; - - for ( int i = 0; i < rects.size(); i++ ) - { - int x1, x2, y1, y2; - rects[i].getCoords( &x1, &y1, &x2, &y2 ); - - x1 = qMax( x1, 0 ); - x2 = qMin( x2, w - 1 ); - y1 = qMax( y1, 0 ); - y2 = qMin( y2, h - 1 ); - - for ( int y = y1; y <= y2; ++y ) - { - bool inRect = false; - int rx0 = -1; - - const uint *line = - reinterpret_cast<const uint *> ( image.scanLine( y ) ) + x1; - for ( int x = x1; x <= x2; x++ ) - { - const bool on = ( ( *line++ >> 24 ) != 0 ); - if ( on != inRect ) - { - if ( inRect ) - { - rect.setCoords( rx0, y, x - 1, y ); - region += rect; - } - else - { - rx0 = x; - } - - inRect = on; - } - } - - if ( inRect ) - { - rect.setCoords( rx0, y, x2, y ); - region = region.united( rect ); - } - } - } - - return region; -} - -class QwtWidgetOverlay::PrivateData -{ -public: - PrivateData(): - maskMode( QwtWidgetOverlay::MaskHint ), - renderMode( QwtWidgetOverlay::AutoRenderMode ), - rgbaBuffer( NULL ) - { - } - - ~PrivateData() - { - resetRgbaBuffer(); - } - - void resetRgbaBuffer() - { - if ( rgbaBuffer ) - { - ::free( rgbaBuffer ); - rgbaBuffer = NULL; - } - } - - MaskMode maskMode; - RenderMode renderMode; - uchar *rgbaBuffer; -}; - -/*! - \brief Constructor - \param widget Parent widget, where the overlay is aligned to -*/ -QwtWidgetOverlay::QwtWidgetOverlay( QWidget* widget ): - QWidget( widget ) -{ - d_data = new PrivateData; - - setAttribute( Qt::WA_TransparentForMouseEvents ); - setAttribute( Qt::WA_NoSystemBackground ); - setFocusPolicy( Qt::NoFocus ); - - if ( widget ) - { - resize( widget->size() ); - widget->installEventFilter( this ); - } -} - -//! Destructor -QwtWidgetOverlay::~QwtWidgetOverlay() -{ - delete d_data; -} - -/*! - \brief Specify how to find the mask for the overlay - - \param mode New mode - \sa maskMode() - */ -void QwtWidgetOverlay::setMaskMode( MaskMode mode ) -{ - if ( mode != d_data->maskMode ) - { - d_data->maskMode = mode; - d_data->resetRgbaBuffer(); - } -} - -/*! - \return Mode how to find the mask for the overlay - \sa setMaskMode() - */ -QwtWidgetOverlay::MaskMode QwtWidgetOverlay::maskMode() const -{ - return d_data->maskMode; -} - -/*! - Set the render mode - \param mode Render mode - - \sa RenderMode, renderMode() -*/ -void QwtWidgetOverlay::setRenderMode( RenderMode mode ) -{ - d_data->renderMode = mode; -} - -/*! - \return Render mode - \sa RenderMode, setRenderMode() - */ -QwtWidgetOverlay::RenderMode QwtWidgetOverlay::renderMode() const -{ - return d_data->renderMode; -} - -/*! - Recalculate the mask and repaint the overlay - */ -void QwtWidgetOverlay::updateOverlay() -{ - updateMask(); - update(); -} - -void QwtWidgetOverlay::updateMask() -{ - d_data->resetRgbaBuffer(); - - QRegion mask; - - if ( d_data->maskMode == QwtWidgetOverlay::MaskHint ) - { - mask = maskHint(); - } - else if ( d_data->maskMode == QwtWidgetOverlay::AlphaMask ) - { - // TODO: the image doesn't need to be larger than - // the bounding rectangle of the hint !! - - QRegion hint = maskHint(); - if ( hint.isEmpty() ) - hint += QRect( 0, 0, width(), height() ); - - // A fresh buffer from calloc() is usually faster - // than reinitializing an existing one with - // QImage::fill( 0 ) or memset() - - d_data->rgbaBuffer = ( uchar* )::calloc( width() * height(), 4 ); - - QImage image( d_data->rgbaBuffer, - width(), height(), qwtMaskImageFormat() ); - - QPainter painter( &image ); - draw( &painter ); - painter.end(); - - mask = qwtAlphaMask( image, hint.rects() ); - - if ( d_data->renderMode == QwtWidgetOverlay::DrawOverlay ) - { - // we don't need the buffer later - d_data->resetRgbaBuffer(); - } - } - - // A bug in Qt initiates a full repaint of the widget - // when we change the mask, while we are visible ! - - setVisible( false ); - - if ( mask.isEmpty() ) - clearMask(); - else - setMask( mask ); - - setVisible( true ); -} - -/*! - Paint event - \param event Paint event - - \sa drawOverlay() -*/ -void QwtWidgetOverlay::paintEvent( QPaintEvent* event ) -{ - const QRegion clipRegion = event->region(); - - QPainter painter( this ); - - bool useRgbaBuffer = false; - if ( d_data->renderMode == QwtWidgetOverlay::CopyAlphaMask ) - { - useRgbaBuffer = true; - } - else if ( d_data->renderMode == QwtWidgetOverlay::AutoRenderMode ) - { - if ( painter.paintEngine()->type() == QPaintEngine::Raster ) - useRgbaBuffer = true; - } - - if ( d_data->rgbaBuffer && useRgbaBuffer ) - { - const QImage image( d_data->rgbaBuffer, - width(), height(), qwtMaskImageFormat() ); - - QVector<QRect> rects; - if ( clipRegion.rects().size() > 2000 ) - { - // the region is to complex - painter.setClipRegion( clipRegion ); - rects += clipRegion.boundingRect(); - } - else - { - rects = clipRegion.rects(); - } - - for ( int i = 0; i < rects.size(); i++ ) - { - const QRect r = rects[i]; - painter.drawImage( r.topLeft(), image, r ); - } - } - else - { - painter.setClipRegion( clipRegion ); - draw( &painter ); - } -} - -/*! - Resize event - \param event Resize event -*/ -void QwtWidgetOverlay::resizeEvent( QResizeEvent* event ) -{ - Q_UNUSED( event ); - - d_data->resetRgbaBuffer(); -} - -void QwtWidgetOverlay::draw( QPainter *painter ) const -{ - QWidget *widget = const_cast< QWidget *>( parentWidget() ); - if ( widget ) - { - painter->setClipRect( parentWidget()->contentsRect() ); - - // something special for the plot canvas - - const int idx = widget->metaObject()->indexOfMethod( "borderPath(QRect)" ); - if ( idx >= 0 ) - { - QPainterPath clipPath; - - ( void )QMetaObject::invokeMethod( - widget, "borderPath", Qt::DirectConnection, - Q_RETURN_ARG( QPainterPath, clipPath ), Q_ARG( QRect, rect() ) ); - - if (!clipPath.isEmpty()) - painter->setClipPath( clipPath, Qt::IntersectClip ); - } - } - - drawOverlay( painter ); -} - -/*! - \brief Calculate an approximation for the mask - - - MaskHint - The hint is used as mask. - - - AlphaMask - The hint is used to speed up the algorithm - for calculating a mask from non transparent pixels - - - NoMask - The hint is unused. - - The default implementation returns an invalid region - indicating no hint. - - \return Hint for the mask - */ -QRegion QwtWidgetOverlay::maskHint() const -{ - return QRegion(); -} - -/*! - \brief Event filter - - Resize the overlay according to the size of the parent widget. - - \param object Object to be filtered - \param event Event - - \return See QObject::eventFilter() -*/ - -bool QwtWidgetOverlay::eventFilter( QObject* object, QEvent* event ) -{ - if ( object == parent() && event->type() == QEvent::Resize ) - { - QResizeEvent *resizeEvent = static_cast<QResizeEvent *>( event ); - resize( resizeEvent->size() ); - } - - return QObject::eventFilter( object, event ); -} diff --git a/source/ui/plugins/color_plugin.cpp b/source/ui/plugins/color_plugin.cpp index 4614547a1a359a4b48bff5bf06822413c8ea7fc3..d800810400c50f6291f2750c7b16a3a4c47a6719 100644 --- a/source/ui/plugins/color_plugin.cpp +++ b/source/ui/plugins/color_plugin.cpp @@ -1,6 +1,7 @@ #include <pli_vis/ui/plugins/color_plugin.hpp> #include <boost/format.hpp> +#include <QDoubleValidator> #include <pli_vis/ui/utility/line_edit.hpp> @@ -68,4 +69,21 @@ bool color_plugin::inverted() const { return checkbox_invert_k->isChecked(); } + +void color_plugin::set_mode (const int mode ) +{ + if(mode == 0) radio_button_hsl_1->setChecked(true); + if(mode == 1) radio_button_hsl_2->setChecked(true); + if(mode == 2) radio_button_hsv_1->setChecked(true); + if(mode == 3) radio_button_hsv_2->setChecked(true); + if(mode == 4) radio_button_rgb ->setChecked(true); +} +void color_plugin::set_k (const float k ) +{ + line_edit_k->setText(QString::fromStdString(std::to_string(k))); +} +void color_plugin::set_inverted(const bool inverted) +{ + checkbox_invert_k->setChecked(inverted); +} } diff --git a/source/ui/plugins/data_plugin.cpp b/source/ui/plugins/data_plugin.cpp index 882e6fe5726ccda8e93fafa229480cecd4296767..3192fe3a40045a97e740d032a506143599a3b299 100644 --- a/source/ui/plugins/data_plugin.cpp +++ b/source/ui/plugins/data_plugin.cpp @@ -191,6 +191,16 @@ std::array<std::size_t, 3> data_plugin::selection_offset() const line_edit::get_text<std::size_t>(line_edit_offset_z) }; } + +std::array<std::size_t, 3> data_plugin::selection_bounds() const +{ + return + { + line_edit::get_text<std::size_t>(line_edit_size_x), + line_edit::get_text<std::size_t>(line_edit_size_y), + line_edit::get_text<std::size_t>(line_edit_size_z) + }; +} std::array<std::size_t, 3> data_plugin::selection_size () const { auto stride = selection_stride(); @@ -310,6 +320,45 @@ boost::multi_array<float3, 3> data_plugin::generate_vectors (bool } } +void data_plugin::unserialize(const std::string& filename, const std::array<std::size_t, 3>& offset, const std::array<std::size_t, 3>& bounds, const std::array<std::size_t, 3>& stride) +{ + if(filename.find("MSA") != std::string::npos) + { + io_.set_filepath (filename.c_str()); + io_.set_transmittance_path("Transmittance"); + io_.set_retardation_path ("Retardation" ); + io_.set_direction_path ("Direction" ); + io_.set_inclination_path ("Inclination" ); + io_.set_mask_path ("Mask" ); + io_.set_unit_vector_path ("UnitVector" ); + } + else + { + io_.set_filepath (filename.c_str()); + io_.set_transmittance_path("%Slice%/Microscope/Processed/Registered/NTransmittance"); + io_.set_retardation_path ("%Slice%/Microscope/Processed/Registered/Retardation" ); + io_.set_direction_path ("%Slice%/Microscope/Processed/Registered/Direction" ); + io_.set_inclination_path ("%Slice%/Microscope/Processed/Registered/Inclination" ); + io_.set_mask_path ("%Slice%/Microscope/Processed/Registered/Mask" ); + io_.set_unit_vector_path ("%Slice%/Microscope/Processed/Registered/UnitVector" ); + } + setup(); + + line_edit_offset_x->setText(QString::fromStdString(std::to_string(offset[0]))); + line_edit_offset_y->setText(QString::fromStdString(std::to_string(offset[1]))); + line_edit_offset_z->setText(QString::fromStdString(std::to_string(offset[2]))); + + line_edit_size_x ->setText(QString::fromStdString(std::to_string(bounds[0]))); + line_edit_size_y ->setText(QString::fromStdString(std::to_string(bounds[1]))); + line_edit_size_z ->setText(QString::fromStdString(std::to_string(bounds[2]))); + + line_edit_stride_x->setText(QString::fromStdString(std::to_string(stride[0]))); + line_edit_stride_y->setText(QString::fromStdString(std::to_string(stride[1]))); + line_edit_stride_z->setText(QString::fromStdString(std::to_string(stride[2]))); + + button_update->click(); +} + void data_plugin::start() { set_sink(std::make_shared<text_browser_sink>(owner_->console)); diff --git a/source/ui/plugins/demo_plugin.cpp b/source/ui/plugins/demo_plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..333a4c3aab284b8b1febc79a585cca1861a3b4d9 --- /dev/null +++ b/source/ui/plugins/demo_plugin.cpp @@ -0,0 +1,274 @@ +#include <pli_vis/ui/plugins/demo_plugin.hpp> + +#include <boost/lexical_cast.hpp> +#include <json/json.hpp> +#include <QTextDocument> + +#include <pli_vis/ui/utility/line_edit.hpp> +#include <pli_vis/ui/utility/text_browser_sink.hpp> +#include <pli_vis/ui/application.hpp> + +namespace pli +{ +demo_plugin::demo_plugin (QWidget* parent) : plugin(parent), buttons_{button_1, button_2, button_3, button_4, button_5, button_6, button_7, button_8, button_9, button_10} +{ + if (!std::ifstream(presets_filepath_).good()) + create_default(); + + for (auto& button : buttons_) + { + connect(button, &QPushButton::clicked, [&] + { + bool save = QApplication::keyboardModifiers() & Qt::ControlModifier; + auto index = boost::lexical_cast<std::size_t>(button->text().toStdString()); + save ? save_preset(index - 1) : load_preset(index - 1); + logger_->info("{} preset {}.", save ? "Saved" : "Loaded", index); + }); + } +} + +void demo_plugin::start () +{ + set_sink(std::make_shared<text_browser_sink>(owner_->console)); +} + +void demo_plugin::create_default() const +{ + nlohmann::json json; + json["presets"] = nlohmann::json::array({ + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object(), + nlohmann::json::object()}); + + std::ofstream file(presets_filepath_); + file << std::setw(4) << json << std::endl; +} +void demo_plugin::load_preset (std::size_t index) const +{ + std::ifstream file(presets_filepath_); + nlohmann::json json; + file >> json; + + auto data_plugin = owner_->get_plugin<pli::data_plugin> (); + auto interactor_plugin = owner_->get_plugin<pli::interactor_plugin> (); + auto color_plugin = owner_->get_plugin<pli::color_plugin> (); + auto scalar_plugin = owner_->get_plugin<pli::scalar_plugin> (); + auto fom_plugin = owner_->get_plugin<pli::fom_plugin> (); + auto polar_plot_plugin = owner_->get_plugin<pli::polar_plot_plugin> (); + auto odf_plugin = owner_->get_plugin<pli::odf_plugin> (); + auto local_tractography_plugin = owner_->get_plugin<pli::local_tractography_plugin>(); + + auto& preset = json["presets"][index]; + auto& data_plugin_data = preset["data_plugin" ]; + auto& interactor_plugin_data = preset["interactor_plugin" ]; + auto& color_plugin_data = preset["color_plugin" ]; + auto& scalar_plugin_data = preset["scalar_plugin" ]; + auto& fom_plugin_data = preset["fom_plugin" ]; + auto& polar_plot_plugin_data = preset["polar_plot_plugin" ]; + auto& odf_plugin_data = preset["odf_plugin" ]; + auto& local_tractography_plugin_data = preset["local_tractography_plugin"]; + auto& demo_plugin_data = preset["demo_plugin" ]; + + data_plugin->unserialize( + data_plugin_data["dataset"], + { + data_plugin_data["offset"][0].get<std::size_t>(), + data_plugin_data["offset"][1].get<std::size_t>(), + data_plugin_data["offset"][2].get<std::size_t>() + }, + { + data_plugin_data["size"] [0].get<std::size_t>(), + data_plugin_data["size"] [1].get<std::size_t>(), + data_plugin_data["size"] [2].get<std::size_t>() + }, + { + data_plugin_data["stride"][0].get<std::size_t>(), + data_plugin_data["stride"][1].get<std::size_t>(), + data_plugin_data["stride"][2].get<std::size_t>() + }); + + owner_->viewer->camera()->set_translation ( + { + interactor_plugin_data["translation"][0].get<float>(), + interactor_plugin_data["translation"][1].get<float>(), + interactor_plugin_data["translation"][2].get<float>() + }); + owner_->viewer->camera()->set_rotation_euler( + { + interactor_plugin_data["rotation"] [0].get<float>(), + interactor_plugin_data["rotation"] [1].get<float>(), + interactor_plugin_data["rotation"] [2].get<float>() + }); + + color_plugin->set_mode (color_plugin_data["mode" ].get<int> ()); + color_plugin->set_k (color_plugin_data["k" ].get<float>()); + color_plugin->set_inverted(color_plugin_data["invert_p"].get<bool> ()); + + scalar_plugin->checkbox_enabled->setChecked(scalar_plugin_data["enabled"].get<bool>()); + scalar_plugin_data["mode"].get<bool>() ? scalar_plugin->checkbox_retardation->setChecked(true) : scalar_plugin->checkbox_transmittance->setChecked(true); + + fom_plugin->checkbox_enabled->setChecked(fom_plugin_data["enabled"].get<bool>()); + fom_plugin->line_edit_fiber_scale->setText(QString::fromStdString(std::to_string(fom_plugin_data["scale"].get<float>()))); + + polar_plot_plugin->checkbox_enabled ->setChecked(polar_plot_plugin_data["enabled" ].get<bool>()); + polar_plot_plugin->checkbox_symmetric ->setChecked(polar_plot_plugin_data["symmetric"].get<bool>()); + polar_plot_plugin->line_edit_superpixel_size ->setText (QString::fromStdString(std::to_string(polar_plot_plugin_data["superpixel_size" ].get<std::size_t>()))); + polar_plot_plugin->line_edit_angular_partitions->setText (QString::fromStdString(std::to_string(polar_plot_plugin_data["angular_partitions"].get<std::size_t>()))); + if (polar_plot_plugin->checkbox_enabled->isChecked()) + polar_plot_plugin->button_calculate->click(); + + odf_plugin->checkbox_enabled ->setChecked(odf_plugin_data["enabled" ].get<bool>()); + odf_plugin->checkbox_even_only ->setChecked(odf_plugin_data["symmetric"].get<bool>()); + odf_plugin->line_edit_vector_block_x ->setText (QString::fromStdString(std::to_string(odf_plugin_data["supervoxel_extent" ][0].get<std::size_t>()))); + odf_plugin->line_edit_vector_block_y ->setText (QString::fromStdString(std::to_string(odf_plugin_data["supervoxel_extent" ][1].get<std::size_t>()))); + odf_plugin->line_edit_vector_block_z ->setText (QString::fromStdString(std::to_string(odf_plugin_data["supervoxel_extent" ][2].get<std::size_t>()))); + odf_plugin->line_edit_histogram_theta ->setText (QString::fromStdString(std::to_string(odf_plugin_data["histogram_bins" ][0].get<std::size_t>()))); + odf_plugin->line_edit_histogram_phi ->setText (QString::fromStdString(std::to_string(odf_plugin_data["histogram_bins" ][1].get<std::size_t>()))); + odf_plugin->line_edit_maximum_sh_degree->setText (QString::fromStdString(std::to_string(odf_plugin_data["maximum_sh_degree" ] .get<std::size_t>()))); + odf_plugin->line_edit_sampling_theta ->setText (QString::fromStdString(std::to_string(odf_plugin_data["sampling_partitions"][0].get<std::size_t>()))); + odf_plugin->line_edit_sampling_phi ->setText (QString::fromStdString(std::to_string(odf_plugin_data["sampling_partitions"][1].get<std::size_t>()))); + odf_plugin->checkbox_hierarchical ->setChecked(odf_plugin_data["hierarchical" ] .get<bool>()); + odf_plugin->checkbox_depth_0 ->setChecked(odf_plugin_data["visible_layers"][0].get<bool>()); + odf_plugin->checkbox_depth_1 ->setChecked(odf_plugin_data["visible_layers"][1].get<bool>()); + odf_plugin->checkbox_depth_2 ->setChecked(odf_plugin_data["visible_layers"][2].get<bool>()); + odf_plugin->checkbox_depth_3 ->setChecked(odf_plugin_data["visible_layers"][3].get<bool>()); + odf_plugin->checkbox_depth_4 ->setChecked(odf_plugin_data["visible_layers"][4].get<bool>()); + odf_plugin->checkbox_depth_5 ->setChecked(odf_plugin_data["visible_layers"][5].get<bool>()); + odf_plugin->checkbox_depth_6 ->setChecked(odf_plugin_data["visible_layers"][6].get<bool>()); + odf_plugin->checkbox_depth_7 ->setChecked(odf_plugin_data["visible_layers"][7].get<bool>()); + odf_plugin->checkbox_depth_8 ->setChecked(odf_plugin_data["visible_layers"][8].get<bool>()); + odf_plugin->checkbox_depth_9 ->setChecked(odf_plugin_data["visible_layers"][9].get<bool>()); + if (odf_plugin->checkbox_enabled->isChecked()) + odf_plugin->button_calculate->click(); + + local_tractography_plugin->checkbox_enabled ->setChecked(local_tractography_plugin_data["enabled"].get<bool>()); + local_tractography_plugin->line_edit_offset_x ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["offset"][0] .get<std::size_t>()))); + local_tractography_plugin->line_edit_offset_y ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["offset"][1] .get<std::size_t>()))); + local_tractography_plugin->line_edit_offset_z ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["offset"][2] .get<std::size_t>()))); + local_tractography_plugin->line_edit_size_x ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["size" ][0] .get<std::size_t>()))); + local_tractography_plugin->line_edit_size_y ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["size" ][1] .get<std::size_t>()))); + local_tractography_plugin->line_edit_size_z ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["size" ][2] .get<std::size_t>()))); + local_tractography_plugin->line_edit_stride_x ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["stride"][0] .get<std::size_t>()))); + local_tractography_plugin->line_edit_stride_y ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["stride"][1] .get<std::size_t>()))); + local_tractography_plugin->line_edit_stride_z ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["stride"][2] .get<std::size_t>()))); + local_tractography_plugin->line_edit_integration_step ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["integration_step"] .get<float> ()))); + local_tractography_plugin->line_edit_iterations ->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["iterations"] .get<std::size_t>()))); + local_tractography_plugin->line_edit_streamline_radius->setText(QString::fromStdString(std::to_string(local_tractography_plugin_data["streamline_radius"].get<float> ()))); + local_tractography_plugin->line_edit_remote_address ->setText(QString::fromStdString(local_tractography_plugin_data["remote_address"].get<std::string>())); + local_tractography_plugin->line_edit_dataset_folder ->setText(QString::fromStdString(local_tractography_plugin_data["remote_folder" ].get<std::string>())); + if(local_tractography_plugin->checkbox_enabled->isChecked()) + local_tractography_plugin->button_remote_trace->click(); + local_tractography_plugin->updateGeometry(); + + text_content->document()->setPlainText(QString::fromStdString(demo_plugin_data["description"].get<std::string>())); +} +void demo_plugin::save_preset (std::size_t index) const +{ + std::ifstream file(presets_filepath_); + nlohmann::json json; + file >> json; + + auto data_plugin = owner_->get_plugin<pli::data_plugin> (); + auto interactor_plugin = owner_->get_plugin<pli::interactor_plugin> (); + auto color_plugin = owner_->get_plugin<pli::color_plugin> (); + auto scalar_plugin = owner_->get_plugin<pli::scalar_plugin> (); + auto fom_plugin = owner_->get_plugin<pli::fom_plugin> (); + auto polar_plot_plugin = owner_->get_plugin<pli::polar_plot_plugin> (); + auto odf_plugin = owner_->get_plugin<pli::odf_plugin> (); + auto local_tractography_plugin = owner_->get_plugin<pli::local_tractography_plugin>(); + + auto& preset = json["presets"][index]; + preset["data_plugin" ] = nlohmann::json::object(); + preset["interactor_plugin" ] = nlohmann::json::object(); + preset["color_plugin" ] = nlohmann::json::object(); + preset["scalar_plugin" ] = nlohmann::json::object(); + preset["fom_plugin" ] = nlohmann::json::object(); + preset["polar_plot_plugin" ] = nlohmann::json::object(); + preset["odf_plugin" ] = nlohmann::json::object(); + preset["local_tractography_plugin"] = nlohmann::json::object(); + preset["demo_plugin" ] = nlohmann::json::object(); + auto& data_plugin_data = preset["data_plugin" ]; + auto& interactor_plugin_data = preset["interactor_plugin" ]; + auto& color_plugin_data = preset["color_plugin" ]; + auto& scalar_plugin_data = preset["scalar_plugin" ]; + auto& fom_plugin_data = preset["fom_plugin" ]; + auto& polar_plot_plugin_data = preset["polar_plot_plugin" ]; + auto& odf_plugin_data = preset["odf_plugin" ]; + auto& local_tractography_plugin_data = preset["local_tractography_plugin"]; + auto& demo_plugin_data = preset["demo_plugin" ]; + + data_plugin_data ["dataset" ] = data_plugin->filepath (); + data_plugin_data ["offset" ] = data_plugin->selection_offset(); + data_plugin_data ["size" ] = data_plugin->selection_bounds(); + data_plugin_data ["stride" ] = data_plugin->selection_stride(); + + auto translation = owner_->viewer->camera()->translation (); + auto rotation = owner_->viewer->camera()->rotation_euler(); + interactor_plugin_data["translation" ] = {translation.x, translation.y, translation.z}; + interactor_plugin_data["rotation" ] = {rotation .x, rotation .y, rotation .z}; + + color_plugin_data ["mode" ] = std::uint32_t(color_plugin->mode()); + color_plugin_data ["k" ] = color_plugin->k (); + color_plugin_data ["invert_p" ] = color_plugin->inverted(); + + scalar_plugin_data ["enabled" ] = scalar_plugin->checkbox_enabled ->isChecked(); + scalar_plugin_data ["mode" ] = scalar_plugin->checkbox_retardation->isChecked(); // 0 - transmittance, 1 - retardation + + fom_plugin_data ["enabled" ] = fom_plugin->checkbox_enabled->isChecked(); + fom_plugin_data ["scale" ] = line_edit::get_text<float>(fom_plugin->line_edit_fiber_scale); + + polar_plot_plugin_data["enabled" ] = polar_plot_plugin->checkbox_enabled ->isChecked(); + polar_plot_plugin_data["symmetric" ] = polar_plot_plugin->checkbox_symmetric->isChecked(); + polar_plot_plugin_data["superpixel_size" ] = line_edit::get_text<std::size_t>(polar_plot_plugin->line_edit_superpixel_size); + polar_plot_plugin_data["angular_partitions" ] = line_edit::get_text<std::size_t>(polar_plot_plugin->line_edit_angular_partitions); + + odf_plugin_data ["enabled" ] = odf_plugin->checkbox_enabled ->isChecked(); + odf_plugin_data ["symmetric" ] = odf_plugin->checkbox_even_only->isChecked(); + odf_plugin_data ["supervoxel_extent" ] = { + line_edit::get_text<std::size_t>(odf_plugin->line_edit_vector_block_x), + line_edit::get_text<std::size_t>(odf_plugin->line_edit_vector_block_y), + line_edit::get_text<std::size_t>(odf_plugin->line_edit_vector_block_z)}; + odf_plugin_data ["histogram_bins" ] = { + line_edit::get_text<std::size_t>(odf_plugin->line_edit_histogram_theta), + line_edit::get_text<std::size_t>(odf_plugin->line_edit_histogram_phi )}; + odf_plugin_data ["maximum_sh_degree" ] = + line_edit::get_text<std::size_t>(odf_plugin->line_edit_maximum_sh_degree); + odf_plugin_data ["sampling_partitions"] = { + line_edit::get_text<std::size_t>(odf_plugin->line_edit_sampling_theta), + line_edit::get_text<std::size_t>(odf_plugin->line_edit_sampling_phi )}; + odf_plugin_data ["hierarchical" ] = odf_plugin->checkbox_hierarchical->isChecked(); + odf_plugin_data ["visible_layers" ] = { + odf_plugin->checkbox_depth_0->isChecked(), + odf_plugin->checkbox_depth_1->isChecked(), + odf_plugin->checkbox_depth_2->isChecked(), + odf_plugin->checkbox_depth_3->isChecked(), + odf_plugin->checkbox_depth_4->isChecked(), + odf_plugin->checkbox_depth_5->isChecked(), + odf_plugin->checkbox_depth_6->isChecked(), + odf_plugin->checkbox_depth_7->isChecked(), + odf_plugin->checkbox_depth_8->isChecked(), + odf_plugin->checkbox_depth_9->isChecked()}; + + local_tractography_plugin_data["enabled" ] = local_tractography_plugin->checkbox_enabled->isChecked(); + local_tractography_plugin_data["offset" ] = local_tractography_plugin->seed_offset (); + local_tractography_plugin_data["size" ] = local_tractography_plugin->seed_size (); + local_tractography_plugin_data["stride" ] = local_tractography_plugin->seed_stride (); + local_tractography_plugin_data["integration_step" ] = local_tractography_plugin->step (); + local_tractography_plugin_data["iterations" ] = local_tractography_plugin->iterations (); + local_tractography_plugin_data["streamline_radius"] = local_tractography_plugin->streamline_radius(); + local_tractography_plugin_data["remote_address" ] = line_edit::get_text<std::string>(local_tractography_plugin->line_edit_remote_address); + local_tractography_plugin_data["remote_folder" ] = line_edit::get_text<std::string>(local_tractography_plugin->line_edit_dataset_folder); + + demo_plugin_data["description"] = text_content->document()->toPlainText().toStdString(); + + std::ofstream mutable_file(presets_filepath_); + mutable_file << std::setw(4) << json << std::endl; +} +} diff --git a/source/ui/plugins/fom_plugin.cpp b/source/ui/plugins/fom_plugin.cpp index b96936881c2f8759dcf6b6a20137775fb44f0a03..900e2ccd2a7fb8688c92e470d19ca7d2c5ec938f 100644 --- a/source/ui/plugins/fom_plugin.cpp +++ b/source/ui/plugins/fom_plugin.cpp @@ -3,6 +3,7 @@ #include <limits> #include <boost/format.hpp> +#include <QDoubleValidator> #include <vector_functions.hpp> #include <pli_vis/ui/plugins/color_plugin.hpp> diff --git a/source/ui/plugins/global_tractography_plugin.cpp b/source/ui/plugins/global_tractography_plugin.cpp deleted file mode 100644 index 0b291f5f754d578b2412ebe79673b9ccf37c3674..0000000000000000000000000000000000000000 --- a/source/ui/plugins/global_tractography_plugin.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include <pli_vis/ui/plugins/global_tractography_plugin.hpp> - -#include <pli_vis/ui/utility/text_browser_sink.hpp> -#include <pli_vis/ui/application.hpp> - -namespace pli -{ -global_tractography_plugin::global_tractography_plugin(QWidget* parent) : plugin(parent) -{ - connect(checkbox_enabled , &QCheckBox::stateChanged, [&] (bool state) - { - logger_->info(std::string(state ? "Enabled." : "Disabled.")); - streamline_renderer_->set_active(state); - }); - connect(button_trace_selection, &QPushButton::clicked , [&] - { - trace(); - }); -} - -void global_tractography_plugin::start() -{ - set_sink(std::make_shared<text_browser_sink>(owner_->console)); - streamline_renderer_ = owner_->viewer->add_renderable<streamline_renderer>(); -} -void global_tractography_plugin::trace() -{ - owner_ ->set_is_loading(true); - logger_->info (std::string("Tracing...")); - - std::vector<float3> points ; - std::vector<float3> directions; - future_ = std::async(std::launch::async, [&] - { - try - { - auto vectors = owner_->get_plugin<data_plugin>()->generate_vectors(true); - auto shape = vectors.shape(); - - // TODO. - } - catch (std::exception& exception) - { - logger_->error(std::string(exception.what())); - } - }); - while (future_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) - QApplication::processEvents(); - - logger_->info (std::string("Trace complete.")); - owner_ ->set_is_loading(false); -} -} diff --git a/source/ui/plugins/interactor_plugin.cpp b/source/ui/plugins/interactor_plugin.cpp index b2abbece44f7cd3290b2cb51fa216341ffcb9713..61e055d2659f98c057a48c331272d44e23146850 100644 --- a/source/ui/plugins/interactor_plugin.cpp +++ b/source/ui/plugins/interactor_plugin.cpp @@ -1,12 +1,12 @@ #include <pli_vis/ui/plugins/interactor_plugin.hpp> #include <boost/format.hpp> +#include <QDoubleValidator> #include <pli_vis/ui/utility/line_edit.hpp> #include <pli_vis/ui/utility/text_browser_sink.hpp> #include <pli_vis/ui/application.hpp> #include <pli_vis/visualization/interactors/first_person_interactor.hpp> -#include <pli_vis/visualization/interactors/orbit_interactor.hpp> #include <pli_vis/visualization/interactors/simple_interactor.hpp> namespace pli @@ -23,13 +23,6 @@ interactor_plugin::interactor_plugin(QWidget* parent) : plugin(parent) owner_->viewer->interactor()->set_move_speed(float(slider_move_speed->value()) / slider_move_speed->maximum()); owner_->viewer->interactor()->set_look_speed(float(slider_look_speed->value()) / slider_look_speed->maximum()); }); - connect(radio_button_orbit , &QRadioButton::clicked , [&] - { - logger_->info(std::string("Orbit controls selected.")); - owner_->viewer->set_interactor<orbit_interactor>(); - owner_->viewer->interactor()->set_move_speed(float(slider_move_speed->value()) / slider_move_speed->maximum()); - owner_->viewer->interactor()->set_look_speed(float(slider_look_speed->value()) / slider_look_speed->maximum()); - }); connect(radio_button_wasd , &QRadioButton::clicked , [&] { logger_->info(std::string("WASD controls selected.")); @@ -37,18 +30,6 @@ interactor_plugin::interactor_plugin(QWidget* parent) : plugin(parent) owner_->viewer->interactor()->set_move_speed(float(slider_move_speed->value()) / slider_move_speed->maximum()); owner_->viewer->interactor()->set_look_speed(float(slider_look_speed->value()) / slider_look_speed->maximum()); }); - connect(radio_button_orthographic, &QRadioButton::clicked , [&] - { - logger_->info(std::string("Orthographic projection selected.")); - owner_->viewer->camera()->set_orthographic(true); - owner_->viewer->reset_camera_transform(); - }); - connect(radio_button_perspective , &QRadioButton::clicked , [&] - { - logger_->info(std::string("Perspective projection selected.")); - owner_->viewer->camera()->set_orthographic(false); - owner_->viewer->reset_camera_transform(); - }); connect(slider_move_speed , &QSlider::valueChanged , [&] { auto speed = float(slider_move_speed->value()) / slider_move_speed->maximum(); diff --git a/source/ui/plugins/local_tractography_plugin.cpp b/source/ui/plugins/local_tractography_plugin.cpp index 004e3423ae20ff0e0c431993b159f92d8f36c17f..b63e73f608b8823ccc75305256fa01408f70ad5b 100644 --- a/source/ui/plugins/local_tractography_plugin.cpp +++ b/source/ui/plugins/local_tractography_plugin.cpp @@ -4,11 +4,16 @@ #include <random> #include <boost/format.hpp> +#include <QDoubleValidator> +#include <QFileDialog> +#include <QIntValidator> #include <tangent-base/default_tracers.hpp> +#include <tangent-tbb/tbb_default_tracers.hpp> #include <pli_vis/cuda/pt/tracer.h> #include <pli_vis/cuda/utility/vector_ops.h> #include <pli_vis/ui/plugins/data_plugin.hpp> +#include <pli_vis/ui/widgets/remote_viewer.hpp> #include <pli_vis/ui/utility/line_edit.hpp> #include <pli_vis/ui/utility/text_browser_sink.hpp> #include <pli_vis/ui/application.hpp> @@ -20,11 +25,13 @@ namespace pli { local_tractography_plugin::local_tractography_plugin(QWidget* parent) : plugin(parent) { - line_edit_integration_step->setValidator(new QDoubleValidator(0, std::numeric_limits<double>::max(), 10, this)); - line_edit_iterations ->setValidator(new QIntValidator (0, std::numeric_limits<int> ::max(), this)); + line_edit_integration_step ->setValidator(new QDoubleValidator(0, std::numeric_limits<double>::max(), 10, this)); + line_edit_iterations ->setValidator(new QIntValidator (0, std::numeric_limits<int> ::max(), this)); + line_edit_streamline_radius->setValidator(new QDoubleValidator(0, std::numeric_limits<double>::max(), 10, this)); - line_edit_integration_step->setText(QString::fromStdString((boost::format("%.4f") % (float(slider_integration_step->value()) / slider_integration_step->maximum())).str())); - line_edit_iterations ->setText(QString::fromStdString(std::to_string(slider_iterations ->value()))); + line_edit_integration_step ->setText(QString::fromStdString((boost::format("%.4f") % (float(slider_integration_step ->value()) / slider_integration_step ->maximum())).str())); + line_edit_iterations ->setText(QString::fromStdString(std::to_string(slider_iterations ->value()))); + line_edit_streamline_radius->setText(QString::fromStdString((boost::format("%.4f") % (float(slider_streamline_radius->value()) / slider_streamline_radius->maximum())).str())); connect(checkbox_enabled , &QCheckBox::stateChanged , [&] (bool state) { @@ -83,7 +90,7 @@ local_tractography_plugin::local_tractography_plugin(QWidget* parent) : plugin(p }); connect(line_edit_offset_x , &QLineEdit::editingFinished , [&] { - auto value = std::max(std::min(make_even(line_edit::get_text<int>(line_edit_offset_x)), int(slider_x->maximum())), int(slider_x->minimum())); + auto value = make_even(line_edit::get_text<int>(line_edit_offset_x)); // std::max(std::min(make_even(line_edit::get_text<int>(line_edit_offset_x)), int(slider_x->maximum())), int(slider_x->minimum())); if (slider_x->upperValue() < value) slider_x->setUpperValue(value); slider_x ->setLowerValue (value); @@ -93,13 +100,13 @@ local_tractography_plugin::local_tractography_plugin(QWidget* parent) : plugin(p }); connect(line_edit_size_x , &QLineEdit::editingFinished , [&] { - auto value = std::max(std::min(make_even(line_edit::get_text<int>(line_edit_size_x)), int(slider_x->maximum())), int(slider_x->minimum())); + auto value = make_even(line_edit::get_text<int>(line_edit_size_x)); // std::max(std::min(make_even(line_edit::get_text<int>(line_edit_size_x)), int(slider_x->maximum())), int(slider_x->minimum())); slider_x->setUpperValue (make_even(slider_x->lowerValue() + value)); image ->set_selection_size_percentage({static_cast<float>(value) / slider_x->maximum(), image->selection_size_percentage()[1]}); }); connect(line_edit_offset_y , &QLineEdit::editingFinished , [&] { - auto value = std::max(std::min(make_even(line_edit::get_text<int>(line_edit_offset_y)), int(slider_y->maximum())), int(slider_y->minimum())); + auto value = make_even(line_edit::get_text<int>(line_edit_offset_y)); // std::max(std::min(make_even(line_edit::get_text<int>(line_edit_offset_y)), int(slider_y->maximum())), int(slider_y->minimum())); if (slider_y->upperValue() < value) slider_y->setUpperValue(value); slider_y ->setLowerValue (value); @@ -109,13 +116,13 @@ local_tractography_plugin::local_tractography_plugin(QWidget* parent) : plugin(p }); connect(line_edit_size_y , &QLineEdit::editingFinished , [&] { - auto value = std::max(std::min(make_even(line_edit::get_text<int>(line_edit_size_y)), int(slider_y->maximum())), int(slider_y->minimum())); + auto value = make_even(line_edit::get_text<int>(line_edit_size_y)); // std::max(std::min(make_even(line_edit::get_text<int>(line_edit_size_y)), int(slider_y->maximum())), int(slider_y->minimum())); slider_y->setUpperValue (make_even(slider_y->lowerValue() + value)); image ->set_selection_size_percentage({image->selection_size_percentage()[0], static_cast<float>(value) / slider_y->maximum()}); }); connect(line_edit_offset_z , &QLineEdit::editingFinished , [&] { - auto value = std::max(std::min(line_edit::get_text<int>(line_edit_offset_z), int(slider_z->maximum())), int(slider_z->minimum())); + auto value = make_even(line_edit::get_text<int>(line_edit_offset_z)); // std::max(std::min(line_edit::get_text<int>(line_edit_offset_z), int(slider_z->maximum())), int(slider_z->minimum())); if (slider_z->upperValue() < value) slider_z->setUpperValue(value + 1); slider_z ->setLowerValue(value); @@ -123,7 +130,7 @@ local_tractography_plugin::local_tractography_plugin(QWidget* parent) : plugin(p }); connect(line_edit_size_z , &QLineEdit::editingFinished , [&] { - auto value = std::min(line_edit::get_text<int>(line_edit_size_z), int(slider_z->maximum() - slider_z->minimum())); + auto value = make_even(line_edit::get_text<int>(line_edit_size_z)); // std::min(line_edit::get_text<int>(line_edit_size_z), int(slider_z->maximum() - slider_z->minimum())); slider_z->setUpperValue(slider_z->lowerValue() + value); }); connect(slider_integration_step , &QSlider::valueChanged , [&] @@ -142,29 +149,21 @@ local_tractography_plugin::local_tractography_plugin(QWidget* parent) : plugin(p { slider_iterations->setValue(line_edit::get_text<int>(line_edit_iterations)); }); - connect(button_trace_selection, &QPushButton::clicked, [&] + connect(slider_streamline_radius , &QSlider::valueChanged , [&] { - trace(); - }); - connect(radio_button_cpu , &QRadioButton::clicked , [&] - { - logger_->info(std::string("CPU particle tracing selected.")); - gpu_tracing_ = false; + line_edit_streamline_radius->setText(QString::fromStdString((boost::format("%.4f") % (float(slider_streamline_radius->value()) / slider_streamline_radius->maximum())).str())); }); - connect(radio_button_gpu , &QRadioButton::clicked , [&] + connect(line_edit_streamline_radius, &QLineEdit::editingFinished , [&] { - logger_->info(std::string("GPU particle tracing selected.")); - gpu_tracing_ = true; + slider_streamline_radius->setValue(line_edit::get_text<double>(line_edit_streamline_radius) * slider_streamline_radius->maximum()); }); - connect(radio_button_regular , &QRadioButton::clicked , [&] + connect(button_local_trace , &QPushButton::clicked , [&] { - owner_->viewer->remove_renderable(streamline_renderer_); - streamline_renderer_ = owner_->viewer->add_renderable<streamline_renderer>(); + trace(); }); - connect(radio_button_lineao , &QRadioButton::clicked , [&] + connect(button_remote_trace , &QPushButton::clicked , [&] { - owner_->viewer->remove_renderable(streamline_renderer_); - streamline_renderer_ = owner_->viewer->add_renderable<lineao_streamline_renderer>(); + remote_trace(); }); } @@ -172,11 +171,8 @@ void local_tractography_plugin::start() { set_sink(std::make_shared<text_browser_sink>(owner_->console)); - if(radio_button_lineao->isChecked()) - streamline_renderer_ = owner_->viewer->add_renderable<lineao_streamline_renderer>(); - else - streamline_renderer_ = owner_->viewer->add_renderable<streamline_renderer>(); - + streamline_renderer_ = owner_->viewer->add_renderable<streamline_renderer>(); + connect(owner_->toolbox, &QToolBox::currentChanged, [&](int tab) { // Hack for enforcing a UI update. @@ -225,8 +221,10 @@ void local_tractography_plugin::trace() logger_->info(std::string("Tracing...")); - std::vector<float3> points ; - std::vector<float3> directions ; + vertices_.clear(); + tangents_.clear(); + indices_ .clear(); + std::vector<float4> random_vectors; future_ = std::async(std::launch::async, [&] { @@ -235,86 +233,71 @@ void local_tractography_plugin::trace() auto vectors = owner_->get_plugin<data_plugin>()->generate_vectors(true); auto shape = vectors.shape(); - if(!gpu_tracing_) - { - tangent::CartesianGrid data(tangent::grid_dim_t{{shape[0], shape[1], shape[2]}}, tangent::vector_t{{1.0, 1.0, 1.0}}); - auto data_ptr = data.GetVectorPointer(0); - for (auto x = 0; x < shape[0]; x++) - for (auto y = 0; y < shape[1]; y++) - for (auto z = 0; z < shape[2]; z++) - { - auto vector = vectors[x][y][z]; - data_ptr[x + shape[0] * (y + shape[1] * z)] = tangent::vector_t{{vector.x, vector.y, vector.z}}; - } + tangent::CartesianGrid data(tangent::grid_dim_t{{shape[0], shape[1], shape[2]}}, tangent::vector_t{{1.0, 1.0, 1.0}}); + auto data_ptr = data.GetVectorPointer(0); + for (auto x = 0; x < shape[0]; x++) + for (auto y = 0; y < shape[1]; y++) + for (auto z = 0; z < shape[2]; z++) + { + auto& vector = vectors[x][y][z]; + data_ptr[x + shape[0] * (y + shape[1] * z)] = tangent::vector_t{{vector.x, vector.y, vector.z}}; + } - auto offset = seed_offset(); - auto size = seed_size (); - auto stride = seed_stride(); - std::vector<tangent::point_t> seeds; - for (auto x = offset[0]; x < offset[0] + size[0]; x+= stride[0]) - for (auto y = offset[1]; y < offset[1] + size[1]; y += stride[1]) - for (auto z = offset[2]; z < offset[2] + size[2]; z += stride[2]) - seeds.push_back({{float(x), float(y), float(z), 0.0F}}); + auto offset = seed_offset(); + auto size = seed_size (); + auto stride = seed_stride(); + std::vector<tangent::point_t> seeds; + for (auto x = offset[0]; x < offset[0] + size[0]; x+= stride[0]) + for (auto y = offset[1]; y < offset[1] + size[1]; y += stride[1]) + for (auto z = offset[2]; z < offset[2] + size[2]; z += stride[2]) + seeds.push_back({{float(x), float(y), float(z), 0.0F}}); - tangent::TraceRecorder recorder; - tangent::OmpCartGridStreamlineTracer tracer(&recorder); - tracer.SetData (&data); - tracer.SetIntegrationStep (float(slider_integration_step->value()) / slider_integration_step->maximum()); - tracer.SetNumberOfIterations(slider_iterations->value()); - auto output = tracer.TraceSeeds(seeds); + tangent::TraceRecorder recorder; + tangent::TBBCartGridStreamlineTracer tracer(&recorder); + tracer.SetData (&data); + tracer.SetIntegrationStep (step()); + tracer.SetNumberOfIterations(iterations()); + auto output = tracer.TraceSeeds(seeds); - auto& population = recorder.GetPopulation(); - for(auto i = 0; i < population.GetNumberOfTraces(); i++) - { - auto& path = population[i]; - for(auto j = 0; j < path.size() - 1; j++) - { - float3 start {path[j] [0], path[j] [1], path[j] [2]}; - float3 end {path[j + 1][0], path[j + 1][1], path[j + 1][2]}; - points.push_back(start); - points.push_back(end ); - directions.push_back(normalize(end - start)); - directions.push_back(normalize(start - end )); - } - } - } - else + auto& population = recorder.GetPopulation(); + for (auto i = 0; i < population.GetNumberOfTraces(); ++i) { - std::vector<float3> data(shape[0] * shape[1] * shape[2]); - for (auto x = 0; x < shape[0]; x++) - for (auto y = 0; y < shape[1]; y++) - for (auto z = 0; z < shape[2]; z++) - data[x + shape[0] * (y + shape[1] * z)] = vectors[x][y][z]; + auto& path = population[i]; + auto vertex_offset = vertices_.size(); + for(auto j = 0; j < path.size(); ++j) + { + auto& vertex = path[j]; + if (isnan(vertex[0]) || + isnan(vertex[1]) || + isnan(vertex[2]) || + vertex[0] == 0.0F && + vertex[1] == 0.0F && + vertex[2] == 0.0F) + continue; - std::vector<float3> seeds; - auto offset = seed_offset(); - auto size = seed_size (); - auto stride = seed_stride(); - for (auto x = offset[0]; x < offset[0] + size[0]; x += stride[0]) - for (auto y = offset[1]; y < offset[1] + size[1]; y += stride[1]) - for (auto z = offset[2]; z < offset[2] + size[2]; z += stride[2]) - seeds.push_back(float3{float(x), float(y), float(z)}); - - auto traces = cupt::trace( - slider_iterations->value(), - float(slider_integration_step->value()) / slider_integration_step->maximum(), - uint3 {unsigned(shape[0]), unsigned(shape[1]), unsigned(shape[2])}, - float3 {1.0f, 1.0f, 1.0f}, - data , - seeds); + vertices_.push_back(float4{vertex[0], vertex[1], vertex[2], 1.0}); + + if (j > 0) + tangents_.push_back(normalize(float4{ + path[j][0] - path[j - 1][0], + path[j][1] - path[j - 1][1], + path[j][2] - path[j - 1][2], + 0.0})); + else if (path.size() > 1) + tangents_.push_back(normalize(float4{ + path[j + 1][0] - path[j][0], + path[j + 1][1] - path[j][1], + path[j + 1][2] - path[j][2], + 0.0})); + else + tangents_.push_back(float4{0.0F, 0.0F, 0.0F, 0.0F}); - for (auto i = 0; i < traces.size(); ++i) - for (auto j = 0; j < traces[i].size() - 1; ++j) + if (j > 0) { - auto& start = traces[i][j ]; - auto& end = traces[i][j+1]; - if(end.x == 0.0f && end.y == 0.0f && end.z == 0.0f) - break; - points .push_back(start); - points .push_back(end ); - directions.push_back(normalize(end - start)); - directions.push_back(normalize(start - end )); + indices_.push_back(vertex_offset + j - 1); + indices_.push_back(vertex_offset + j); } + } } std::random_device random_device; @@ -344,15 +327,15 @@ void local_tractography_plugin::trace() while (future_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) QApplication::processEvents(); - if (points.size() > 0 && directions.size() > 0) + if (vertices_.size() > 0 && tangents_.size() > 0) { logger_->info(std::string("Trace successful.")); - auto lineao_renderer = dynamic_cast<lineao_streamline_renderer*>(streamline_renderer_); - if (lineao_renderer) lineao_renderer ->set_data(points, directions, random_vectors); + auto regular_renderer = dynamic_cast<streamline_renderer*> (streamline_renderer_); + if (regular_renderer) regular_renderer->set_data(vertices_, tangents_, indices_); - auto regular_renderer = dynamic_cast<streamline_renderer*>(streamline_renderer_); - if (regular_renderer) regular_renderer->set_data(points, directions); + //auto lineao_renderer = dynamic_cast<lineao_streamline_renderer*>(streamline_renderer_); + //if (lineao_renderer) lineao_renderer ->set_data(vertices_, tangents_, random_vectors); } else { @@ -361,6 +344,18 @@ void local_tractography_plugin::trace() owner_->set_is_loading(false); } +void local_tractography_plugin::remote_trace() +{ + remote_viewer_ = std::make_unique<remote_viewer>( + line_edit::get_text<std::string>(line_edit_remote_address), + line_edit::get_text<std::string>(line_edit_dataset_folder), + owner_, + owner_->viewer->interactor()); + remote_viewer_->on_close.connect([&]() + { + remote_viewer_.reset(); + }); +} std::array<std::size_t, 3> local_tractography_plugin::seed_offset() const { diff --git a/source/ui/plugins/odf_plugin.cpp b/source/ui/plugins/odf_plugin.cpp index 21e45380e671ec84f559e38c39113ac0fb2c6128..ca1a7c15a7a904177274b3b77d37567258b848be 100644 --- a/source/ui/plugins/odf_plugin.cpp +++ b/source/ui/plugins/odf_plugin.cpp @@ -4,6 +4,7 @@ #include <string> #include <boost/format.hpp> +#include <QIntValidator> #include <vector_functions.hpp> #include <pli_vis/cuda/sh/spherical_harmonics.h> @@ -36,7 +37,6 @@ odf_plugin::odf_plugin(QWidget* parent) : plugin(parent) line_edit_maximum_sh_degree->setText(QString::fromStdString(std::to_string(slider_maximum_sh_degree->value()))); line_edit_sampling_theta ->setText(QString::fromStdString(std::to_string(slider_sampling_theta ->value()))); line_edit_sampling_phi ->setText(QString::fromStdString(std::to_string(slider_sampling_phi ->value()))); - line_edit_threshold ->setText(QString::fromStdString((boost::format("%.2f") % (threshold_multiplier_ * slider_threshold->value())).str())); connect(checkbox_enabled, &QCheckBox::stateChanged, [&](int state) { @@ -165,30 +165,10 @@ odf_plugin::odf_plugin(QWidget* parent) : plugin(parent) set_visible_layers(); }); - connect(checkbox_clustering_enabled, &QCheckBox::stateChanged , [&](int state) - { - logger_->info("Clustering is {}.", state ? "enabled" : "disabled"); - label_threshold ->setEnabled(state); - slider_threshold ->setEnabled(state); - line_edit_threshold->setEnabled(state); - }); - connect(slider_threshold , &QxtSpanSlider::valueChanged, [&] - { - line_edit_threshold->setText(QString::fromStdString((boost::format("%.2f") % (threshold_multiplier_ * slider_threshold->value())).str())); - }); - connect(line_edit_threshold , &QLineEdit::editingFinished , [&] - { - slider_threshold->setValue(line_edit::get_text<double>(line_edit_threshold) / threshold_multiplier_); - }); - connect(button_calculate , &QAbstractButton::clicked , [&] { calculate(); }); - connect(button_extract_peaks , &QAbstractButton::clicked , [&] - { - extract_peaks(); - }); } void odf_plugin::start () @@ -285,61 +265,15 @@ void odf_plugin::calculate () sampling_dimensions, block_dimensions, 1.0F, - checkbox_hierarchical ->isChecked(), - checkbox_clustering_enabled->isChecked(), - threshold_multiplier_ * float(slider_threshold->value()), + checkbox_hierarchical->isChecked(), + false, + 0.1f , [&] (const std::string& message) { logger_->info(message); }); logger_->info(std::string("Update successful.")); owner_->set_is_loading(false); } -void odf_plugin::extract_peaks () -{ - owner_->set_is_loading(true); - - logger_->info(std::string("Extracting peaks...")); - - auto dimensions = make_uint3( - coefficients_.shape()[0], - coefficients_.shape()[1], - coefficients_.shape()[2]); - - uint2 sampling_dimensions = { - line_edit::get_text<unsigned>(line_edit_sampling_theta ), - line_edit::get_text<unsigned>(line_edit_sampling_phi )}; - - future_ = std::async(std::launch::async, [&] - { - try - { - maxima_.resize(boost::extents - [coefficients_.shape()[0]] - [coefficients_.shape()[1]] - [coefficients_.shape()[2]] - [maxima_count_]); - - pli::extract_peaks( - dimensions, - maximum_degree(coefficients_.shape()[3]), - coefficients_.data(), - sampling_dimensions , - maxima_count_ , - maxima_.data() , - [&] (const std::string& message) { logger_->info(message); }); - } - catch (std::exception& exception) - { - logger_->error(std::string(exception.what())); - } - }); - while (future_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) - QApplication::processEvents(); - - logger_->info(std::string("Extraction successful.")); - - owner_->set_is_loading(false); -} void odf_plugin::set_visible_layers() const { odf_field_->set_visible_layers({ diff --git a/source/ui/plugins/polar_plot_plugin.cpp b/source/ui/plugins/polar_plot_plugin.cpp index 5e065294ff8db72b0978a7e245d807bbed770e08..d515301d014d642f50c940455a87bf255ed8107a 100644 --- a/source/ui/plugins/polar_plot_plugin.cpp +++ b/source/ui/plugins/polar_plot_plugin.cpp @@ -1,5 +1,7 @@ #include <pli_vis/ui/plugins/polar_plot_plugin.hpp> +#include <QIntValidator> + #include <pli_vis/cuda/polar_plot.h> #include <pli_vis/cuda/utility/vector_ops.h> #include <pli_vis/ui/utility/line_edit.hpp> diff --git a/source/ui/plugins/volume_rendering_plugin.cpp b/source/ui/plugins/volume_rendering_plugin.cpp deleted file mode 100644 index 8a43fe656b4e9f181917d8f42731f97d448d3ac9..0000000000000000000000000000000000000000 --- a/source/ui/plugins/volume_rendering_plugin.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include <pli_vis/ui/plugins/volume_rendering_plugin.hpp> - -#include <boost/format.hpp> -#include <vector_functions.hpp> - -#include <pli_vis/ui/utility/line_edit.hpp> -#include <pli_vis/ui/utility/text_browser_sink.hpp> -#include <pli_vis/ui/application.hpp> -#include <pli_vis/visualization/algorithms/volume_renderer.hpp> - -namespace pli -{ -volume_rendering_plugin::volume_rendering_plugin(QWidget* parent) : plugin(parent) -{ - line_edit_step_size->setText(QString::fromStdString((boost::format("%.4f") % (double(slider_step_size->value()) / slider_step_size->maximum())).str())); - - connect(checkbox_enabled , &QCheckBox::stateChanged , [&](bool state) - { - logger_->info(std::string(state ? "Enabled." : "Disabled.")); - volume_renderer_->set_active(state); - }); - connect(slider_step_size , &QSlider::valueChanged , [&] - { - line_edit_step_size->setText(QString::fromStdString((boost::format("%.4f") % (float(slider_step_size->value()) / slider_step_size->maximum())).str())); - }); - connect(slider_step_size , &QSlider::sliderReleased , [&] - { - volume_renderer_->set_step_size(line_edit::get_text<double>(line_edit_step_size)); - }); - connect(line_edit_step_size , &QLineEdit::editingFinished , [&] - { - auto step_size = line_edit::get_text<double>(line_edit_step_size); - slider_step_size->setValue(step_size * slider_step_size->maximum()); - volume_renderer_->set_step_size(step_size); - }); - connect(transfer_function_editor, &transfer_function_editor::on_change, [&] - { - volume_renderer_->set_transfer_function(transfer_function_editor->get_function()); - }); -} - -void volume_rendering_plugin::start () -{ - set_sink(std::make_shared<text_browser_sink>(owner_->console)); - - connect(owner_->get_plugin<data_plugin>(), &data_plugin::on_load, [&] - { - upload(); - }); - - auto step_size = double(slider_step_size->value()) / slider_step_size->maximum(); - volume_renderer_ = owner_->viewer->add_renderable<volume_renderer>(); - volume_renderer_->set_active (checkbox_enabled->isChecked()); - volume_renderer_->set_step_size (step_size); - volume_renderer_->set_transfer_function(transfer_function_editor->get_function()); -} -void volume_rendering_plugin::upload() -{ - logger_->info(std::string("Updating viewer...")); - - auto& retardation = owner_->get_plugin<data_plugin>()->retardation(); - - std::vector<std::size_t> histogram(255); - std::for_each(retardation.origin(), retardation.origin() + retardation.num_elements(), - [&histogram] (const float& value) - { - histogram[value]++; - }); - - auto ratio = 255.0F / *std::max_element(histogram.begin(), histogram.end()); - std::transform(histogram.begin(), histogram.end(), histogram.begin(), - [&ratio](const std::size_t& value) - { - return float(value) * ratio; - }); - - volume_renderer_ ->set_data (make_uint3(retardation.shape()[0], retardation.shape()[1], retardation.shape()[2]), retardation.data()); - transfer_function_editor->set_histogram_entries(histogram); - - logger_->info(std::string("Update successful.")); -} -} diff --git a/source/ui/plugins/zernike_plugin.cpp b/source/ui/plugins/zernike_plugin.cpp deleted file mode 100644 index 24bb53cfb6d79b89f400853fa83cb0effdf2c578..0000000000000000000000000000000000000000 --- a/source/ui/plugins/zernike_plugin.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include <pli_vis/ui/plugins/zernike_plugin.hpp> - -#include <pli_vis/cuda/utility/vector_ops.h> -#include <pli_vis/cuda/zernike/launch.h> -#include <pli_vis/cuda/zernike/zernike.h> -#include <pli_vis/ui/utility/line_edit.hpp> -#include <pli_vis/ui/utility/text_browser_sink.hpp> -#include <pli_vis/ui/application.hpp> -#include <pli_vis/visualization/algorithms/zernike_field.hpp> - -namespace pli -{ -zernike_plugin::zernike_plugin(QWidget* parent) -{ - line_edit_superpixel_x ->setValidator(new QIntValidator(0, std::numeric_limits<int>::max(), this)); - line_edit_superpixel_y ->setValidator(new QIntValidator(0, std::numeric_limits<int>::max(), this)); - line_edit_partitions_theta->setValidator(new QIntValidator(0, std::numeric_limits<int>::max(), this)); - line_edit_partitions_rho ->setValidator(new QIntValidator(0, std::numeric_limits<int>::max(), this)); - line_edit_maximum_degree ->setValidator(new QIntValidator(0, std::numeric_limits<int>::max(), this)); - - line_edit_superpixel_x ->setText(QString::fromStdString(std::to_string(slider_superpixel_x ->value()))); - line_edit_superpixel_y ->setText(QString::fromStdString(std::to_string(slider_superpixel_y ->value()))); - line_edit_partitions_theta->setText(QString::fromStdString(std::to_string(slider_partitions_theta->value()))); - line_edit_partitions_rho ->setText(QString::fromStdString(std::to_string(slider_partitions_rho ->value()))); - line_edit_maximum_degree ->setText(QString::fromStdString(std::to_string(slider_maximum_degree ->value()))); - - connect(checkbox_enabled , &QCheckBox::stateChanged , [&](int state) - { - logger_->info(std::string(state ? "Enabled." : "Disabled.")); - zernike_field_->set_active(state); - }); - - connect(slider_superpixel_x , &QxtSpanSlider::valueChanged, [&] - { - line_edit_superpixel_x ->setText(QString::fromStdString(std::to_string(slider_superpixel_x ->value()))); - }); - connect(slider_superpixel_y , &QxtSpanSlider::valueChanged, [&] - { - line_edit_superpixel_y ->setText(QString::fromStdString(std::to_string(slider_superpixel_y ->value()))); - }); - connect(slider_partitions_theta , &QxtSpanSlider::valueChanged, [&] - { - line_edit_partitions_theta->setText(QString::fromStdString(std::to_string(slider_partitions_theta->value()))); - }); - connect(slider_partitions_rho , &QxtSpanSlider::valueChanged, [&] - { - line_edit_partitions_rho ->setText(QString::fromStdString(std::to_string(slider_partitions_rho ->value()))); - }); - connect(slider_maximum_degree , &QxtSpanSlider::valueChanged, [&] - { - line_edit_maximum_degree ->setText(QString::fromStdString(std::to_string(slider_maximum_degree ->value()))); - }); - - connect(line_edit_superpixel_x , &QLineEdit::editingFinished , [&] - { - slider_superpixel_x ->setValue(line_edit::get_text<int>(line_edit_superpixel_x)); - }); - connect(line_edit_superpixel_y , &QLineEdit::editingFinished , [&] - { - slider_superpixel_y ->setValue(line_edit::get_text<int>(line_edit_superpixel_y)); - }); - connect(line_edit_partitions_theta, &QLineEdit::editingFinished , [&] - { - slider_partitions_theta->setValue(line_edit::get_text<int>(line_edit_partitions_theta)); - }); - connect(line_edit_partitions_rho , &QLineEdit::editingFinished , [&] - { - slider_partitions_rho ->setValue(line_edit::get_text<int>(line_edit_partitions_rho)); - }); - connect(line_edit_maximum_degree , &QLineEdit::editingFinished , [&] - { - slider_maximum_degree ->setValue(line_edit::get_text<int>(line_edit_maximum_degree)); - }); - - connect(button_calculate , &QAbstractButton::clicked , [&] - { - owner_ ->set_is_loading(true); - logger_->info(std::string("Updating viewer...")); - - auto parameters = get_parameters(); - auto vectors = owner_->get_plugin<data_plugin>()->generate_vectors(false); - uint2 superpixel_dimensions = - { - unsigned(vectors.shape()[0]) / parameters.superpixel_size.x, - unsigned(vectors.shape()[1]) / parameters.superpixel_size.y, - }; - std::vector<float> coefficients; - - future_ = std::async(std::launch::async, [&] - { - try - { - auto vector_dimensions = parameters.superpixel_size * superpixel_dimensions; - vectors.resize(boost::extents[vector_dimensions.x][vector_dimensions.y][1]); - - std::vector<float3> vectors_linear(vectors.num_elements()); - std::copy_n(vectors.data(), vectors.num_elements(), vectors_linear.begin()); - coefficients = zer::launch( - vectors_linear , - parameters.vectors_size , - parameters.superpixel_size, - parameters.partitions , - parameters.maximum_degree , - parameters.symmetric , - parameters.normalize , - parameters.even_only , - parameters.edge_only ); - } - catch (std::exception& exception) - { - logger_->error(std::string(exception.what())); - } - }); - while (future_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) - QApplication::processEvents(); - - zernike_field_->set_data(superpixel_dimensions, parameters.superpixel_size, zer::expansion_size(parameters.maximum_degree), coefficients); - - logger_->info(std::string("Update successful.")); - owner_ ->set_is_loading(false); - }); -} - -void zernike_plugin::start () -{ - set_sink(std::make_shared<text_browser_sink>(owner_->console)); - - zernike_field_ = owner_->viewer->add_renderable<zernike_field>(); - connect(owner_->get_plugin<color_plugin>(), &color_plugin::on_change, [&](int mode, float k, bool inverted) - { - zernike_field_->set_color_mapping(mode, k, inverted); - }); -} -zernike_plugin::parameters zernike_plugin::get_parameters() const -{ - return - { - { - unsigned(owner_->get_plugin<data_plugin>()->selection_size()[0]), - unsigned(owner_->get_plugin<data_plugin>()->selection_size()[1]) - }, - { - line_edit::get_text<unsigned>(line_edit_superpixel_x), - line_edit::get_text<unsigned>(line_edit_superpixel_y) - }, - { - line_edit::get_text<unsigned>(line_edit_partitions_theta), - line_edit::get_text<unsigned>(line_edit_partitions_rho ) - }, - line_edit::get_text<unsigned>(line_edit_maximum_degree), - checkbox_symmetric->isChecked(), - checkbox_normalize->isChecked(), - checkbox_even_only->isChecked(), - checkbox_edge_only->isChecked() - }; -} -} diff --git a/source/ui/utility/plot_interactor.cpp b/source/ui/utility/plot_interactor.cpp deleted file mode 100644 index 68dd7f69e7c9e1a78a87e81dcc1c23cf6c2b11b3..0000000000000000000000000000000000000000 --- a/source/ui/utility/plot_interactor.cpp +++ /dev/null @@ -1,390 +0,0 @@ -#include <pli_vis/ui/utility/plot_interactor.hpp> - -#include <qapplication.h> -#include <qevent.h> -#include <qwhatsthis.h> -#include <qpainter.h> - -#include <qwt/qwt_plot.h> -#include <qwt/qwt_symbol.h> -#include <qwt/qwt_plot_canvas.h> -#include <qwt/qwt_plot_curve.h> -#include <qwt/qwt_plot_directpainter.h> - -namespace pli -{ -plot_interactor::plot_interactor(QwtPlot* plot) : QObject(plot), selected_curve_(nullptr), selected_point_(-1) -{ - auto canvas = qobject_cast<QwtPlotCanvas*>(plot->canvas()); - canvas->installEventFilter(this); - - canvas->setFocusPolicy (Qt::StrongFocus); - canvas->setCursor (Qt::PointingHandCursor); - canvas->setFocusIndicator(QwtPlotCanvas::ItemFocusIndicator); - canvas->setFocus (); - - shift_curve_cursor(true); -} - -bool plot_interactor::eventFilter(QObject* object, QEvent* event) -{ - if (plot() == nullptr || object != plot()->canvas()) - return false; - - switch (event->type()) - { - case QEvent::FocusIn: - { - show_cursor(true); - break; - } - case QEvent::FocusOut: - { - show_cursor(false); - break; - } - case QEvent::Paint: - { - QApplication::postEvent(this, new QEvent(QEvent::User)); - break; - } - case QEvent::MouseButtonPress: - { - const QMouseEvent* mouse_event = static_cast<QMouseEvent *>(event); - - if (mouse_event->buttons() == Qt::LeftButton) - select_or_add(mouse_event->pos()); - else if (mouse_event->buttons() == Qt::RightButton) - remove(mouse_event->pos()); - return true; - } - case QEvent::MouseMove: - { - const QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event); - move(mouse_event->pos()); - return true; - } - case QEvent::KeyPress: - { - const QKeyEvent* key_event = static_cast<QKeyEvent*>(event); - - const auto delta = 5; - switch (key_event->key()) - { - case Qt::Key_Up: - { - shift_curve_cursor(true); - return true; - } - case Qt::Key_Down: - { - shift_curve_cursor(false); - return true; - } - case Qt::Key_Right: - case Qt::Key_Plus: - { - if (selected_curve_) - shift_point_cursor(true); - else - shift_curve_cursor(true); - return true; - } - case Qt::Key_Left: - case Qt::Key_Minus: - { - if (selected_curve_) - shift_point_cursor(false); - else - shift_curve_cursor(true); - return true; - } - - case Qt::Key_1: - { - move_by(-delta, delta); - break; - } - case Qt::Key_2: - { - move_by(0, delta); - break; - } - case Qt::Key_3: - { - move_by(delta, delta); - break; - } - case Qt::Key_4: - { - move_by(-delta, 0); - break; - } - case Qt::Key_6: - { - move_by(delta, 0); - break; - } - case Qt::Key_7: - { - move_by(-delta, -delta); - break; - } - case Qt::Key_8: - { - move_by(0, -delta); - break; - } - case Qt::Key_9: - { - move_by(delta, -delta); - break; - } - default: - break; - } - } - default: - break; - } - - return QObject::eventFilter(object, event); -} -bool plot_interactor::event (QEvent* event) -{ - if (event->type() == QEvent::User) - { - show_cursor(true); - return true; - } - return QObject::event(event); -} - -void plot_interactor::select_or_add(const QPoint& pos) -{ - QwtPlotCurve* curve = nullptr; - auto dist = 10e10; - auto index = -1; - - const auto& item_list = plot()->itemList(); - for (auto it = item_list.begin(); it != item_list.end(); ++it) - { - if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve) - { - auto c = static_cast<QwtPlotCurve*>(*it); - - double d; - auto idx = c->closestPoint(pos, &d); - if (d < dist && idx != 0 && idx != c->dataSize() - 1) - { - curve = c; - index = idx; - dist = d; - } - } - } - - show_cursor(false); - selected_curve_ = nullptr; - selected_point_ = -1; - - if (curve) - { - selected_curve_ = curve; - selected_point_ = index; - show_cursor(true); - - if(dist >= 8) - { - auto x = plot()->invTransform(selected_curve_->xAxis(), pos.x()); - auto y = plot()->invTransform(selected_curve_->yAxis(), pos.y()); - QPointF sample(x, y); - - selected_point_ = curve->sample(index).x() < sample.x() ? index + 1 : index; - - QVector<QPointF> samples; - for (auto i = 0; i < curve->dataSize(); ++i) - samples.push_back(curve->sample(i)); - samples.insert(selected_point_, sample); - curve->setSamples(samples); - } - } - - on_change(); -} -void plot_interactor::remove (const QPoint& pos) -{ - QwtPlotCurve* curve = nullptr; - auto dist = 10e10; - auto index = -1; - - const auto& item_list = plot()->itemList(); - for (auto it = item_list.begin(); it != item_list.end(); ++it) - { - if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve) - { - auto c = static_cast<QwtPlotCurve*>(*it); - - double d; - auto idx = c->closestPoint(pos, &d); - if (d < dist && idx != 0 && idx != c->dataSize() - 1) - { - curve = c; - index = idx; - dist = d; - } - } - } - - show_cursor(false); - selected_curve_ = nullptr; - selected_point_ = -1; - - if (curve && dist < 4) - { - QVector<QPointF> samples; - for(auto i = 0; i < curve->dataSize(); ++i) - if(i != index) - samples.push_back(curve->sample(i)); - curve->setSamples(samples); - } - - on_change(); -} -void plot_interactor::move (const QPoint& pos) -{ - if (!selected_curve_) - return; - - QVector<double> xData(selected_curve_->dataSize()); - QVector<double> yData(selected_curve_->dataSize()); - - for (auto i = 0; i < static_cast<int>(selected_curve_->dataSize()); i++) - { - if (i == selected_point_) - { - xData[i] = plot()->invTransform(selected_curve_->xAxis(), pos.x()); - yData[i] = plot()->invTransform(selected_curve_->yAxis(), pos.y()); - } - else - { - const auto sample = selected_curve_->sample(i); - xData[i] = sample.x(); - yData[i] = sample.y(); - } - } - selected_curve_->setSamples(xData, yData); - - auto plotCanvas = qobject_cast<QwtPlotCanvas *>(plot()->canvas()); - - plotCanvas->setPaintAttribute(QwtPlotCanvas::ImmediatePaint, true); - plot()->replot(); - plotCanvas->setPaintAttribute(QwtPlotCanvas::ImmediatePaint, false); - - show_cursor(true); - - on_change(); -} -void plot_interactor::move_by (int dx, int dy) -{ - if (dx == 0 && dy == 0) - return; - if (!selected_curve_) - return; - const auto sample = selected_curve_->sample(selected_point_); - const auto x = plot()->transform(selected_curve_->xAxis(), sample.x()); - const auto y = plot()->transform(selected_curve_->yAxis(), sample.y()); - move(QPoint(qRound(x + dx), qRound(y + dy))); - - on_change(); -} - -void plot_interactor::show_cursor (bool enable) -{ - if (!selected_curve_) - return; - - auto symbol = const_cast<QwtSymbol *>(selected_curve_->symbol()); - - const auto brush = symbol->brush(); - if (enable) - symbol->setBrush(symbol->brush().color().dark(180)); - - QwtPlotDirectPainter direct_painter; - direct_painter.drawSeries(selected_curve_, selected_point_, selected_point_); - - if (enable) - symbol->setBrush(brush); -} -void plot_interactor::shift_curve_cursor(bool up ) -{ - QwtPlotItemIterator it; - - const auto& item_list = plot()->itemList(); - - QwtPlotItemList curve_list; - for (it = item_list.begin(); it != item_list.end(); ++it) - { - if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve) - curve_list += *it; - } - if (curve_list.isEmpty()) - return; - - it = curve_list.begin(); - - if (selected_curve_) - { - for (it = curve_list.begin(); it != curve_list.end(); ++it) - { - if (selected_curve_ == *it) - break; - } - if (it == curve_list.end()) - it = curve_list.begin(); - - if (up) - { - ++it; - if (it == curve_list.end()) - it = curve_list.begin(); - } - else - { - if (it == curve_list.begin()) - it = curve_list.end(); - --it; - } - } - - show_cursor(false); - selected_point_ = 0; - selected_curve_ = static_cast<QwtPlotCurve *>(*it); - show_cursor(true ); -} -void plot_interactor::shift_point_cursor(bool up ) -{ - if (!selected_curve_) - return; - - auto index = selected_point_ + (up ? 1 : -1); - index = (index + selected_curve_->dataSize()) % selected_curve_->dataSize(); - - if (index != selected_point_) - { - show_cursor(false); - selected_point_ = index; - show_cursor(true); - } -} - - QwtPlot* plot_interactor::plot() -{ - return qobject_cast<QwtPlot*>(parent()); -} -const QwtPlot* plot_interactor::plot() const -{ - return qobject_cast<const QwtPlot *>(parent()); -} - -} \ No newline at end of file diff --git a/source/ui/widgets/remote_viewer.cpp b/source/ui/widgets/remote_viewer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3dfcdd3b5022b3aa7b4752b6043e2bd52b1ba35 --- /dev/null +++ b/source/ui/widgets/remote_viewer.cpp @@ -0,0 +1,195 @@ +#include <pli_vis/ui/widgets/remote_viewer.hpp> + +#ifdef NDEBUG +#undef NDEBUG +#endif + +#include <array> +#include <cstdint> +#include <filesystem> + +#include <pli_vis/third_party/cppzmq/zmq.hpp> +#include <pli_vis/ui/plugins/data_plugin.hpp> +#include <pli_vis/ui/plugins/local_tractography_plugin.hpp> +#include <pli_vis/ui/application.hpp> +#include <pli_vis/visualization/primitives/camera.hpp> + +#include <image.pb.h> +#include <parameters.pb.h> + +namespace pli +{ +remote_viewer::remote_viewer(const std::string& address, const std::string& folder, application* owner, interactor* interactor, QWidget* parent) : QLabel(parent), owner_(owner), interactor_(interactor), alive_(true) +{ + setAttribute (Qt::WidgetAttribute::WA_StaticContents, true); + setWindowTitle(std::string("Remote Viewer " + address).c_str()); + move (12 , 32 ); + resize (640, 480); + show (); + + address_ = address; + folder_ = folder ; + + future_ = std::async(std::launch::async, [&] + { + auto camera = owner_->viewer->camera (); + auto data_plugin = owner_->get_plugin<pli::data_plugin> (); + auto color_plugin = owner_->get_plugin<pli::color_plugin> (); + auto tractography_plugin = owner_->get_plugin<pli::local_tractography_plugin>(); + + zmq::context_t context(1); + zmq::socket_t socket(context, ZMQ_PAIR); + socket.connect(std::string(address_)); + + while(alive_) + { + tt::parameters parameters; + + auto offset = data_plugin->selection_offset(); + auto size = data_plugin->selection_bounds(); + auto stride = data_plugin->selection_stride(); + if(data_plugin->filepath() != filepath_ || offset != offset_ || size != size_ || stride != stride_) + { + filepath_ = data_plugin->filepath(); + offset_ = offset; + size_ = size ; + stride_ = stride; + + auto data_loading_parameters = parameters.mutable_data_loading(); + data_loading_parameters->set_filepath (folder_ + std::experimental::filesystem::path(filepath_).filename().string()); + data_loading_parameters->set_dataset_format(filepath_.find("MSA") != std::string::npos ? tt::msa0309 : tt::vervet1818); + data_loading_parameters->mutable_selection()->mutable_offset()->set_x(offset_[0]); + data_loading_parameters->mutable_selection()->mutable_offset()->set_y(offset_[1]); + data_loading_parameters->mutable_selection()->mutable_offset()->set_z(offset_[2]); + data_loading_parameters->mutable_selection()->mutable_size ()->set_x(size_ [0]); + data_loading_parameters->mutable_selection()->mutable_size ()->set_y(size_ [1]); + data_loading_parameters->mutable_selection()->mutable_size ()->set_z(size_ [2]); + data_loading_parameters->mutable_selection()->mutable_stride()->set_x(stride_[0]); + data_loading_parameters->mutable_selection()->mutable_stride()->set_y(stride_[1]); + data_loading_parameters->mutable_selection()->mutable_stride()->set_z(stride_[2]); + } + + auto seed_offset = tractography_plugin->seed_offset(); + auto seed_size = tractography_plugin->seed_size (); + auto seed_stride = tractography_plugin->seed_stride(); + if (tractography_plugin->step () != step_ || + tractography_plugin->iterations() != iterations_ || + tractography_plugin->streamline_radius() != streamline_radius_ || + seed_offset != seed_offset_ || + seed_size != seed_size_ || + seed_stride != seed_stride_ || + color_plugin->mode() != color_mapping_ || + color_plugin->k () != k_ ) + { + step_ = tractography_plugin->step (); + iterations_ = tractography_plugin->iterations (); + streamline_radius_ = tractography_plugin->streamline_radius(); + seed_offset_ = seed_offset; + seed_size_ = seed_size ; + seed_stride_ = seed_stride; + color_mapping_ = color_plugin->mode(); + k_ = color_plugin->k(); + + auto particle_tracing_parameters = parameters.mutable_particle_tracing(); + particle_tracing_parameters->set_step (step_ ); + particle_tracing_parameters->set_iterations(iterations_); + particle_tracing_parameters->mutable_seeds()->mutable_offset()->set_x(seed_offset_[0]); + particle_tracing_parameters->mutable_seeds()->mutable_offset()->set_y(seed_offset_[1]); + particle_tracing_parameters->mutable_seeds()->mutable_offset()->set_z(seed_offset_[2]); + particle_tracing_parameters->mutable_seeds()->mutable_size ()->set_x(seed_size_ [0]); + particle_tracing_parameters->mutable_seeds()->mutable_size ()->set_y(seed_size_ [1]); + particle_tracing_parameters->mutable_seeds()->mutable_size ()->set_z(seed_size_ [2]); + particle_tracing_parameters->mutable_seeds()->mutable_stride()->set_x(seed_stride_[0]); + particle_tracing_parameters->mutable_seeds()->mutable_stride()->set_y(seed_stride_[1]); + particle_tracing_parameters->mutable_seeds()->mutable_stride()->set_z(seed_stride_[2]); + + auto color_mapping_parameters = parameters.mutable_color_mapping(); + color_mapping_parameters->set_mapping(tt::color_mapping(color_mapping_)); + color_mapping_parameters->set_k (k_); + + parameters.mutable_raytracing()->set_streamline_radius(streamline_radius_); + } + + if(camera->translation() != translation_ || + camera->forward () != forward_ || + camera->up () != up_ || + remote_viewer::size().width () != image_size_[0] || + remote_viewer::size().height() != image_size_[1] ) + { + translation_ = camera->translation(); + forward_ = camera->forward (); + up_ = camera->up (); + image_size_ = {std::size_t(remote_viewer::size().width()) , std::size_t(remote_viewer::size().height())}; + + auto raytracing_parameters = parameters.mutable_raytracing(); + raytracing_parameters->mutable_camera()->mutable_position()->set_x( translation_[0]); + raytracing_parameters->mutable_camera()->mutable_position()->set_y( translation_[1]); + raytracing_parameters->mutable_camera()->mutable_position()->set_z( translation_[2]); + raytracing_parameters->mutable_camera()->mutable_forward ()->set_x(-forward_ [0]); + raytracing_parameters->mutable_camera()->mutable_forward ()->set_y(-forward_ [1]); + raytracing_parameters->mutable_camera()->mutable_forward ()->set_z(-forward_ [2]); + raytracing_parameters->mutable_camera()->mutable_up ()->set_x( up_ [0]); + raytracing_parameters->mutable_camera()->mutable_up ()->set_y( up_ [1]); + raytracing_parameters->mutable_camera()->mutable_up ()->set_z( up_ [2]); + raytracing_parameters->mutable_image_size()->set_x(image_size_[0]); + raytracing_parameters->mutable_image_size()->set_y(image_size_[1]); + } + + std::string buffer; + parameters.SerializeToString(&buffer); + + zmq::message_t request(buffer.size()); + memcpy(request.data(), buffer.data(), buffer.size()); + socket.send(request); + + zmq::message_t reply; + socket.recv(&reply); + + tt::image image; + image.ParseFromArray(reply.data(), static_cast<std::int32_t>(reply.size())); + + image_ = QImage(reinterpret_cast<const unsigned char*>(image.data().c_str()), image.size().x(), image.size().y(), QImage::Format_RGBA8888); + on_render(); + } + }); + + on_render.connect([&] () + { + setPixmap(QPixmap::fromImage(image_)); + }); +} +remote_viewer::~remote_viewer() +{ + alive_ = false; + try + { + future_.get(); + } + catch(...) + { + + } +} + +void remote_viewer::closeEvent (QCloseEvent* event) +{ + QLabel::closeEvent(event); + on_close(); +} +void remote_viewer::keyPressEvent (QKeyEvent* event) +{ + interactor_->key_press_handler (event); +} +void remote_viewer::keyReleaseEvent(QKeyEvent* event) +{ + interactor_->key_release_handler(event); +} +void remote_viewer::mousePressEvent(QMouseEvent* event) +{ + interactor_->mouse_press_handler(event); +} +void remote_viewer::mouseMoveEvent (QMouseEvent* event) +{ + interactor_->mouse_move_handler (event); +} +} diff --git a/source/ui/widgets/transfer_function_editor.cpp b/source/ui/widgets/transfer_function_editor.cpp deleted file mode 100644 index e1f734f3db5e1e618939350f87825df3a0181e85..0000000000000000000000000000000000000000 --- a/source/ui/widgets/transfer_function_editor.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include <pli_vis/ui/widgets/transfer_function_editor.hpp> - -#include <qwt/qwt_curve_fitter.h> -#include <qwt/qwt_plot_curve.h> -#include <qwt/qwt_plot_grid.h> -#include <qwt/qwt_plot_histogram.h> -#include <qwt/qwt_symbol.h> - -#include <pli_vis/ui/utility/plot_interactor.hpp> - -namespace pli -{ -transfer_function_editor::transfer_function_editor(QWidget* parent) : QwtPlot(parent) -{ - auto font = axisFont(0); - font.setPointSize(8); - setAxisFont (0, font); - setAxisFont (2, font); - setAxisScale (0, 0, 255); - setAxisScale (2, 0, 255); - setAutoReplot(true); - - auto grid = new QwtPlotGrid; - grid->enableXMin (true); - grid->enableYMin (true); - grid->setMajorPen(QPen(Qt::black, 0, Qt::DotLine)); - grid->setMinorPen(QPen(Qt::gray , 0, Qt::DotLine)); - grid->attach (this); - - histogram_ = new QwtPlotHistogram; - histogram_->setPen (QPen (Qt::gray, 0)); - histogram_->setBrush(QBrush(Qt::gray)); - histogram_->setStyle(QwtPlotHistogram::HistogramStyle::Columns); - histogram_->attach (this); - - for (auto i = 0; i < 4; i++) - { - curves_[i] = new QwtPlotCurve(); - curves_[i]->setStyle (QwtPlotCurve::CurveStyle::Lines); - curves_[i]->setCurveAttribute(QwtPlotCurve::CurveAttribute::Fitted); - curves_[i]->setRenderHint (QwtPlotItem::RenderHint::RenderAntialiased); - curves_[i]->attach (this); - - auto curve_fitter = new QwtSplineCurveFitter; - curve_fitter->setFitMode (QwtSplineCurveFitter::FitMode::ParametricSpline); - curve_fitter->setSplineSize (100); - curves_[i] ->setCurveFitter(curve_fitter); - - QVector<QPointF> values; - values.push_back(QPointF(0 , 0 )); - values.push_back(QPointF(125, 10 * i)); - values.push_back(QPointF(250, 0 )); - curves_[i]->setSamples(values); - } - curves_[0]->setPen (Qt::red); - curves_[0]->setSymbol(new QwtSymbol(QwtSymbol::Ellipse, QBrush(Qt::red ), QPen(Qt::red , 1), QSize(4, 4))); - curves_[1]->setPen (Qt::green); - curves_[1]->setSymbol(new QwtSymbol(QwtSymbol::Ellipse, QBrush(Qt::green), QPen(Qt::green, 1), QSize(4, 4))); - curves_[2]->setPen (Qt::blue ); - curves_[2]->setSymbol(new QwtSymbol(QwtSymbol::Ellipse, QBrush(Qt::blue ), QPen(Qt::blue , 1), QSize(4, 4))); - curves_[3]->setPen (Qt::black); - curves_[3]->setSymbol(new QwtSymbol(QwtSymbol::Ellipse, QBrush(Qt::black), QPen(Qt::black, 1), QSize(4, 4))); - - auto point_picker = new plot_interactor(this); - connect(point_picker, SIGNAL(on_change()), this, SIGNAL(on_change())); -} - -std::vector<float4> transfer_function_editor::get_function() -{ - std::vector<float4> function(256, float4{0.0, 0.0, 0.0, 0.0}); - QwtSplineCurveFitter fitter; - fitter.setFitMode (QwtSplineCurveFitter::FitMode::ParametricSpline); - fitter.setSplineSize(256); - QVector<QPointF> red_points ; for (auto i = 0; i < curves_[0]->dataSize(); i++) red_points .push_back(curves_[0]->sample(i)); auto reds = fitter.fitCurve(red_points ); - QVector<QPointF> green_points; for (auto i = 0; i < curves_[1]->dataSize(); i++) green_points.push_back(curves_[1]->sample(i)); auto greens = fitter.fitCurve(green_points); - QVector<QPointF> blue_points ; for (auto i = 0; i < curves_[2]->dataSize(); i++) blue_points .push_back(curves_[2]->sample(i)); auto blues = fitter.fitCurve(blue_points ); - QVector<QPointF> alpha_points; for (auto i = 0; i < curves_[3]->dataSize(); i++) alpha_points.push_back(curves_[3]->sample(i)); auto alphas = fitter.fitCurve(alpha_points); - for (auto i = 0; i < 256; i++) - function[i] = float4{float(reds[i].y()) / 255.0F, float(greens[i].y()) / 255.0F, float(blues[i].y()) / 255.0F, float(alphas[i].y()) / 255.0F}; - return function; -} - -void transfer_function_editor::set_histogram_entries(const std::vector<std::size_t>& histogram_entries) -{ - QVector<QwtIntervalSample> samples; - for (auto i = 0; i < histogram_entries.size(); i++) - samples.push_back(QwtIntervalSample(histogram_entries[i], i, i + 1)); - histogram_->setSamples(samples); -} -} diff --git a/source/ui/widgets/viewer.cpp b/source/ui/widgets/viewer.cpp index aa3b566bb68ed25c2e041eb5ea98fdd5ea84892f..a384f786d5d11f05518a9969b51c01f4f30981e6 100644 --- a/source/ui/widgets/viewer.cpp +++ b/source/ui/widgets/viewer.cpp @@ -1,21 +1,23 @@ #include <pli_vis/ui/widgets/viewer.hpp> #include <QKeyEvent> -#include <QTimer> #include <pli_vis/visualization/interactors/simple_interactor.hpp> namespace pli { -viewer::viewer(QWidget* parent) : QOpenGLWidget(parent), interactor_(std::make_unique<simple_interactor>(&camera_)) +viewer::viewer(QWidget* parent) : QOpenGLWidget(parent), interactor_(std::make_unique<simple_interactor>(&camera_)), timer_(this) { reset_camera_transform(); setFocusPolicy(Qt::StrongFocus); - auto timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(16); + connect(&timer_, &QTimer::timeout, [&] () + { + update(); + timer_.start(); + }); + timer_.start(); } void viewer::remove_renderable(renderable* renderable) diff --git a/source/visualization/algorithms/streamline_renderer.cpp b/source/visualization/algorithms/streamline_renderer.cpp index bd754a41dae445edbc9026ba6dd0c2053a5b9c03..57b220148b44b1f626727b7ab03b120f1e25a0af 100644 --- a/source/visualization/algorithms/streamline_renderer.cpp +++ b/source/visualization/algorithms/streamline_renderer.cpp @@ -12,28 +12,33 @@ void streamline_renderer::initialize() vertex_array_ .reset(new gl::vertex_array); vertex_buffer_ .reset(new gl::array_buffer); direction_buffer_.reset(new gl::array_buffer); + index_buffer_ .reset(new gl::index_buffer); - program_->attach_shader(gl::vertex_shader (shaders::streamline_renderer_vert)); - program_->attach_shader(gl::fragment_shader(shaders::streamline_renderer_frag)); - program_->link(); - - vertex_array_ ->bind (); - program_ ->bind (); - vertex_buffer_ ->bind (); - program_ ->set_attribute_buffer ("vertex", 3, GL_FLOAT); + program_ ->attach_shader (gl::vertex_shader (shaders::streamline_renderer_vert)); + program_ ->attach_shader (gl::fragment_shader(shaders::streamline_renderer_frag)); + program_ ->link (); + vertex_array_ ->bind (); + program_ ->bind (); + vertex_buffer_ ->bind (); + program_ ->set_attribute_buffer ("vertex" , 4, GL_FLOAT); program_ ->enable_attribute_array("vertex"); - vertex_buffer_ ->unbind(); - direction_buffer_->bind (); - program_ ->set_attribute_buffer ("direction" , 3, GL_FLOAT); + vertex_buffer_ ->unbind (); + direction_buffer_->bind (); + program_ ->set_attribute_buffer ("direction", 4, GL_FLOAT); program_ ->enable_attribute_array("direction"); - direction_buffer_->unbind(); - program_ ->unbind(); - vertex_array_ ->unbind(); + direction_buffer_->unbind (); + index_buffer_ ->bind (); + vertex_array_ ->set_element_buffer (*index_buffer_.get()); + index_buffer_ ->unbind (); + program_ ->unbind (); + vertex_array_ ->unbind (); } void streamline_renderer::render (const camera* camera) { - vertex_array_->bind (); - program_ ->bind (); + vertex_array_->bind (); + program_ ->bind (); + index_buffer_->bind (); + program_ ->set_uniform("color_mode" , color_mode_); program_ ->set_uniform("color_k" , color_k_); program_ ->set_uniform("color_inverted", color_inverted_); @@ -41,30 +46,30 @@ void streamline_renderer::render (const camera* camera) program_ ->set_uniform("view" , camera->inverse_absolute_matrix()); program_ ->set_uniform("projection" , camera->projection_matrix ()); - glEnable (GL_LINE_SMOOTH); - glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDrawArrays(GL_LINES, 0, GLsizei(draw_count_)); - glDisable (GL_BLEND); - glDisable (GL_LINE_SMOOTH); + glDrawElements(GL_LINES, GLsizei(draw_count_), GL_UNSIGNED_INT, nullptr); - program_ ->unbind(); - vertex_array_->unbind(); + index_buffer_->unbind (); + program_ ->unbind (); + vertex_array_->unbind (); } - + void streamline_renderer::set_data( - const std::vector<float3>& points , - const std::vector<float3>& directions) + const std::vector<float4>& points , + const std::vector<float4>& directions, + const std::vector<unsigned>& indices ) { - draw_count_ = points.size(); - vertex_buffer_ ->bind (); - vertex_buffer_ ->set_data(draw_count_ * sizeof(float3), points .data()); + vertex_buffer_ ->set_data(points .size() * sizeof(float4) , points .data()); vertex_buffer_ ->unbind (); direction_buffer_->bind (); - direction_buffer_->set_data(draw_count_ * sizeof(float3), directions.data()); + direction_buffer_->set_data(directions.size() * sizeof(float4) , directions.data()); direction_buffer_->unbind (); + + index_buffer_ ->bind (); + index_buffer_ ->set_data(indices .size() * sizeof(unsigned), indices .data()); + index_buffer_ ->unbind (); + + draw_count_ = indices.size(); } } diff --git a/source/visualization/algorithms/volume_renderer.cpp b/source/visualization/algorithms/volume_renderer.cpp deleted file mode 100644 index 633785999bd07748ca417236fd83c736ba861739..0000000000000000000000000000000000000000 --- a/source/visualization/algorithms/volume_renderer.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include <pli_vis/visualization/algorithms/volume_renderer.hpp> - -#include <pli_vis/visualization/primitives/camera.hpp> -#include <shaders/volume_renderer_prepass.vert.glsl> -#include <shaders/volume_renderer_prepass.frag.glsl> -#include <shaders/volume_renderer.vert.glsl> -#include <shaders/volume_renderer.frag.glsl> - -namespace pli -{ -void volume_renderer::initialize() -{ - GLint default_framebuffer_id; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &default_framebuffer_id); - gl::framebuffer default_framebuffer(default_framebuffer_id); - - glm::ivec4 viewport; - glGetIntegerv(GL_VIEWPORT, reinterpret_cast<GLint*>(&viewport)); - - prepass_shader_program_ .reset(new gl::program ); - shader_program_ .reset(new gl::program ); - prepass_vertex_array_ .reset(new gl::vertex_array); - vertex_array_ .reset(new gl::vertex_array); - vertex_buffer_ .reset(new gl::array_buffer); - color_buffer_ .reset(new gl::array_buffer); - index_buffer_ .reset(new gl::index_buffer); - transfer_function_texture_.reset(new gl::texture_1d ); - volume_texture_ .reset(new gl::texture_3d ); - framebuffer_ .reset(new gl::framebuffer ); - exit_points_color_texture_.reset(new gl::texture_2d ); - exit_points_depth_texture_.reset(new gl::texture_2d ); - - prepass_shader_program_->attach_shader(gl::vertex_shader (shaders::volume_renderer_prepass_vert)); - prepass_shader_program_->attach_shader(gl::fragment_shader(shaders::volume_renderer_prepass_frag)); - prepass_shader_program_->link(); - - shader_program_ ->attach_shader(gl::vertex_shader (shaders::volume_renderer_vert)); - shader_program_ ->attach_shader(gl::fragment_shader(shaders::volume_renderer_frag)); - shader_program_ ->link(); - - // Initialize prepass shader program and vertex array. - prepass_shader_program_->bind(); - prepass_vertex_array_ ->bind(); - - vertex_buffer_ ->bind(); - prepass_shader_program_->set_attribute_buffer ("vertex", 3, GL_FLOAT); - prepass_shader_program_->enable_attribute_array("vertex"); - vertex_buffer_ ->unbind(); - - prepass_vertex_array_ ->unbind(); - prepass_shader_program_->unbind(); - - // Initialize main pass shader program and vertex array. - shader_program_ ->bind(); - vertex_array_ ->bind(); - - vertex_buffer_ ->bind(); - shader_program_ ->set_attribute_buffer ("vertex", 3, GL_FLOAT); - shader_program_ ->enable_attribute_array("vertex"); - vertex_buffer_ ->unbind(); - - vertex_array_ ->unbind(); - shader_program_ ->unbind(); - - // Set buffers for a unit cube. - std::vector<float> vertices = { - 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, - 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, - 1.0, 1.0, 0.0, 1.0, 1.0, 1.0 - }; - std::vector<unsigned> indices = { - 1, 5, 7, 7, 3, 1, 0, 2, 6, 6, 4, 0, - 0, 1, 3, 3, 2, 0, 7, 5, 4, 4, 6, 7, - 2, 3, 7, 7, 6, 2, 1, 0, 4, 4, 5, 1 - }; - - vertex_buffer_->bind (); - vertex_buffer_->set_data(sizeof(float) * vertices.size(), vertices.data()); - vertex_buffer_->unbind (); - - index_buffer_ ->bind (); - index_buffer_ ->set_data(sizeof(unsigned) * indices .size(), indices .data()); - index_buffer_ ->unbind (); - - draw_count_ = indices.size(); - - // Set textures. - transfer_function_texture_->bind (); - transfer_function_texture_->wrap_s (GL_REPEAT ); - transfer_function_texture_->min_filter(GL_NEAREST); - transfer_function_texture_->mag_filter(GL_NEAREST); - transfer_function_texture_->set_image (GL_RGBA32F, 256, GL_RGBA, GL_FLOAT); - transfer_function_texture_->unbind (); - - exit_points_color_texture_->bind (); - exit_points_color_texture_->wrap_s (GL_REPEAT); - exit_points_color_texture_->wrap_t (GL_REPEAT); - exit_points_color_texture_->min_filter(GL_NEAREST); - exit_points_color_texture_->mag_filter(GL_NEAREST); - exit_points_color_texture_->set_image (GL_RGBA32F, viewport[2], viewport[3], GL_RGBA, GL_FLOAT); - exit_points_color_texture_->unbind (); - - exit_points_depth_texture_->bind (); - exit_points_depth_texture_->wrap_s (GL_REPEAT); - exit_points_depth_texture_->wrap_t (GL_REPEAT); - exit_points_depth_texture_->min_filter(GL_NEAREST); - exit_points_depth_texture_->mag_filter(GL_NEAREST); - exit_points_depth_texture_->set_image (GL_DEPTH_COMPONENT24, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_FLOAT); - exit_points_depth_texture_->unbind (); - - volume_texture_ ->bind (); - volume_texture_ ->wrap_s (GL_REPEAT); - volume_texture_ ->wrap_t (GL_REPEAT); - volume_texture_ ->wrap_r (GL_REPEAT); - volume_texture_ ->min_filter(GL_LINEAR); - volume_texture_ ->mag_filter(GL_LINEAR); - volume_texture_ ->set_image (GL_R32F, 1, 1, 1, GL_RED, GL_FLOAT); - volume_texture_ ->unbind (); - - // Setup the framebuffer. - framebuffer_->bind (); - framebuffer_->set_texture (GL_COLOR_ATTACHMENT0, *exit_points_color_texture_.get()); - framebuffer_->set_texture (GL_DEPTH_ATTACHMENT , *exit_points_depth_texture_.get()); - assert(framebuffer_->is_valid() && framebuffer_->is_complete()); - default_framebuffer.bind(); -} -void volume_renderer::render (const camera* camera) -{ - GLint default_framebuffer_id; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &default_framebuffer_id); - gl::framebuffer default_framebuffer(default_framebuffer_id); - - glm::ivec4 viewport; - glGetIntegerv(GL_VIEWPORT, reinterpret_cast<GLint*>(&viewport)); - - // Apply prepass. - exit_points_color_texture_->bind (); - exit_points_color_texture_->set_image(GL_RGBA32F, viewport[2], viewport[3], GL_RGBA, GL_FLOAT); - exit_points_color_texture_->unbind (); - exit_points_depth_texture_->bind (); - exit_points_depth_texture_->set_image(GL_DEPTH_COMPONENT24, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_FLOAT); - exit_points_depth_texture_->unbind (); - - framebuffer_ ->bind(); - prepass_shader_program_ ->bind(); - prepass_vertex_array_ ->bind(); - index_buffer_ ->bind(); - - prepass_shader_program_ ->set_uniform("projection", camera->projection_matrix ()); - prepass_shader_program_ ->set_uniform("view" , camera->inverse_absolute_matrix()); - - glViewport (viewport[0], viewport[1], viewport[2], viewport[3]); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable (GL_CULL_FACE); - glCullFace (GL_FRONT); - glDrawElements(GL_TRIANGLES, draw_count_, GL_UNSIGNED_INT, nullptr); - glDisable (GL_CULL_FACE); - - prepass_shader_program_ ->unbind(); - prepass_vertex_array_ ->unbind(); - index_buffer_ ->unbind(); - default_framebuffer .bind(); - - // Apply main pass. - shader_program_ ->bind(); - vertex_array_ ->bind(); - index_buffer_ ->bind(); - - gl::texture_1d::set_active(GL_TEXTURE0); - transfer_function_texture_->bind(); - gl::texture_2d::set_active(GL_TEXTURE1); - exit_points_color_texture_->bind(); - gl::texture_3d::set_active(GL_TEXTURE2); - volume_texture_ ->bind(); - - shader_program_ ->set_uniform("projection" , camera->projection_matrix ()); - shader_program_ ->set_uniform("view" , camera->inverse_absolute_matrix()); - shader_program_ ->set_uniform("screen_size" , glm::uvec2(viewport[2], viewport[3])); - shader_program_ ->set_uniform("transfer_function", 0); - shader_program_ ->set_uniform("exit_points" , 1); - shader_program_ ->set_uniform("volume" , 2); - - glEnable (GL_CULL_FACE); - glCullFace (GL_BACK); - glDrawElements(GL_TRIANGLES, draw_count_, GL_UNSIGNED_INT, nullptr); - glDisable (GL_CULL_FACE); - - gl::texture_3d::set_active(GL_TEXTURE2); - volume_texture_ ->unbind(); - gl::texture_2d::set_active(GL_TEXTURE1); - exit_points_color_texture_->unbind(); - gl::texture_1d::set_active(GL_TEXTURE0); - transfer_function_texture_->unbind(); - - shader_program_ ->unbind(); - vertex_array_ ->unbind(); - index_buffer_ ->unbind(); -} - -void volume_renderer::set_data (const uint3& dimensions, const float* data) -{ - volume_texture_->bind (); - volume_texture_->set_image(GL_R32F, dimensions.x, dimensions.y, dimensions.z, GL_RED, GL_FLOAT, data); - volume_texture_->unbind (); -} -void volume_renderer::set_transfer_function(const std::vector<float4>& transfer_function) -{ - transfer_function_texture_->bind (); - transfer_function_texture_->set_image(GL_RGBA32F, 256, GL_RGBA, GL_FLOAT, transfer_function.data()); - transfer_function_texture_->unbind (); -} -void volume_renderer::set_step_size (float step_size) -{ - shader_program_->bind (); - shader_program_->set_uniform("step_size", step_size); - shader_program_->unbind (); -} -} diff --git a/source/visualization/algorithms/zernike_field.cpp b/source/visualization/algorithms/zernike_field.cpp deleted file mode 100644 index 0a2d8139575ef6f8163523aa39ee6f1720c2d39b..0000000000000000000000000000000000000000 --- a/source/visualization/algorithms/zernike_field.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include <pli_vis/visualization/algorithms/zernike_field.hpp> - -#include <pli_vis/visualization/primitives/camera.hpp> -#include <shaders/simple_color_texture.vert.glsl> -#include <shaders/simple_color_texture.frag.glsl> -#include <shaders/zernike.vert.glsl> -#include <shaders/zernike.frag.glsl> - -namespace pli -{ -void zernike_field::initialize() -{ - std::vector<float> vertices = {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f}; - std::vector<float> texcoords = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; - std::vector<unsigned> indices = {0u, 1u, 2u, 0u, 2u, 3u}; - - prepass_program_ = std::make_unique<gl::program> (); - prepass_vertex_array_ = std::make_unique<gl::vertex_array> (); - main_program_ = std::make_unique<gl::program> (); - main_vertex_array_ = std::make_unique<gl::vertex_array> (); - - vertex_buffer_ = std::make_unique<gl::array_buffer> (); - texcoord_buffer_ = std::make_unique<gl::array_buffer> (); - index_buffer_ = std::make_unique<gl::index_buffer> (); - coefficient_buffer_ = std::make_unique<gl::shader_storage_buffer>(); - - render_target_ = std::make_unique<render_target> (); - - prepass_program_ ->attach_shader (gl::vertex_shader (shaders::zernike_vert)); - prepass_program_ ->attach_shader (gl::fragment_shader(shaders::zernike_frag)); - prepass_program_ ->link (); - prepass_vertex_array_->bind (); - prepass_program_ ->bind (); - vertex_buffer_ ->bind (); - vertex_buffer_ ->set_data (vertices.size() * sizeof(float), vertices.data()); - prepass_program_ ->set_attribute_buffer ("position", 3, GL_FLOAT); - prepass_program_ ->enable_attribute_array("position"); - vertex_buffer_ ->unbind (); - index_buffer_ ->bind (); - index_buffer_ ->set_data (indices.size() * sizeof(unsigned), indices.data()); - index_buffer_ ->unbind (); - prepass_vertex_array_->set_element_buffer (*index_buffer_.get()); - prepass_program_ ->unbind (); - prepass_vertex_array_->unbind (); - - main_program_ ->attach_shader (gl::vertex_shader (shaders::simple_color_texture_vert)); - main_program_ ->attach_shader (gl::fragment_shader(shaders::simple_color_texture_frag)); - main_program_ ->link (); - main_vertex_array_ ->bind (); - main_program_ ->bind (); - vertex_buffer_ ->bind (); - vertex_buffer_ ->set_data (vertices.size() * sizeof(float), vertices.data()); - main_program_ ->set_attribute_buffer ("position", 3, GL_FLOAT); - main_program_ ->enable_attribute_array("position"); - vertex_buffer_ ->unbind (); - texcoord_buffer_ ->bind (); - texcoord_buffer_ ->set_data (texcoords.size() * sizeof(float), texcoords.data()); - main_program_ ->set_attribute_buffer ("texcoords", 2, GL_FLOAT); - main_program_ ->enable_attribute_array("texcoords"); - texcoord_buffer_ ->unbind (); - index_buffer_ ->bind (); - index_buffer_ ->set_data (indices.size() * sizeof(unsigned), indices.data()); - index_buffer_ ->unbind (); - main_vertex_array_ ->set_element_buffer (*index_buffer_.get()); - main_program_ ->unbind (); - main_vertex_array_ ->unbind (); - - draw_count_ = indices.size(); -} -void zernike_field::render (const camera* camera) -{ - if(needs_update_) - { - render_target_ ->resize ({8192u, 8192u}); - render_target_ ->bind (); - prepass_program_ ->bind (); - prepass_vertex_array_->bind (); - coefficient_buffer_ ->bind_base (0); - - prepass_program_ ->set_uniform("dimensions" , dimensions_ ); - prepass_program_ ->set_uniform("spacing" , spacing_ ); - prepass_program_ ->set_uniform("coefficients_per_voxel", coefficients_per_voxel_); - prepass_program_ ->set_uniform("color_mode" , color_mode_ ); - prepass_program_ ->set_uniform("color_k" , color_k_ ); - prepass_program_ ->set_uniform("color_inverted" , color_inverted_ ); - glViewport (0, 0, 8192, 8192); - glClearColor (0.0, 0.0, 0.0, 0.0); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glDrawElementsInstanced(GL_TRIANGLES, draw_count_, GL_UNSIGNED_INT, nullptr, primitive_count_); - - prepass_vertex_array_->unbind (); - prepass_program_ ->unbind (); - render_target_ ->unbind (); - - render_target_->color_texture()->bind (); - render_target_->color_texture()->generate_mipmaps(); - render_target_->color_texture()->unbind (); - - needs_update_ = false; - } - - gl::texture_2d::set_active(GL_TEXTURE0); - - render_target_ ->color_texture()->bind(); - main_program_ ->bind(); - main_vertex_array_->bind(); - - main_program_ ->set_uniform("texture_unit", 0); - main_program_ ->set_uniform("model" , absolute_matrix ()); - main_program_ ->set_uniform("view" , camera->inverse_absolute_matrix ()); - main_program_ ->set_uniform("projection" , camera->projection_matrix ()); - main_program_ ->set_uniform("size" , glm::vec2(dimensions_ * spacing_ )); - glDrawElements(GL_TRIANGLES, draw_count_, GL_UNSIGNED_INT, nullptr); - - main_vertex_array_->unbind(); - main_program_ ->unbind(); - render_target_ ->color_texture()->unbind(); -} - -void zernike_field::set_data (const uint2& dimensions, const uint2& spacing, const unsigned coefficients_per_voxel, const std::vector<float>& coefficients) -{ - dimensions_ = {dimensions.x , dimensions.y}; - spacing_ = {spacing .x , spacing .y}; - coefficients_per_voxel_ = coefficients_per_voxel; - primitive_count_ = dimensions_.x * dimensions_.y; - - coefficient_buffer_->bind () ; - coefficient_buffer_->set_data (coefficients.size() * sizeof(float), coefficients.data()); - coefficient_buffer_->bind_base(0); - coefficient_buffer_->unbind () ; - - needs_update_ = true; -} -} diff --git a/source/visualization/interactors/orbit_interactor.cpp b/source/visualization/interactors/orbit_interactor.cpp deleted file mode 100644 index 59987f36c3680c96384773a7a0b9b9cfaee564b8..0000000000000000000000000000000000000000 --- a/source/visualization/interactors/orbit_interactor.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include <pli_vis/visualization/interactors/orbit_interactor.hpp> - -#include <QKeyEvent> - -#include <pli_vis/visualization/primitives/camera.hpp> - -namespace pli -{ -orbit_interactor::orbit_interactor(camera* camera) : interactor(camera) -{ - -} - -void orbit_interactor::mouse_press_handler(QMouseEvent* event) -{ - last_mouse_position_ = event->pos(); -} -void orbit_interactor::mouse_move_handler (QMouseEvent* event) -{ - auto dx = event->x() - last_mouse_position_.x(); - auto dy = event->y() - last_mouse_position_.y(); - - if (event->buttons() & Qt::LeftButton) - { - auto translation = camera_->translation(); - camera_->translate(-translation); - camera_->rotate (glm::angleAxis(glm::radians( look_speed_ * dx), glm::vec3(0.0, 0.0, 1.0))); - camera_->rotate (glm::angleAxis(glm::radians(-look_speed_ * dy), camera_->right())); - camera_->translate(glm::length(translation) * camera_->forward()); - } - if (event->buttons() & Qt::RightButton) - { - if(camera_->orthographic()) - camera_->set_scale(camera_->scale() + glm::vec3(1.0) * ((1.0F / (2.0F * camera_->orthographic_size())) * move_speed_ * dy)); - else - camera_->translate(move_speed_ * dy * camera_->forward()); - } - - last_mouse_position_ = event->pos(); -} -}