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