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

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 KCHARTLEGEND_H
0010 #define KCHARTLEGEND_H
0011 
0012 #include "KChartAbstractAreaWidget.h"
0013 #include "KChartPosition.h"
0014 #include "KChartMarkerAttributes.h"
0015 
0016 class QTextTable;
0017 
0018 namespace KChart {
0019 
0020 class AbstractDiagram;
0021 typedef QList<AbstractDiagram*> DiagramList;
0022 typedef QList<const AbstractDiagram*> ConstDiagramList;
0023 
0024 /**
0025   * @brief Legend defines the interface for the legend drawing class.
0026   *
0027   * Legend is the class for drawing legends for all kinds of diagrams ("chart types").
0028   *
0029   * Legend is drawn on chart level, not per diagram, but you can have more than one
0030   * legend per chart, using KChart::Chart::addLegend().
0031   *
0032   * \note Legend is different from all other classes of KChart, since it can be
0033   * displayed outside of the Chart's area.  If you want to, you can embed the legend
0034   * into your own widget, or into another part of a bigger layout, into which you might
0035   * have inserted the Chart.
0036   *
0037   * On the other hand, please note that you MUST call Chart::addLegend to get your
0038   * legend positioned into the correct place of your chart - if you want to have
0039   * the legend shown inside of the chart (that's probably true for most cases).
0040   */
0041 class KCHART_EXPORT Legend : public AbstractAreaWidget
0042 {
0043     Q_OBJECT
0044 
0045     Q_DISABLE_COPY( Legend )
0046     KCHART_DECLARE_PRIVATE_DERIVED_QWIDGET( Legend )
0047 
0048 public:
0049     explicit Legend( QWidget* parent = nullptr );
0050     explicit Legend( KChart::AbstractDiagram* diagram, QWidget* parent = nullptr );
0051     ~Legend() override;
0052 
0053 
0054     enum LegendStyle { MarkersOnly     = 0,
0055                        LinesOnly       = 1,
0056                        MarkersAndLines = 2 };
0057 
0058 
0059     void setLegendStyle( LegendStyle style );
0060     LegendStyle legendStyle() const;
0061 
0062 
0063 
0064     /**
0065       * Creates an exact copy of this legend.
0066       */
0067     virtual Legend * clone() const;
0068 
0069     /**
0070      * Returns true if both legends have the same settings.
0071      */
0072     bool compare( const Legend* other ) const;
0073 
0074     void resizeEvent( QResizeEvent * event ) override; // TODO: should be protected
0075 
0076     virtual void paint( QPainter* painter ) override;
0077     void paint( QPainter* painter, const QRect &rect);
0078     void setVisible( bool visible ) override;
0079 
0080     /**
0081         Specifies the reference area for font size of title text,
0082         and for font size of the item texts, IF automatic area
0083         detection is set.
0084 
0085         \note This parameter is ignored, if the Measure given for
0086         setTitleTextAttributes (or setTextAttributes, resp.) is
0087         not specifying automatic area detection.
0088 
0089         If no reference area is specified, but automatic area
0090         detection is set, then the size of the legend's parent
0091         widget will be used.
0092 
0093         \sa KChart::Measure, KChartEnums::MeasureCalculationMode
0094     */
0095     void setReferenceArea( const QWidget* area );
0096     /**
0097         Returns the reference area, that is used for font size of title text,
0098         and for font size of the item texts, IF automatic area
0099         detection is set.
0100 
0101         \sa setReferenceArea
0102     */
0103     const QWidget* referenceArea() const;
0104 
0105     /**
0106       * The first diagram of the legend or 0 if there was none added to the legend.
0107       * @return The first diagram of the legend or 0.
0108       *
0109       * \sa diagrams, addDiagram, removeDiagram, removeDiagrams, replaceDiagram, setDiagram
0110       */
0111     KChart::AbstractDiagram* diagram() const;
0112 
0113     /**
0114       * The list of all diagrams associated with the legend.
0115       * @return The list of all diagrams associated with the legend.
0116       *
0117       * \sa diagram, addDiagram, removeDiagram, removeDiagrams, replaceDiagram, setDiagram
0118       */
0119     DiagramList diagrams() const;
0120 
0121     /**
0122      * @return The list of diagrams associated with this legend.
0123      */
0124     ConstDiagramList constDiagrams() const;
0125 
0126     /**
0127       * Add the given diagram to the legend.
0128       * @param newDiagram The diagram to add.
0129       *
0130       * \sa diagram, diagrams, removeDiagram, removeDiagrams, replaceDiagram, setDiagram
0131       */
0132     void addDiagram( KChart::AbstractDiagram* newDiagram );
0133 
0134     /**
0135       * Removes the diagram from the legend's list of diagrams.
0136       *
0137       * \sa diagram, diagrams, addDiagram, removeDiagrams, replaceDiagram, setDiagram
0138       */
0139     void removeDiagram( KChart::AbstractDiagram* oldDiagram );
0140 
0141     /**
0142       * Removes all diagrams from the legend's list of diagrams.
0143       *
0144       * \sa diagram, diagrams, addDiagram, removeDiagram, replaceDiagram, setDiagram
0145       */
0146     void removeDiagrams();
0147 
0148     /**
0149       * Replaces the old diagram, or appends the
0150       * new diagram, it there is none yet.
0151       *
0152       * @param newDiagram The diagram to be used instead of the old one.
0153       * If this parameter is zero, the first diagram will just be removed.
0154       *
0155       * @param oldDiagram The diagram to be removed by the new one. This
0156       * diagram will be deleted automatically. If the parameter is omitted,
0157       * the very first diagram will be replaced. In case, there was no
0158       * diagram yet, the new diagram will just be added.
0159       *
0160       * \sa diagram, diagrams, addDiagram, removeDiagram, removeDiagrams, setDiagram
0161       */
0162     void replaceDiagram( KChart::AbstractDiagram* newDiagram,
0163                          KChart::AbstractDiagram* oldDiagram = nullptr );
0164 
0165     /**
0166       * Returns the offset of the first dataset of \c diagram.
0167       *
0168       */
0169     uint dataSetOffset( KChart::AbstractDiagram* diagram );
0170 
0171     /**
0172       * @brief A convenience method doing the same as replaceDiagram( newDiagram, 0 );
0173       *
0174       * Replaces the first diagram by the given diagram.
0175       * If the legend's list of diagram is empty the given diagram is added to the list.
0176       *
0177       * \sa diagram, diagrams, addDiagram, removeDiagram, removeDiagrams, replaceDiagram
0178       */
0179     void setDiagram( KChart::AbstractDiagram* newDiagram );
0180 
0181     /**
0182      * \brief Specify the position of a non-floating legend.
0183      *
0184      * Use setFloatingPosition to set position and alignment
0185      * if your legend is floating.
0186      *
0187      * \sa setAlignment, setFloatingPosition
0188      */
0189     void setPosition( Position position );
0190 
0191     /**
0192      * Returns the position of a non-floating legend.
0193      * \sa setPosition
0194      */
0195     Position position() const;
0196 
0197     /**
0198      * \brief Specify the alignment of a non-floating legend.
0199      *
0200      * Use setFloatingPosition to set position and alignment
0201      * if your legend is floating.
0202      *
0203      * \sa alignment, setPosition, setFloatingPosition
0204      */
0205     void setAlignment( Qt::Alignment );
0206 
0207     /**
0208      * Returns the alignment of a non-floating legend.
0209      * \sa setAlignment
0210      */
0211     Qt::Alignment alignment() const;
0212 
0213     /**
0214      * \brief Specify the alignment of the text elements within the legend
0215      *
0216      * \sa textAlignment()
0217      */
0218     void setTextAlignment( Qt::Alignment );
0219 
0220     /**
0221      * \brief Returns the alignment used while rendering text elements within the legend.
0222      *
0223      * \sa setTextAlignment()
0224      */
0225      Qt::Alignment textAlignment() const;
0226 
0227      /**
0228       * \brief Specify the alignment of the legend symbol( alignment of Legend::LinesOnly)
0229       *  within the legend
0230       *
0231       * \sa legendSymbolAlignment()
0232       */
0233      void setLegendSymbolAlignment(Qt::Alignment);
0234 
0235      /**
0236       * \brief Returns the alignment used while drawing legend symbol(alignment of Legend::LinesOnly)
0237       * within the legend.
0238       *
0239       * \sa setLegendSymbolAlignment()
0240       */
0241      Qt::Alignment legendSymbolAlignment() const;
0242 
0243     /**
0244      * \brief Specify the position and alignment of a floating legend.
0245      *
0246      * Use setPosition and setAlignment to set position and alignment
0247      * if your legend is non-floating.
0248      *
0249      * \note When setFloatingPosition is called, the Legend's position value is set to
0250      * KChart::Position::Floating automatically.
0251      *
0252      * If your Chart is pointed to by m_chart, your could have the floating legend
0253      * aligned exactly to the chart's coordinate plane's top-right corner
0254      * with the following commands:
0255 \verbatim
0256 KChart::RelativePosition relativePosition;
0257 relativePosition.setReferenceArea( m_chart->coordinatePlane() );
0258 relativePosition.setReferencePosition( Position::NorthEast );
0259 relativePosition.setAlignment( Qt::AlignTop | Qt::AlignRight );
0260 relativePosition.setHorizontalPadding(
0261     KChart::Measure( -1.0, KChartEnums::MeasureCalculationModeAbsolute ) );
0262 relativePosition.setVerticalPadding(
0263     KChart::Measure( 0.0, KChartEnums::MeasureCalculationModeAbsolute ) );
0264 m_legend->setFloatingPosition( relativePosition );
0265 \endverbatim
0266      *
0267      * To have the legend positioned at a fixed point, measured from the QPainter's top left corner,
0268      * you could use the following code code:
0269      *
0270 \verbatim
0271 KChart::RelativePosition relativePosition;
0272 relativePosition.setReferencePoints( PositionPoints( QPointF( 0.0, 0.0 ) ) );
0273 relativePosition.setReferencePosition( Position::NorthWest );
0274 relativePosition.setAlignment( Qt::AlignTop | Qt::AlignLeft );
0275 relativePosition.setHorizontalPadding(
0276     KChart::Measure( 4.0, KChartEnums::MeasureCalculationModeAbsolute ) );
0277 relativePosition.setVerticalPadding(
0278     KChart::Measure( 4.0, KChartEnums::MeasureCalculationModeAbsolute ) );
0279 m_legend->setFloatingPosition( relativePosition );
0280 \endverbatim
0281      * Actually that's exactly the code KChart is using as default position for any floating legends,
0282      * so if you just say setPosition( KChart::Position::Floating ) without calling setFloatingPosition
0283      * your legend will be positioned at point 4/4.
0284      *
0285      * \sa setPosition, setAlignment
0286      */
0287     void setFloatingPosition( const RelativePosition& relativePosition );
0288 
0289     /**
0290      * Returns the position of a floating legend.
0291      * \sa setFloatingPosition
0292      */
0293     const RelativePosition floatingPosition() const;
0294 
0295     void setOrientation( Qt::Orientation orientation );
0296     Qt::Orientation orientation() const;
0297 
0298 
0299     void setSortOrder( Qt::SortOrder order );
0300     Qt::SortOrder sortOrder() const;
0301 
0302     void setShowLines( bool legendShowLines );
0303     bool showLines() const;
0304 
0305 
0306     /**
0307         \brief Removes all legend texts that might have been set by setText.
0308 
0309         This resets the Legend to default behaviour: Texts are created automatically.
0310     */
0311     void resetTexts();
0312     void setText( uint dataset, const QString& text );
0313     QString text( uint dataset ) const;
0314     const QMap<uint,QString> texts() const;
0315 
0316     /**
0317      * Sets a list of datasets that are to be hidden in the legend.
0318      *
0319      * By passing an empty list, you show all datasets.
0320      * All datasets are shown by default, which means
0321      * that hiddenDatasets() returns an empty list.
0322      */
0323     void setHiddenDatasets( const QList<uint> hiddenDatasets );
0324     const QList<uint> hiddenDatasets() const;
0325     void setDatasetHidden( uint dataset, bool hidden );
0326     bool datasetIsHidden( uint dataset ) const;
0327 
0328     uint datasetCount() const;
0329 
0330     void setDefaultColors();
0331     void setRainbowColors();
0332     void setSubduedColors( bool ordered = false );
0333 
0334     void setBrushesFromDiagram( KChart::AbstractDiagram* diagram );
0335 
0336     /**
0337      * Note: there is no color() getter method, since setColor
0338      * just sets a QBrush with the respective color, so the
0339      * brush() getter method is sufficient.
0340      */
0341     void setColor( uint dataset, const QColor& color );
0342 
0343     void setBrush( uint dataset, const QBrush& brush );
0344     QBrush brush( uint dataset ) const;
0345     const QMap<uint,QBrush> brushes() const;
0346 
0347     void setPen( uint dataset, const QPen& pen );
0348     QPen pen( uint dataset ) const;
0349     const QMap<uint,QPen> pens() const;
0350 
0351     /**
0352      * Note that any sizes specified via setMarkerAttributes are ignored,
0353      * unless you disable the automatic size calculation, by saying
0354      * setUseAutomaticMarkerSize( false )
0355      */
0356     void setMarkerAttributes( uint dataset, const MarkerAttributes& );
0357     MarkerAttributes markerAttributes( uint dataset ) const;
0358     const QMap<uint, MarkerAttributes> markerAttributes() const;
0359 
0360     /**
0361      * This option is on by default, it means that Marker sizes in the Legend
0362      * will be the same as the font height used for their respective label texts.
0363      *
0364      * Set this to false, if you want to specify the marker sizes via setMarkerAttributes
0365      * or if you want the Legend to use the same marker sizes as they are used in the Diagrams.
0366      */
0367     void setUseAutomaticMarkerSize( bool useAutomaticMarkerSize );
0368     bool useAutomaticMarkerSize() const;
0369 
0370     void setTextAttributes( const TextAttributes &a );
0371     TextAttributes textAttributes() const;
0372 
0373     void setTitleText( const QString& text );
0374     QString titleText() const;
0375 
0376     void setTitleTextAttributes( const TextAttributes &a );
0377     TextAttributes titleTextAttributes() const;
0378 
0379     void setSpacing( uint space );
0380     uint spacing() const;
0381 
0382     // called internally by KChart::Chart, when painting into a custom QPainter
0383     void forceRebuild() override;
0384 
0385     QSize minimumSizeHint() const override;
0386     QSize sizeHint() const override;
0387     bool hasHeightForWidth() const override;
0388     int heightForWidth( int width ) const override;
0389     void needSizeHint() override;
0390     void resizeLayout( const QSize& size ) override;
0391 
0392 Q_SIGNALS:
0393     void destroyedLegend( KChart::Legend* );
0394     /** Emitted upon change of a property of the Legend or any of its components. */
0395     void propertiesChanged();
0396 
0397 private Q_SLOTS:
0398     void emitPositionChanged();
0399     void resetDiagram( KChart::AbstractDiagram* );
0400     void activateTheLayout();
0401     void setNeedRebuild();
0402     void buildLegend();
0403 }; // End of class Legend
0404 
0405 }
0406 
0407 
0408 #endif // KCHARTLEGEND_H