File indexing completed on 2025-02-23 03:35:00
0001 /* 0002 File : CartesianPlot.h 0003 Project : LabPlot 0004 Description : Cartesian plot 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2011-2023 Alexander Semke <alexander.semke@web.de> 0007 SPDX-FileCopyrightText: 2012-2021 Stefan Gerlach <stefan.gerlach@uni.kn> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #ifndef CARTESIANPLOT_H 0013 #define CARTESIANPLOT_H 0014 0015 #include "backend/lib/Range.h" 0016 #include "backend/worksheet/plots/AbstractPlot.h" 0017 #include "backend/worksheet/plots/cartesian/Axis.h" 0018 #include "backend/worksheet/plots/cartesian/CartesianCoordinateSystem.h" 0019 0020 #include "backend/nsl/nsl_sf_stats.h" 0021 0022 class AbstractColumn; 0023 class CartesianPlotPrivate; 0024 class CartesianPlotLegend; 0025 class CartesianCoordinateSystem; 0026 class CartesianPlotDock; 0027 class Histogram; 0028 class InfoElementDialog; 0029 class Line; 0030 class XYCurve; 0031 class KConfig; 0032 0033 using Dimension = CartesianCoordinateSystem::Dimension; 0034 0035 #ifdef SDK 0036 #include "labplot_export.h" 0037 class LABPLOT_EXPORT CartesianPlot : public AbstractPlot { 0038 #else 0039 class CartesianPlot : public AbstractPlot { 0040 #endif 0041 Q_OBJECT 0042 0043 public: 0044 explicit CartesianPlot(const QString& name); 0045 ~CartesianPlot() override; 0046 0047 enum class Type { FourAxes, TwoAxes, TwoAxesCentered, TwoAxesCenteredZero }; 0048 enum class MouseMode { Selection, ZoomSelection, ZoomXSelection, ZoomYSelection, Cursor, Crosshair }; 0049 enum class NavigationOperation { 0050 ScaleAuto, 0051 ScaleAutoX, 0052 ScaleAutoY, 0053 ZoomIn, 0054 ZoomOut, 0055 ZoomInX, 0056 ZoomOutX, 0057 ZoomInY, 0058 ZoomOutY, 0059 ShiftLeftX, 0060 ShiftRightX, 0061 ShiftUpY, 0062 ShiftDownY 0063 }; 0064 enum class RangeType { Free, Last, First }; 0065 Q_ENUM(RangeType) 0066 enum class RangeBreakStyle { Simple, Vertical, Sloped }; 0067 0068 struct RangeBreak { 0069 RangeBreak() 0070 : range(qQNaN(), qQNaN()) 0071 , position(0.5) 0072 , style(RangeBreakStyle::Sloped) { 0073 } 0074 bool isValid() const { 0075 return range.valid(); 0076 } 0077 Range<double> range; 0078 double position; 0079 RangeBreakStyle style; 0080 }; 0081 0082 // simple wrapper for QList<RangeBreaking> in order to get our macros working 0083 // TODO: same for xRanges, etc.? 0084 struct RangeBreaks { 0085 RangeBreaks() 0086 : lastChanged(-1) { 0087 RangeBreak b; 0088 list << b; 0089 } 0090 QList<RangeBreak> list; 0091 int lastChanged; 0092 }; 0093 0094 void setType(Type type); 0095 Type type() const; 0096 0097 static int cSystemIndex(WorksheetElement* e); 0098 0099 QIcon icon() const override; 0100 virtual QMenu* createContextMenu() override; 0101 QMenu* addNewMenu(); 0102 QMenu* analysisMenu(); 0103 QVector<AbstractAspect*> dependsOn() const override; 0104 QVector<AspectType> pasteTypes() const override; 0105 0106 void setRect(const QRectF&) override; 0107 void setPrevRect(const QRectF&) override; 0108 QRectF dataRect() const; 0109 void setMouseMode(MouseMode); 0110 MouseMode mouseMode() const; 0111 BASIC_D_ACCESSOR_DECL(bool, isInteractive, Interactive) 0112 void navigate(int cSystemIndex, NavigationOperation); 0113 const QList<QColor>& themeColorPalette() const; 0114 const QColor themeColorPalette(int index) const; 0115 void processDropEvent(const QVector<quintptr>&) override; 0116 bool isPanningActive() const; 0117 bool isPrinted() const; 0118 bool isSelected() const; 0119 0120 void addLegend(CartesianPlotLegend*); 0121 int curveCount(); 0122 const XYCurve* getCurve(int index); 0123 double cursorPos(int cursorNumber); 0124 int curveChildIndex(const WorksheetElement*) const; 0125 0126 void save(QXmlStreamWriter*) const override; 0127 bool load(XmlStreamReader*, bool preview) override; 0128 void finalizeLoad(); 0129 void loadThemeConfig(const KConfig&) override; 0130 void saveTheme(KConfig& config); 0131 void wheelEvent(const QPointF& sceneRelPos, int delta, int xIndex, int yIndex, bool considerDimension, Dimension dim); 0132 void mousePressZoomSelectionMode(QPointF logicPos, int cSystemIndex); 0133 void mousePressCursorMode(int cursorNumber, QPointF logicPos); 0134 void mouseMoveZoomSelectionMode(QPointF logicPos, int cSystemIndex); 0135 void mouseMoveSelectionMode(QPointF logicStart, QPointF logicEnd); 0136 void mouseMoveCursorMode(int cursorNumber, QPointF logicPos); 0137 void mouseReleaseZoomSelectionMode(int cSystemIndex); 0138 void mouseHoverZoomSelectionMode(QPointF logicPos, int cSystemIndex); 0139 void mouseHoverOutsideDataRect(); 0140 0141 const QString rangeDateTimeFormat(const Dimension) const; 0142 const QString rangeDateTimeFormat(const Dimension, const int index) const; 0143 BASIC_D_ACCESSOR_DECL(CartesianPlot::RangeType, rangeType, RangeType) 0144 BASIC_D_ACCESSOR_DECL(bool, niceExtend, NiceExtend) 0145 BASIC_D_ACCESSOR_DECL(int, rangeLastValues, RangeLastValues) 0146 BASIC_D_ACCESSOR_DECL(int, rangeFirstValues, RangeFirstValues) 0147 0148 bool autoScale(const Dimension, int index = -1) const; 0149 void enableAutoScale(const Dimension, int index, bool enable, bool fullRange = false); 0150 0151 int rangeCount(const Dimension) const; 0152 const Range<double>& range(const Dimension, int index = -1) const; // get range of (default) plot range 0153 void setRangeDefault(const Dimension, const Range<double>); // set range of default plot range 0154 void setRange(const Dimension, const int index, const Range<double>& range); 0155 void setXRange(int index, const Range<double>&); 0156 void setYRange(int index, const Range<double>&); 0157 const Range<double>& dataRange(const Dimension, int index = -1); 0158 bool rangeDirty(const Dimension, int index) const; 0159 void setRangeDirty(const Dimension, int index, bool dirty); 0160 void addXRange(); // add new x range 0161 void addYRange(); // add new y range 0162 void addXRange(const Range<double>&); // add x range 0163 void addYRange(const Range<double>&); // add y range 0164 void removeRange(const Dimension, int index); // remove selected range 0165 0166 // convenience methods 0167 void setMin(const Dimension, int index, double); // set x min of range index 0168 void setMax(const Dimension, int index, double); // set x max of range index 0169 void setRangeFormat(const Dimension, const RangeT::Format); 0170 void setRangeFormat(const Dimension, const int, const RangeT::Format); 0171 RangeT::Format rangeFormat(const Dimension, const int) const; 0172 RangeT::Scale rangeScale(const Dimension, const int index) const; 0173 RangeT::Format xRangeFormatDefault() const; // range format of default cSystem 0174 RangeT::Format yRangeFormatDefault() const; // range format of default cSystem 0175 BASIC_D_INDEX_ACCESSOR_DECL(RangeT::Format, xRangeFormat, XRangeFormat) // range format of x range index 0176 BASIC_D_INDEX_ACCESSOR_DECL(RangeT::Format, yRangeFormat, YRangeFormat) // range format of x range index 0177 void setRangeScale(const Dimension, const int index, const RangeT::Scale scale); 0178 BASIC_D_ACCESSOR_DECL(RangeT::Scale, xRangeScale, XRangeScale) // x range scale of default cSystem 0179 BASIC_D_INDEX_ACCESSOR_DECL(RangeT::Scale, xRangeScale, XRangeScale) // range scale of x range index 0180 BASIC_D_ACCESSOR_DECL(RangeT::Scale, yRangeScale, YRangeScale) // y range scale of default cSystem 0181 BASIC_D_INDEX_ACCESSOR_DECL(RangeT::Scale, yRangeScale, YRangeScale) // range scale of x range index 0182 0183 // range breaks 0184 BASIC_D_ACCESSOR_DECL(bool, xRangeBreakingEnabled, XRangeBreakingEnabled) 0185 BASIC_D_ACCESSOR_DECL(bool, yRangeBreakingEnabled, YRangeBreakingEnabled) 0186 CLASS_D_ACCESSOR_DECL(RangeBreaks, xRangeBreaks, XRangeBreaks) 0187 CLASS_D_ACCESSOR_DECL(RangeBreaks, yRangeBreaks, YRangeBreaks) 0188 0189 // cursor 0190 Line* cursorLine() const; 0191 CLASS_D_ACCESSOR_DECL(bool, cursor0Enable, Cursor0Enable) 0192 CLASS_D_ACCESSOR_DECL(bool, cursor1Enable, Cursor1Enable) 0193 0194 int coordinateSystemCount() const; // get number of coordinate systems 0195 CartesianCoordinateSystem* coordinateSystem(int) const; // get coordinate system index 0196 CartesianCoordinateSystem* defaultCoordinateSystem() const; // return default coordinate system 0197 void addCoordinateSystem(); // add a new coordinate system 0198 void addCoordinateSystem(CartesianCoordinateSystem* cSystem); // add a coordinate system 0199 void removeCoordinateSystem(int index); // remove coordinate system index 0200 BASIC_D_ACCESSOR_DECL(int, defaultCoordinateSystemIndex, DefaultCoordinateSystemIndex) 0201 void setCoordinateSystemRangeIndex(int cSystemIndex, Dimension, int rangeIndex); 0202 0203 void retransformScales(); 0204 void retransformScale(Dimension, int index); 0205 0206 QString theme() const; 0207 0208 typedef CartesianPlotPrivate Private; 0209 0210 public Q_SLOTS: 0211 void setTheme(const QString&); 0212 virtual void retransform() override; 0213 0214 private: 0215 void init(); 0216 void initActions(); 0217 void initMenus(); 0218 void setColorPalette(const KConfig&); 0219 const XYCurve* currentCurve() const; 0220 void zoom(int index, const Dimension, bool in, const double relPosSceneRange); 0221 void checkAxisFormat(const int cSystemIndex, const AbstractColumn*, Axis::Orientation); 0222 void calculateDataRange(const Dimension, const int index, bool completeRange = true); 0223 int curveTotalCount() const; 0224 0225 CartesianPlotLegend* m_legend{nullptr}; 0226 double m_zoomFactor{1.2}; 0227 QList<QColor> m_themeColorPalette; 0228 bool m_menusInitialized{false}; 0229 0230 //"add new" actions 0231 QAction* addCurveAction{nullptr}; 0232 QAction* addEquationCurveAction{nullptr}; 0233 0234 // statistical plots 0235 QAction* addHistogramAction{nullptr}; 0236 QAction* addBoxPlotAction{nullptr}; 0237 QAction* addQQPlotAction{nullptr}; 0238 QAction* addKDEPlotAction{nullptr}; 0239 0240 // bar plots 0241 QAction* addBarPlotAction{nullptr}; 0242 QAction* addLollipopPlotAction{nullptr}; 0243 0244 // analysis curves 0245 QAction* addDataReductionCurveAction{nullptr}; 0246 QAction* addDifferentiationCurveAction{nullptr}; 0247 QAction* addIntegrationCurveAction{nullptr}; 0248 QAction* addInterpolationCurveAction{nullptr}; 0249 QAction* addSmoothCurveAction{nullptr}; 0250 QAction* addFitCurveAction{nullptr}; 0251 QAction* addFourierFilterCurveAction{nullptr}; 0252 QAction* addFourierTransformCurveAction{nullptr}; 0253 QAction* addHilbertTransformCurveAction{nullptr}; 0254 QAction* addConvolutionCurveAction{nullptr}; 0255 QAction* addCorrelationCurveAction{nullptr}; 0256 0257 QAction* addHorizontalAxisAction{nullptr}; 0258 QAction* addVerticalAxisAction{nullptr}; 0259 QAction* addLegendAction{nullptr}; 0260 QAction* addTextLabelAction{nullptr}; 0261 QAction* addImageAction{nullptr}; 0262 QAction* addInfoElementAction{nullptr}; 0263 QAction* addCustomPointAction{nullptr}; 0264 QAction* addReferenceLineAction{nullptr}; 0265 QAction* addReferenceRangeAction{nullptr}; 0266 0267 // analysis menu actions 0268 QAction* addDataOperationAction{nullptr}; 0269 QAction* addDataReductionAction{nullptr}; 0270 QAction* addDifferentiationAction{nullptr}; 0271 QAction* addIntegrationAction{nullptr}; 0272 QAction* addInterpolationAction{nullptr}; 0273 QAction* addSmoothAction{nullptr}; 0274 QVector<QAction*> addFitActions; 0275 QAction* addFourierFilterAction{nullptr}; 0276 QAction* addFourierTransformAction{nullptr}; 0277 QAction* addHilbertTransformAction{nullptr}; 0278 QAction* addConvolutionAction{nullptr}; 0279 QAction* addCorrelationAction{nullptr}; 0280 0281 QMenu* m_addNewMenu{nullptr}; 0282 QMenu* addNewAnalysisMenu{nullptr}; 0283 QMenu* dataAnalysisMenu{nullptr}; 0284 QMenu* themeMenu{nullptr}; 0285 0286 // storing the pointer, because then it can be implemented also interactive clicking on a curve 0287 // otherwise I have to do QDialog::exec and everything is blocked 0288 // When saving, it is possible to use show 0289 InfoElementDialog* m_infoElementDialog{nullptr}; 0290 0291 Q_DECLARE_PRIVATE(CartesianPlot) 0292 0293 friend CartesianPlotDock; 0294 friend class CartesianPlotTest; 0295 friend class MultiRangeTest2; 0296 0297 public Q_SLOTS: 0298 void addHorizontalAxis(); 0299 void addVerticalAxis(); 0300 void addHistogramFit(Histogram*, nsl_sf_stats_distribution); 0301 0302 void addDataReductionCurve(); 0303 void addDifferentiationCurve(); 0304 void addIntegrationCurve(); 0305 void addInterpolationCurve(); 0306 void addSmoothCurve(); 0307 void addFitCurve(); 0308 void addFourierFilterCurve(); 0309 0310 void addLegend(); 0311 void addTextLabel(); 0312 void addImage(); 0313 void addCustomPoint(); 0314 void addReferenceLine(); 0315 void addReferenceRange(); 0316 void addInfoElement(); 0317 0318 bool scaleAuto(int xIndex = -1, int yIndex = -1, bool fullRange = true, bool suppressRetransformScale = false); 0319 bool scaleAuto(const Dimension, int index = -1, bool fullRange = true, bool suppressRetransformScale = false); 0320 0321 void zoomIn(int xIndex = -1, int yIndex = -1, const QPointF& sceneRelPos = QPointF(0.5, 0.5)); 0322 void zoomOut(int xIndex = -1, int yIndex = -1, const QPointF& sceneRelPos = QPointF(0.5, 0.5)); 0323 void zoomInX(int index = -1); 0324 void zoomOutX(int index = -1); 0325 void zoomInY(int index = -1); 0326 void zoomOutY(int index = -1); 0327 void zoomInOut(const int index, const Dimension dim, const bool zoomIn, const double relScenePosRange = 0.5); 0328 0329 void shiftLeftX(int index = -1); 0330 void shiftRightX(int index = -1); 0331 void shiftUpY(int index = -1); 0332 void shiftDownY(int index = -1); 0333 void shift(int index, const Dimension, bool leftOrDown); 0334 0335 void cursor(); 0336 0337 void dataChanged(int xIndex = -1, int yIndex = -1, WorksheetElement* sender = nullptr); 0338 0339 private Q_SLOTS: 0340 void updateLegend(); 0341 void childAdded(const AbstractAspect*); 0342 void childRemoved(const AbstractAspect* parent, const AbstractAspect* before, const AbstractAspect* child); 0343 void childHovered(); 0344 0345 void dataChanged(WorksheetElement*); 0346 void dataChanged(XYCurve*, const Dimension); 0347 void plotColorChanged(); 0348 void curveVisibilityChanged(); 0349 void boxPlotOrientationChanged(WorksheetElement::Orientation); 0350 0351 // SLOTs for changes triggered via QActions in the context menu 0352 void loadTheme(const QString&); 0353 0354 protected: 0355 CartesianPlot(const QString& name, CartesianPlotPrivate* dd); 0356 0357 Q_SIGNALS: 0358 void rangeTypeChanged(CartesianPlot::RangeType); 0359 void niceExtendChanged(bool); 0360 void rangeFormatChanged(const Dimension, int rangeIndex, RangeT::Format); 0361 void rangeLastValuesChanged(int); 0362 void rangeFirstValuesChanged(int); 0363 void rectChanged(QRectF&); 0364 void autoScaleChanged(const Dimension, int xRangeIndex, bool); 0365 void rangeChanged(const Dimension, int, Range<double>); 0366 void minChanged(const Dimension, int rangeIndex, double); 0367 void maxChanged(const Dimension, int rangeIndex, double); 0368 void scaleChanged(const Dimension, int rangeIndex, RangeT::Scale); 0369 void defaultCoordinateSystemIndexChanged(int); 0370 void xRangeBreakingEnabledChanged(bool); 0371 void xRangeBreaksChanged(const CartesianPlot::RangeBreaks&); 0372 void yRangeBreakingEnabledChanged(bool); 0373 void yRangeBreaksChanged(const CartesianPlot::RangeBreaks&); 0374 void themeChanged(const QString&); 0375 void axisShiftSignal(int delta, Dimension dim, int index); 0376 void mousePressZoomSelectionModeSignal(QPointF logicPos); 0377 void mousePressCursorModeSignal(int cursorNumber, QPointF logicPos); 0378 void mouseMoveSelectionModeSignal(QPointF logicalStart, QPointF logicalEnd); 0379 void mouseMoveZoomSelectionModeSignal(QPointF logicPos); 0380 void mouseMoveCursorModeSignal(int cursorNumber, QPointF logicPos); 0381 void mouseReleaseCursorModeSignal(); 0382 void mouseReleaseZoomSelectionModeSignal(); 0383 void mouseHoverZoomSelectionModeSignal(QPointF logicalPoint); 0384 void mouseHoverOutsideDataRectSignal(); 0385 void wheelEventSignal(const QPointF& sceneRelPos, int delta, int xIndex, int yIndex, bool considerDimension, Dimension dim); 0386 void curveNameChanged(const AbstractAspect* curve); 0387 void cursorPosChanged(int cursorNumber, double xPos); 0388 void curveAdded(const XYCurve*); 0389 void curveRemoved(const XYCurve*); 0390 void plotColorChanged(const QColor&, const QString& curveName); 0391 void cursorPenChanged(QPen); 0392 void curveDataChanged(const XYCurve*); 0393 void curveVisibilityChangedSignal(); 0394 void mouseModeChanged(CartesianPlot::MouseMode); 0395 void cursor0EnableChanged(bool enable); 0396 void cursor1EnableChanged(bool enable); 0397 0398 void scaleRetransformed(const CartesianPlot* plot, const Dimension dim, int index); 0399 }; 0400 0401 #endif