Warning, file /office/calligra/filters/libodf2/chart/Charting.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Sebastian Sauer <sebsauer@kdab.com> 0003 * SPDX-FileCopyrightText: 2010 Carlos Licea <carlos@kdab.com> 0004 * SPDX-FileCopyrightText: 2014 Inge Wallin <inge@lysator.liu.se> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 0009 #ifndef CHARTING_H 0010 #define CHARTING_H 0011 0012 #include <QString> 0013 #include <QRect> 0014 #include <QMap> 0015 #include <QHash> 0016 #include <QVector> 0017 #include <QColor> 0018 0019 0020 namespace KoChart 0021 { 0022 0023 class Value 0024 { 0025 public: 0026 enum DataId { 0027 SeriesLegendOrTrendlineName = 0x00, ///< Referenced data specifies the series, legend entry, or trendline name. Error bars name MUST be empty. 0028 HorizontalValues = 0x01, ///< Referenced data specifies the values or horizontal values on bubble and scatter chart groups of the series and error bars. 0029 VerticalValues = 0x02, ///< Referenced data specifies the categories or vertical values on bubble and scatter chart groups of the series and error bars. 0030 BubbleSizeValues = 0x03 ///< Referenced data specifies the bubble size values of the series. 0031 }; 0032 DataId m_dataId; 0033 0034 enum DataType { 0035 AutoGeneratedName = 0x00, ///< The data source is a category (3) name, series name or bubble size that was automatically generated. 0036 TextOrValue = 0x01, ///< The data source is the text or value as specified by the formula field. 0037 CellRange = 0x02 ///< The data source is the value from a range of cells in a sheet specified by the formula field. 0038 }; 0039 DataType m_type; 0040 0041 bool m_isUnlinkedFormat; ///< false=data uses the number formatting of the referenced data, true=data uses the custom formatting specified via m_numberFormat. 0042 unsigned m_numberFormat; ///< specifies the number format to use for the data. 0043 QString m_formula; ///< the optional formula. could be for example "[Sheet1.$D$2:$F$2]" 0044 0045 Value(DataId dataId, DataType type, 0046 const QString& formula = QString(), 0047 bool isUnlinkedFormat = false, unsigned numberFormat = 0) 0048 : m_dataId(dataId) 0049 , m_type(type) 0050 , m_isUnlinkedFormat(isUnlinkedFormat) 0051 , m_numberFormat(numberFormat) 0052 , m_formula(formula) 0053 {} 0054 virtual ~Value() {} 0055 }; 0056 0057 0058 // ---------------------------------------------------------------- 0059 // Formats 0060 0061 0062 class Format 0063 { 0064 public: 0065 Format() {} 0066 virtual ~Format() {} 0067 }; 0068 0069 class LineFormat : public Format 0070 { 0071 public: 0072 enum Style { 0073 Solid = 0x0000, 0074 Dash = 0x0001, 0075 Dot = 0x0002, 0076 DashDot = 0x0003, 0077 DashDotDot = 0x0004, 0078 None = 0x0005, 0079 DarkGrayPattern = 0x0006, 0080 MediumGrayPattern = 0x0007, 0081 LightGrayPattern = 0x0008 0082 }; 0083 0084 enum Thickness { 0085 Hairline = 0xFFFF, 0086 NarrowSingle = 0x0000, 0087 MediumDouble = 0x0001, 0088 WideTriple = 0x0002 0089 }; 0090 0091 Style m_style; 0092 Thickness m_thickness; 0093 0094 explicit LineFormat(const Style& style = None, const Thickness& thickness = Hairline) 0095 : Format() 0096 , m_style(style) 0097 , m_thickness(thickness) 0098 {} 0099 }; 0100 0101 class PieFormat : public Format 0102 { 0103 public: 0104 int m_pcExplode; // from PieFormat 0105 0106 explicit PieFormat(int pcExplode = 0) 0107 : Format() 0108 , m_pcExplode(pcExplode) 0109 {} 0110 }; 0111 0112 class AreaFormat : public Format 0113 { 0114 public: 0115 QColor m_foreground; 0116 QColor m_background; 0117 bool m_fill; 0118 0119 explicit AreaFormat(const QColor &foreground = QColor(), const QColor &background = QColor(), 0120 bool fill = false) 0121 : Format() 0122 , m_foreground(foreground) 0123 , m_background(background) 0124 , m_fill(fill) 0125 {} 0126 }; 0127 0128 class Gradient 0129 { 0130 public: 0131 Gradient() { angle = 0.0; } 0132 0133 class GradientStop 0134 { 0135 public: 0136 void reset() 0137 { 0138 position = 1.0; 0139 knownColorValue = QColor(); 0140 tintVal = 0; 0141 satVal = 0; 0142 shadeVal = 0; 0143 referenceColor.clear(); 0144 } 0145 0146 qreal position; 0147 QColor knownColorValue; 0148 qreal tintVal; 0149 qreal satVal; 0150 qreal shadeVal; 0151 QString referenceColor; 0152 }; 0153 0154 QVector< GradientStop > gradientStops; 0155 qreal angle; 0156 }; 0157 0158 class Fill 0159 { 0160 public: 0161 enum FillType {Blip, Gradient, Group, None, Pattern, Solid}; 0162 0163 Fill() 0164 : type(None) 0165 , valid(false) 0166 {} 0167 0168 void setColor(const QColor& color){ solidColor = color; valid = true; type = Solid; } 0169 void setType(FillType type){ this->type = type; valid = true; } 0170 0171 QColor solidColor; 0172 QString pixmapFile; 0173 KoChart::Gradient gradient; 0174 FillType type; 0175 bool valid; 0176 }; 0177 0178 class ShapeProperties 0179 { 0180 public: 0181 int lineWidth; 0182 Fill lineFill; 0183 Fill areaFill; 0184 }; 0185 0186 0187 // ---------------------------------------------------------------- 0188 // Chart types 0189 0190 0191 class ChartImpl 0192 { 0193 public: 0194 ChartImpl() {} 0195 virtual ~ChartImpl() {} 0196 virtual QByteArray name() const = 0; 0197 }; 0198 0199 class PieImpl : public ChartImpl 0200 { 0201 public: 0202 /// Starting angle of the first data point clockwise from the top of the circle. 0203 int m_anStart; 0204 0205 explicit PieImpl(int anStart = 0) 0206 : ChartImpl() 0207 , m_anStart(anStart) 0208 {} 0209 0210 QByteArray name() const override { return "circle"; } 0211 }; 0212 0213 class RingImpl : public PieImpl 0214 { 0215 public: 0216 /// Size of the center hole in a doughnut chart group as a percentage of the plot area size. 0217 int m_pcDonut; 0218 0219 explicit RingImpl(int anStart = 0, int pcDonut = 0) 0220 : PieImpl(anStart) 0221 , m_pcDonut(pcDonut) 0222 {} 0223 0224 QByteArray name() const override { return "ring"; } 0225 }; 0226 0227 class BarImpl : public ChartImpl 0228 { 0229 public: 0230 QByteArray name() const override { return "bar"; } 0231 }; 0232 0233 class LineImpl : public ChartImpl 0234 { 0235 public: 0236 QByteArray name() const override { return "line"; } 0237 }; 0238 0239 class RadarImpl : public ChartImpl 0240 { 0241 public: 0242 /// If true then the radar-chart is filled (a RadarArea chart), else not. 0243 bool m_filled; 0244 0245 explicit RadarImpl(bool filled = false) 0246 : ChartImpl() 0247 , m_filled(filled) 0248 {} 0249 0250 QByteArray name() const override { return m_filled ? "filled-radar" : "radar"; } 0251 }; 0252 0253 class AreaImpl : public ChartImpl 0254 { 0255 public: 0256 AreaImpl() : ChartImpl() {} 0257 0258 QByteArray name() const override { return "area"; } 0259 }; 0260 0261 class StockImpl : public ChartImpl 0262 { 0263 public: 0264 StockImpl() : ChartImpl() {} 0265 0266 QByteArray name() const override { return "stock"; } 0267 }; 0268 0269 class ScatterImpl : public ChartImpl 0270 { 0271 public: 0272 enum ScatterStyle { None, Line, LineMarker, Marker, Smooth, SmoothMarker }; 0273 ScatterStyle style; 0274 0275 ScatterImpl() 0276 : ChartImpl() 0277 , style(LineMarker) 0278 {} 0279 0280 QByteArray name() const override { return "scatter"; } 0281 }; 0282 0283 class BubbleImpl : public ChartImpl 0284 { 0285 public: 0286 enum SizeType { 0287 Area = 0x0001, ///< The area of the data point represents the value. 0288 Width = 0x0002 ///< The width of the data point represents the value. 0289 }; 0290 /// Specifies how the default size of the data points represents the value. 0291 SizeType m_sizeType; 0292 0293 /// The size of the data points as a percentage of their default size. A 0294 /// value of 100 shows all the data points in their default size, as 0295 /// determined by the application. 0296 unsigned int m_sizeRatio; 0297 0298 /// Specifies whether data points with negative values are shown. 0299 bool m_showNegativeBubbles; 0300 0301 explicit BubbleImpl(SizeType sizeType = Area, unsigned int sizeRatio = 100, 0302 bool showNegativeBubbles = true) 0303 : ChartImpl() 0304 , m_sizeType(sizeType) 0305 , m_sizeRatio(sizeRatio) 0306 , m_showNegativeBubbles(showNegativeBubbles) 0307 {} 0308 0309 QByteArray name() const override { return "bubble"; } 0310 }; 0311 0312 class SurfaceImpl : public ChartImpl 0313 { 0314 public: 0315 /// Specifies that the surface is either filled or a wireframe. 0316 bool m_fill; 0317 0318 explicit SurfaceImpl(bool fill = false) : ChartImpl(), m_fill(fill) {} 0319 0320 QByteArray name() const override { return "surface"; } 0321 }; 0322 0323 0324 // ---------------------------------------------------------------- 0325 // Objects within the chart 0326 0327 0328 class Obj 0329 { 0330 public: 0331 unsigned int m_mdTopLt; 0332 unsigned int m_mdBotRt; 0333 unsigned int m_x1; 0334 unsigned int m_y1; 0335 unsigned int m_x2; 0336 unsigned int m_y2; 0337 KoChart::AreaFormat *m_areaFormat; 0338 0339 explicit Obj() 0340 : m_mdTopLt(0) 0341 , m_mdBotRt(0) 0342 , m_x1(0) 0343 , m_y1(0) 0344 , m_x2(0) 0345 , m_y2(0) 0346 , m_areaFormat(0) 0347 {} 0348 virtual ~Obj() { delete m_areaFormat; } 0349 }; 0350 0351 class Text : public Obj 0352 { 0353 public: 0354 QString m_text; 0355 0356 explicit Text(const QString &text = QString()) 0357 : Obj() 0358 , m_text(text) 0359 {} 0360 ~Text() override {} 0361 }; 0362 0363 class Axis : public Obj 0364 { 0365 public: 0366 enum Type { 0367 HorizontalValueAxis = 0x0000, 0368 VerticalValueAxis = 0x0001, 0369 SeriesAxis = 0x0002 0370 }; 0371 Type m_type; 0372 0373 class Gridline 0374 { 0375 public: 0376 LineFormat m_format; 0377 explicit Gridline(const LineFormat &format = LineFormat()) 0378 : m_format(format) 0379 {} 0380 }; 0381 0382 Gridline m_majorGridlines; 0383 Gridline m_minorGridlines; 0384 0385 LineFormat m_format; 0386 0387 QString m_numberFormat; 0388 0389 bool m_reversed; 0390 bool m_logarithmic; 0391 0392 bool m_autoMinimum; 0393 bool m_autoMaximum; 0394 qreal m_minimum; 0395 qreal m_maximum; 0396 0397 explicit Axis(Type type) 0398 : Obj() 0399 , m_type(type) 0400 , m_reversed(false) 0401 , m_logarithmic(false) 0402 , m_autoMinimum(true) 0403 , m_autoMaximum(true) 0404 , m_minimum(0) 0405 , m_maximum(0) 0406 {} 0407 ~Axis() override {} 0408 }; 0409 0410 class Cell 0411 { 0412 public: 0413 int m_column; 0414 int m_row; 0415 QString m_value; 0416 QString m_valueType; 0417 0418 Cell(int columnIndex, int rowIndex) 0419 : m_column(columnIndex) 0420 , m_row(rowIndex) 0421 , m_valueType("string") 0422 {} 0423 }; 0424 0425 0426 /// cell data representation of internal table 0427 class InternalTable 0428 { 0429 public: 0430 InternalTable() 0431 : m_maxRow(0) 0432 , m_maxColumn(0) 0433 {} 0434 ~InternalTable() 0435 { 0436 qDeleteAll(m_cells); 0437 } 0438 0439 Cell* cell(int columnIndex, int rowIndex, bool autoCreate) 0440 { 0441 const uint maximumSpreadsheetColumns = 0x7FFF; // MSOOXML::maximumSpreadsheetColumns() 0442 const unsigned hashed = (rowIndex + 1) * maximumSpreadsheetColumns + columnIndex + 1; 0443 0444 Cell* c = m_cells[hashed]; 0445 if (!c && autoCreate) { 0446 c = new Cell(columnIndex, rowIndex); 0447 m_cells[hashed] = c; 0448 0449 if (rowIndex > m_maxRow) 0450 m_maxRow = rowIndex; 0451 if (columnIndex > m_maxColumn) 0452 m_maxColumn = columnIndex; 0453 if (!m_maxCellsInRow.contains(rowIndex) || columnIndex > m_maxCellsInRow[rowIndex]) 0454 m_maxCellsInRow[rowIndex] = columnIndex; 0455 } 0456 0457 return c; 0458 } 0459 0460 int maxCellsInRow(int rowIndex) const { return m_maxCellsInRow[rowIndex]; } 0461 int maxRow() const { return m_maxRow; } 0462 int maxColumn() const { return m_maxColumn; } 0463 0464 private: 0465 int m_maxRow; 0466 int m_maxColumn; 0467 QHash<unsigned, Cell*> m_cells; 0468 QHash<int, int> m_maxCellsInRow; 0469 }; 0470 0471 0472 /// Different types of markers. 0473 enum MarkerType { 0474 NoMarker, 0475 AutoMarker, 0476 SquareMarker, 0477 DiamondMarker, 0478 StarMarker, 0479 DotMarker, 0480 DashMarker, 0481 PlusMarker, 0482 CircleMarker, 0483 SymbolXMarker, 0484 TriangleMarker 0485 // TODO fill the missing marker types in 0486 }; 0487 0488 class DataPoint : public Obj 0489 { 0490 public: 0491 }; 0492 0493 class Series : public Obj 0494 { 0495 public: 0496 /// the type of data in categories, or horizontal values on bubble and 0497 /// scatter chart groups, in the series. MUST be either 0x0001=numeric or 0498 /// 0x0003=text. 0499 int m_dataTypeX; 0500 0501 /// the count of categories (3), or horizontal values on bubble and 0502 /// scatter chart groups, in the series. 0503 int m_countXValues; 0504 0505 /// the count of values, or vertical values on bubble and scatter chart 0506 /// groups, in the series. 0507 int m_countYValues; 0508 0509 /// the count of bubble size values in the series. 0510 int m_countBubbleSizeValues; 0511 0512 /// determines if the data values are shown in raw values as labels 0513 bool m_showDataLabelValues; 0514 0515 /// determines if the data values are shown in percent as labels or not 0516 bool m_showDataLabelPercent; 0517 0518 /// determines if the category data is shown as labels or not 0519 bool m_showDataLabelCategory; 0520 0521 /// determines if the name of the series is shown as labels 0522 bool m_showDataLabelSeries; 0523 0524 /// range that contains the values that should be visualized by the dataSeries. 0525 QString m_valuesCellRangeAddress; 0526 0527 /// Ranges that contain the values that should be visualized by the dataSeries. 0528 QStringList m_domainValuesCellRangeAddress; 0529 0530 /// The referenced values used in the chart 0531 QMap<Value::DataId, Value*> m_datasetValue; 0532 0533 /// The data-points in the series. 0534 QList<DataPoint*> m_dataPoints; 0535 0536 /// The formatting for the referenced values 0537 QList<Format*> m_datasetFormat; 0538 0539 /// List of text records attached to the series. 0540 QList<Text*> m_texts; 0541 0542 /// range that contains label 0543 QString m_labelCell; 0544 0545 /// marker type 0546 MarkerType m_markerType; 0547 ShapeProperties* spPr; 0548 QString m_numberFormat; 0549 0550 explicit Series() 0551 : Obj() 0552 , m_dataTypeX(0) 0553 , m_countXValues(0) 0554 , m_countYValues(0) 0555 , m_countBubbleSizeValues(0) 0556 , m_showDataLabelValues(false) 0557 , m_showDataLabelPercent(false) 0558 , m_showDataLabelCategory(false) 0559 , m_showDataLabelSeries(false) 0560 , m_markerType(NoMarker) 0561 ,spPr(0) 0562 {} 0563 ~Series() override 0564 { 0565 qDeleteAll(m_datasetValue); 0566 qDeleteAll(m_dataPoints); 0567 qDeleteAll(m_datasetFormat); 0568 0569 delete spPr; 0570 } 0571 }; 0572 0573 class PlotArea : public Obj 0574 { 0575 public: 0576 explicit PlotArea() 0577 : Obj() 0578 {} 0579 ~PlotArea() override {} 0580 }; 0581 0582 class Legend : public Obj 0583 { 0584 public: 0585 explicit Legend() : Obj() {} 0586 ~Legend() override {} 0587 }; 0588 0589 /// The main charting class that represents a single chart. 0590 class Chart : public Obj 0591 { 0592 public: 0593 QString m_sheetName; 0594 0595 /// If true then the chart is a 3d chart else the chart is 2d. 0596 bool m_is3d; 0597 0598 /// Specifies a counter clockwise rotation of a polar coordinate in a 0599 /// circle, ring or polar chart. 0600 int m_angleOffset; 0601 0602 //int anRot, anElv, pcDist; 0603 0604 /// Margins around the chart object 0605 int m_leftMargin; 0606 int m_topMargin; 0607 int m_rightMargin; 0608 int m_bottomMargin; 0609 0610 /// List of series 0611 QList<Series*> m_series; 0612 0613 /// List of text records attached to the chart. 0614 QList<Text*> m_texts; 0615 0616 /// Range of all referenced cells. 0617 QRect m_cellRangeAddress; 0618 0619 /// Range that contains the vertical values (the categories) for the plot-area. 0620 QString m_verticalCellRangeAddress; 0621 0622 // The ChartTitle 0623 QString m_title; 0624 0625 /// The more concrete chart implementation like e.g. a PieImpl for a pie chart. 0626 ChartImpl *m_impl; 0627 0628 /// The plot-area. 0629 PlotArea *m_plotArea; 0630 0631 /// The legend. 0632 Legend *m_legend; 0633 0634 /// List of defined axes. 0635 QList<Axis*> m_axes; 0636 0637 /// Whether the chart is vertical or not. 0638 bool m_transpose; 0639 0640 /// Whether the chart is stacked or not. 0641 bool m_stacked; 0642 0643 /// Whether the chart is percentage or not. 0644 bool m_f100; 0645 0646 /// style for colors fills, line types, etc 0647 int m_style; 0648 0649 Gradient* m_fillGradient; 0650 Gradient* m_plotAreaFillGradient; 0651 MarkerType m_markerType; 0652 bool m_showLines; 0653 qreal m_textSize; 0654 0655 // the chart's internal table 0656 InternalTable m_internalTable; 0657 0658 explicit Chart() 0659 : Obj() 0660 , m_is3d(false) 0661 , m_angleOffset(0) 0662 , m_leftMargin(0) 0663 , m_topMargin(0) 0664 , m_rightMargin(0) 0665 , m_bottomMargin(0) 0666 , m_impl(0) 0667 , m_plotArea(0) 0668 , m_legend(0) 0669 , m_transpose(false) 0670 , m_stacked(false) 0671 , m_f100(false) 0672 , m_style(2) 0673 , m_fillGradient(0) 0674 , m_plotAreaFillGradient(0) 0675 , m_markerType(NoMarker) 0676 , m_showLines(false) 0677 , m_textSize(10) 0678 { 0679 m_x1 = m_y1 = m_x2 = m_y2 = -1; // -1 means autoposition/autosize 0680 } 0681 ~Chart() override 0682 { 0683 qDeleteAll(m_axes); 0684 qDeleteAll(m_series); 0685 qDeleteAll(m_texts); 0686 delete m_impl; 0687 delete m_plotArea; 0688 delete m_legend; 0689 delete m_fillGradient; 0690 delete m_plotAreaFillGradient; 0691 } 0692 0693 void addRange(const QRect& range) 0694 { 0695 if (range.isValid()) { 0696 if (m_cellRangeAddress.isValid()) { 0697 if (range.left() < m_cellRangeAddress.left()) 0698 m_cellRangeAddress.setLeft(range.left()); 0699 if (range.top() < m_cellRangeAddress.top()) 0700 m_cellRangeAddress.setTop(range.top()); 0701 if (range.right() > m_cellRangeAddress.right()) 0702 m_cellRangeAddress.setRight(range.right()); 0703 if (range.bottom() > m_cellRangeAddress.bottom()) 0704 m_cellRangeAddress.setBottom(range.bottom()); 0705 } else { 0706 m_cellRangeAddress = range; 0707 } 0708 } 0709 } 0710 }; 0711 0712 } // namespace Charting 0713 0714 #endif