labplot  2.8.2
About: LabPlot is an application for plotting and analysis of 2D and 3D functions and data. It is a complete rewrite of LabPlot1 and lacks in the first release a lot of features available in the predecessor. On the other hand, the GUI and the usability is more superior.
  Fossies Dox: labplot-2.8.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

CartesianPlotLegend.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : CartesianPlotLegend.cpp
3  Project : LabPlot
4  Description : Legend for the cartesian plot
5  --------------------------------------------------------------------
6  Copyright : (C) 2013-2020 Alexander Semke (alexander.semke@web.de)
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  * This program is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19  * GNU General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU General Public License *
22  * along with this program; if not, write to the Free Software *
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
24  * Boston, MA 02110-1301 USA *
25  * *
26  ***************************************************************************/
27 
28 /*!
29  \class CartesianPlotLegend
30  \brief Legend for the cartesian plot.
31 
32  \ingroup kdefrontend
33 */
34 
35 #include "CartesianPlotLegend.h"
43 
44 #include <QGraphicsSceneContextMenuEvent>
45 #include <QKeyEvent>
46 #include <QMenu>
47 #include <QPainterPath>
48 #include <QPainter>
49 
50 #include <KConfig>
51 #include <KConfigGroup>
52 #include <KLocalizedString>
53 
55  : WorksheetElement(name, AspectType::CartesianPlotLegend), d_ptr(new CartesianPlotLegendPrivate(this)), m_plot(plot) {
56 
57  init();
58 }
59 
61  : WorksheetElement(name, AspectType::CartesianPlotLegend), d_ptr(dd), m_plot(plot) {
62 
63  init();
64 }
65 
66 //no need to delete the d-pointer here - it inherits from QGraphicsItem
67 //and is deleted during the cleanup in QGraphicsScene
69 
72 
73  KConfig config;
74  KConfigGroup group = config.group( "CartesianPlotLegend" );
75 
76  d->labelFont = group.readEntry("LabelsFont", QFont());
77  d->labelFont.setPixelSize( Worksheet::convertToSceneUnits( 10, Worksheet::Unit::Point ) );
78 
79  d->labelColor = group.readEntry("FontColor", QColor(Qt::black));
80  d->labelColumnMajor = true;
81  d->lineSymbolWidth = group.readEntry("LineSymbolWidth", Worksheet::convertToSceneUnits(1, Worksheet::Unit::Centimeter));
82  d->rowCount = 0;
83  d->columnCount = 0;
84 
85  d->position.horizontalPosition = WorksheetElement::HorizontalPosition::Right;
86  d->position.verticalPosition = WorksheetElement::VerticalPosition::Bottom;
87 
88  d->rotationAngle = group.readEntry("Rotation", 0.0);
89 
90  //Title
91  d->title = new TextLabel(this->name(), TextLabel::Type::PlotLegendTitle);
92  d->title->setBorderShape(TextLabel::BorderShape::NoBorder);
93  addChild(d->title);
94  d->title->setHidden(true);
95  d->title->setParentGraphicsItem(d);
96  d->title->graphicsItem()->setFlag(QGraphicsItem::ItemIsMovable, false);
97  d->title->graphicsItem()->setFlag(QGraphicsItem::ItemIsFocusable, false);
98  connect(d->title, &TextLabel::changed, this, &CartesianPlotLegend::retransform);
99 
100  //Background
101  d->backgroundType = (PlotArea::BackgroundType) group.readEntry("BackgroundType", static_cast<int>(PlotArea::BackgroundType::Color));
102  d->backgroundColorStyle = (PlotArea::BackgroundColorStyle) group.readEntry("BackgroundColorStyle", static_cast<int>(PlotArea::BackgroundColorStyle::SingleColor));
103  d->backgroundImageStyle = (PlotArea::BackgroundImageStyle) group.readEntry("BackgroundImageStyle", static_cast<int>(PlotArea::BackgroundImageStyle::Scaled));
104  d->backgroundBrushStyle = (Qt::BrushStyle) group.readEntry("BackgroundBrushStyle", static_cast<int>(Qt::SolidPattern));
105  d->backgroundFileName = group.readEntry("BackgroundFileName", QString());
106  d->backgroundFirstColor = group.readEntry("BackgroundFirstColor", QColor(Qt::white));
107  d->backgroundSecondColor = group.readEntry("BackgroundSecondColor", QColor(Qt::black));
108  d->backgroundOpacity = group.readEntry("BackgroundOpacity", 1.0);
109 
110  //Border
111  d->borderPen = QPen(group.readEntry("BorderColor", QColor(Qt::black)), group.readEntry("BorderWidth", Worksheet::convertToSceneUnits(1.0, Worksheet::Unit::Point)),
112  (Qt::PenStyle) group.readEntry("BorderStyle", (int)Qt::SolidLine));
113  d->borderCornerRadius = group.readEntry("BorderCornerRadius", 0.0);
114  d->borderOpacity = group.readEntry("BorderOpacity", 1.0);
115 
116  //Layout
117  d->layoutTopMargin = group.readEntry("LayoutTopMargin", Worksheet::convertToSceneUnits(0.2f, Worksheet::Unit::Centimeter));
118  d->layoutBottomMargin = group.readEntry("LayoutBottomMargin", Worksheet::convertToSceneUnits(0.2f, Worksheet::Unit::Centimeter));
119  d->layoutLeftMargin = group.readEntry("LayoutLeftMargin", Worksheet::convertToSceneUnits(0.2f, Worksheet::Unit::Centimeter));
120  d->layoutRightMargin = group.readEntry("LayoutRightMargin", Worksheet::convertToSceneUnits(0.2f, Worksheet::Unit::Centimeter));
121  d->layoutVerticalSpacing = group.readEntry("LayoutVerticalSpacing", Worksheet::convertToSceneUnits(0.1f, Worksheet::Unit::Centimeter));
122  d->layoutHorizontalSpacing = group.readEntry("LayoutHorizontalSpacing", Worksheet::convertToSceneUnits(0.1f, Worksheet::Unit::Centimeter));
123  d->layoutColumnCount = group.readEntry("LayoutColumnCount", 1);
124 
125  this->initActions();
126 }
127 
129  visibilityAction = new QAction(QIcon::fromTheme("view-visible"), i18n("Visible"), this);
130  visibilityAction->setCheckable(true);
131  connect(visibilityAction, &QAction::triggered, this, &CartesianPlotLegend::visibilityChangedSlot);
132 }
133 
135  QMenu *menu = WorksheetElement::createContextMenu();
136  QAction* firstAction = menu->actions().at(1); //skip the first action because of the "title-action"
137 
138  visibilityAction->setChecked(isVisible());
139  menu->insertAction(firstAction, visibilityAction);
140 
141  return menu;
142 }
143 
144 /*!
145  Returns an icon to be used in the project explorer.
146 */
148  return QIcon::fromTheme("text-field");
149 }
150 
151 STD_SWAP_METHOD_SETTER_CMD_IMPL(CartesianPlotLegend, SetVisible, bool, swapVisible)
152 void CartesianPlotLegend::setVisible(bool on) {
153  Q_D(CartesianPlotLegend);
154  exec(new CartesianPlotLegendSetVisibleCmd(d, on, on ? ki18n("%1: set visible") : ki18n("%1: set invisible")));
155 }
156 
158  Q_D(const CartesianPlotLegend);
159  return d->isVisible();
160 }
161 
163  Q_D(CartesianPlotLegend);
164  d->m_printing = on;
165 }
166 
167 QGraphicsItem *CartesianPlotLegend::graphicsItem() const{
168  return d_ptr;
169 }
170 
172  d_ptr->retransform();
173 }
174 
175 /*!
176  * overrides the implementation in WorksheetElement and sets the z-value to the maximal possible,
177  * legends are drawn on top of all other object in the plot.
178  */
180  Q_D(CartesianPlotLegend);
181  d->setZValue(std::numeric_limits<double>::max());
182 }
183 
184 void CartesianPlotLegend::handleResize(double horizontalRatio, double verticalRatio, bool pageResize) {
185  Q_UNUSED(horizontalRatio);
186  Q_UNUSED(verticalRatio);
187  Q_UNUSED(pageResize);
188  //TODO
189 // Q_D(const CartesianPlotLegend);
190 }
191 
192 //##############################################################################
193 //################################ getter methods ############################
194 //##############################################################################
195 CLASS_SHARED_D_READER_IMPL(CartesianPlotLegend, QFont, labelFont, labelFont)
196 CLASS_SHARED_D_READER_IMPL(CartesianPlotLegend, QColor, labelColor, labelColor)
197 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, bool, labelColumnMajor, labelColumnMajor)
199 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, qreal, rotationAngle, rotationAngle)
200 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, lineSymbolWidth, lineSymbolWidth)
201 
202 //Title
204  return d_ptr->title;
205 }
206 
207 //Background
209 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, PlotArea::BackgroundColorStyle, backgroundColorStyle, backgroundColorStyle)
210 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, PlotArea::BackgroundImageStyle, backgroundImageStyle, backgroundImageStyle)
211 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, Qt::BrushStyle, backgroundBrushStyle, backgroundBrushStyle)
212 CLASS_SHARED_D_READER_IMPL(CartesianPlotLegend, QColor, backgroundFirstColor, backgroundFirstColor)
213 CLASS_SHARED_D_READER_IMPL(CartesianPlotLegend, QColor, backgroundSecondColor, backgroundSecondColor)
214 CLASS_SHARED_D_READER_IMPL(CartesianPlotLegend, QString, backgroundFileName, backgroundFileName)
215 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, backgroundOpacity, backgroundOpacity)
216 
217 //Border
218 CLASS_SHARED_D_READER_IMPL(CartesianPlotLegend, QPen, borderPen, borderPen)
219 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, borderCornerRadius, borderCornerRadius)
220 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, borderOpacity, borderOpacity)
221 
222 //Layout
223 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, layoutTopMargin, layoutTopMargin)
224 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, layoutBottomMargin, layoutBottomMargin)
225 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, layoutLeftMargin, layoutLeftMargin)
226 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, layoutRightMargin, layoutRightMargin)
227 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, layoutHorizontalSpacing, layoutHorizontalSpacing)
228 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, float, layoutVerticalSpacing, layoutVerticalSpacing)
229 BASIC_SHARED_D_READER_IMPL(CartesianPlotLegend, int, layoutColumnCount, layoutColumnCount)
230 
231 //##############################################################################
232 //###################### setter methods and undo commands ####################
233 //##############################################################################
234 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLabelFont, QFont, labelFont, retransform)
235 void CartesianPlotLegend::setLabelFont(const QFont& font) {
236  Q_D(CartesianPlotLegend);
237  if (font!= d->labelFont)
238  exec(new CartesianPlotLegendSetLabelFontCmd(d, font, ki18n("%1: set font")));
239 }
240 
241 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLabelColor, QColor, labelColor, update)
242 void CartesianPlotLegend::setLabelColor(const QColor& color) {
243  Q_D(CartesianPlotLegend);
244  if (color!= d->labelColor)
245  exec(new CartesianPlotLegendSetLabelColorCmd(d, color, ki18n("%1: set font color")));
246 }
247 
248 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLabelColumnMajor, bool, labelColumnMajor, retransform)
249 void CartesianPlotLegend::setLabelColumnMajor(bool columnMajor) {
250  Q_D(CartesianPlotLegend);
251  if (columnMajor != d->labelColumnMajor)
252  exec(new CartesianPlotLegendSetLabelColumnMajorCmd(d, columnMajor, ki18n("%1: change column order")));
253 }
254 
255 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLineSymbolWidth, float, lineSymbolWidth, retransform)
256 void CartesianPlotLegend::setLineSymbolWidth(float width) {
257  Q_D(CartesianPlotLegend);
258  if (width != d->lineSymbolWidth)
259  exec(new CartesianPlotLegendSetLineSymbolWidthCmd(d, width, ki18n("%1: change line+symbol width")));
260 }
261 
263 void CartesianPlotLegend::setPosition(const PositionWrapper& pos) {
264  Q_D(CartesianPlotLegend);
265  if (pos.point != d->position.point
266  || pos.horizontalPosition != d->position.horizontalPosition
267  || pos.verticalPosition != d->position.verticalPosition)
268  exec(new CartesianPlotLegendSetPositionCmd(d, pos, ki18n("%1: set position")));
269 }
270 
271 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetRotationAngle, qreal, rotationAngle, retransform)
272 void CartesianPlotLegend::setRotationAngle(qreal angle) {
273  Q_D(CartesianPlotLegend);
274  if (angle != d->rotationAngle) {
275  exec(new CartesianPlotLegendSetRotationAngleCmd(d, angle, ki18n("%1: set rotation angle")));
276  d->title->setRotationAngle(angle);
277  }
278 }
279 
280 //Background
281 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundType, PlotArea::BackgroundType, backgroundType, update)
282 void CartesianPlotLegend::setBackgroundType(PlotArea::BackgroundType type) {
283  Q_D(CartesianPlotLegend);
284  if (type != d->backgroundType)
285  exec(new CartesianPlotLegendSetBackgroundTypeCmd(d, type, ki18n("%1: background type changed")));
286 }
287 
288 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundColorStyle, PlotArea::BackgroundColorStyle, backgroundColorStyle, update)
289 void CartesianPlotLegend::setBackgroundColorStyle(PlotArea::BackgroundColorStyle style) {
290  Q_D(CartesianPlotLegend);
291  if (style != d->backgroundColorStyle)
292  exec(new CartesianPlotLegendSetBackgroundColorStyleCmd(d, style, ki18n("%1: background color style changed")));
293 }
294 
295 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundImageStyle, PlotArea::BackgroundImageStyle, backgroundImageStyle, update)
296 void CartesianPlotLegend::setBackgroundImageStyle(PlotArea::BackgroundImageStyle style) {
297  Q_D(CartesianPlotLegend);
298  if (style != d->backgroundImageStyle)
299  exec(new CartesianPlotLegendSetBackgroundImageStyleCmd(d, style, ki18n("%1: background image style changed")));
300 }
301 
302 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundBrushStyle, Qt::BrushStyle, backgroundBrushStyle, update)
303 void CartesianPlotLegend::setBackgroundBrushStyle(Qt::BrushStyle style) {
304  Q_D(CartesianPlotLegend);
305  if (style != d->backgroundBrushStyle)
306  exec(new CartesianPlotLegendSetBackgroundBrushStyleCmd(d, style, ki18n("%1: background brush style changed")));
307 }
308 
309 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundFirstColor, QColor, backgroundFirstColor, update)
310 void CartesianPlotLegend::setBackgroundFirstColor(const QColor &color) {
311  Q_D(CartesianPlotLegend);
312  if (color!= d->backgroundFirstColor)
313  exec(new CartesianPlotLegendSetBackgroundFirstColorCmd(d, color, ki18n("%1: set background first color")));
314 }
315 
316 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundSecondColor, QColor, backgroundSecondColor, update)
317 void CartesianPlotLegend::setBackgroundSecondColor(const QColor &color) {
318  Q_D(CartesianPlotLegend);
319  if (color!= d->backgroundSecondColor)
320  exec(new CartesianPlotLegendSetBackgroundSecondColorCmd(d, color, ki18n("%1: set background second color")));
321 }
322 
323 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundFileName, QString, backgroundFileName, update)
324 void CartesianPlotLegend::setBackgroundFileName(const QString& fileName) {
325  Q_D(CartesianPlotLegend);
326  if (fileName!= d->backgroundFileName)
327  exec(new CartesianPlotLegendSetBackgroundFileNameCmd(d, fileName, ki18n("%1: set background image")));
328 }
329 
330 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBackgroundOpacity, float, backgroundOpacity, update)
331 void CartesianPlotLegend::setBackgroundOpacity(float opacity) {
332  Q_D(CartesianPlotLegend);
333  if (opacity != d->backgroundOpacity)
334  exec(new CartesianPlotLegendSetBackgroundOpacityCmd(d, opacity, ki18n("%1: set opacity")));
335 }
336 
337 //Border
338 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBorderPen, QPen, borderPen, update)
339 void CartesianPlotLegend::setBorderPen(const QPen &pen) {
340  Q_D(CartesianPlotLegend);
341  if (pen != d->borderPen)
342  exec(new CartesianPlotLegendSetBorderPenCmd(d, pen, ki18n("%1: set border style")));
343 }
344 
345 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBorderCornerRadius, qreal, borderCornerRadius, update)
346 void CartesianPlotLegend::setBorderCornerRadius(float radius) {
347  Q_D(CartesianPlotLegend);
348  if (radius != d->borderCornerRadius)
349  exec(new CartesianPlotLegendSetBorderCornerRadiusCmd(d, radius, ki18n("%1: set border corner radius")));
350 }
351 
352 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetBorderOpacity, qreal, borderOpacity, update)
353 void CartesianPlotLegend::setBorderOpacity(float opacity) {
354  Q_D(CartesianPlotLegend);
355  if (opacity != d->borderOpacity)
356  exec(new CartesianPlotLegendSetBorderOpacityCmd(d, opacity, ki18n("%1: set border opacity")));
357 }
358 
359 //Layout
360 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutTopMargin, float, layoutTopMargin, retransform)
361 void CartesianPlotLegend::setLayoutTopMargin(float margin) {
362  Q_D(CartesianPlotLegend);
363  if (margin != d->layoutTopMargin)
364  exec(new CartesianPlotLegendSetLayoutTopMarginCmd(d, margin, ki18n("%1: set layout top margin")));
365 }
366 
367 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutBottomMargin, float, layoutBottomMargin, retransform)
368 void CartesianPlotLegend::setLayoutBottomMargin(float margin) {
369  Q_D(CartesianPlotLegend);
370  if (margin != d->layoutBottomMargin)
371  exec(new CartesianPlotLegendSetLayoutBottomMarginCmd(d, margin, ki18n("%1: set layout bottom margin")));
372 }
373 
374 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutLeftMargin, float, layoutLeftMargin, retransform)
375 void CartesianPlotLegend::setLayoutLeftMargin(float margin) {
376  Q_D(CartesianPlotLegend);
377  if (margin != d->layoutLeftMargin)
378  exec(new CartesianPlotLegendSetLayoutLeftMarginCmd(d, margin, ki18n("%1: set layout left margin")));
379 }
380 
381 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutRightMargin, float, layoutRightMargin, retransform)
382 void CartesianPlotLegend::setLayoutRightMargin(float margin) {
383  Q_D(CartesianPlotLegend);
384  if (margin != d->layoutRightMargin)
385  exec(new CartesianPlotLegendSetLayoutRightMarginCmd(d, margin, ki18n("%1: set layout right margin")));
386 }
387 
388 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutVerticalSpacing, float, layoutVerticalSpacing, retransform)
389 void CartesianPlotLegend::setLayoutVerticalSpacing(float spacing) {
390  Q_D(CartesianPlotLegend);
391  if (spacing != d->layoutVerticalSpacing)
392  exec(new CartesianPlotLegendSetLayoutVerticalSpacingCmd(d, spacing, ki18n("%1: set layout vertical spacing")));
393 }
394 
395 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutHorizontalSpacing, float, layoutHorizontalSpacing, retransform)
396 void CartesianPlotLegend::setLayoutHorizontalSpacing(float spacing) {
397  Q_D(CartesianPlotLegend);
398  if (spacing != d->layoutHorizontalSpacing)
399  exec(new CartesianPlotLegendSetLayoutHorizontalSpacingCmd(d, spacing, ki18n("%1: set layout horizontal spacing")));
400 }
401 
402 STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetLayoutColumnCount, int, layoutColumnCount, retransform)
403 void CartesianPlotLegend::setLayoutColumnCount(int count) {
404  Q_D(CartesianPlotLegend);
405  if (count != d->layoutColumnCount)
406  exec(new CartesianPlotLegendSetLayoutColumnCountCmd(d, count, ki18n("%1: set layout column count")));
407 }
408 
409 //##############################################################################
410 //################################# SLOTS ####################################
411 //##############################################################################
412 
413 
414 //##############################################################################
415 //###### SLOTs for changes triggered via QActions in the context menu ########
416 //##############################################################################
418  Q_D(const CartesianPlotLegend);
419  this->setVisible(!d->isVisible());
420 }
421 
422 //##############################################################################
423 //######################### Private implementation #############################
424 //##############################################################################
426  setFlag(QGraphicsItem::ItemIsSelectable, true);
427  setFlag(QGraphicsItem::ItemIsMovable);
428  setFlag(QGraphicsItem::ItemSendsGeometryChanges);
429  setFlag(QGraphicsItem::ItemIsFocusable);
430  setAcceptHoverEvents(true);
431 }
432 
434  return q->name();
435 }
436 
438  if (rotationAngle != 0) {
439  QMatrix matrix;
440  matrix.rotate(-rotationAngle);
441  return matrix.mapRect(rect);
442  } else
443  return rect;
444 }
445 
446 void CartesianPlotLegendPrivate::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
447  q->createContextMenu()->exec(event->screenPos());
448 }
449 
450 /*!
451  Returns the shape of the CartesianPlotLegend as a QPainterPath in local coordinates
452 */
453 QPainterPath CartesianPlotLegendPrivate::shape() const {
454  QPainterPath path;
455  if ( qFuzzyIsNull(borderCornerRadius) )
456  path.addRect(rect);
457  else
458  path.addRoundedRect(rect, borderCornerRadius, borderCornerRadius);
459 
460  if (rotationAngle != 0) {
461  QTransform trafo;
462  trafo.rotate(-rotationAngle);
463  path = trafo.map(path);
464  }
465 
466  return path;
467 }
468 
470  bool oldValue = isVisible();
471 
472  //When making a graphics item invisible, it gets deselected in the scene.
473  //In this case we don't want to deselect the item in the project explorer.
474  //We need to supress the deselection in the view.
475  auto* worksheet = static_cast<Worksheet*>(q->parent(AspectType::Worksheet));
476  worksheet->suppressSelectionChangedEvent(true);
477  setVisible(on);
478  worksheet->suppressSelectionChangedEvent(false);
479 
480  emit q->visibilityChanged(on);
481  return oldValue;
482 }
483 
484 /*!
485  recalculates the rectangular of the legend.
486 */
489  return;
490 
491  prepareGeometryChange();
492 
493  curvesList.clear();
494 
495  //add xy-curves
496  for (auto* curve : q->m_plot->children<XYCurve>()) {
497  if (curve && curve->isVisible())
498  curvesList.push_back(curve);
499  }
500 
501  //add histograms
502  for (auto* hist : q->m_plot->children<Histogram>()) {
503  if (hist && hist->isVisible())
504  curvesList.push_back(hist);
505  }
506 
507  int curveCount = curvesList.size();
508  columnCount = (curveCount<layoutColumnCount) ? curveCount : layoutColumnCount;
509  if (columnCount == 0) //no curves available
510  rowCount = 0;
511  else
512  rowCount = ceil(double(curveCount)/double(columnCount));
513 
514  maxColumnTextWidths.clear();
515 
516  //determine the width of the legend
517  QFontMetrics fm(labelFont);
518  float w;
519  float h = fm.ascent();
520 
521  float maxTextWidth = 0;
522  float legendWidth = 0;
523  int index;
524  for (int c = 0; c < columnCount; ++c) {
525  for (int r = 0; r < rowCount; ++r) {
526  if (labelColumnMajor)
527  index = c*rowCount + r;
528  else
529  index = r*columnCount + c;
530 
531  if ( index >= curveCount )
532  break;
533 
534  const WorksheetElement* curve = dynamic_cast<WorksheetElement*>(curvesList.at(index));
535  if (curve) {
536  if (!curve->isVisible())
537  continue;
538 
539  w = fm.boundingRect(curve->name()).width();
540  if (w>maxTextWidth)
541  maxTextWidth = w;
542  }
543  }
544  maxColumnTextWidths.append(maxTextWidth);
545  legendWidth += maxTextWidth;
546  }
547  legendWidth += layoutLeftMargin + layoutRightMargin; //margins
548  legendWidth += columnCount*lineSymbolWidth + layoutHorizontalSpacing; //width of the columns without the text
549  legendWidth += (columnCount-1)*2*layoutHorizontalSpacing; //spacings between the columns
550  if (title->isVisible() && !title->text().text.isEmpty()) {
551  float titleWidth;
552  if (rotationAngle == 0.0)
553  titleWidth = title->graphicsItem()->boundingRect().width();
554  else {
555  QRectF rect = title->graphicsItem()->boundingRect();
556  QMatrix matrix;
557  matrix.rotate(-rotationAngle);
558  rect = matrix.mapRect(rect);
559  titleWidth = rect.width();
560  }
561 
562  if (titleWidth > legendWidth)
563  legendWidth = titleWidth;
564  }
565 
566  //determine the height of the legend
567  float legendHeight = layoutTopMargin + layoutBottomMargin; //margins
568  legendHeight += rowCount*h; //height of the rows
569  legendHeight += (rowCount-1)*layoutVerticalSpacing; //spacing between the rows
570  if (title->isVisible() && !title->text().text.isEmpty()) {
571  if (rotationAngle == 0.0)
572  legendHeight += title->graphicsItem()->boundingRect().height(); //legend title
573  else {
574  QRectF rect = title->graphicsItem()->boundingRect();
575  QMatrix matrix;
576  matrix.rotate(-rotationAngle);
577  rect = matrix.mapRect(rect);
578  legendHeight += rect.height(); //legend title
579  }
580  }
581 
582  rect.setX(-legendWidth/2);
583  rect.setY(-legendHeight/2);
584  rect.setWidth(legendWidth);
585  rect.setHeight(legendHeight);
586 
587  updatePosition();
588 }
589 
590 /*!
591  calculates the position of the legend, when the position relative to the parent was specified (left, right, etc.)
592 */
594  //position the legend relative to the actual plot size minus small offset
595  //TODO: make the offset dependent on the size of axis ticks.
596  const QRectF parentRect = q->m_plot->dataRect();
599 
602  position.point.setX(parentRect.x() + rect.width()/2 + hOffset);
604  position.point.setX(parentRect.x() + parentRect.width()/2);
606  position.point.setX(parentRect.x() + parentRect.width() - rect.width()/2 - hOffset);
607  }
608 
611  position.point.setY(parentRect.y() + rect.height()/2 + vOffset);
613  position.point.setY(parentRect.y() + parentRect.height()/2);
615  position.point.setY(parentRect.y() + parentRect.height() - rect.height()/2 -vOffset);
616  }
617 
619  setPos(position.point);
620  suppressItemChangeEvent = false;
621  emit q->positionChanged(position);
622 
623  suppressRetransform = true;
624  title->retransform();
625  suppressRetransform = false;
626 }
627 
628 /*!
629  Reimplementation of QGraphicsItem::paint(). This function does the actual painting of the legend.
630  \sa QGraphicsItem::paint().
631 */
632 void CartesianPlotLegendPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
633  Q_UNUSED(option);
634  Q_UNUSED(widget);
635  if (!isVisible())
636  return;
637 
638  painter->save();
639 
640  painter->rotate(-rotationAngle);
641 
642  //draw the area
643  painter->setOpacity(backgroundOpacity);
644  painter->setPen(Qt::NoPen);
646  switch (backgroundColorStyle) {
648  painter->setBrush(QBrush(backgroundFirstColor));
649  break;
650  }
652  QLinearGradient linearGrad(rect.topLeft(), rect.topRight());
653  linearGrad.setColorAt(0, backgroundFirstColor);
654  linearGrad.setColorAt(1, backgroundSecondColor);
655  painter->setBrush(QBrush(linearGrad));
656  break;
657  }
659  QLinearGradient linearGrad(rect.topLeft(), rect.bottomLeft());
660  linearGrad.setColorAt(0, backgroundFirstColor);
661  linearGrad.setColorAt(1, backgroundSecondColor);
662  painter->setBrush(QBrush(linearGrad));
663  break;
664  }
666  QLinearGradient linearGrad(rect.topLeft(), rect.bottomRight());
667  linearGrad.setColorAt(0, backgroundFirstColor);
668  linearGrad.setColorAt(1, backgroundSecondColor);
669  painter->setBrush(QBrush(linearGrad));
670  break;
671  }
673  QLinearGradient linearGrad(rect.bottomLeft(), rect.topRight());
674  linearGrad.setColorAt(0, backgroundFirstColor);
675  linearGrad.setColorAt(1, backgroundSecondColor);
676  painter->setBrush(QBrush(linearGrad));
677  break;
678  }
680  QRadialGradient radialGrad(rect.center(), rect.width()/2);
681  radialGrad.setColorAt(0, backgroundFirstColor);
682  radialGrad.setColorAt(1, backgroundSecondColor);
683  painter->setBrush(QBrush(radialGrad));
684  break;
685  }
686  }
688  if ( !backgroundFileName.trimmed().isEmpty() ) {
689  QPixmap pix(backgroundFileName);
690  switch (backgroundImageStyle) {
692  pix = pix.scaled(rect.size().toSize(),Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation);
693  painter->drawPixmap(rect.topLeft(),pix);
694  break;
696  pix = pix.scaled(rect.size().toSize(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
697  painter->drawPixmap(rect.topLeft(),pix);
698  break;
700  pix = pix.scaled(rect.size().toSize(),Qt::KeepAspectRatio,Qt::SmoothTransformation);
701  painter->drawPixmap(rect.topLeft(),pix);
702  break;
704  painter->drawPixmap(QPointF(rect.center().x()-pix.size().width()/2,rect.center().y()-pix.size().height()/2),pix);
705  break;
707  painter->drawTiledPixmap(rect,pix);
708  break;
710  painter->drawTiledPixmap(rect,pix,QPoint(rect.size().width()/2,rect.size().height()/2));
711  }
712  }
714  painter->setBrush(QBrush(backgroundFirstColor,backgroundBrushStyle));
715  }
716 
717  if ( qFuzzyIsNull(borderCornerRadius) )
718  painter->drawRect(rect);
719  else
720  painter->drawRoundedRect(rect, borderCornerRadius, borderCornerRadius);
721 
722  //draw the border
723  if (borderPen.style() != Qt::NoPen) {
724  painter->setPen(borderPen);
725  painter->setBrush(Qt::NoBrush);
726  painter->setOpacity(borderOpacity);
727  if ( qFuzzyIsNull(borderCornerRadius) )
728  painter->drawRect(rect);
729  else
730  painter->drawRoundedRect(rect, borderCornerRadius, borderCornerRadius);
731  }
732 
733  //draw curve's line+symbol and the names
734  int curveCount = curvesList.size();
735  QFontMetrics fm(labelFont);
736  float h = fm.ascent();
737  painter->setFont(labelFont);
738 
739  //translate to left upper corner of the bounding rect plus the layout offset and the height of the title
740  painter->translate(-rect.width()/2+layoutLeftMargin, -rect.height()/2+layoutTopMargin);
741  if (title->isVisible() && !title->text().text.isEmpty())
742  painter->translate(0, title->graphicsItem()->boundingRect().height());
743 
744  painter->save();
745 
746  int index;
747  for (int c = 0; c < columnCount; ++c) {
748  for (int r = 0; r < rowCount; ++r) {
749  if (labelColumnMajor)
750  index = c*rowCount + r;
751  else
752  index = r*columnCount + c;
753 
754  if ( index >= curveCount )
755  break;
756 
757  //draw the legend item for histogram (simple rectangular with the sizes of the ascent)
758  const Histogram* hist = dynamic_cast<Histogram*>(curvesList.at(index));
759  if (hist) {
760  //use line's pen (histogram bars, envelope or drop lines) if available,
761  if (hist->lineType() != Histogram::NoLine && hist->linePen() != Qt::NoPen) {
762  painter->setOpacity(hist->lineOpacity());
763  painter->setPen(hist->linePen());
764  }
765 
766  //for the brush, use the histogram filling or symbols filling or no brush
767  if (hist->fillingEnabled())
768  painter->setBrush(QBrush(hist->fillingFirstColor(), hist->fillingBrushStyle()));
769  else if (hist->symbolsStyle() != Symbol::Style::NoSymbols)
770  painter->setBrush(hist->symbolsBrush());
771  else
772  painter->setBrush(Qt::NoBrush);
773 
774  painter->translate(QPointF(lineSymbolWidth/2, h/2));
775  painter->drawRect(QRectF(-h/2, -h/2, h, h));
776  painter->translate(-QPointF(lineSymbolWidth/2, h/2));
777 
778  //curve's name
779  painter->setPen(QPen(labelColor));
780  painter->setOpacity(1.0);
781  //TODO: support HTML text?
782  painter->drawText(QPoint(lineSymbolWidth + layoutHorizontalSpacing, h), hist->name());
783  painter->translate(0, layoutVerticalSpacing + h);
784  continue;
785  }
786 
787  //draw the legend item for histogram
788  const XYCurve* curve = static_cast<XYCurve*>(curvesList.at(index));
789 
790  //curve's line (painted at the half of the ascent size)
791  if (curve->lineType() != XYCurve::LineType::NoLine) {
792  painter->setPen(curve->linePen());
793  painter->setOpacity(curve->lineOpacity());
794  painter->drawLine(0, h/2, lineSymbolWidth, h/2);
795  }
796 
797  //error bars
798  if ( (curve->xErrorType() != XYCurve::ErrorType::NoError && curve->xErrorPlusColumn()) || (curve->yErrorType() != XYCurve::ErrorType::NoError && curve->yErrorPlusColumn()) ) {
799  painter->setOpacity(curve->errorBarsOpacity());
800  painter->setPen(curve->errorBarsPen());
801 
802  //curve's error bars for x
803  float errorBarsSize = Worksheet::convertToSceneUnits(10, Worksheet::Unit::Point);
804  if (curve->symbolsStyle()!=Symbol::Style::NoSymbols && errorBarsSize<curve->symbolsSize()*1.4)
805  errorBarsSize = curve->symbolsSize()*1.4;
806 
807  switch (curve->errorBarsType()) {
809  //horiz. line
810  if (curve->xErrorType() != XYCurve::ErrorType::NoError)
811  painter->drawLine(lineSymbolWidth/2-errorBarsSize/2, h/2,
812  lineSymbolWidth/2+errorBarsSize/2, h/2);
813  //vert. line
814  if (curve->yErrorType() != XYCurve::ErrorType::NoError)
815  painter->drawLine(lineSymbolWidth/2, h/2-errorBarsSize/2,
816  lineSymbolWidth/2, h/2+errorBarsSize/2);
817  break;
819  //horiz. line
820  if (curve->xErrorType() != XYCurve::ErrorType::NoError) {
821  painter->drawLine(lineSymbolWidth/2-errorBarsSize/2, h/2,
822  lineSymbolWidth/2+errorBarsSize/2, h/2);
823 
824  //caps for the horiz. line
825  painter->drawLine(lineSymbolWidth/2-errorBarsSize/2, h/2-errorBarsSize/4,
826  lineSymbolWidth/2-errorBarsSize/2, h/2+errorBarsSize/4);
827  painter->drawLine(lineSymbolWidth/2+errorBarsSize/2, h/2-errorBarsSize/4,
828  lineSymbolWidth/2+errorBarsSize/2, h/2+errorBarsSize/4);
829  }
830 
831  //vert. line
832  if (curve->yErrorType() != XYCurve::ErrorType::NoError) {
833  painter->drawLine(lineSymbolWidth/2, h/2-errorBarsSize/2,
834  lineSymbolWidth/2, h/2+errorBarsSize/2);
835 
836 
837  //caps for the vert. line
838  painter->drawLine(lineSymbolWidth/2-errorBarsSize/4, h/2-errorBarsSize/2,
839  lineSymbolWidth/2+errorBarsSize/4, h/2-errorBarsSize/2);
840  painter->drawLine(lineSymbolWidth/2-errorBarsSize/4, h/2+errorBarsSize/2,
841  lineSymbolWidth/2+errorBarsSize/4, h/2+errorBarsSize/2);
842  }
843  break;
844  }
845  }
846 
847  //curve's symbol
848  if (curve->symbolsStyle() != Symbol::Style::NoSymbols) {
849  painter->setOpacity(curve->symbolsOpacity());
850  painter->setBrush(curve->symbolsBrush());
851  painter->setPen(curve->symbolsPen());
852 
853  QPainterPath path = Symbol::pathFromStyle(curve->symbolsStyle());
854  QTransform trafo;
855  trafo.scale(curve->symbolsSize(), curve->symbolsSize());
856  path = trafo.map(path);
857 
858  if (curve->symbolsRotationAngle() != 0) {
859  trafo.reset();
860  trafo.rotate(curve->symbolsRotationAngle());
861  path = trafo.map(path);
862  }
863 
864  painter->translate(QPointF(lineSymbolWidth/2, h/2));
865  painter->drawPath(path);
866  painter->translate(-QPointF(lineSymbolWidth/2, h/2));
867  }
868 
869  //curve's name
870  painter->setPen(QPen(labelColor));
871  painter->setOpacity(1.0);
872  //TODO: support HTML text?
873  painter->drawText(QPoint(lineSymbolWidth+layoutHorizontalSpacing, h), curve->name());
874  painter->translate(0,layoutVerticalSpacing+h);
875  }
876 
877  //translate to the beginning of the next column
878  painter->restore();
879  int deltaX = lineSymbolWidth+layoutHorizontalSpacing+maxColumnTextWidths.at(c); //the width of the current columns
880  deltaX += 2*layoutHorizontalSpacing; //spacing between two columns
881  painter->translate(deltaX,0);
882  painter->save();
883  }
884 
885  painter->restore();
886  painter->restore();
887 
888  if (m_hovered && !isSelected() && !m_printing) {
889  painter->setPen(QPen(QApplication::palette().color(QPalette::Shadow), 2, Qt::SolidLine));
890  painter->drawPath(shape());
891  }
892 
893  if (isSelected() && !m_printing) {
894  painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine));
895  painter->drawPath(shape());
896  }
897 }
898 
899 QVariant CartesianPlotLegendPrivate::itemChange(GraphicsItemChange change, const QVariant &value) {
901  return value;
902 
903  if (change == QGraphicsItem::ItemPositionChange) {
904  //convert item's center point in parent's coordinates
906  tempPosition.point = value.toPointF();
909 
910  //emit the signals in order to notify the UI.
911  //we don't set the position related member variables during the mouse movements.
912  //this is done on mouse release events only.
913  emit q->positionChanged(tempPosition);
914  }
915 
916  return QGraphicsItem::itemChange(change, value);
917 }
918 
919 void CartesianPlotLegendPrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
920  //convert position of the item in parent coordinates to label's position
921  QPointF point = pos();
922  if (point != position.point) {
923  //position was changed -> set the position related member variables
924  suppressRetransform = true;
926  tempPosition.point = point;
929  q->setPosition(tempPosition);
930  suppressRetransform = false;
931  }
932 
933  QGraphicsItem::mouseReleaseEvent(event);
934 }
935 
937  if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right
938  || event->key() == Qt::Key_Up ||event->key() == Qt::Key_Down) {
939  const int delta = 5;
940  QPointF point = pos();
942 
943  if (event->key() == Qt::Key_Left) {
944  point.setX(point.x() - delta);
947  } else if (event->key() == Qt::Key_Right) {
948  point.setX(point.x() + delta);
951  } else if (event->key() == Qt::Key_Up) {
952  point.setY(point.y() - delta);
955  } else if (event->key() == Qt::Key_Down) {
956  point.setY(point.y() + delta);
959  }
960 
961  tempPosition.point = point;
962  q->setPosition(tempPosition);
963  }
964 
965  QGraphicsItem::keyPressEvent(event);
966 }
967 
968 void CartesianPlotLegendPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) {
969  if (!isSelected()) {
970  m_hovered = true;
971  emit q->hovered();
972  update();
973  }
974 }
975 
976 void CartesianPlotLegendPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
977  if (m_hovered) {
978  m_hovered = false;
979  emit q->unhovered();
980  update();
981  }
982 }
983 
984 //##############################################################################
985 //################## Serialization/Deserialization ###########################
986 //##############################################################################
987 //! Save as XML
988 void CartesianPlotLegend::save(QXmlStreamWriter* writer) const {
989  Q_D(const CartesianPlotLegend);
990 
991  writer->writeStartElement( "cartesianPlotLegend" );
992  writeBasicAttributes( writer );
993  writeCommentElement( writer );
994 
995  //general
996  writer->writeStartElement( "general" );
997  WRITE_QCOLOR(d->labelColor);
998  WRITE_QFONT(d->labelFont);
999  writer->writeAttribute( "columnMajor", QString::number(d->labelColumnMajor) );
1000  writer->writeAttribute( "lineSymbolWidth", QString::number(d->lineSymbolWidth) );
1001  writer->writeAttribute( "visible", QString::number(d->isVisible()) );
1002  writer->writeEndElement();
1003 
1004  //geometry
1005  writer->writeStartElement( "geometry" );
1006  writer->writeAttribute( "x", QString::number(d->position.point.x()) );
1007  writer->writeAttribute( "y", QString::number(d->position.point.y()) );
1008  writer->writeAttribute( "horizontalPosition", QString::number(static_cast<int>(d->position.horizontalPosition)) );
1009  writer->writeAttribute( "verticalPosition", QString::number(static_cast<int>(d->position.verticalPosition)) );
1010  writer->writeAttribute( "rotation", QString::number(d->rotationAngle) );
1011  writer->writeEndElement();
1012 
1013  //title
1014  d->title->save(writer);
1015 
1016  //background
1017  writer->writeStartElement( "background" );
1018  writer->writeAttribute( "type", QString::number(static_cast<int>(d->backgroundType)) );
1019  writer->writeAttribute( "colorStyle", QString::number(static_cast<int>(d->backgroundColorStyle)) );
1020  writer->writeAttribute( "imageStyle", QString::number(static_cast<int>(d->backgroundImageStyle)) );
1021  writer->writeAttribute( "brushStyle", QString::number(d->backgroundBrushStyle) );
1022  writer->writeAttribute( "firstColor_r", QString::number(d->backgroundFirstColor.red()) );
1023  writer->writeAttribute( "firstColor_g", QString::number(d->backgroundFirstColor.green()) );
1024  writer->writeAttribute( "firstColor_b", QString::number(d->backgroundFirstColor.blue()) );
1025  writer->writeAttribute( "secondColor_r", QString::number(d->backgroundSecondColor.red()) );
1026  writer->writeAttribute( "secondColor_g", QString::number(d->backgroundSecondColor.green()) );
1027  writer->writeAttribute( "secondColor_b", QString::number(d->backgroundSecondColor.blue()) );
1028  writer->writeAttribute( "fileName", d->backgroundFileName );
1029  writer->writeAttribute( "opacity", QString::number(d->backgroundOpacity) );
1030  writer->writeEndElement();
1031 
1032  //border
1033  writer->writeStartElement( "border" );
1034  WRITE_QPEN(d->borderPen);
1035  writer->writeAttribute( "borderOpacity", QString::number(d->borderOpacity) );
1036  writer->writeAttribute( "borderCornerRadius", QString::number(d->borderCornerRadius) );
1037  writer->writeEndElement();
1038 
1039  //layout
1040  writer->writeStartElement( "layout" );
1041  writer->writeAttribute( "topMargin", QString::number(d->layoutTopMargin) );
1042  writer->writeAttribute( "bottomMargin", QString::number(d->layoutBottomMargin) );
1043  writer->writeAttribute( "leftMargin", QString::number(d->layoutLeftMargin) );
1044  writer->writeAttribute( "rightMargin", QString::number(d->layoutRightMargin) );
1045  writer->writeAttribute( "verticalSpacing", QString::number(d->layoutVerticalSpacing) );
1046  writer->writeAttribute( "horizontalSpacing", QString::number(d->layoutHorizontalSpacing) );
1047  writer->writeAttribute( "columnCount", QString::number(d->layoutColumnCount) );
1048  writer->writeEndElement();
1049 
1050  writer->writeEndElement(); // close "cartesianPlotLegend" section
1051 }
1052 
1053 //! Load from XML
1054 bool CartesianPlotLegend::load(XmlStreamReader* reader, bool preview) {
1055  Q_D(CartesianPlotLegend);
1056 
1057  if (!readBasicAttributes(reader))
1058  return false;
1059 
1060  KLocalizedString attributeWarning = ki18n("Attribute '%1' missing or empty, default value is used");
1061  QXmlStreamAttributes attribs;
1062  QString str;
1063 
1064  while (!reader->atEnd()) {
1065  reader->readNext();
1066  if (reader->isEndElement() && reader->name() == "cartesianPlotLegend")
1067  break;
1068 
1069  if (!reader->isStartElement())
1070  continue;
1071 
1072  if (!preview && reader->name() == "comment") {
1073  if (!readCommentElement(reader)) return false;
1074  } else if (!preview && reader->name() == "general") {
1075  attribs = reader->attributes();
1076 
1077  READ_QCOLOR(d->labelColor);
1078  READ_QFONT(d->labelFont);
1079  READ_INT_VALUE("columnMajor", labelColumnMajor, int);
1080  READ_DOUBLE_VALUE("lineSymbolWidth", lineSymbolWidth);
1081 
1082  str = attribs.value("visible").toString();
1083  if (str.isEmpty())
1084  reader->raiseWarning(attributeWarning.subs("visible").toString());
1085  else
1086  d->setVisible(str.toInt());
1087  } else if (!preview && reader->name() == "geometry") {
1088  attribs = reader->attributes();
1089 
1090  str = attribs.value("x").toString();
1091  if (str.isEmpty())
1092  reader->raiseWarning(attributeWarning.subs("x").toString());
1093  else
1094  d->position.point.setX(str.toDouble());
1095 
1096  str = attribs.value("y").toString();
1097  if (str.isEmpty())
1098  reader->raiseWarning(attributeWarning.subs("y").toString());
1099  else
1100  d->position.point.setY(str.toDouble());
1101 
1102  str = attribs.value("horizontalPosition").toString();
1103  if (str.isEmpty())
1104  reader->raiseWarning(attributeWarning.subs("horizontalPosition").toString());
1105  else
1106  d->position.horizontalPosition = (WorksheetElement::HorizontalPosition)str.toInt();
1107 
1108  str = attribs.value("verticalPosition").toString();
1109  if (str.isEmpty())
1110  reader->raiseWarning(attributeWarning.subs("verticalPosition").toString());
1111  else
1112  d->position.verticalPosition = (WorksheetElement::VerticalPosition)str.toInt();
1113 
1114  READ_DOUBLE_VALUE("rotation", rotationAngle);
1115  } else if (reader->name() == "textLabel") {
1116  if (!d->title->load(reader, preview)) {
1117  delete d->title;
1118  d->title = nullptr;
1119  return false;
1120  }
1121  } else if (!preview && reader->name() == "background") {
1122  attribs = reader->attributes();
1123 
1124  READ_INT_VALUE("type", backgroundType, PlotArea::BackgroundType);
1125  READ_INT_VALUE("colorStyle", backgroundColorStyle, PlotArea::BackgroundColorStyle);
1126  READ_INT_VALUE("imageStyle", backgroundImageStyle, PlotArea::BackgroundImageStyle);
1127  READ_INT_VALUE("brushStyle", backgroundBrushStyle, Qt::BrushStyle);
1128 
1129  str = attribs.value("firstColor_r").toString();
1130  if (str.isEmpty())
1131  reader->raiseWarning(attributeWarning.subs("firstColor_r").toString());
1132  else
1133  d->backgroundFirstColor.setRed(str.toInt());
1134 
1135  str = attribs.value("firstColor_g").toString();
1136  if (str.isEmpty())
1137  reader->raiseWarning(attributeWarning.subs("firstColor_g").toString());
1138  else
1139  d->backgroundFirstColor.setGreen(str.toInt());
1140 
1141  str = attribs.value("firstColor_b").toString();
1142  if (str.isEmpty())
1143  reader->raiseWarning(attributeWarning.subs("firstColor_b").toString());
1144  else
1145  d->backgroundFirstColor.setBlue(str.toInt());
1146 
1147  str = attribs.value("secondColor_r").toString();
1148  if (str.isEmpty())
1149  reader->raiseWarning(attributeWarning.subs("secondColor_r").toString());
1150  else
1151  d->backgroundSecondColor.setRed(str.toInt());
1152 
1153  str = attribs.value("secondColor_g").toString();
1154  if (str.isEmpty())
1155  reader->raiseWarning(attributeWarning.subs("secondColor_g").toString());
1156  else
1157  d->backgroundSecondColor.setGreen(str.toInt());
1158 
1159  str = attribs.value("secondColor_b").toString();
1160  if (str.isEmpty())
1161  reader->raiseWarning(attributeWarning.subs("secondColor_b").toString());
1162  else
1163  d->backgroundSecondColor.setBlue(str.toInt());
1164 
1165  str = attribs.value("fileName").toString();
1166  d->backgroundFileName = str;
1167 
1168  READ_DOUBLE_VALUE("opacity", backgroundOpacity);
1169  } else if (!preview && reader->name() == "border") {
1170  attribs = reader->attributes();
1171  READ_QPEN(d->borderPen);
1172  READ_DOUBLE_VALUE("borderCornerRadius", borderCornerRadius);
1173  READ_DOUBLE_VALUE("borderOpacity", borderOpacity);
1174  } else if (!preview && reader->name() == "layout") {
1175  attribs = reader->attributes();
1176  READ_DOUBLE_VALUE("topMargin", layoutTopMargin);
1177  READ_DOUBLE_VALUE("bottomMargin", layoutBottomMargin);
1178  READ_DOUBLE_VALUE("leftMargin", layoutLeftMargin);
1179  READ_DOUBLE_VALUE("rightMargin", layoutRightMargin);
1180  READ_DOUBLE_VALUE("verticalSpacing", layoutVerticalSpacing);
1181  READ_DOUBLE_VALUE("horizontalSpacing", layoutHorizontalSpacing);
1182  READ_INT_VALUE("columnCount", layoutColumnCount, int);
1183  }
1184  }
1185 
1186  return true;
1187 }
1188 
1189 void CartesianPlotLegend::loadThemeConfig(const KConfig& config) {
1190  KConfigGroup group;
1191 
1192  //for the font color use the value defined in the theme config for Label
1193  if (config.hasGroup(QLatin1String("Theme")))
1194  group = config.group(QLatin1String("Label"));
1195  else
1196  group = config.group(QLatin1String("CartesianPlotLegend"));
1197 
1198  this->setLabelColor(group.readEntry("FontColor", QColor(Qt::white)));
1199 
1200  //for other theme dependent settings use the values defined in the theme config for CartesianPlot
1201  if (config.hasGroup(QLatin1String("Theme")))
1202  group = config.group("CartesianPlot");
1203 
1204  //background
1205  this->setBackgroundBrushStyle((Qt::BrushStyle)group.readEntry("BackgroundBrushStyle", (int)Qt::SolidPattern));
1206  this->setBackgroundColorStyle((PlotArea::BackgroundColorStyle)(group.readEntry("BackgroundColorStyle", (int)PlotArea::BackgroundColorStyle::SingleColor)));
1207  this->setBackgroundFirstColor(group.readEntry("BackgroundFirstColor", QColor(Qt::white)));
1208  this->setBackgroundImageStyle((PlotArea::BackgroundImageStyle)group.readEntry("BackgroundImageStyle", (int)PlotArea::BackgroundImageStyle::Scaled));
1209  this->setBackgroundOpacity(group.readEntry("BackgroundOpacity", 1.0));
1210  this->setBackgroundSecondColor(group.readEntry("BackgroundSecondColor", QColor(Qt::black)));
1211  this->setBackgroundType((PlotArea::BackgroundType)(group.readEntry("BackgroundType", (int)PlotArea::BackgroundType::Color)));
1212 
1213  //border
1214  QPen pen;
1215  pen.setColor(group.readEntry("BorderColor", QColor(Qt::black)));
1216  pen.setStyle((Qt::PenStyle)(group.readEntry("BorderStyle", (int)Qt::SolidLine)));
1217  pen.setWidthF(group.readEntry("BorderWidth", Worksheet::convertToSceneUnits(1.0, Worksheet::Unit::Point)));
1218  this->setBorderPen(pen);
1219  this->setBorderCornerRadius(group.readEntry("BorderCornerRadius", 0.0));
1220  this->setBorderOpacity(group.readEntry("BorderOpacity", 1.0));
1221 
1222  title()->loadThemeConfig(config);
1223 }
AspectType
STD_SETTER_CMD_IMPL_F_S(CartesianPlotLegend, SetPosition, WorksheetElement::PositionWrapper, position, updatePosition)
static const QRgb white
Definition: ImageEditor.cpp:37
static const QRgb black
Definition: ImageEditor.cpp:38
AspectType type() const
bool readCommentElement(XmlStreamReader *)
Load comment from an XML element.
void addChild(AbstractAspect *)
Add the given Aspect to my list of children.
AbstractAspect * parent(AspectType type) const
In the parent-child hierarchy, return the first parent of type.
QString name() const
void writeBasicAttributes(QXmlStreamWriter *) const
Save name and creation time to XML.
void exec(QUndoCommand *)
Execute the given command, pushing it on the undoStack() if available.
QVector< AbstractAspect * > children(AspectType type, ChildIndexFlags flags={}) const
bool readBasicAttributes(XmlStreamReader *)
Load name and creation time from XML.
void writeCommentElement(QXmlStreamWriter *) const
Save the comment to XML.
AbstractAspectPrivate * d
PlotArea::BackgroundType backgroundType
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override
void hoverLeaveEvent(QGraphicsSceneHoverEvent *) override
QList< WorksheetElement * > curvesList
void hoverEnterEvent(QGraphicsSceneHoverEvent *) override
QRectF boundingRect() const override
PlotArea::BackgroundColorStyle backgroundColorStyle
void keyPressEvent(QKeyEvent *) override
void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override
CartesianPlotLegendPrivate(CartesianPlotLegend *owner)
PlotArea::BackgroundImageStyle backgroundImageStyle
void contextMenuEvent(QGraphicsSceneContextMenuEvent *) override
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
CartesianPlotLegend *const q
WorksheetElement::PositionWrapper position
QPainterPath shape() const override
Legend for the cartesian plot.
void handleResize(double horizontalRatio, double verticalRatio, bool pageResize) override
void visibilityChanged(bool)
void retransform() override
Tell the element to newly transform its graphics item into its coordinate system.
void setZValue(qreal) override
bool load(XmlStreamReader *, bool preview) override
Load from XML.
void setVisible(bool) override
Show/hide the element.
QMenu * createContextMenu() override
Return a new context menu.
void positionChanged(const CartesianPlotLegend::PositionWrapper &)
bool isVisible() const override
Return whether the element is (at least) partially visible.
CartesianPlotLegendPrivate *const d_ptr
void save(QXmlStreamWriter *) const override
Save as XML.
void loadThemeConfig(const KConfig &config) override
QGraphicsItem * graphicsItem() const override
Return the graphics item representing this element.
CartesianPlotLegend(CartesianPlot *parentPlot, const QString &name)
~CartesianPlotLegend() override
void setPrinting(bool) override
Switches the printing mode on/off.
QIcon icon() const override
A xy-plot.
Definition: CartesianPlot.h:58
QRectF dataRect() const
A 2D-curve, provides an interface for editing many properties of the curve.
Definition: Histogram.h:42
BackgroundColorStyle
Definition: PlotArea.h:46
BackgroundImageStyle
Definition: PlotArea.h:48
BackgroundType
Definition: PlotArea.h:45
static QPainterPath pathFromStyle(Symbol::Style)
Definition: Symbol.cpp:43
A label supporting rendering of html- and tex-formatted texts.
Definition: TextLabel.h:44
void changed()
void loadThemeConfig(const KConfig &) override
Definition: TextLabel.cpp:1082
bool isVisible() const override
Return whether the element is (at least) partially visible.
Definition: TextLabel.cpp:343
QGraphicsItem * graphicsItem() const override
Return the graphics item representing this element.
Definition: TextLabel.cpp:156
void retransform() override
Tell the element to newly transform its graphics item into its coordinate system.
Definition: TextLabel.cpp:166
Base class for all Worksheet children.
virtual bool isVisible() const =0
Return whether the element is (at least) partially visible.
QMenu * createContextMenu() override
Return a new context menu.
Top-level container for worksheet elements like plot, labels, etc.
Definition: Worksheet.h:46
void suppressSelectionChangedEvent(bool)
Definition: Worksheet.cpp:408
static double convertToSceneUnits(const double value, const Worksheet::Unit unit)
Definition: Worksheet.cpp:113
A 2D-curve, provides an interface for editing many properties of the curve.
Definition: XYCurve.h:46
XML stream parser that supports errors as well as warnings. This class also adds line and column numb...
void raiseWarning(const QString &)
#define READ_DOUBLE_VALUE(name, var)
Definition: macros.h:475
#define WRITE_QCOLOR(color)
Definition: macros.h:286
#define CLASS_SHARED_D_READER_IMPL(classname, type, method, var)
Definition: macros.h:154
#define READ_INT_VALUE(name, var, type)
Definition: macros.h:468
#define READ_QPEN(pen)
Definition: macros.h:324
#define WRITE_QPEN(pen)
Definition: macros.h:315
#define READ_QCOLOR(color)
Definition: macros.h:293
#define STD_SWAP_METHOD_SETTER_CMD_IMPL(class_name, cmd_name, value_type, method_name)
Definition: macros.h:250
#define BASIC_SHARED_D_READER_IMPL(classname, type, method, var)
Definition: macros.h:127
#define WRITE_QFONT(font)
Definition: macros.h:361
#define READ_QFONT(font)
Definition: macros.h:370
@ Shadow
Definition: OriginObj.h:71
#define i18n(m)
Definition: nsl_common.h:38
WorksheetElement::VerticalPosition verticalPosition
WorksheetElement::HorizontalPosition horizontalPosition