1 /* 2 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 3 * 4 * This file is part of the KD Chart library. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef KCHARTLEGEND_H 21 #define KCHARTLEGEND_H 22 23 #include "KChartAbstractAreaWidget.h" 24 #include "KChartPosition.h" 25 #include "KChartMarkerAttributes.h" 26 27 class QTextTable; 28 29 namespace KChart { 30 31 class AbstractDiagram; 32 typedef QList<AbstractDiagram*> DiagramList; 33 typedef QList<const AbstractDiagram*> ConstDiagramList; 34 35 /** 36 * @brief Legend defines the interface for the legend drawing class. 37 * 38 * Legend is the class for drawing legends for all kinds of diagrams ("chart types"). 39 * 40 * Legend is drawn on chart level, not per diagram, but you can have more than one 41 * legend per chart, using KChart::Chart::addLegend(). 42 * 43 * \note Legend is different from all other classes of KChart, since it can be 44 * displayed outside of the Chart's area. If you want to, you can embedd the legend 45 * into your own widget, or into another part of a bigger layout, into which you might 46 * have inserted the Chart. 47 * 48 * On the other hand, please note that you MUST call Chart::addLegend to get your 49 * legend positioned into the correct place of your chart - if you want to have 50 * the legend shown inside of the chart (that's probably true for most cases). 51 */ 52 class KCHART_EXPORT Legend : public AbstractAreaWidget 53 { 54 Q_OBJECT 55 56 Q_DISABLE_COPY( Legend ) 57 KCHART_DECLARE_PRIVATE_DERIVED_QWIDGET( Legend ) 58 59 public: 60 explicit Legend( QWidget* parent = nullptr ); 61 explicit Legend( KChart::AbstractDiagram* diagram, QWidget* parent = nullptr ); 62 virtual ~Legend(); 63 64 65 enum LegendStyle { MarkersOnly = 0, 66 LinesOnly = 1, 67 MarkersAndLines = 2 }; 68 69 70 void setLegendStyle( LegendStyle style ); 71 LegendStyle legendStyle() const; 72 73 74 75 /** 76 * Creates an exact copy of this legend. 77 */ 78 virtual Legend * clone() const; 79 80 /** 81 * Returns true if both legends have the same settings. 82 */ 83 bool compare( const Legend* other ) const; 84 85 void resizeEvent( QResizeEvent * event ) override; // TODO: should be protected 86 87 virtual void paint( QPainter* painter ) override; 88 void paint( QPainter* painter, const QRect &rect); 89 void setVisible( bool visible ) override; 90 91 /** 92 Specifies the reference area for font size of title text, 93 and for font size of the item texts, IF automatic area 94 detection is set. 95 96 \note This parameter is ignored, if the Measure given for 97 setTitleTextAttributes (or setTextAttributes, resp.) is 98 not specifying automatic area detection. 99 100 If no reference area is specified, but automatic area 101 detection is set, then the size of the legend's parent 102 widget will be used. 103 104 \sa KChart::Measure, KChartEnums::MeasureCalculationMode 105 */ 106 void setReferenceArea( const QWidget* area ); 107 /** 108 Returns the reference area, that is used for font size of title text, 109 and for font size of the item texts, IF automatic area 110 detection is set. 111 112 \sa setReferenceArea 113 */ 114 const QWidget* referenceArea() const; 115 116 /** 117 * The first diagram of the legend or 0 if there was none added to the legend. 118 * @return The first diagram of the legend or 0. 119 * 120 * \sa diagrams, addDiagram, removeDiagram, removeDiagrams, replaceDiagram, setDiagram 121 */ 122 KChart::AbstractDiagram* diagram() const; 123 124 /** 125 * The list of all diagrams associated with the legend. 126 * @return The list of all diagrams associated with the legend. 127 * 128 * \sa diagram, addDiagram, removeDiagram, removeDiagrams, replaceDiagram, setDiagram 129 */ 130 DiagramList diagrams() const; 131 132 /** 133 * @return The list of diagrams associated with this legend. 134 */ 135 ConstDiagramList constDiagrams() const; 136 137 /** 138 * Add the given diagram to the legend. 139 * @param newDiagram The diagram to add. 140 * 141 * \sa diagram, diagrams, removeDiagram, removeDiagrams, replaceDiagram, setDiagram 142 */ 143 void addDiagram( KChart::AbstractDiagram* newDiagram ); 144 145 /** 146 * Removes the diagram from the legend's list of diagrams. 147 * 148 * \sa diagram, diagrams, addDiagram, removeDiagrams, replaceDiagram, setDiagram 149 */ 150 void removeDiagram( KChart::AbstractDiagram* oldDiagram ); 151 152 /** 153 * Removes all diagrams from the legend's list of diagrams. 154 * 155 * \sa diagram, diagrams, addDiagram, removeDiagram, replaceDiagram, setDiagram 156 */ 157 void removeDiagrams(); 158 159 /** 160 * Replaces the old diagram, or appends the 161 * new diagram, it there is none yet. 162 * 163 * @param newDiagram The diagram to be used instead of the old one. 164 * If this parameter is zero, the first diagram will just be removed. 165 * 166 * @param oldDiagram The diagram to be removed by the new one. This 167 * diagram will be deleted automatically. If the parameter is omitted, 168 * the very first diagram will be replaced. In case, there was no 169 * diagram yet, the new diagram will just be added. 170 * 171 * \sa diagram, diagrams, addDiagram, removeDiagram, removeDiagrams, setDiagram 172 */ 173 void replaceDiagram( KChart::AbstractDiagram* newDiagram, 174 KChart::AbstractDiagram* oldDiagram = nullptr ); 175 176 /** 177 * Returns the offset of the first dataset of \c diagram. 178 * 179 */ 180 uint dataSetOffset( KChart::AbstractDiagram* diagram ); 181 182 /** 183 * @brief A convenience method doing the same as replaceDiagram( newDiagram, 0 ); 184 * 185 * Replaces the first diagram by the given diagram. 186 * If the legend's list of diagram is empty the given diagram is added to the list. 187 * 188 * \sa diagram, diagrams, addDiagram, removeDiagram, removeDiagrams, replaceDiagram 189 */ 190 void setDiagram( KChart::AbstractDiagram* newDiagram ); 191 192 /** 193 * \brief Specify the position of a non-floating legend. 194 * 195 * Use setFloatingPosition to set position and alignment 196 * if your legend is floating. 197 * 198 * \sa setAlignment, setFloatingPosition 199 */ 200 void setPosition( Position position ); 201 202 /** 203 * Returns the position of a non-floating legend. 204 * \sa setPosition 205 */ 206 Position position() const; 207 208 /** 209 * \brief Specify the alignment of a non-floating legend. 210 * 211 * Use setFloatingPosition to set position and alignment 212 * if your legend is floating. 213 * 214 * \sa alignment, setPosition, setFloatingPosition 215 */ 216 void setAlignment( Qt::Alignment ); 217 218 /** 219 * Returns the alignment of a non-floating legend. 220 * \sa setAlignment 221 */ 222 Qt::Alignment alignment() const; 223 224 /** 225 * \brief Specify the alignment of the text elements within the legend 226 * 227 * \sa textAlignment() 228 */ 229 void setTextAlignment( Qt::Alignment ); 230 231 /** 232 * \brief Returns the alignment used while rendering text elements within the legend. 233 * 234 * \sa setTextAlignment() 235 */ 236 Qt::Alignment textAlignment() const; 237 238 /** 239 * \brief Specify the alignment of the legend symbol( alignment of Legend::LinesOnly) 240 * within the legend 241 * 242 * \sa legendSymbolAlignment() 243 */ 244 void setLegendSymbolAlignment(Qt::Alignment); 245 246 /** 247 * \brief Returns the alignment used while drawing legend symbol(alignment of Legend::LinesOnly) 248 * within the legend. 249 * 250 * \sa setLegendSymbolAlignment() 251 */ 252 Qt::Alignment legendSymbolAlignment() const; 253 254 /** 255 * \brief Specify the position and alignment of a floating legend. 256 * 257 * Use setPosition and setAlignment to set position and alignment 258 * if your legend is non-floating. 259 * 260 * \note When setFloatingPosition is called, the Legend's position value is set to 261 * KChart::Position::Floating automatically. 262 * 263 * If your Chart is pointed to by m_chart, your could have the floating legend 264 * aligned exactly to the chart's coordinate plane's top-right corner 265 * with the following commands: 266 \verbatim 267 KChart::RelativePosition relativePosition; 268 relativePosition.setReferenceArea( m_chart->coordinatePlane() ); 269 relativePosition.setReferencePosition( Position::NorthEast ); 270 relativePosition.setAlignment( Qt::AlignTop | Qt::AlignRight ); 271 relativePosition.setHorizontalPadding( 272 KChart::Measure( -1.0, KChartEnums::MeasureCalculationModeAbsolute ) ); 273 relativePosition.setVerticalPadding( 274 KChart::Measure( 0.0, KChartEnums::MeasureCalculationModeAbsolute ) ); 275 m_legend->setFloatingPosition( relativePosition ); 276 \endverbatim 277 * 278 * To have the legend positioned at a fixed point, measured from the QPainter's top left corner, 279 * you could use the following code code: 280 * 281 \verbatim 282 KChart::RelativePosition relativePosition; 283 relativePosition.setReferencePoints( PositionPoints( QPointF( 0.0, 0.0 ) ) ); 284 relativePosition.setReferencePosition( Position::NorthWest ); 285 relativePosition.setAlignment( Qt::AlignTop | Qt::AlignLeft ); 286 relativePosition.setHorizontalPadding( 287 KChart::Measure( 4.0, KChartEnums::MeasureCalculationModeAbsolute ) ); 288 relativePosition.setVerticalPadding( 289 KChart::Measure( 4.0, KChartEnums::MeasureCalculationModeAbsolute ) ); 290 m_legend->setFloatingPosition( relativePosition ); 291 \endverbatim 292 * Actually that's exactly the code KChart is using as default position for any floating legends, 293 * so if you just say setPosition( KChart::Position::Floating ) without calling setFloatingPosition 294 * your legend will be positioned at point 4/4. 295 * 296 * \sa setPosition, setAlignment 297 */ 298 void setFloatingPosition( const RelativePosition& relativePosition ); 299 300 /** 301 * Returns the position of a floating legend. 302 * \sa setFloatingPosition 303 */ 304 const RelativePosition floatingPosition() const; 305 306 void setOrientation( Qt::Orientation orientation ); 307 Qt::Orientation orientation() const; 308 309 310 void setSortOrder( Qt::SortOrder order ); 311 Qt::SortOrder sortOrder() const; 312 313 void setShowLines( bool legendShowLines ); 314 bool showLines() const; 315 316 317 /** 318 \brief Removes all legend texts that might have been set by setText. 319 320 This resets the Legend to default behaviour: Texts are created automatically. 321 */ 322 void resetTexts(); 323 void setText( uint dataset, const QString& text ); 324 QString text( uint dataset ) const; 325 const QMap<uint,QString> texts() const; 326 327 /** 328 * Sets a list of datasets that are to be hidden in the legend. 329 * 330 * By passing an empty list, you show all datasets. 331 * All datasets are shown by default, which means 332 * that hiddenDatasets() returns an empty list. 333 */ 334 void setHiddenDatasets( const QList<uint> hiddenDatasets ); 335 const QList<uint> hiddenDatasets() const; 336 void setDatasetHidden( uint dataset, bool hidden ); 337 bool datasetIsHidden( uint dataset ) const; 338 339 uint datasetCount() const; 340 341 void setDefaultColors(); 342 void setRainbowColors(); 343 void setSubduedColors( bool ordered = false ); 344 345 void setBrushesFromDiagram( KChart::AbstractDiagram* diagram ); 346 347 /** 348 * Note: there is no color() getter method, since setColor 349 * just sets a QBrush with the respective color, so the 350 * brush() getter method is sufficient. 351 */ 352 void setColor( uint dataset, const QColor& color ); 353 354 void setBrush( uint dataset, const QBrush& brush ); 355 QBrush brush( uint dataset ) const; 356 const QMap<uint,QBrush> brushes() const; 357 358 void setPen( uint dataset, const QPen& pen ); 359 QPen pen( uint dataset ) const; 360 const QMap<uint,QPen> pens() const; 361 362 /** 363 * Note that any sizes specified via setMarkerAttributes are ignored, 364 * unless you disable the automatic size calculation, by saying 365 * setUseAutomaticMarkerSize( false ) 366 */ 367 void setMarkerAttributes( uint dataset, const MarkerAttributes& ); 368 MarkerAttributes markerAttributes( uint dataset ) const; 369 const QMap<uint, MarkerAttributes> markerAttributes() const; 370 371 /** 372 * This option is on by default, it means that Marker sizes in the Legend 373 * will be the same as the font height used for their respective label texts. 374 * 375 * Set this to false, if you want to specify the marker sizes via setMarkerAttributes 376 * or if you want the Legend to use the same marker sizes as they are used in the Diagrams. 377 */ 378 void setUseAutomaticMarkerSize( bool useAutomaticMarkerSize ); 379 bool useAutomaticMarkerSize() const; 380 381 void setTextAttributes( const TextAttributes &a ); 382 TextAttributes textAttributes() const; 383 384 void setTitleText( const QString& text ); 385 QString titleText() const; 386 387 void setTitleTextAttributes( const TextAttributes &a ); 388 TextAttributes titleTextAttributes() const; 389 390 void setSpacing( uint space ); 391 uint spacing() const; 392 393 // called internally by KChart::Chart, when painting into a custom QPainter 394 void forceRebuild() override; 395 396 QSize minimumSizeHint() const override; 397 QSize sizeHint() const override; 398 bool hasHeightForWidth() const override; 399 int heightForWidth( int width ) const override; 400 void needSizeHint() override; 401 void resizeLayout( const QSize& size ) override; 402 403 Q_SIGNALS: 404 void destroyedLegend( Legend* ); 405 /** Emitted upon change of a property of the Legend or any of its components. */ 406 void propertiesChanged(); 407 408 private Q_SLOTS: 409 void emitPositionChanged(); 410 void resetDiagram( AbstractDiagram* ); 411 void activateTheLayout(); 412 void setNeedRebuild(); 413 void buildLegend(); 414 }; // End of class Legend 415 416 } 417 418 419 #endif // KCHARTLEGEND_H 420