File indexing completed on 2024-05-12 04:20:32

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef KCHARTCHART_H
0010 #define KCHARTCHART_H
0011 
0012 #include <QWidget>
0013 
0014 #include "kchart_export.h"
0015 #include "KChartGlobal.h"
0016 
0017 /*
0018 Simplified(*) overview of object ownership in a chart:
0019 
0020                 Chart is-a QWidget
0021                  |
0022           n CoordinatePlanes is-a AbstractArea is-a AbstractLayoutItem is-a QLayoutItem
0023                  |
0024             n Diagrams is-a QAbstractItemView is-a QWidget
0025               /   |   \
0026   AbstractGrid    |   Axes (can be shared between diagrams) is-a AbstractArea is-a... QLayoutItem
0027  (no base class)  |
0028                 Legends is-a AbstractAreaWidget is-a QWidget
0029 
0030 (*) less important classes, including base classes, removed.
0031 
0032 
0033 Layout rules:
0034 
0035 In principle, every size or existence change in one of the objects listed above must be propagated
0036 to all other objects. This could change their size.
0037 There are also settings changes that invalidate the size of other components, where the size changes
0038 are detected and propagated.
0039 
0040 
0041 Painting call tree (simplified):
0042 
0043 Chart::paint() (from users) / paintEvent() (from framework)
0044 ChartPrivate::paintAll()-----------------------------------------------\
0045 CoordinatePlane::paintAll() (from AbstractArea)--------\               Axis::paintAll()-\
0046 CoordinatePlane::paint() (from AbstractLayoutItem)     Grid::drawGrid()                 Axis::paint()
0047 Diagram::paint( PaintContext* paintContext )
0048 
0049 Note that grids are painted from the coordinate plane, not from the diagram as ownership would suggest.
0050 
0051 */
0052 
0053 namespace KChart {
0054 
0055     class BackgroundAttributes;
0056     class FrameAttributes;
0057     class AbstractDiagram;
0058     class AbstractCoordinatePlane;
0059     class HeaderFooter;
0060     class Legend;
0061 
0062     typedef QList<AbstractCoordinatePlane*> CoordinatePlaneList;
0063     typedef QList<HeaderFooter*> HeaderFooterList;
0064     typedef QList<Legend*> LegendList;
0065 
0066 
0067     /**
0068      * @class Chart KChartChart.h KChartChart
0069      * @brief A chart with one or more diagrams.
0070      *
0071      * The Chart class represents a drawing consisting of one or more diagrams
0072      * and various optional elements such as legends, axes, text boxes, headers
0073      * or footers. It takes ownership of all these elements when they are assigned
0074      * to it. Each diagram is associated with a coordinate plane, of which the chart
0075      * can have more than one. The coordinate planes (and thus the associated diagrams)
0076      * can be laid out in various ways.
0077      *
0078      * The Chart class makes heavy use of the Qt Interview framework for model/view
0079      * programming, and thus requires data to be presented to it in a QAbstractItemModel
0080      * compatible way. For many simple charts, especially if the visualized data is
0081      * static, KChart::Widget provides an abstracted interface, that hides the complexity
0082      * of Interview to a large extent.
0083      */
0084     class KCHART_EXPORT Chart : public QWidget
0085     {
0086         Q_OBJECT
0087          // KD Chart 3.0: leading is inter-line distance of text. this here is MARGIN or SPACING.
0088         Q_PROPERTY( int globalLeadingTop READ globalLeadingTop WRITE setGlobalLeadingTop )
0089         Q_PROPERTY( int globalLeadingBottom READ globalLeadingBottom WRITE setGlobalLeadingBottom )
0090         Q_PROPERTY( int globalLeadingLeft READ globalLeadingLeft WRITE setGlobalLeadingLeft )
0091         Q_PROPERTY( int globalLeadingRight READ globalLeadingRight WRITE setGlobalLeadingRight )
0092         Q_PROPERTY( bool useNewLayoutSystem READ useNewLayoutSystem WRITE setUseNewLayoutSystem )
0093 
0094         KCHART_DECLARE_PRIVATE_BASE_POLYMORPHIC_QWIDGET( Chart )
0095 
0096     public:
0097         explicit Chart ( QWidget* parent = nullptr );
0098         ~Chart() override;
0099 
0100         /**
0101          * @brief useNewLayoutSystem
0102          * Be very careful activating the new layout system,
0103          * its still experimental and works only if the user knows
0104          * what he is doing. The reason is that the system does not prevent
0105          * the user from creating sharing graphs that are not layoutable in a
0106          * plane and still needs assistance from the user.
0107          */
0108         bool useNewLayoutSystem() const;
0109         void setUseNewLayoutSystem( bool value );
0110 
0111         /**
0112           \brief Specify the frame attributes to be used, by default is it a thin black line.
0113 
0114           To hide the frame line, you could do something like this:
0115           \verbatim
0116           KChart::FrameAttributes frameAttrs( my_chart->frameAttributes() );
0117           frameAttrs.setVisible( false );
0118           my_chart->setFrameAttributes( frameAttrs );
0119           \endverbatim
0120 
0121           \sa setBackgroundAttributes
0122           */
0123         void setFrameAttributes( const FrameAttributes &a );
0124         FrameAttributes frameAttributes() const;
0125 
0126         /**
0127           \brief Specify the background attributes to be used, by default there is no background.
0128 
0129           To set a light blue background, you could do something like this:
0130           \verbatim
0131           KChart::BackgroundAttributes backgroundAttrs( my_chart->backgroundAttributes() );
0132           backgroundAttrs.setVisible( true );
0133           backgroundAttrs.setBrush( QColor(0xd0,0xd0,0xff) );
0134           my_chart->setBackgroundAttributes( backgroundAttrs );
0135           \endverbatim
0136 
0137           \sa setFrameAttributes
0138           */
0139         void setBackgroundAttributes( const BackgroundAttributes &a );
0140         BackgroundAttributes backgroundAttributes() const;
0141 
0142         /**
0143          * Each chart must have at least one coordinate plane.
0144          * Initially a default CartesianCoordinatePlane is created.
0145          * Use replaceCoordinatePlane() to replace it with a different
0146          * one, such as a PolarCoordinatePlane.
0147          * @return The first coordinate plane of the chart.
0148          */
0149         AbstractCoordinatePlane* coordinatePlane();
0150 
0151         /**
0152          * The list of coordinate planes.
0153          * @return The list of coordinate planes.
0154          */
0155         CoordinatePlaneList coordinatePlanes();
0156 
0157         /**
0158          * Adds a coordinate plane to the chart. The chart takes ownership.
0159          * @param plane The coordinate plane to add.
0160          *
0161          * \sa replaceCoordinatePlane, takeCoordinatePlane
0162          */
0163         void addCoordinatePlane( AbstractCoordinatePlane* plane );
0164 
0165         /**
0166          * Inserts a coordinate plane to the chart at index @p index.
0167          * The chart takes ownership.
0168          *
0169          * @param index The index where to add the plane
0170          * @param plane The coordinate plane to add.
0171          *
0172          * \sa replaceCoordinatePlane, takeCoordinatePlane
0173          */
0174         void insertCoordinatePlane( int index, AbstractCoordinatePlane* plane );
0175 
0176         /**
0177          * Replaces the old coordinate plane, or appends the
0178          * plane, it there is none yet.
0179          *
0180          * @param plane The coordinate plane to be used instead of the old plane.
0181          * This parameter must not be zero, or the method will do nothing.
0182          *
0183          * @param oldPlane The coordinate plane to be removed by the new plane. This
0184          * plane will be deleted automatically. If the parameter is omitted,
0185          * the very first coordinate plane will be replaced. In case, there was no
0186          * plane yet, the new plane will just be added.
0187          *
0188          * \note If you want to re-use the old coordinate plane, call takeCoordinatePlane and
0189          * addCoordinatePlane, instead of using replaceCoordinatePlane.
0190          *
0191          * \sa addCoordinatePlane, takeCoordinatePlane
0192          */
0193         void replaceCoordinatePlane( AbstractCoordinatePlane* plane,
0194                                      AbstractCoordinatePlane* oldPlane = nullptr );
0195 
0196         /**
0197          * Removes the coordinate plane from the chart, without deleting it.
0198          *
0199          * The chart no longer owns the plane, so it is
0200          * the caller's responsibility to delete the plane.
0201          *
0202          * \sa addCoordinatePlane, takeCoordinatePlane
0203          */
0204         void takeCoordinatePlane( AbstractCoordinatePlane* plane );
0205 
0206         /**
0207          * Set the coordinate plane layout that should be used as model for
0208          * the internal used layout. The layout needs to be an instance of
0209          * QHBoxLayout or QVBoxLayout.
0210          */
0211         void setCoordinatePlaneLayout( QLayout * layout );
0212         QLayout* coordinatePlaneLayout();
0213 
0214         /**
0215          * The first header or footer of the chart. By default there is none.
0216          * @return The first header or footer of the chart or 0 if there was none
0217          * added to the chart.
0218          */
0219         HeaderFooter* headerFooter();
0220 
0221         /**
0222          * The list of headers and footers associated with the chart.
0223          * @return The list of headers and footers associated with the chart.
0224          */
0225         HeaderFooterList headerFooters();
0226 
0227         /**
0228          * Adds a header or a footer to the chart. The chart takes ownership.
0229          * @param headerFooter The header (or footer, resp.) to add.
0230          *
0231          * \sa replaceHeaderFooter, takeHeaderFooter
0232          */
0233         void addHeaderFooter( HeaderFooter* headerFooter );
0234 
0235         /**
0236          * Replaces the old header (or footer, resp.), or appends the
0237          * new header or footer, it there is none yet.
0238          *
0239          * @param headerFooter The header or footer to be used instead of the old one.
0240          * This parameter must not be zero, or the method will do nothing.
0241          *
0242          * @param oldHeaderFooter The header or footer to be removed by the new one. This
0243          * header or footer will be deleted automatically. If the parameter is omitted,
0244          * the very first header or footer will be replaced. In case, there was no
0245          * header and no footer yet, the new header or footer will just be added.
0246          *
0247          * \note If you want to re-use the old header or footer, call takeHeaderFooter and
0248          * addHeaderFooter, instead of using replaceHeaderFooter.
0249          *
0250          * \sa addHeaderFooter, takeHeaderFooter
0251          */
0252         void replaceHeaderFooter ( HeaderFooter* headerFooter,
0253                                    HeaderFooter* oldHeaderFooter = nullptr );
0254 
0255         /**
0256          * Removes the header (or footer, resp.) from the chart, without deleting it.
0257          *
0258          * The chart no longer owns the header or footer, so it is
0259          * the caller's responsibility to delete the header or footer.
0260          *
0261          * \sa addHeaderFooter, replaceHeaderFooter
0262          */
0263         void takeHeaderFooter( HeaderFooter* headerFooter );
0264 
0265         /**
0266          * The first legend of the chart or 0 if there was none added to the chart.
0267          * @return The first legend of the chart or 0 if none exists.
0268          */
0269         Legend* legend();
0270 
0271         /**
0272          * The list of all legends associated with the chart.
0273          * @return The list of all legends associated with the chart.
0274          */
0275         LegendList legends();
0276 
0277         /**
0278          * Add the given legend to the chart. The chart takes ownership.
0279          * @param legend The legend to add.
0280          *
0281          * \sa replaceLegend, takeLegend
0282          */
0283         void addLegend( Legend* legend );
0284 
0285         /**
0286          * Replaces the old legend, or appends the
0287          * new legend, it there is none yet.
0288          *
0289          * @param legend The legend to be used instead of the old one.
0290          * This parameter must not be zero, or the method will do nothing.
0291          *
0292          * @param oldLegend The legend to be removed by the new one. This
0293          * legend will be deleted automatically. If the parameter is omitted,
0294          * the very first legend will be replaced. In case, there was no
0295          * legend yet, the new legend will just be added.
0296          *
0297          * If you want to re-use the old legend, call takeLegend and
0298          * addLegend, instead of using replaceLegend.
0299          *
0300          * \note Whenever addLegend is called the font sizes used by the
0301          * Legend are set to relative and they get coupled to the Chart's size,
0302          * with their relative values being 20 for the item texts and 24 to the
0303          * title text. So if you want to use custom font sizes for the Legend
0304          * make sure to set them after calling addLegend.
0305          *
0306          * \sa addLegend, takeLegend
0307          */
0308         void replaceLegend ( Legend* legend, Legend* oldLegend = nullptr );
0309 
0310         /**
0311          * Removes the legend from the chart, without deleting it.
0312          *
0313          * The chart no longer owns the legend, so it is
0314          * the caller's responsibility to delete the legend.
0315          *
0316          * \sa addLegend, takeLegend
0317          */
0318         void takeLegend( Legend* legend );
0319 
0320         /**
0321          * Set the padding between the margin of the widget and the area that
0322          * the contents are drawn into.
0323          * @param left The padding on the left side.
0324          * @param top The padding at the top.
0325          * @param right The padding on the left hand side.
0326          * @param bottom The padding on the bottom.
0327          *
0328          * \note Using previous versions of KD Chart you might have called
0329          * setGlobalLeading() to make room for long Abscissa labels (or for an
0330          * overlapping top label of an Ordinate axis, resp.) that would not fit
0331          * into the normal axis area. This is \em no \em longer \em needed
0332          * because KD Chart now is using hidden auto-spacer items reserving
0333          * as much free space as is needed for axes with overlapping content
0334          * at the respective sides.
0335          *
0336          * \sa setGlobalLeadingTop, setGlobalLeadingBottom, setGlobalLeadingLeft, setGlobalLeadingRight
0337          * \sa globalLeadingTop, globalLeadingBottom, globalLeadingLeft, globalLeadingRight
0338          */
0339         void setGlobalLeading( int left, int top, int right, int bottom );
0340 
0341         /**
0342          * Set the padding between the start of the widget and the start
0343          * of the area that is used for drawing on the left.
0344          * @param leading The padding value.
0345          *
0346          * \sa setGlobalLeading
0347          */
0348         void setGlobalLeadingLeft( int leading );
0349 
0350         /**
0351          * The padding between the start of the widget and the start
0352          * of the area that is used for drawing on the left.
0353          * @return The padding between the start of the widget and the start
0354          * of the area that is used for drawing on the left.
0355          *
0356          * \sa setGlobalLeading
0357          */
0358         int globalLeadingLeft() const;
0359 
0360         /**
0361          * Set the padding between the start of the widget and the start
0362          * of the area that is used for drawing at the top.
0363          * @param leading The padding value.
0364          *
0365          * \sa setGlobalLeading
0366          */
0367         void setGlobalLeadingTop( int leading );
0368 
0369         /**
0370          * The padding between the start of the widget and the start
0371          * of the area that is used for drawing at the top.
0372          * @return The padding between the start of the widget and the start
0373          * of the area that is used for drawing at the top.
0374          *
0375          * \sa setGlobalLeading
0376          */
0377         int globalLeadingTop() const;
0378 
0379         /**
0380          * Set the padding between the start of the widget and the start
0381          * of the area that is used for drawing on the right.
0382          * @param leading The padding value.
0383          *
0384          * \sa setGlobalLeading
0385          */
0386         void setGlobalLeadingRight( int leading );
0387 
0388         /**
0389          * The padding between the start of the widget and the start
0390          * of the area that is used for drawing on the right.
0391          * @return The padding between the start of the widget and the start
0392          * of the area that is used for drawing on the right.
0393          *
0394          * \sa setGlobalLeading
0395          */
0396         int globalLeadingRight() const;
0397 
0398         /**
0399          * Set the padding between the start of the widget and the start
0400          * of the area that is used for drawing on the bottom.
0401          * @param leading The padding value.
0402          *
0403          * \sa setGlobalLeading
0404          */
0405         void setGlobalLeadingBottom( int leading );
0406 
0407         /**
0408          * The padding between the start of the widget and the start
0409          * of the area that is used for drawing at the bottom.
0410          * @return The padding between the start of the widget and the start
0411          * of the area that is used for drawing at the bottom.
0412          *
0413          * \sa setGlobalLeading
0414          */
0415         int globalLeadingBottom() const;
0416 
0417         /**
0418           * Paints all the contents of the chart. Use this method to make KChart
0419           * draw into your QPainter.
0420           *
0421           * \note Any global leading settings will be used by the paint method too,
0422           * so make sure to set them to zero, if you want the drawing to have the exact
0423           * size of the target rectangle.
0424           *
0425           * \param painter The painter to be drawn into.
0426           * \param rect The rectangle to be filled by the Chart's drawing.
0427           *
0428           * \sa setGlobalLeading
0429           */
0430         void paint( QPainter* painter, const QRect& rect );
0431 
0432         void reLayoutFloatingLegends();
0433 
0434     Q_SIGNALS:
0435         /** Emitted upon change of a property of the Chart or any of its components. */
0436         void propertiesChanged();
0437         void finishedDrawing();
0438 
0439     protected:
0440         /**
0441           * Adjusts the internal layout when the chart is resized.
0442           */
0443         /* reimp */ void resizeEvent ( QResizeEvent * event ) override;
0444 
0445         /**
0446           * @brief Draws the background and frame, then calls paint().
0447           *
0448           * In most cases there is no need to override this method in a derived
0449           * class, but if you do, do not forget to call paint().
0450           * @sa paint
0451           */
0452         /* reimp */ void paintEvent( QPaintEvent* event ) override;
0453 
0454         /** reimp */
0455         void mousePressEvent( QMouseEvent* event ) override;
0456         /** reimp */
0457         void mouseDoubleClickEvent( QMouseEvent* event ) override;
0458         /** reimp */
0459         void mouseMoveEvent( QMouseEvent* event ) override;
0460         /** reimp */
0461         void mouseReleaseEvent( QMouseEvent* event ) override;
0462         /** reimp */
0463         bool event( QEvent* event ) override;
0464 
0465     private:
0466         // TODO move this to the private class
0467         void addLegendInternal( Legend *legend, bool setMeasures );
0468     };
0469 
0470 // Here we have a few docu block to be included into the API documentation:
0471 /**
0472      * \dir src
0473      * \brief Implementation directory of KChart.
0474      *
0475      * This directory contains the header files and the source files of both,
0476      * the private and the public classes.
0477      *
0478      * \note Only classes that have an include wrapper in the \c $KCHARTDIR/include
0479      * directory are part of the supported API.
0480      * All other classes are to be considered as implementation details, they
0481      * could be changed in future versions of KChart without notice.
0482      *
0483      * In other words: No class that is not mentioned in the \c $KCHARTDIR/include
0484      * directory may be directly used by your application.
0485      *
0486      * The recommended way to include classes of the KChart API is including
0487      * them by class name, so instead of including KChartChart.h you would say:
0488      *
0489     \verbatim
0490 #include <KChartChart>
0491     \endverbatim
0492      *
0493      * When following this there is no reason to include the \c $KCHARTDIR/src
0494      * directory, it is sufficient to include \c $KCHARTDIR/include
0495  */
0496 }
0497 /**
0498      * @class QAbstractItemView "(do not include)"
0499      * @brief Class only listed here to document inheritance of some KChart classes.
0500      *
0501      * Please consult the respective Qt documentation for details:
0502      * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0503  */
0504 /**
0505      * @class QAbstractProxyModel "(do not include)"
0506      * @brief Class only listed here to document inheritance of some KChart classes.
0507      *
0508  * Please consult the respective Qt documentation for details:
0509      * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0510  */
0511 /**
0512      * @class QFrame "(do not include)"
0513      * @brief Class only listed here to document inheritance of some KChart classes.
0514      *
0515  * Please consult the respective Qt documentation for details:
0516      * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0517  */
0518 /**
0519      * @class QObject "(do not include)"
0520      * @brief Class only listed here to document inheritance of some KChart classes.
0521      *
0522  * Please consult the respective Qt documentation for details:
0523      * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0524  */
0525 /**
0526      * @class QSortFilterProxyModel "(do not include)"
0527      * @brief Class only listed here to document inheritance of some KChart classes.
0528      *
0529  * Please consult the respective Qt documentation for details:
0530      * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0531  */
0532 /**
0533  * @class QWidget "(do not include)"
0534  * @brief Class only listed here to document inheritance of some KChart classes.
0535  *
0536  * Please consult the respective Qt documentation for details:
0537  * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0538  */
0539 /**
0540  * @class QTextDocument "(do not include)"
0541  * @brief Class only listed here to document inheritance of some KChart classes.
0542  *
0543  * Please consult the respective Qt documentation for details:
0544  * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0545  */
0546 /**
0547  * @class QLayoutItem "(do not include)"
0548  * @brief Class only listed here to document inheritance of some KChart classes.
0549  *
0550  * Please consult the respective Qt documentation for details:
0551  * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0552  */
0553 /**
0554  * @class QGraphicsPolygonItem "(do not include)"
0555  * @brief Class only listed here to document inheritance of some KChart classes.
0556  *
0557  * Please consult the respective Qt documentation for details:
0558  * <A HREF="http://doc.trolltech.com/">http://doc.trolltech.com/</A>
0559  */
0560 
0561 
0562 #endif